X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Ffd-tracker%2Futils.c;h=fe2cdcc4ed4f84f1c629e27c630964d25d10f377;hp=b3df040c2088b22fce9d5cd10b3b05f8dfc02634;hb=dd95933f8371a8c81ffc1dc5b306f2263f1ff808;hpb=5c1f54d1d586f61a92704753411bd82c5c928218 diff --git a/src/common/fd-tracker/utils.c b/src/common/fd-tracker/utils.c index b3df040c2..fe2cdcc4e 100644 --- a/src/common/fd-tracker/utils.c +++ b/src/common/fd-tracker/utils.c @@ -1,43 +1,39 @@ /* - * 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 -static int open_pipe_cloexec(void *data, int *fds) +static +int open_pipe_cloexec(void *data, int *fds) { return utils_create_pipe_cloexec(fds); } -static int close_pipe(void *data, int *pipe) +static +int close_pipe(void *data, int *pipe) { utils_close_pipe(pipe); pipe[0] = pipe[1] = -1; return 0; } +LTTNG_HIDDEN int fd_tracker_util_close_fd(void *unused, int *fd) { return close(*fd); } +LTTNG_HIDDEN int fd_tracker_util_pipe_open_cloexec( struct fd_tracker *tracker, const char *name, int *pipe) { @@ -63,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); } + +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; +}