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