+ free(addr_f);
+ free(tmp_uris);
+error:
+ return -1;
+}
+
+/*
+ * Parse a string URL and creates URI(s) returning the size of the populated
+ * array.
+ */
+LTTNG_HIDDEN
+ssize_t uri_parse_str_urls(const char *ctrl_url, const char *data_url,
+ struct lttng_uri **uris)
+{
+ unsigned int equal = 1, idx = 0;
+ /* Add the "file://" size to the URL maximum size */
+ char url[PATH_MAX + 7];
+ ssize_t ctrl_uri_count = 0, data_uri_count = 0, uri_count;
+ struct lttng_uri *ctrl_uris = NULL, *data_uris = NULL;
+ struct lttng_uri *tmp_uris = NULL;
+
+ /* No URL(s) is allowed. This means that the consumer will be disabled. */
+ if (ctrl_url == NULL && data_url == NULL) {
+ return 0;
+ }
+
+ /* Check if URLs are equal and if so, only use the control URL */
+ if ((ctrl_url && *ctrl_url != '\0') && (data_url && *data_url != '\0')) {
+ equal = !strcmp(ctrl_url, data_url);
+ }
+
+ /*
+ * Since we allow the str_url to be a full local filesystem path, we are
+ * going to create a valid file:// URL if it's the case.
+ *
+ * Check if first character is a '/' or else reject the URL.
+ */
+ if (ctrl_url && ctrl_url[0] == '/') {
+ int ret;
+
+ ret = snprintf(url, sizeof(url), "file://%s", ctrl_url);
+ if (ret < 0) {
+ PERROR("snprintf file url");
+ goto parse_error;
+ } else if (ret >= sizeof(url)) {
+ PERROR("snprintf file url is too long");
+ goto parse_error;
+
+ }
+ ctrl_url = url;
+ }
+
+ /* Parse the control URL if there is one */
+ if (ctrl_url && *ctrl_url != '\0') {
+ ctrl_uri_count = uri_parse(ctrl_url, &ctrl_uris);
+ if (ctrl_uri_count < 1) {
+ ERR("Unable to parse the URL %s", ctrl_url);
+ goto parse_error;
+ }
+
+ /* 1 and 2 are the only expected values on success. */
+ assert(ctrl_uri_count == 1 || ctrl_uri_count == 2);
+
+ /* At this point, we know there is at least one URI in the array */
+ set_default_uri_attr(&ctrl_uris[0], LTTNG_STREAM_CONTROL);
+
+ if (ctrl_uris[0].dtype == LTTNG_DST_PATH &&
+ (data_url && *data_url != '\0')) {
+ ERR("Cannot have a data URL when destination is file://");
+ goto error;
+ }
+
+ /* URL are not equal but the control URL uses a net:// protocol */
+ if (ctrl_uri_count == 2) {
+ if (!equal) {
+ ERR("Control URL uses the net:// protocol and the data URL is "
+ "different. Not allowed.");
+ goto error;
+ } else {
+ set_default_uri_attr(&ctrl_uris[1], LTTNG_STREAM_DATA);
+ /*
+ * The data_url and ctrl_url are equal and the ctrl_url
+ * contains a net:// protocol so we just skip the data part.
+ */
+ data_url = NULL;
+ }
+ }
+ }
+
+ if (data_url && *data_url != '\0') {
+ int ret;
+
+ /* We have to parse the data URL in this case */
+ data_uri_count = uri_parse(data_url, &data_uris);
+ if (data_uri_count < 1) {
+ ERR("Unable to parse the URL %s", data_url);
+ goto error;
+ } else if (data_uri_count == 2) {
+ ERR("Data URL can not be set with the net[4|6]:// protocol");
+ goto error;
+ } else {
+ /* 1 and 2 are the only expected values on success. */
+ assert(data_uri_count == 1);
+ }
+
+ set_default_uri_attr(&data_uris[0], LTTNG_STREAM_DATA);
+
+ if (ctrl_uris) {
+ ret = compare_destination(&ctrl_uris[0], &data_uris[0]);
+ if (ret != 0) {
+ ERR("Control and data destination mismatch");
+ goto error;
+ }
+ }
+ }
+
+ /* Compute total size. */
+ uri_count = ctrl_uri_count + data_uri_count;
+ if (uri_count <= 0) {
+ goto error;
+ }
+
+ tmp_uris = zmalloc(sizeof(struct lttng_uri) * uri_count);
+ if (tmp_uris == NULL) {
+ PERROR("zmalloc uris");
+ goto error;
+ }
+
+ if (ctrl_uris) {
+ /* It's possible the control URIs array contains more than one URI */
+ memcpy(tmp_uris, ctrl_uris, sizeof(struct lttng_uri) * ctrl_uri_count);
+ ++idx;
+ free(ctrl_uris);
+ }
+
+ if (data_uris) {
+ memcpy(&tmp_uris[idx], data_uris, sizeof(struct lttng_uri));
+ free(data_uris);
+ }
+
+ *uris = tmp_uris;
+
+ return uri_count;
+