filestuff.cc revision 1.1.1.3 1 1.1 christos /* Low-level file-handling.
2 1.1.1.3 christos Copyright (C) 2012-2024 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of GDB.
5 1.1 christos
6 1.1 christos This program is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3 of the License, or
9 1.1 christos (at your option) any later version.
10 1.1 christos
11 1.1 christos This program is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 1.1 christos
19 1.1 christos #include "filestuff.h"
20 1.1 christos #include "gdb_vecs.h"
21 1.1 christos #include <fcntl.h>
22 1.1 christos #include <unistd.h>
23 1.1 christos #include <sys/types.h>
24 1.1 christos #include <sys/stat.h>
25 1.1 christos #include <algorithm>
26 1.1 christos
27 1.1 christos #ifdef USE_WIN32API
28 1.1 christos #include <winsock2.h>
29 1.1 christos #include <windows.h>
30 1.1 christos #define HAVE_SOCKETS 1
31 1.1 christos #elif defined HAVE_SYS_SOCKET_H
32 1.1 christos #include <sys/socket.h>
33 1.1 christos /* Define HAVE_F_GETFD if we plan to use F_GETFD. */
34 1.1 christos #define HAVE_F_GETFD F_GETFD
35 1.1 christos #define HAVE_SOCKETS 1
36 1.1 christos #endif
37 1.1 christos
38 1.1 christos #ifdef HAVE_KINFO_GETFILE
39 1.1 christos #include <sys/user.h>
40 1.1 christos #include <libutil.h>
41 1.1 christos #endif
42 1.1 christos
43 1.1 christos #ifdef HAVE_SYS_RESOURCE_H
44 1.1 christos #include <sys/resource.h>
45 1.1 christos #endif /* HAVE_SYS_RESOURCE_H */
46 1.1 christos
47 1.1 christos #ifndef O_CLOEXEC
48 1.1 christos #define O_CLOEXEC 0
49 1.1 christos #endif
50 1.1 christos
51 1.1 christos #ifndef O_NOINHERIT
52 1.1 christos #define O_NOINHERIT 0
53 1.1 christos #endif
54 1.1 christos
55 1.1 christos #ifndef SOCK_CLOEXEC
56 1.1 christos #define SOCK_CLOEXEC 0
57 1.1 christos #endif
58 1.1 christos
59 1.1 christos
60 1.1 christos
62 1.1 christos #ifndef HAVE_FDWALK
63 1.1 christos
64 1.1 christos #include <dirent.h>
65 1.1 christos
66 1.1 christos /* Replacement for fdwalk, if the system doesn't define it. Walks all
67 1.1 christos open file descriptors (though this implementation may walk closed
68 1.1 christos ones as well, depending on the host platform's capabilities) and
69 1.1 christos call FUNC with ARG. If FUNC returns non-zero, stops immediately
70 1.1 christos and returns the same value. Otherwise, returns zero when
71 1.1 christos finished. */
72 1.1 christos
73 1.1 christos static int
74 1.1 christos fdwalk (int (*func) (void *, int), void *arg)
75 1.1 christos {
76 1.1 christos /* Checking __linux__ isn't great but it isn't clear what would be
77 1.1 christos better. There doesn't seem to be a good way to check for this in
78 1.1 christos configure. */
79 1.1 christos #ifdef __linux__
80 1.1 christos DIR *dir;
81 1.1 christos
82 1.1 christos dir = opendir ("/proc/self/fd");
83 1.1 christos if (dir != NULL)
84 1.1 christos {
85 1.1 christos struct dirent *entry;
86 1.1 christos int result = 0;
87 1.1 christos
88 1.1 christos for (entry = readdir (dir); entry != NULL; entry = readdir (dir))
89 1.1 christos {
90 1.1 christos long fd;
91 1.1 christos char *tail;
92 1.1 christos
93 1.1 christos errno = 0;
94 1.1 christos fd = strtol (entry->d_name, &tail, 10);
95 1.1 christos if (*tail != '\0' || errno != 0)
96 1.1 christos continue;
97 1.1 christos if ((int) fd != fd)
98 1.1 christos {
99 1.1 christos /* What can we do here really? */
100 1.1 christos continue;
101 1.1 christos }
102 1.1 christos
103 1.1 christos if (fd == dirfd (dir))
104 1.1 christos continue;
105 1.1 christos
106 1.1 christos result = func (arg, fd);
107 1.1 christos if (result != 0)
108 1.1 christos break;
109 1.1 christos }
110 1.1 christos
111 1.1 christos closedir (dir);
112 1.1 christos return result;
113 1.1 christos }
114 1.1 christos /* We may fall through to the next case. */
115 1.1 christos #endif
116 1.1 christos #ifdef HAVE_KINFO_GETFILE
117 1.1 christos int nfd;
118 1.1 christos gdb::unique_xmalloc_ptr<struct kinfo_file[]> fdtbl
119 1.1 christos (kinfo_getfile (getpid (), &nfd));
120 1.1 christos if (fdtbl != NULL)
121 1.1 christos {
122 1.1 christos for (int i = 0; i < nfd; i++)
123 1.1 christos {
124 1.1 christos if (fdtbl[i].kf_fd >= 0)
125 1.1 christos {
126 1.1 christos int result = func (arg, fdtbl[i].kf_fd);
127 1.1 christos if (result != 0)
128 1.1 christos return result;
129 1.1 christos }
130 1.1 christos }
131 1.1 christos return 0;
132 1.1 christos }
133 1.1 christos /* We may fall through to the next case. */
134 1.1 christos #endif
135 1.1 christos
136 1.1 christos {
137 1.1 christos int max, fd;
138 1.1 christos
139 1.1 christos #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
140 1.1 christos struct rlimit rlim;
141 1.1 christos
142 1.1 christos if (getrlimit (RLIMIT_NOFILE, &rlim) == 0 && rlim.rlim_max != RLIM_INFINITY)
143 1.1 christos max = rlim.rlim_max;
144 1.1 christos else
145 1.1 christos #endif
146 1.1 christos {
147 1.1 christos #ifdef _SC_OPEN_MAX
148 1.1 christos max = sysconf (_SC_OPEN_MAX);
149 1.1 christos #else
150 1.1 christos /* Whoops. */
151 1.1 christos return 0;
152 1.1 christos #endif /* _SC_OPEN_MAX */
153 1.1 christos }
154 1.1 christos
155 1.1 christos for (fd = 0; fd < max; ++fd)
156 1.1 christos {
157 1.1 christos struct stat sb;
158 1.1 christos int result;
159 1.1 christos
160 1.1 christos /* Only call FUNC for open fds. */
161 1.1 christos if (fstat (fd, &sb) == -1)
162 1.1 christos continue;
163 1.1 christos
164 1.1 christos result = func (arg, fd);
165 1.1 christos if (result != 0)
166 1.1 christos return result;
167 1.1 christos }
168 1.1 christos
169 1.1 christos return 0;
170 1.1 christos }
171 1.1 christos }
172 1.1 christos
173 1.1 christos #endif /* HAVE_FDWALK */
174 1.1 christos
175 1.1 christos
176 1.1 christos
178 1.1 christos /* A vector holding all the fds open when notice_open_fds was called. We
179 1.1 christos don't use a hashtab because we don't expect there to be many open fds. */
180 1.1 christos
181 1.1 christos static std::vector<int> open_fds;
182 1.1 christos
183 1.1 christos /* An fdwalk callback function used by notice_open_fds. It puts the
184 1.1 christos given file descriptor into the vec. */
185 1.1 christos
186 1.1 christos static int
187 1.1 christos do_mark_open_fd (void *ignore, int fd)
188 1.1 christos {
189 1.1 christos open_fds.push_back (fd);
190 1.1 christos return 0;
191 1.1 christos }
192 1.1 christos
193 1.1 christos /* See filestuff.h. */
194 1.1 christos
195 1.1 christos void
196 1.1 christos notice_open_fds (void)
197 1.1 christos {
198 1.1 christos fdwalk (do_mark_open_fd, NULL);
199 1.1 christos }
200 1.1 christos
201 1.1 christos /* See filestuff.h. */
202 1.1 christos
203 1.1 christos void
204 1.1 christos mark_fd_no_cloexec (int fd)
205 1.1 christos {
206 1.1 christos do_mark_open_fd (NULL, fd);
207 1.1 christos }
208 1.1 christos
209 1.1 christos /* See filestuff.h. */
210 1.1 christos
211 1.1 christos void
212 1.1 christos unmark_fd_no_cloexec (int fd)
213 1.1 christos {
214 1.1 christos auto it = std::remove (open_fds.begin (), open_fds.end (), fd);
215 1.1 christos
216 1.1 christos if (it != open_fds.end ())
217 1.1.1.2 christos open_fds.erase (it);
218 1.1 christos else
219 1.1 christos gdb_assert_not_reached ("fd not found in open_fds");
220 1.1 christos }
221 1.1 christos
222 1.1 christos /* Helper function for close_most_fds that closes the file descriptor
223 1.1 christos if appropriate. */
224 1.1 christos
225 1.1 christos static int
226 1.1 christos do_close (void *ignore, int fd)
227 1.1 christos {
228 1.1 christos for (int val : open_fds)
229 1.1 christos {
230 1.1 christos if (fd == val)
231 1.1 christos {
232 1.1 christos /* Keep this one open. */
233 1.1 christos return 0;
234 1.1 christos }
235 1.1 christos }
236 1.1 christos
237 1.1 christos close (fd);
238 1.1 christos return 0;
239 1.1 christos }
240 1.1 christos
241 1.1 christos /* See filestuff.h. */
242 1.1 christos
243 1.1 christos void
244 1.1 christos close_most_fds (void)
245 1.1 christos {
246 1.1 christos fdwalk (do_close, NULL);
247 1.1 christos }
248 1.1 christos
249 1.1 christos
250 1.1 christos
252 1.1 christos /* This is a tri-state flag. When zero it means we haven't yet tried
253 1.1 christos O_CLOEXEC. When positive it means that O_CLOEXEC works on this
254 1.1 christos host. When negative, it means that O_CLOEXEC doesn't work. We
255 1.1 christos track this state because, while gdb might have been compiled
256 1.1 christos against a libc that supplies O_CLOEXEC, there is no guarantee that
257 1.1 christos the kernel supports it. */
258 1.1 christos
259 1.1 christos static int trust_o_cloexec;
260 1.1 christos
261 1.1 christos /* Mark FD as close-on-exec, ignoring errors. Update
262 1.1 christos TRUST_O_CLOEXEC. */
263 1.1 christos
264 1.1 christos static void
265 1.1 christos mark_cloexec (int fd)
266 1.1 christos {
267 1.1 christos #ifdef HAVE_F_GETFD
268 1.1 christos int old = fcntl (fd, F_GETFD, 0);
269 1.1 christos
270 1.1 christos if (old != -1)
271 1.1 christos {
272 1.1 christos fcntl (fd, F_SETFD, old | FD_CLOEXEC);
273 1.1 christos
274 1.1 christos if (trust_o_cloexec == 0)
275 1.1 christos {
276 1.1 christos if ((old & FD_CLOEXEC) != 0)
277 1.1 christos trust_o_cloexec = 1;
278 1.1 christos else
279 1.1 christos trust_o_cloexec = -1;
280 1.1 christos }
281 1.1 christos }
282 1.1 christos #endif /* HAVE_F_GETFD */
283 1.1 christos }
284 1.1 christos
285 1.1 christos /* Depending on TRUST_O_CLOEXEC, mark FD as close-on-exec. */
286 1.1 christos
287 1.1 christos static void
288 1.1 christos maybe_mark_cloexec (int fd)
289 1.1 christos {
290 1.1 christos if (trust_o_cloexec <= 0)
291 1.1 christos mark_cloexec (fd);
292 1.1 christos }
293 1.1 christos
294 1.1 christos #ifdef HAVE_SOCKETS
295 1.1 christos
296 1.1 christos /* Like maybe_mark_cloexec, but for callers that use SOCK_CLOEXEC. */
297 1.1 christos
298 1.1 christos static void
299 1.1 christos socket_mark_cloexec (int fd)
300 1.1 christos {
301 1.1 christos if (SOCK_CLOEXEC == 0 || trust_o_cloexec <= 0)
302 1.1 christos mark_cloexec (fd);
303 1.1 christos }
304 1.1 christos
305 1.1 christos #endif
306 1.1 christos
307 1.1 christos
308 1.1.1.2 christos
310 1.1 christos /* See filestuff.h. */
311 1.1.1.2 christos
312 1.1 christos scoped_fd
313 1.1.1.2 christos gdb_open_cloexec (const char *filename, int flags, unsigned long mode)
314 1.1.1.2 christos {
315 1.1 christos scoped_fd fd (open (filename, flags | O_CLOEXEC, mode));
316 1.1 christos
317 1.1 christos if (fd.get () >= 0)
318 1.1 christos maybe_mark_cloexec (fd.get ());
319 1.1 christos
320 1.1 christos return fd;
321 1.1 christos }
322 1.1 christos
323 1.1 christos /* See filestuff.h. */
324 1.1 christos
325 1.1 christos gdb_file_up
326 1.1 christos gdb_fopen_cloexec (const char *filename, const char *opentype)
327 1.1 christos {
328 1.1 christos FILE *result;
329 1.1 christos /* Probe for "e" support once. But, if we can tell the operating
330 1.1 christos system doesn't know about close on exec mode "e" without probing,
331 1.1 christos skip it. E.g., the Windows runtime issues an "Invalid parameter
332 1.1 christos passed to C runtime function" OutputDebugString warning for
333 1.1 christos unknown modes. Assume that if O_CLOEXEC is zero, then "e" isn't
334 1.1 christos supported. On MinGW, O_CLOEXEC is an alias of O_NOINHERIT, and
335 1.1 christos "e" isn't supported. */
336 1.1 christos static int fopen_e_ever_failed_einval =
337 1.1 christos O_CLOEXEC == 0 || O_CLOEXEC == O_NOINHERIT;
338 1.1 christos
339 1.1 christos if (!fopen_e_ever_failed_einval)
340 1.1 christos {
341 1.1 christos char *copy;
342 1.1 christos
343 1.1 christos copy = (char *) alloca (strlen (opentype) + 2);
344 1.1 christos strcpy (copy, opentype);
345 1.1 christos /* This is a glibc extension but we try it unconditionally on
346 1.1 christos this path. */
347 1.1 christos strcat (copy, "e");
348 1.1 christos result = fopen (filename, copy);
349 1.1 christos
350 1.1 christos if (result == NULL && errno == EINVAL)
351 1.1 christos {
352 1.1 christos result = fopen (filename, opentype);
353 1.1 christos if (result != NULL)
354 1.1 christos fopen_e_ever_failed_einval = 1;
355 1.1 christos }
356 1.1 christos }
357 1.1 christos else
358 1.1 christos result = fopen (filename, opentype);
359 1.1 christos
360 1.1 christos if (result != NULL)
361 1.1 christos maybe_mark_cloexec (fileno (result));
362 1.1 christos
363 1.1 christos return gdb_file_up (result);
364 1.1 christos }
365 1.1 christos
366 1.1 christos #ifdef HAVE_SOCKETS
367 1.1 christos /* See filestuff.h. */
368 1.1 christos
369 1.1 christos int
370 1.1 christos gdb_socketpair_cloexec (int domain, int style, int protocol,
371 1.1 christos int filedes[2])
372 1.1 christos {
373 1.1 christos #ifdef HAVE_SOCKETPAIR
374 1.1 christos int result = socketpair (domain, style | SOCK_CLOEXEC, protocol, filedes);
375 1.1 christos
376 1.1 christos if (result != -1)
377 1.1 christos {
378 1.1 christos socket_mark_cloexec (filedes[0]);
379 1.1 christos socket_mark_cloexec (filedes[1]);
380 1.1.1.2 christos }
381 1.1 christos
382 1.1 christos return result;
383 1.1 christos #else
384 1.1 christos gdb_assert_not_reached ("socketpair not available on this host");
385 1.1 christos #endif
386 1.1 christos }
387 1.1 christos
388 1.1 christos /* See filestuff.h. */
389 1.1 christos
390 1.1 christos int
391 1.1 christos gdb_socket_cloexec (int domain, int style, int protocol)
392 1.1 christos {
393 1.1 christos int result = socket (domain, style | SOCK_CLOEXEC, protocol);
394 1.1 christos
395 1.1 christos if (result != -1)
396 1.1 christos socket_mark_cloexec (result);
397 1.1 christos
398 1.1 christos return result;
399 1.1 christos }
400 1.1 christos #endif
401 1.1 christos
402 1.1 christos /* See filestuff.h. */
403 1.1 christos
404 1.1 christos int
405 1.1 christos gdb_pipe_cloexec (int filedes[2])
406 1.1 christos {
407 1.1 christos int result;
408 1.1 christos
409 1.1 christos #ifdef HAVE_PIPE2
410 1.1 christos result = pipe2 (filedes, O_CLOEXEC);
411 1.1 christos if (result != -1)
412 1.1 christos {
413 1.1 christos maybe_mark_cloexec (filedes[0]);
414 1.1 christos maybe_mark_cloexec (filedes[1]);
415 1.1 christos }
416 1.1 christos #else
417 1.1 christos #ifdef HAVE_PIPE
418 1.1 christos result = pipe (filedes);
419 1.1 christos if (result != -1)
420 1.1 christos {
421 1.1.1.2 christos mark_cloexec (filedes[0]);
422 1.1 christos mark_cloexec (filedes[1]);
423 1.1 christos }
424 1.1 christos #else /* HAVE_PIPE */
425 1.1 christos gdb_assert_not_reached ("pipe not available on this host");
426 1.1 christos #endif /* HAVE_PIPE */
427 1.1 christos #endif /* HAVE_PIPE2 */
428 1.1 christos
429 1.1 christos return result;
430 1.1 christos }
431 1.1 christos
432 1.1 christos /* See gdbsupport/filestuff.h. */
433 1.1 christos
434 1.1 christos bool
435 1.1 christos is_regular_file (const char *name, int *errno_ptr)
436 1.1 christos {
437 1.1 christos struct stat st;
438 1.1 christos const int status = stat (name, &st);
439 1.1 christos
440 1.1 christos /* Stat should never fail except when the file does not exist.
441 1.1 christos If stat fails, analyze the source of error and return true
442 1.1 christos unless the file does not exist, to avoid returning false results
443 1.1 christos on obscure systems where stat does not work as expected. */
444 1.1 christos
445 1.1 christos if (status != 0)
446 1.1 christos {
447 1.1 christos if (errno != ENOENT)
448 1.1 christos return true;
449 1.1 christos *errno_ptr = ENOENT;
450 1.1 christos return false;
451 1.1 christos }
452 1.1 christos
453 1.1 christos if (S_ISREG (st.st_mode))
454 1.1 christos return true;
455 1.1 christos
456 1.1 christos if (S_ISDIR (st.st_mode))
457 1.1 christos *errno_ptr = EISDIR;
458 1.1 christos else
459 1.1 christos *errno_ptr = EINVAL;
460 1.1 christos return false;
461 1.1 christos }
462 1.1 christos
463 1.1 christos /* See gdbsupport/filestuff.h. */
464 1.1 christos
465 1.1 christos bool
466 1.1 christos mkdir_recursive (const char *dir)
467 1.1 christos {
468 1.1 christos auto holder = make_unique_xstrdup (dir);
469 1.1 christos char * const start = holder.get ();
470 1.1 christos char *component_start = start;
471 1.1 christos char *component_end = start;
472 1.1 christos
473 1.1 christos while (1)
474 1.1 christos {
475 1.1 christos /* Find the beginning of the next component. */
476 1.1 christos while (*component_start == '/')
477 1.1 christos component_start++;
478 1.1 christos
479 1.1 christos /* Are we done? */
480 1.1 christos if (*component_start == '\0')
481 1.1 christos return true;
482 1.1 christos
483 1.1 christos /* Find the slash or null-terminator after this component. */
484 1.1 christos component_end = component_start;
485 1.1.1.2 christos while (*component_end != '/' && *component_end != '\0')
486 1.1 christos component_end++;
487 1.1 christos
488 1.1 christos /* Temporarily replace the slash with a null terminator, so we can create
489 1.1 christos the directory up to this component. */
490 1.1.1.2 christos char saved_char = *component_end;
491 1.1.1.2 christos *component_end = '\0';
492 1.1.1.2 christos
493 1.1.1.2 christos /* If we get EEXIST and the existing path is a directory, then we're
494 1.1 christos happy. If it exists, but it's a regular file and this is not the last
495 1.1 christos component, we'll fail at the next component. If this is the last
496 1.1 christos component, the caller will fail with ENOTDIR when trying to
497 1.1 christos open/create a file under that path. */
498 1.1 christos if (mkdir (start, 0700) != 0)
499 1.1 christos if (errno != EEXIST)
500 1.1 christos return false;
501 1.1 christos
502 1.1 christos /* Restore the overwritten char. */
503 1.1.1.2 christos *component_end = saved_char;
504 1.1.1.2 christos component_start = component_end;
505 1.1.1.2 christos }
506 1.1.1.3 christos }
507 1.1.1.3 christos
508 1.1.1.2 christos /* See gdbsupport/filestuff.h. */
509 1.1.1.2 christos
510 1.1.1.2 christos std::string
511 1.1.1.2 christos read_remainder_of_file (FILE *file)
512 1.1.1.2 christos {
513 1.1.1.2 christos std::string res;
514 1.1.1.2 christos for (;;)
515 1.1.1.3 christos {
516 1.1.1.2 christos std::string::size_type start_size = res.size ();
517 1.1.1.2 christos constexpr int chunk_size = 1024;
518 1.1.1.3 christos
519 1.1.1.2 christos /* Resize to accommodate CHUNK_SIZE bytes. */
520 1.1.1.2 christos res.resize (start_size + chunk_size);
521 1.1.1.2 christos
522 1.1.1.2 christos int n = fread (&res[start_size], 1, chunk_size, file);
523 1.1.1.2 christos if (n == chunk_size)
524 1.1.1.2 christos continue;
525 1.1.1.3 christos
526 1.1.1.3 christos gdb_assert (n < chunk_size);
527 1.1.1.2 christos
528 1.1.1.2 christos /* Less than CHUNK means EOF or error. If it's an error, return
529 1.1.1.2 christos no value. */
530 1.1.1.2 christos if (ferror (file))
531 1.1.1.2 christos return {};
532 1.1.1.2 christos
533 1.1.1.2 christos /* Resize the string according to the data we read. */
534 1.1.1.2 christos res.resize (start_size + n);
535 1.1.1.2 christos break;
536 1.1.1.3 christos }
537 1.1.1.3 christos
538 1.1.1.3 christos return res;
539 1.1.1.3 christos }
540 1.1.1.3 christos
541 1.1.1.3 christos /* See gdbsupport/filestuff.h. */
542 1.1.1.3 christos
543 1.1.1.3 christos std::optional<std::string>
544 1.1.1.3 christos read_text_file_to_string (const char *path)
545 1.1.1.3 christos {
546 1.1.1.3 christos gdb_file_up file = gdb_fopen_cloexec (path, "r");
547 1.1.1.3 christos if (file == nullptr)
548 return {};
549
550 return read_remainder_of_file (file.get ());
551 }
552