+ v = bt_trace_class_borrow_environment_entry_value_by_name_const(tc, "tracer_major");
+ if (!v || !bt_value_is_integer(v)) {
+ BT_LOGD_STR("Couldn't get environment value: name=\"tracer_major\"");
+ goto error;
+ }
+
+ tracer_major = bt_value_integer_get(v);
+
+ v = bt_trace_class_borrow_environment_entry_value_by_name_const(tc, "tracer_minor");
+ if (!v || !bt_value_is_integer(v)) {
+ BT_LOGD_STR("Couldn't get environment value: name=\"tracer_minor\"");
+ goto error;
+ }
+
+ tracer_minor = bt_value_integer_get(v);
+
+ if (!(tracer_major >= 3 || (tracer_major == 2 && tracer_minor >= 11))) {
+ BT_LOGD("Unsupported LTTng version for automatic trace path: major=%" PRId64 ", minor=%" PRId64,
+ tracer_major, tracer_minor);
+ goto error;
+ }
+
+ v = bt_trace_class_borrow_environment_entry_value_by_name_const(tc, "hostname");
+ if (!v || !bt_value_is_string(v)) {
+ BT_LOGD_STR("Couldn't get environment value: name=\"tracer_hostname\"");
+ goto error;
+ }
+
+ g_string_assign(path, bt_value_string_get(v));
+
+ v = bt_trace_class_borrow_environment_entry_value_by_name_const(tc, "trace_name");
+ if (!v || !bt_value_is_string(v)) {
+ BT_LOGD_STR("Couldn't get environment value: name=\"trace_name\"");
+ goto error;
+ }
+
+ g_string_append_printf(path, G_DIR_SEPARATOR_S "%s", bt_value_string_get(v));
+
+ v = bt_trace_class_borrow_environment_entry_value_by_name_const(tc, "trace_creation_datetime");
+ if (!v || !bt_value_is_string(v)) {
+ BT_LOGD_STR("Couldn't get environment value: name=\"trace_creation_datetime\"");
+ goto error;
+ }
+
+ datetime = bt_value_string_get(v);
+
+ if (lttng_validate_datetime(datetime)) {
+ goto error;
+ }
+
+ g_string_append_printf(path, "-%s", datetime);
+
+ v = bt_trace_class_borrow_environment_entry_value_by_name_const(tc, "domain");
+ if (!v || !bt_value_is_string(v)) {
+ BT_LOGD_STR("Couldn't get environment value: name=\"domain\"");
+ goto error;
+ }
+
+ domain = bt_value_string_get(v);
+ g_string_append_printf(path, G_DIR_SEPARATOR_S "%s", domain);
+
+ if (g_str_equal(domain, "ust")) {
+ const char *tracer_buffering_scheme;
+
+ v = bt_trace_class_borrow_environment_entry_value_by_name_const(tc, "tracer_buffering_scheme");
+ if (!v || !bt_value_is_string(v)) {
+ BT_LOGD_STR("Couldn't get environment value: name=\"tracer_buffering_scheme\"");
+ goto error;
+ }
+
+ tracer_buffering_scheme = bt_value_string_get(v);
+ g_string_append_printf(path, G_DIR_SEPARATOR_S "%s", tracer_buffering_scheme);
+
+ if (g_str_equal(tracer_buffering_scheme, "uid")) {
+ if (append_lttng_trace_path_ust_uid(path, tc)) {
+ goto error;
+ }
+ } else if (g_str_equal(tracer_buffering_scheme, "pid")){
+ if (append_lttng_trace_path_ust_pid(path, tc)) {
+ goto error;
+ }
+ } else {
+ /* Unknown buffering scheme. */
+ BT_LOGD("Unknown buffering scheme: tracer_buffering_scheme=\"%s\"", tracer_buffering_scheme);
+ goto error;
+ }
+ } else if (!g_str_equal(domain, "kernel")) {
+ /* Unknown domain. */
+ BT_LOGD("Unknown domain: domain=\"%s\"", domain);
+ goto error;
+ }
+
+ goto end;
+
+error:
+ if (path) {
+ g_string_free(path, TRUE);
+ path = NULL;
+ }
+
+end:
+ return path;
+}
+
+/* Build the relative output path for `trace`. */
+
+static
+GString *make_trace_path_rel(const struct fs_sink_trace *trace)
+{
+ GString *path = NULL;
+
+ if (trace->fs_sink->assume_single_trace) {
+ /* Use output directory directly */
+ path = g_string_new("");
+ goto end;
+ }
+
+ /* First, try to build a path using environment fields written by LTTng. */
+ path = make_lttng_trace_path_rel(trace);
+ if (path) {
+ goto end;
+ }
+
+ /* Otherwise, use the trace name, if available. */
+ const char *trace_name = bt_trace_get_name(trace->ir_trace);
+ if (trace_name) {
+ path = g_string_new(trace_name);
+ goto end;
+ }
+
+ /* Otherwise, use "trace". */
+ path = g_string_new("trace");
+
+end: