X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Ffd-tracker%2Futils.c;h=fe2cdcc4ed4f84f1c629e27c630964d25d10f377;hp=cd4418ed28895ae9438eb73f29c5598ebdd67da9;hb=dd95933f8371a8c81ffc1dc5b306f2263f1ff808;hpb=c3e9c4c6febdea6b999db5ddc150782f3da5f78a diff --git a/src/common/fd-tracker/utils.c b/src/common/fd-tracker/utils.c index cd4418ed2..fe2cdcc4e 100644 --- a/src/common/fd-tracker/utils.c +++ b/src/common/fd-tracker/utils.c @@ -1,37 +1,22 @@ /* - * Copyright (C) 2018 - Jérémie Galarneau + * Copyright (C) 2018 Jérémie Galarneau * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License, version 2 only, as - * published by the Free Software Foundation. + * SPDX-License-Identifier: GPL-2.0-only * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include -#include -#include +#include #include #include +#include +#include +#include +#include static int open_pipe_cloexec(void *data, int *fds) { - int ret; - - ret = utils_create_pipe_cloexec(fds); - if (ret < 0) { - goto end; - } -end: - return ret; + return utils_create_pipe_cloexec(fds); } static @@ -42,13 +27,15 @@ int close_pipe(void *data, int *pipe) return 0; } +LTTNG_HIDDEN int fd_tracker_util_close_fd(void *unused, int *fd) { return close(*fd); } -int fd_tracker_util_pipe_open_cloexec(struct fd_tracker *tracker, - const char *name, int *pipe) +LTTNG_HIDDEN +int fd_tracker_util_pipe_open_cloexec( + struct fd_tracker *tracker, const char *name, int *pipe) { int ret; const char *name_prefix; @@ -64,7 +51,7 @@ int fd_tracker_util_pipe_open_cloexec(struct fd_tracker *tracker, goto end; } - ret = fd_tracker_open_unsuspendable_fd(tracker, pipe, + ret = fd_tracker_open_unsuspendable_fd(tracker, pipe, (const char **) names, 2, open_pipe_cloexec, NULL); free(names[0]); free(names[1]); @@ -72,8 +59,134 @@ end: return ret; } +LTTNG_HIDDEN int fd_tracker_util_pipe_close(struct fd_tracker *tracker, int *pipe) { - return fd_tracker_close_unsuspendable_fd(tracker, - pipe, 2, close_pipe, NULL); + return fd_tracker_close_unsuspendable_fd( + tracker, pipe, 2, close_pipe, NULL); +} + +struct open_directory_handle_args { + const struct lttng_directory_handle *in_handle; + struct lttng_directory_handle *ret_handle; + const char *path; +}; + +static +int open_directory_handle(void *_args, int *out_fds) +{ + int ret = 0; + struct open_directory_handle_args *args = _args; + struct lttng_directory_handle *new_handle = NULL; + + new_handle = args->in_handle ? + lttng_directory_handle_create_from_handle( + args->path, args->in_handle) : + lttng_directory_handle_create(args->path); + if (!new_handle) { + ret = -errno; + goto end; + } + + args->ret_handle = new_handle; + + /* + * Reserved to indicate that the handle does not use a handle; there is + * nothing to track. We want to indicate an error to the fd-tracker so + * that it doesn't attempt to track the file descriptor, but also want + * the caller to retrieve the newly-created handle. + * + * Calling this a hack is a fair assessment. + */ + if (!lttng_directory_handle_uses_fd(new_handle)) { + ret = ENOTSUP; + } else { +#ifdef COMPAT_DIRFD + *out_fds = new_handle->dirfd; +#else + abort(); +#endif + + } +end: + return ret; +} + +#ifdef COMPAT_DIRFD +static +int fd_close(void *unused, int *in_fds) +{ + const int ret = close(in_fds[0]); + + in_fds[0] = -1; + return ret; +} + +static +void directory_handle_destroy( + struct lttng_directory_handle *handle, void *data) +{ + struct fd_tracker *tracker = data; + const int ret = fd_tracker_close_unsuspendable_fd( + tracker, &handle->dirfd, 1, fd_close, NULL); + + if (ret) { + ERR("Failed to untrack directory handle file descriptor"); + } +} +#endif + +LTTNG_HIDDEN +struct lttng_directory_handle *fd_tracker_create_directory_handle( + struct fd_tracker *tracker, const char *path) +{ + return fd_tracker_create_directory_handle_from_handle( + tracker, NULL, path); +} + +LTTNG_HIDDEN +struct lttng_directory_handle *fd_tracker_create_directory_handle_from_handle( + struct fd_tracker *tracker, + struct lttng_directory_handle *in_handle, + const char *path) +{ + int ret; + int dirfd = -1; + char *handle_name = NULL; + char cwd_path[LTTNG_PATH_MAX] = "working directory"; + struct lttng_directory_handle *new_handle = NULL; + struct open_directory_handle_args open_args = { + .in_handle = in_handle, + .path = path, + }; + + if (!path) { + if (!getcwd(cwd_path, sizeof(cwd_path))) { + PERROR("Failed to get current working directory to name directory handle"); + goto end; + } + } + + ret = asprintf(&handle_name, "Directory handle to %s", + path ? path : cwd_path); + if (ret < 0) { + PERROR("Failed to format directory handle name"); + goto end; + } + + ret = fd_tracker_open_unsuspendable_fd(tracker, &dirfd, + (const char **) &handle_name, 1, open_directory_handle, + &open_args); + if (ret && ret != ENOTSUP) { + ERR("Failed to open directory handle to %s through the fd tracker", path ? path : cwd_path); + } + new_handle = open_args.ret_handle; + +#ifdef COMPAT_DIRFD + new_handle->destroy_cb = directory_handle_destroy; + new_handle->destroy_cb_data = tracker; +#endif +end: + free(handle_name); + return new_handle; }