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