+ free(chunk->path);
+ chunk->path = new_path;
+end:
+ lttng_directory_handle_put(rename_directory);
+ return status;
+}
+
+LTTNG_HIDDEN
+enum lttng_trace_chunk_status lttng_trace_chunk_rename_path(
+ struct lttng_trace_chunk *chunk, const char *path)
+
+{
+ enum lttng_trace_chunk_status status;
+
+ pthread_mutex_lock(&chunk->lock);
+ status = lttng_trace_chunk_rename_path_no_lock(chunk, path);
+ pthread_mutex_unlock(&chunk->lock);
+
+ return status;
+}
+
+LTTNG_HIDDEN
+enum lttng_trace_chunk_status lttng_trace_chunk_get_credentials(
+ struct lttng_trace_chunk *chunk,
+ struct lttng_credentials *credentials)
+{
+ enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
+
+ pthread_mutex_lock(&chunk->lock);
+ if (chunk->credentials.is_set) {
+ if (chunk->credentials.value.use_current_user) {
+ LTTNG_OPTIONAL_SET(&credentials->uid, geteuid());
+ LTTNG_OPTIONAL_SET(&credentials->gid, getegid());
+ } else {
+ *credentials = chunk->credentials.value.user;
+ }
+ } else {
+ status = LTTNG_TRACE_CHUNK_STATUS_NONE;
+ }
+ pthread_mutex_unlock(&chunk->lock);
+ return status;
+}
+
+LTTNG_HIDDEN
+enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials(
+ struct lttng_trace_chunk *chunk,
+ const struct lttng_credentials *user_credentials)
+{
+ enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
+ const struct chunk_credentials credentials = {
+ .user = *user_credentials,
+ .use_current_user = false,
+ };
+
+ pthread_mutex_lock(&chunk->lock);
+ if (chunk->credentials.is_set) {
+ status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
+ goto end;
+ }
+ LTTNG_OPTIONAL_SET(&chunk->credentials, credentials);
+end:
+ pthread_mutex_unlock(&chunk->lock);
+ return status;
+}
+
+LTTNG_HIDDEN
+enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials_current_user(
+ struct lttng_trace_chunk *chunk)
+{
+ enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
+ const struct chunk_credentials credentials = {
+ .use_current_user = true,
+ };
+
+ pthread_mutex_lock(&chunk->lock);
+ if (chunk->credentials.is_set) {
+ status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
+ goto end;
+ }
+ LTTNG_OPTIONAL_SET(&chunk->credentials, credentials);
+end:
+ pthread_mutex_unlock(&chunk->lock);
+ return status;
+}
+
+
+LTTNG_HIDDEN
+enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner(
+ struct lttng_trace_chunk *chunk,
+ struct lttng_directory_handle *session_output_directory)
+{
+ int ret;
+ enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
+ struct lttng_directory_handle *chunk_directory_handle = NULL;
+ bool reference_acquired;
+
+ pthread_mutex_lock(&chunk->lock);
+ if (chunk->mode.is_set) {
+ status = LTTNG_TRACE_CHUNK_STATUS_INVALID_OPERATION;
+ goto end;
+ }
+ if (!chunk->credentials.is_set) {
+ /*
+ * Fatal error, credentials must be set before a
+ * directory is created.
+ */
+ ERR("Credentials of trace chunk are unset: refusing to set session output directory");
+ status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
+ goto end;
+ }
+ if (chunk->path && chunk->path[0] != '\0') {
+ ret = lttng_directory_handle_create_subdirectory_as_user(
+ session_output_directory,
+ chunk->path,
+ DIR_CREATION_MODE,
+ !chunk->credentials.value.use_current_user ?
+ &chunk->credentials.value.user : NULL);
+ if (ret) {
+ PERROR("Failed to create chunk output directory \"%s\"",
+ chunk->path);
+ status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
+ goto end;
+ }
+ chunk_directory_handle =
+ chunk->fd_tracker ?
+ fd_tracker_create_directory_handle_from_handle(
+ chunk->fd_tracker,
+ session_output_directory,
+ chunk->path) :
+ lttng_directory_handle_create_from_handle(
+ chunk->path,
+ session_output_directory);
+ if (!chunk_directory_handle) {
+ /* The function already logs on all error paths. */
+ status = LTTNG_TRACE_CHUNK_STATUS_ERROR;
+ goto end;
+ }
+ } else {
+ /*
+ * A nameless chunk does not need its own output directory.
+ * The session's output directory will be used.
+ */
+ reference_acquired = lttng_directory_handle_get(
+ session_output_directory);
+
+ assert(reference_acquired);
+ chunk_directory_handle = session_output_directory;
+ }
+ chunk->chunk_directory = chunk_directory_handle;
+ chunk_directory_handle = NULL;
+ reference_acquired = lttng_directory_handle_get(
+ session_output_directory);
+ assert(reference_acquired);
+ chunk->session_output_directory = session_output_directory;