Add UST uid/gid contexts
[lttng-tools.git] / src / bin / lttng-sessiond / save.c
index 6b1bf69c424ab1bd18f67a342d4208594f3821fc..865775c8d838108c9691a6010183a8932a1a1abf 100644 (file)
@@ -215,13 +215,16 @@ const char *get_kernel_instrumentation_string(
                instrumentation_string = config_event_type_tracepoint;
                break;
        case LTTNG_KERNEL_KPROBE:
-               instrumentation_string = config_event_type_kprobe;
+               instrumentation_string = config_event_type_probe;
+               break;
+       case LTTNG_KERNEL_UPROBE:
+               instrumentation_string = config_event_type_userspace_probe;
                break;
        case LTTNG_KERNEL_FUNCTION:
-               instrumentation_string = config_event_type_function;
+               instrumentation_string = config_event_type_function_entry;
                break;
        case LTTNG_KERNEL_KRETPROBE:
-               instrumentation_string = config_event_type_kretprobe;
+               instrumentation_string = config_event_type_function;
                break;
        case LTTNG_KERNEL_NOOP:
                instrumentation_string = config_event_type_noop;
@@ -285,6 +288,69 @@ const char *get_kernel_context_type_string(
        case LTTNG_KERNEL_CONTEXT_MIGRATABLE:
                context_type_string = config_event_context_migratable;
                break;
+       case LTTNG_KERNEL_CONTEXT_CALLSTACK_USER:
+               context_type_string = config_event_context_callstack_user;
+               break;
+       case LTTNG_KERNEL_CONTEXT_CALLSTACK_KERNEL:
+               context_type_string = config_event_context_callstack_kernel;
+               break;
+       case LTTNG_KERNEL_CONTEXT_CGROUP_NS:
+               context_type_string = config_event_context_cgroup_ns;
+               break;
+       case LTTNG_KERNEL_CONTEXT_IPC_NS:
+               context_type_string = config_event_context_ipc_ns;
+               break;
+       case LTTNG_KERNEL_CONTEXT_MNT_NS:
+               context_type_string = config_event_context_mnt_ns;
+               break;
+       case LTTNG_KERNEL_CONTEXT_NET_NS:
+               context_type_string = config_event_context_net_ns;
+               break;
+       case LTTNG_KERNEL_CONTEXT_PID_NS:
+               context_type_string = config_event_context_pid_ns;
+               break;
+       case LTTNG_KERNEL_CONTEXT_USER_NS:
+               context_type_string = config_event_context_user_ns;
+               break;
+       case LTTNG_KERNEL_CONTEXT_UTS_NS:
+               context_type_string = config_event_context_uts_ns;
+               break;
+       case LTTNG_KERNEL_CONTEXT_UID:
+               context_type_string = config_event_context_uid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_EUID:
+               context_type_string = config_event_context_euid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_SUID:
+               context_type_string = config_event_context_suid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_GID:
+               context_type_string = config_event_context_gid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_EGID:
+               context_type_string = config_event_context_egid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_SGID:
+               context_type_string = config_event_context_sgid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_VUID:
+               context_type_string = config_event_context_vuid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_VEUID:
+               context_type_string = config_event_context_veuid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_VSUID:
+               context_type_string = config_event_context_vsuid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_VGID:
+               context_type_string = config_event_context_vgid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_VEGID:
+               context_type_string = config_event_context_vegid;
+               break;
+       case LTTNG_KERNEL_CONTEXT_VSGID:
+               context_type_string = config_event_context_vsgid;
+               break;
        default:
                context_type_string = NULL;
        }
@@ -317,6 +383,45 @@ const char *get_ust_context_type_string(
        case LTTNG_UST_CONTEXT_APP_CONTEXT:
                context_type_string = config_event_context_app;
                break;
+       case LTTNG_UST_CONTEXT_CGROUP_NS:
+               context_type_string = config_event_context_cgroup_ns;
+               break;
+       case LTTNG_UST_CONTEXT_IPC_NS:
+               context_type_string = config_event_context_ipc_ns;
+               break;
+       case LTTNG_UST_CONTEXT_MNT_NS:
+               context_type_string = config_event_context_mnt_ns;
+               break;
+       case LTTNG_UST_CONTEXT_NET_NS:
+               context_type_string = config_event_context_net_ns;
+               break;
+       case LTTNG_UST_CONTEXT_PID_NS:
+               context_type_string = config_event_context_pid_ns;
+               break;
+       case LTTNG_UST_CONTEXT_USER_NS:
+               context_type_string = config_event_context_user_ns;
+               break;
+       case LTTNG_UST_CONTEXT_UTS_NS:
+               context_type_string = config_event_context_uts_ns;
+               break;
+       case LTTNG_UST_CONTEXT_VUID:
+               context_type_string = config_event_context_vuid;
+               break;
+       case LTTNG_UST_CONTEXT_VEUID:
+               context_type_string = config_event_context_veuid;
+               break;
+       case LTTNG_UST_CONTEXT_VSUID:
+               context_type_string = config_event_context_vsuid;
+               break;
+       case LTTNG_UST_CONTEXT_VGID:
+               context_type_string = config_event_context_vgid;
+               break;
+       case LTTNG_UST_CONTEXT_VEGID:
+               context_type_string = config_event_context_vegid;
+               break;
+       case LTTNG_UST_CONTEXT_VSGID:
+               context_type_string = config_event_context_vsgid;
+               break;
        case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
                /*
                 * Error, should not be stored in the XML, perf contexts
@@ -376,9 +481,384 @@ const char *get_loglevel_type_string(
        return loglevel_type_string;
 }
 
+static
+int save_kernel_function_event(struct config_writer *writer,
+               struct ltt_kernel_event *event)
+{
+       int ret;
+
+       ret = config_writer_open_element(writer, config_element_function_attributes);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       ret = config_writer_write_element_string(writer, config_element_name,
+                       event->event->u.ftrace.symbol_name);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       /* /function attributes */
+       ret = config_writer_close_element(writer);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+end:
+       return ret;
+}
+
+static
+int save_kernel_kprobe_event(struct config_writer *writer,
+               struct ltt_kernel_event *event)
+{
+       int ret;
+       const char *symbol_name;
+       uint64_t addr;
+       uint64_t offset;
+
+       switch (event->event->instrumentation) {
+       case LTTNG_KERNEL_KPROBE:
+               /*
+                * Comments in lttng-kernel.h mention that
+                * either addr or symbol_name are set, not both.
+                */
+               addr = event->event->u.kprobe.addr;
+               offset = event->event->u.kprobe.offset;
+               symbol_name = addr ? NULL : event->event->u.kprobe.symbol_name;
+               break;
+       case LTTNG_KERNEL_KRETPROBE:
+               addr = event->event->u.kretprobe.addr;
+               offset = event->event->u.kretprobe.offset;
+               symbol_name = addr ? NULL : event->event->u.kretprobe.symbol_name;
+               break;
+       default:
+               assert(1);
+               ERR("Unsupported kernel instrumentation type.");
+               ret = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       ret = config_writer_open_element(writer, config_element_probe_attributes);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       if (addr) {
+               ret = config_writer_write_element_unsigned_int( writer,
+                               config_element_address, addr);
+               if (ret) {
+                       ret = LTTNG_ERR_SAVE_IO_FAIL;
+                       goto end;
+               }
+       } else if (symbol_name) {
+               ret = config_writer_write_element_string(writer,
+                                config_element_symbol_name, symbol_name);
+               if (ret) {
+                       ret = LTTNG_ERR_SAVE_IO_FAIL;
+                       goto end;
+               }
+               /* If the offset is non-zero, write it.*/
+               if (offset) {
+                       ret = config_writer_write_element_unsigned_int(writer,
+                               config_element_offset, offset);
+                       if (ret) {
+                               ret = LTTNG_ERR_SAVE_IO_FAIL;
+                               goto end;
+                       }
+               }
+       } else {
+               /*
+                * This really should not happen as we are either setting the
+                * address or the symbol above.
+                */
+               ERR("Invalid probe/function description.");
+               ret = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+
+       ret = config_writer_close_element(writer);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+end:
+       return ret;
+}
+
+/*
+ * Save the userspace probe tracepoint event associated with the event to the
+ * config writer.
+ */
+static
+int save_kernel_userspace_probe_tracepoint_event(struct config_writer *writer,
+               struct ltt_kernel_event *event)
+{
+       int ret = 0;
+       const char *probe_name, *provider_name, *binary_path;
+       const struct lttng_userspace_probe_location *userspace_probe_location;
+       const struct lttng_userspace_probe_location_lookup_method *lookup_method;
+       enum lttng_userspace_probe_location_lookup_method_type lookup_type;
+
+       /* Get userspace probe location from the event. */
+       userspace_probe_location = event->userspace_probe_location;
+       if (!userspace_probe_location) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       /* Get lookup method and lookup method type. */
+       lookup_method = lttng_userspace_probe_location_get_lookup_method(userspace_probe_location);
+       if (!lookup_method) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       lookup_type = lttng_userspace_probe_location_lookup_method_get_type(lookup_method);
+
+       /* Get the binary path, probe name and provider name. */
+       binary_path =
+               lttng_userspace_probe_location_tracepoint_get_binary_path(
+                               userspace_probe_location);
+       if (!binary_path) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       probe_name =
+               lttng_userspace_probe_location_tracepoint_get_probe_name(
+                               userspace_probe_location);
+       if (!probe_name) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       provider_name =
+               lttng_userspace_probe_location_tracepoint_get_provider_name(
+                               userspace_probe_location);
+       if (!provider_name) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       /* Open a userspace probe tracepoint attribute. */
+       ret = config_writer_open_element(writer, config_element_userspace_probe_tracepoint_attributes);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       switch (lookup_type) {
+       case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
+               ret = config_writer_write_element_string(writer,
+                               config_element_userspace_probe_lookup,
+                               config_element_userspace_probe_lookup_tracepoint_sdt);
+               if (ret) {
+                       ret = LTTNG_ERR_SAVE_IO_FAIL;
+                       goto end;
+               }
+               break;
+       default:
+               ERR("Unsupported kernel userspace probe tracepoint lookup method.");
+               ret = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       /* Write the binary path, provider name and the probe name. */
+       ret = config_writer_write_element_string(writer,
+                       config_element_userspace_probe_location_binary_path,
+                       binary_path);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       ret = config_writer_write_element_string(writer,
+                       config_element_userspace_probe_tracepoint_location_provider_name,
+                       provider_name);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       ret = config_writer_write_element_string(writer,
+                       config_element_userspace_probe_tracepoint_location_probe_name,
+                       probe_name);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       /* Close the userspace probe tracepoint attribute. */
+       ret = config_writer_close_element(writer);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+/*
+ * Save the userspace probe function event associated with the event to the
+ * config writer.
+ */
+static
+int save_kernel_userspace_probe_function_event(struct config_writer *writer,
+               struct ltt_kernel_event *event)
+{
+       int ret = 0;
+       const char *function_name, *binary_path;
+       const struct lttng_userspace_probe_location *userspace_probe_location;
+       const struct lttng_userspace_probe_location_lookup_method *lookup_method;
+       enum lttng_userspace_probe_location_lookup_method_type lookup_type;
+
+       /* Get userspace probe location from the event. */
+       userspace_probe_location = event->userspace_probe_location;
+       if (!userspace_probe_location) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       /* Get lookup method and lookup method type. */
+       lookup_method = lttng_userspace_probe_location_get_lookup_method(
+                       userspace_probe_location);
+       if (!lookup_method) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       /* Get the binary path and the function name. */
+       binary_path =
+               lttng_userspace_probe_location_function_get_binary_path(
+                               userspace_probe_location);
+       if (!binary_path) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       function_name =
+               lttng_userspace_probe_location_function_get_function_name(
+                               userspace_probe_location);
+       if (!function_name) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       /* Open a userspace probe function attribute. */
+       ret = config_writer_open_element(writer,
+                       config_element_userspace_probe_function_attributes);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       lookup_type = lttng_userspace_probe_location_lookup_method_get_type(lookup_method);
+       switch (lookup_type) {
+       case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
+               ret = config_writer_write_element_string(writer,
+                               config_element_userspace_probe_lookup,
+                               config_element_userspace_probe_lookup_function_elf);
+               if (ret) {
+                       ret = LTTNG_ERR_SAVE_IO_FAIL;
+                       goto end;
+               }
+               break;
+       case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
+               ret = config_writer_write_element_string(writer,
+                               config_element_userspace_probe_lookup,
+                               config_element_userspace_probe_lookup_function_default);
+               if (ret) {
+                       ret = LTTNG_ERR_SAVE_IO_FAIL;
+                       goto end;
+               }
+               break;
+       default:
+               ERR("Unsupported kernel userspace probe function lookup method.");
+               ret = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       /* Write the binary path and the function name. */
+       ret = config_writer_write_element_string(writer,
+                       config_element_userspace_probe_location_binary_path,
+                       binary_path);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       ret = config_writer_write_element_string(writer,
+                       config_element_userspace_probe_function_location_function_name,
+                       function_name);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       /* Close the userspace probe function attribute. */
+       ret = config_writer_close_element(writer);
+       if (ret) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+static
+int save_kernel_userspace_probe_event(struct config_writer *writer,
+               struct ltt_kernel_event *event)
+{
+       int ret;
+       struct lttng_userspace_probe_location *userspace_probe_location;
+
+       /* Get userspace probe location from the event. */
+       userspace_probe_location = event->userspace_probe_location;
+       if (!userspace_probe_location) {
+               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               goto end;
+       }
+
+       switch(lttng_userspace_probe_location_get_type(userspace_probe_location)) {
+       case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
+       {
+               ret = save_kernel_userspace_probe_function_event(writer, event);
+               if (ret) {
+                       ret = LTTNG_ERR_SAVE_IO_FAIL;
+                       goto end;
+               }
+               break;
+       }
+       case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
+       {
+               ret = save_kernel_userspace_probe_tracepoint_event(writer, event);
+               if (ret) {
+                       ret = LTTNG_ERR_SAVE_IO_FAIL;
+                       goto end;
+               }
+               break;
+       }
+       case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN:
+       default:
+               ERR("Unsupported kernel userspace probe location type.");
+               ret = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
 static
 int save_kernel_event(struct config_writer *writer,
-       struct ltt_kernel_event *event)
+               struct ltt_kernel_event *event)
 {
        int ret;
        const char *instrumentation_type;
@@ -431,6 +911,7 @@ int save_kernel_event(struct config_writer *writer,
 
        if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
                event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
+               event->event->instrumentation == LTTNG_KERNEL_UPROBE ||
                event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
 
                ret = config_writer_open_element(writer,
@@ -443,94 +924,24 @@ int save_kernel_event(struct config_writer *writer,
                switch (event->event->instrumentation) {
                case LTTNG_KERNEL_SYSCALL:
                case LTTNG_KERNEL_FUNCTION:
-                       ret = config_writer_open_element(writer,
-                               config_element_function_attributes);
-                       if (ret) {
-                               ret = LTTNG_ERR_SAVE_IO_FAIL;
-                               goto end;
-                       }
-
-                       ret = config_writer_write_element_string(writer,
-                               config_element_name,
-                               event->event->u.ftrace.symbol_name);
-                       if (ret) {
-                               ret = LTTNG_ERR_SAVE_IO_FAIL;
-                               goto end;
-                       }
-
-                       /* /function attributes */
-                       ret = config_writer_close_element(writer);
+                       ret = save_kernel_function_event(writer, event);
                        if (ret) {
-                               ret = LTTNG_ERR_SAVE_IO_FAIL;
                                goto end;
                        }
                        break;
                case LTTNG_KERNEL_KPROBE:
                case LTTNG_KERNEL_KRETPROBE:
-               {
-                       const char *symbol_name;
-                       uint64_t addr;
-                       uint64_t offset;
-
-                       if (event->event->instrumentation ==
-                               LTTNG_KERNEL_KPROBE) {
-                               /*
-                                * Comments in lttng-kernel.h mention that
-                                * either addr or symbol_name are set, not both.
-                                */
-                               addr = event->event->u.kprobe.addr;
-                               offset = event->event->u.kprobe.offset;
-                               symbol_name = addr ? NULL :
-                                       event->event->u.kprobe.symbol_name;
-                       } else {
-                               symbol_name =
-                                       event->event->u.kretprobe.symbol_name;
-                               addr = event->event->u.kretprobe.addr;
-                               offset = event->event->u.kretprobe.offset;
-                       }
-
-                       ret = config_writer_open_element(writer,
-                               config_element_probe_attributes);
+                       ret = save_kernel_kprobe_event(writer, event);
                        if (ret) {
-                               ret = LTTNG_ERR_SAVE_IO_FAIL;
                                goto end;
                        }
-
-                       if (symbol_name) {
-                               ret = config_writer_write_element_string(writer,
-                                       config_element_symbol_name,
-                                       symbol_name);
-                               if (ret) {
-                                       ret = LTTNG_ERR_SAVE_IO_FAIL;
-                                       goto end;
-                               }
-                       }
-
-                       if (addr) {
-                               ret = config_writer_write_element_unsigned_int(
-                                       writer, config_element_address, addr);
-                               if (ret) {
-                                       ret = LTTNG_ERR_SAVE_IO_FAIL;
-                                       goto end;
-                               }
-                       }
-
-                       if (offset) {
-                               ret = config_writer_write_element_unsigned_int(
-                                       writer, config_element_offset, offset);
-                               if (ret) {
-                                       ret = LTTNG_ERR_SAVE_IO_FAIL;
-                                       goto end;
-                               }
-                       }
-
-                       ret = config_writer_close_element(writer);
+                       break;
+               case LTTNG_KERNEL_UPROBE:
+                       ret = save_kernel_userspace_probe_event(writer, event);
                        if (ret) {
-                               ret = LTTNG_ERR_SAVE_IO_FAIL;
                                goto end;
                        }
                        break;
-               }
                default:
                        ERR("Unsupported kernel instrumentation type.");
                        ret = LTTNG_ERR_INVALID;
@@ -1880,6 +2291,86 @@ end:
        return ret;
 }
 
+static
+int save_session_rotation_schedule(struct config_writer *writer,
+               enum lttng_rotation_schedule_type type, uint64_t value)
+{
+       int ret = 0;
+       const char *element_name;
+       const char *value_name;
+
+       switch (type) {
+       case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
+               element_name = config_element_rotation_schedule_periodic;
+               value_name = config_element_rotation_schedule_periodic_time_us;
+               break;
+       case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
+               element_name = config_element_rotation_schedule_size_threshold;
+               value_name = config_element_rotation_schedule_size_threshold_bytes;
+               break;
+       default:
+               ret = -1;
+               goto end;
+       }
+
+       ret = config_writer_open_element(writer, element_name);
+       if (ret) {
+               goto end;
+       }
+
+       ret = config_writer_write_element_unsigned_int(writer,
+                       value_name, value);
+       if (ret) {
+               goto end;
+       }
+
+       /* Close schedule descriptor element. */
+       ret = config_writer_close_element(writer);
+       if (ret) {
+               goto end;
+       }
+end:
+       return ret;
+}
+
+static
+int save_session_rotation_schedules(struct config_writer *writer,
+       struct ltt_session *session)
+{
+       int ret;
+
+       ret = config_writer_open_element(writer,
+                       config_element_rotation_schedules);
+       if (ret) {
+               goto end;
+       }
+       if (session->rotate_timer_period) {
+               ret = save_session_rotation_schedule(writer,
+                               LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC,
+                               session->rotate_timer_period);
+               if (ret) {
+                       goto close_schedules;
+               }
+       }
+       if (session->rotate_size) {
+               ret = save_session_rotation_schedule(writer,
+                               LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD,
+                               session->rotate_size);
+               if (ret) {
+                       goto close_schedules;
+               }
+       }
+
+close_schedules:
+       /* Close rotation schedules element. */
+       ret = config_writer_close_element(writer);
+       if (ret) {
+               goto end;
+       }
+end:
+       return ret;
+}
+
 /*
  * Save the given session.
  *
@@ -1889,13 +2380,13 @@ static
 int save_session(struct ltt_session *session,
        struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
 {
-       int ret, fd;
-       unsigned int file_opened = 0;   /* Indicate if the file has been opened */
-       char config_file_path[PATH_MAX];
+       int ret, fd = -1;
+       char config_file_path[LTTNG_PATH_MAX];
        size_t len;
        struct config_writer *writer = NULL;
        size_t session_name_len;
        const char *provided_path;
+       int file_open_flags = O_CREAT | O_WRONLY | O_TRUNC;
 
        assert(session);
        assert(attr);
@@ -1906,7 +2397,7 @@ int save_session(struct ltt_session *session,
 
        if (!session_access_ok(session,
                LTTNG_SOCK_GET_UID_CRED(creds),
-               LTTNG_SOCK_GET_GID_CRED(creds))) {
+               LTTNG_SOCK_GET_GID_CRED(creds)) || session->destroyed) {
                ret = LTTNG_ERR_EPERM;
                goto end;
        }
@@ -1919,7 +2410,7 @@ int save_session(struct ltt_session *session,
                        ret = LTTNG_ERR_SET_URL;
                        goto end;
                }
-               strncpy(config_file_path, provided_path, len);
+               strncpy(config_file_path, provided_path, sizeof(config_file_path));
        } else {
                ssize_t ret_len;
                char *home_dir = utils_get_user_home_dir(
@@ -1963,27 +2454,34 @@ int save_session(struct ltt_session *session,
         * was done just above.
         */
        config_file_path[len++] = '/';
-       strncpy(config_file_path + len, session->name, session_name_len);
+       strncpy(config_file_path + len, session->name, sizeof(config_file_path) - len);
        len += session_name_len;
        strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
        len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
        config_file_path[len] = '\0';
 
-       if (!access(config_file_path, F_OK) && !attr->overwrite) {
-               /* File exists, notify the user since the overwrite flag is off. */
-               ret = LTTNG_ERR_SAVE_FILE_EXIST;
-               goto end;
+       if (!attr->overwrite) {
+               file_open_flags |= O_EXCL;
        }
 
-       fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
+       fd = run_as_open(config_file_path, file_open_flags,
                S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
                LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
        if (fd < 0) {
                PERROR("Could not create configuration file");
-               ret = LTTNG_ERR_SAVE_IO_FAIL;
+               switch (errno) {
+               case EEXIST:
+                       ret = LTTNG_ERR_SAVE_FILE_EXIST;
+                       break;
+               case EACCES:
+                       ret = LTTNG_ERR_EPERM;
+                       break;
+               default:
+                       ret = LTTNG_ERR_SAVE_IO_FAIL;
+                       break;
+               }
                goto end;
        }
-       file_opened = 1;
 
        writer = config_writer_create(fd, 1);
        if (!writer) {
@@ -2055,20 +2553,9 @@ int save_session(struct ltt_session *session,
                                goto end;
                        }
                }
-               if (session->rotate_timer_period) {
-                       ret = config_writer_write_element_unsigned_int(writer,
-                                       config_element_rotation_timer_interval,
-                                       session->rotate_timer_period);
-                       if (ret) {
-                               ret = LTTNG_ERR_SAVE_IO_FAIL;
-                               goto end;
-                       }
-               }
-
-               if (session->rotate_size) {
-                       ret = config_writer_write_element_unsigned_int(writer,
-                                       config_element_rotation_size,
-                                       session->rotate_size);
+               if (session->rotate_timer_period || session->rotate_size) {
+                       ret = save_session_rotation_schedules(writer,
+                                       session);
                        if (ret) {
                                ret = LTTNG_ERR_SAVE_IO_FAIL;
                                goto end;
@@ -2108,12 +2595,12 @@ end:
        }
        if (ret) {
                /* Delete file in case of error */
-               if (file_opened && unlink(config_file_path)) {
+               if ((fd >= 0) && unlink(config_file_path)) {
                        PERROR("Unlinking XML session configuration.");
                }
        }
 
-       if (file_opened) {
+       if (fd >= 0) {
                ret = close(fd);
                if (ret) {
                        PERROR("Closing XML session configuration");
@@ -2143,6 +2630,7 @@ int cmd_save_sessions(struct lttng_save_session_attr *attr,
                session_lock(session);
                ret = save_session(session, attr, creds);
                session_unlock(session);
+               session_put(session);
                if (ret) {
                        goto end;
                }
@@ -2150,10 +2638,13 @@ int cmd_save_sessions(struct lttng_save_session_attr *attr,
                struct ltt_session_list *list = session_get_list();
 
                cds_list_for_each_entry(session, &list->head, list) {
+                       if (!session_get(session)) {
+                               continue;
+                       }
                        session_lock(session);
                        ret = save_session(session, attr, creds);
                        session_unlock(session);
-
+                       session_put(session);
                        /* Don't abort if we don't have the required permissions. */
                        if (ret && ret != LTTNG_ERR_EPERM) {
                                goto end;
This page took 0.031689 seconds and 4 git commands to generate.