+ /* Get the datetime for the snapshot output directory. */
+ ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime,
+ sizeof(output->datetime));
+ if (!ret) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /*
+ * Copy kernel session sockets so we can communicate with the right
+ * consumer for the snapshot record command.
+ */
+ ret = consumer_copy_sockets(output->consumer, usess->consumer);
+ if (ret < 0) {
+ goto error;
+ }
+
+ ret = set_relayd_for_snapshot(usess->consumer, output, session);
+ if (ret < 0) {
+ goto error_snapshot;
+ }
+
+ ret = ust_app_snapshot_record(usess, output, wait, nb_streams);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_SNAPSHOT_FAIL;
+ if (ret == -EINVAL) {
+ ret = -LTTNG_ERR_INVALID;
+ }
+ goto error_snapshot;
+ }
+
+error_snapshot:
+ /* Clean up copied sockets so this output can use some other later on. */
+ consumer_destroy_output_sockets(output->consumer);
+error:
+ return ret;
+}
+
+/*
+ * Returns the total number of streams for a session or a negative value
+ * on error.
+ */
+static unsigned int get_total_nb_stream(struct ltt_session *session)
+{
+ unsigned int total_streams = 0;
+
+ if (session->kernel_session) {
+ struct ltt_kernel_session *ksess = session->kernel_session;
+
+ total_streams += ksess->stream_count_global;
+ }
+
+ if (session->ust_session) {
+ struct ltt_ust_session *usess = session->ust_session;
+
+ total_streams += ust_app_get_nb_stream(usess);
+ }
+
+ return total_streams;
+}
+
+/*
+ * Command LTTNG_SNAPSHOT_RECORD from lib lttng ctl.
+ *
+ * The wait parameter is ignored so this call always wait for the snapshot to
+ * complete before returning.
+ *
+ * Return LTTNG_OK on success or else a LTTNG_ERR code.
+ */
+int cmd_snapshot_record(struct ltt_session *session,
+ struct lttng_snapshot_output *output, int wait)
+{
+ int ret = LTTNG_OK;
+ unsigned int use_tmp_output = 0;
+ struct snapshot_output tmp_output;
+ unsigned int nb_streams;
+
+ assert(session);
+
+ DBG("Cmd snapshot record for session %s", session->name);
+
+ /*
+ * Persmission denied to create an output if the session is not set in no
+ * output mode.
+ */
+ if (session->output_traces) {
+ ret = LTTNG_ERR_EPERM;
+ goto error;
+ }
+
+ /* The session needs to be started at least once. */
+ if (!session->started) {
+ ret = LTTNG_ERR_START_SESSION_ONCE;
+ goto error;
+ }
+
+ /* Use temporary output for the session. */
+ if (output && *output->ctrl_url != '\0') {
+ ret = snapshot_output_init(output->max_size, output->name,
+ output->ctrl_url, output->data_url, session->consumer,
+ &tmp_output, NULL);
+ if (ret < 0) {
+ if (ret == -ENOMEM) {
+ ret = LTTNG_ERR_NOMEM;
+ } else {
+ ret = LTTNG_ERR_INVALID;