+enum lttng_error_code lttng_create_session_ext(
+ struct lttng_session_descriptor *session_descriptor)
+{
+ enum lttng_error_code ret_code;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_CREATE_SESSION_EXT,
+ };
+ void *reply = NULL;
+ struct lttng_buffer_view reply_view;
+ int reply_ret;
+ bool sessiond_must_generate_ouput;
+ struct lttng_dynamic_buffer payload;
+ int ret;
+ size_t descriptor_size;
+ struct lttng_session_descriptor *descriptor_reply = NULL;
+
+ lttng_dynamic_buffer_init(&payload);
+ if (!session_descriptor) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ sessiond_must_generate_ouput =
+ !lttng_session_descriptor_is_output_destination_initialized(
+ session_descriptor);
+ if (sessiond_must_generate_ouput) {
+ const char *home_dir = utils_get_home_dir();
+ size_t home_dir_len = home_dir ? strlen(home_dir) + 1 : 0;
+
+ if (!home_dir || home_dir_len > LTTNG_PATH_MAX) {
+ ret_code = LTTNG_ERR_FATAL;
+ goto end;
+ }
+
+ lsm.u.create_session.home_dir_size = (uint16_t) home_dir_len;
+ ret = lttng_dynamic_buffer_append(&payload, home_dir,
+ home_dir_len);
+ if (ret) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ }
+
+ descriptor_size = payload.size;
+ ret = lttng_session_descriptor_serialize(session_descriptor,
+ &payload);
+ if (ret) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
+ descriptor_size = payload.size - descriptor_size;
+ lsm.u.create_session.session_descriptor_size = descriptor_size;
+
+ /* Command returns a session descriptor on success. */
+ reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, payload.data,
+ payload.size, &reply);
+ if (reply_ret < 0) {
+ ret_code = -reply_ret;
+ goto end;
+ } else if (reply_ret == 0) {
+ /* Socket unexpectedly closed by the session daemon. */
+ ret_code = LTTNG_ERR_FATAL;
+ goto end;
+ }
+
+ reply_view = lttng_buffer_view_init(reply, 0, reply_ret);
+ ret = lttng_session_descriptor_create_from_buffer(&reply_view,
+ &descriptor_reply);
+ if (ret < 0) {
+ ret_code = LTTNG_ERR_FATAL;
+ goto end;
+ }
+ ret_code = LTTNG_OK;
+ lttng_session_descriptor_assign(session_descriptor, descriptor_reply);
+end:
+ free(reply);
+ lttng_dynamic_buffer_reset(&payload);
+ lttng_session_descriptor_destroy(descriptor_reply);
+ return ret_code;
+}
+