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