relayd: track directory handles through the fd-tracker
[lttng-tools.git] / src / common / fd-tracker / utils.c
CommitLineData
df038819 1/*
ab5be9fa 2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
df038819 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
df038819 5 *
df038819
JG
6 */
7
dd95933f 8#include <common/error.h>
df038819 9#include <common/fd-tracker/utils.h>
c3e9c4c6 10#include <common/utils.h>
dd95933f 11#include <lttng/constant.h>
5c1f54d1
JG
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
c3e9c4c6 15
dd95933f
JG
16static
17int open_pipe_cloexec(void *data, int *fds)
c3e9c4c6 18{
e51dc192 19 return utils_create_pipe_cloexec(fds);
c3e9c4c6
JG
20}
21
dd95933f
JG
22static
23int close_pipe(void *data, int *pipe)
c3e9c4c6
JG
24{
25 utils_close_pipe(pipe);
26 pipe[0] = pipe[1] = -1;
27 return 0;
28}
df038819 29
dd95933f 30LTTNG_HIDDEN
df038819
JG
31int fd_tracker_util_close_fd(void *unused, int *fd)
32{
33 return close(*fd);
34}
c3e9c4c6 35
dd95933f 36LTTNG_HIDDEN
5c1f54d1
JG
37int fd_tracker_util_pipe_open_cloexec(
38 struct fd_tracker *tracker, const char *name, int *pipe)
c3e9c4c6
JG
39{
40 int ret;
41 const char *name_prefix;
42 char *names[2];
43
44 name_prefix = name ? name : "Unknown pipe";
45 ret = asprintf(&names[0], "%s (read end)", name_prefix);
46 if (ret < 0) {
47 goto end;
48 }
49 ret = asprintf(&names[1], "%s (write end)", name_prefix);
50 if (ret < 0) {
51 goto end;
52 }
53
5c1f54d1 54 ret = fd_tracker_open_unsuspendable_fd(tracker, pipe,
c3e9c4c6
JG
55 (const char **) names, 2, open_pipe_cloexec, NULL);
56 free(names[0]);
57 free(names[1]);
58end:
59 return ret;
60}
61
dd95933f 62LTTNG_HIDDEN
c3e9c4c6
JG
63int fd_tracker_util_pipe_close(struct fd_tracker *tracker, int *pipe)
64{
5c1f54d1
JG
65 return fd_tracker_close_unsuspendable_fd(
66 tracker, pipe, 2, close_pipe, NULL);
c3e9c4c6 67}
dd95933f
JG
68
69struct open_directory_handle_args {
70 const struct lttng_directory_handle *in_handle;
71 struct lttng_directory_handle *ret_handle;
72 const char *path;
73};
74
75static
76int open_directory_handle(void *_args, int *out_fds)
77{
78 int ret = 0;
79 struct open_directory_handle_args *args = _args;
80 struct lttng_directory_handle *new_handle = NULL;
81
82 new_handle = args->in_handle ?
83 lttng_directory_handle_create_from_handle(
84 args->path, args->in_handle) :
85 lttng_directory_handle_create(args->path);
86 if (!new_handle) {
87 ret = -errno;
88 goto end;
89 }
90
91 args->ret_handle = new_handle;
92
93 /*
94 * Reserved to indicate that the handle does not use a handle; there is
95 * nothing to track. We want to indicate an error to the fd-tracker so
96 * that it doesn't attempt to track the file descriptor, but also want
97 * the caller to retrieve the newly-created handle.
98 *
99 * Calling this a hack is a fair assessment.
100 */
101 if (!lttng_directory_handle_uses_fd(new_handle)) {
102 ret = ENOTSUP;
103 } else {
104#ifdef COMPAT_DIRFD
105 *out_fds = new_handle->dirfd;
106#else
107 abort();
108#endif
109
110 }
111end:
112 return ret;
113}
114
115#ifdef COMPAT_DIRFD
116static
117int fd_close(void *unused, int *in_fds)
118{
119 const int ret = close(in_fds[0]);
120
121 in_fds[0] = -1;
122 return ret;
123}
124
125static
126void directory_handle_destroy(
127 struct lttng_directory_handle *handle, void *data)
128{
129 struct fd_tracker *tracker = data;
130 const int ret = fd_tracker_close_unsuspendable_fd(
131 tracker, &handle->dirfd, 1, fd_close, NULL);
132
133 if (ret) {
134 ERR("Failed to untrack directory handle file descriptor");
135 }
136}
137#endif
138
139LTTNG_HIDDEN
140struct lttng_directory_handle *fd_tracker_create_directory_handle(
141 struct fd_tracker *tracker, const char *path)
142{
143 return fd_tracker_create_directory_handle_from_handle(
144 tracker, NULL, path);
145}
146
147LTTNG_HIDDEN
148struct lttng_directory_handle *fd_tracker_create_directory_handle_from_handle(
149 struct fd_tracker *tracker,
150 struct lttng_directory_handle *in_handle,
151 const char *path)
152{
153 int ret;
154 int dirfd = -1;
155 char *handle_name = NULL;
156 char cwd_path[LTTNG_PATH_MAX] = "working directory";
157 struct lttng_directory_handle *new_handle = NULL;
158 struct open_directory_handle_args open_args = {
159 .in_handle = in_handle,
160 .path = path,
161 };
162
163 if (!path) {
164 if (!getcwd(cwd_path, sizeof(cwd_path))) {
165 PERROR("Failed to get current working directory to name directory handle");
166 goto end;
167 }
168 }
169
170 ret = asprintf(&handle_name, "Directory handle to %s",
171 path ? path : cwd_path);
172 if (ret < 0) {
173 PERROR("Failed to format directory handle name");
174 goto end;
175 }
176
177 ret = fd_tracker_open_unsuspendable_fd(tracker, &dirfd,
178 (const char **) &handle_name, 1, open_directory_handle,
179 &open_args);
180 if (ret && ret != ENOTSUP) {
181 ERR("Failed to open directory handle to %s through the fd tracker", path ? path : cwd_path);
182 }
183 new_handle = open_args.ret_handle;
184
185#ifdef COMPAT_DIRFD
186 new_handle->destroy_cb = directory_handle_destroy;
187 new_handle->destroy_cb_data = tracker;
188#endif
189end:
190 free(handle_name);
191 return new_handle;
192}
This page took 0.030476 seconds and 4 git commands to generate.