Home | History | Annotate | Line # | Download | only in gdbsupport
filestuff.cc revision 1.1.1.4
      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 <fcntl.h>
     21 #include <unistd.h>
     22 #include <sys/types.h>
     23 #include <sys/stat.h>
     24 #include <algorithm>
     25 
     26 #ifdef USE_WIN32API
     27 #include <winsock2.h>
     28 #include <windows.h>
     29 #define HAVE_SOCKETS 1
     30 #elif defined HAVE_SYS_SOCKET_H
     31 #include <sys/socket.h>
     32 /* Define HAVE_F_GETFD if we plan to use F_GETFD.  */
     33 #define HAVE_F_GETFD F_GETFD
     34 #define HAVE_SOCKETS 1
     35 #endif
     36 
     37 #ifdef HAVE_KINFO_GETFILE
     38 #include <sys/user.h>
     39 #include <libutil.h>
     40 #endif
     41 
     42 #ifdef HAVE_SYS_RESOURCE_H
     43 #include <sys/resource.h>
     44 #endif /* HAVE_SYS_RESOURCE_H */
     45 
     46 #ifndef O_CLOEXEC
     47 #define O_CLOEXEC 0
     48 #endif
     49 
     50 #ifndef O_NOINHERIT
     51 #define O_NOINHERIT 0
     52 #endif
     53 
     54 #ifndef SOCK_CLOEXEC
     55 #define SOCK_CLOEXEC 0
     56 #endif
     57 
     58 
     59 
     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 
    177 /* A vector holding all the fds open when notice_open_fds was called.  We
    178    don't use a hashtab because we don't expect there to be many open fds.  */
    179 
    180 static std::vector<int> open_fds;
    181 
    182 /* An fdwalk callback function used by notice_open_fds.  It puts the
    183    given file descriptor into the vec.  */
    184 
    185 static int
    186 do_mark_open_fd (void *ignore, int fd)
    187 {
    188   open_fds.push_back (fd);
    189   return 0;
    190 }
    191 
    192 /* See filestuff.h.  */
    193 
    194 void
    195 notice_open_fds (void)
    196 {
    197   fdwalk (do_mark_open_fd, NULL);
    198 }
    199 
    200 /* See filestuff.h.  */
    201 
    202 void
    203 mark_fd_no_cloexec (int fd)
    204 {
    205   do_mark_open_fd (NULL, fd);
    206 }
    207 
    208 /* See filestuff.h.  */
    209 
    210 void
    211 unmark_fd_no_cloexec (int fd)
    212 {
    213   auto it = std::remove (open_fds.begin (), open_fds.end (), fd);
    214 
    215   if (it != open_fds.end ())
    216     open_fds.erase (it);
    217   else
    218     gdb_assert_not_reached ("fd not found in open_fds");
    219 }
    220 
    221 /* Helper function for close_most_fds that closes the file descriptor
    222    if appropriate.  */
    223 
    224 static int
    225 do_close (void *ignore, int fd)
    226 {
    227   for (int val : open_fds)
    228     {
    229       if (fd == val)
    230 	{
    231 	  /* Keep this one open.  */
    232 	  return 0;
    233 	}
    234     }
    235 
    236   close (fd);
    237   return 0;
    238 }
    239 
    240 /* See filestuff.h.  */
    241 
    242 void
    243 close_most_fds (void)
    244 {
    245   fdwalk (do_close, NULL);
    246 }
    247 
    248 
    249 
    251 /* This is a tri-state flag.  When zero it means we haven't yet tried
    252    O_CLOEXEC.  When positive it means that O_CLOEXEC works on this
    253    host.  When negative, it means that O_CLOEXEC doesn't work.  We
    254    track this state because, while gdb might have been compiled
    255    against a libc that supplies O_CLOEXEC, there is no guarantee that
    256    the kernel supports it.  */
    257 
    258 static int trust_o_cloexec;
    259 
    260 /* Mark FD as close-on-exec, ignoring errors.  Update
    261    TRUST_O_CLOEXEC.  */
    262 
    263 static void
    264 mark_cloexec (int fd)
    265 {
    266 #ifdef HAVE_F_GETFD
    267   int old = fcntl (fd, F_GETFD, 0);
    268 
    269   if (old != -1)
    270     {
    271       fcntl (fd, F_SETFD, old | FD_CLOEXEC);
    272 
    273       if (trust_o_cloexec == 0)
    274 	{
    275 	  if ((old & FD_CLOEXEC) != 0)
    276 	    trust_o_cloexec = 1;
    277 	  else
    278 	    trust_o_cloexec = -1;
    279 	}
    280     }
    281 #endif /* HAVE_F_GETFD */
    282 }
    283 
    284 /* Depending on TRUST_O_CLOEXEC, mark FD as close-on-exec.  */
    285 
    286 static void
    287 maybe_mark_cloexec (int fd)
    288 {
    289   if (trust_o_cloexec <= 0)
    290     mark_cloexec (fd);
    291 }
    292 
    293 #ifdef HAVE_SOCKETS
    294 
    295 /* Like maybe_mark_cloexec, but for callers that use SOCK_CLOEXEC.  */
    296 
    297 static void
    298 socket_mark_cloexec (int fd)
    299 {
    300   if (SOCK_CLOEXEC == 0 || trust_o_cloexec <= 0)
    301     mark_cloexec (fd);
    302 }
    303 
    304 #endif
    305 
    306 
    307 
    309 /* See filestuff.h.  */
    310 
    311 scoped_fd
    312 gdb_open_cloexec (const char *filename, int flags, unsigned long mode)
    313 {
    314   scoped_fd fd (open (filename, flags | O_CLOEXEC, mode));
    315 
    316   if (fd.get () >= 0)
    317     maybe_mark_cloexec (fd.get ());
    318 
    319   return fd;
    320 }
    321 
    322 /* See filestuff.h.  */
    323 
    324 gdb_file_up
    325 gdb_fopen_cloexec (const char *filename, const char *opentype)
    326 {
    327   FILE *result;
    328   /* Probe for "e" support once.  But, if we can tell the operating
    329      system doesn't know about close on exec mode "e" without probing,
    330      skip it.  E.g., the Windows runtime issues an "Invalid parameter
    331      passed to C runtime function" OutputDebugString warning for
    332      unknown modes.  Assume that if O_CLOEXEC is zero, then "e" isn't
    333      supported.  On MinGW, O_CLOEXEC is an alias of O_NOINHERIT, and
    334      "e" isn't supported.  */
    335   static int fopen_e_ever_failed_einval =
    336     O_CLOEXEC == 0 || O_CLOEXEC == O_NOINHERIT;
    337 
    338   if (!fopen_e_ever_failed_einval)
    339     {
    340       char *copy;
    341 
    342       copy = (char *) alloca (strlen (opentype) + 2);
    343       strcpy (copy, opentype);
    344       /* This is a glibc extension but we try it unconditionally on
    345 	 this path.  */
    346       strcat (copy, "e");
    347       result = fopen (filename, copy);
    348 
    349       if (result == NULL && errno == EINVAL)
    350 	{
    351 	  result = fopen (filename, opentype);
    352 	  if (result != NULL)
    353 	    fopen_e_ever_failed_einval = 1;
    354 	}
    355     }
    356   else
    357     result = fopen (filename, opentype);
    358 
    359   if (result != NULL)
    360     maybe_mark_cloexec (fileno (result));
    361 
    362   return gdb_file_up (result);
    363 }
    364 
    365 #ifdef HAVE_SOCKETS
    366 /* See filestuff.h.  */
    367 
    368 int
    369 gdb_socketpair_cloexec (int domain, int style, int protocol,
    370 			int filedes[2])
    371 {
    372 #ifdef HAVE_SOCKETPAIR
    373   int result = socketpair (domain, style | SOCK_CLOEXEC, protocol, filedes);
    374 
    375   if (result != -1)
    376     {
    377       socket_mark_cloexec (filedes[0]);
    378       socket_mark_cloexec (filedes[1]);
    379     }
    380 
    381   return result;
    382 #else
    383   gdb_assert_not_reached ("socketpair not available on this host");
    384 #endif
    385 }
    386 
    387 /* See filestuff.h.  */
    388 
    389 int
    390 gdb_socket_cloexec (int domain, int style, int protocol)
    391 {
    392   int result = socket (domain, style | SOCK_CLOEXEC, protocol);
    393 
    394   if (result != -1)
    395     socket_mark_cloexec (result);
    396 
    397   return result;
    398 }
    399 #endif
    400 
    401 /* See filestuff.h.  */
    402 
    403 int
    404 gdb_pipe_cloexec (int filedes[2])
    405 {
    406   int result;
    407 
    408 #ifdef HAVE_PIPE2
    409   result = pipe2 (filedes, O_CLOEXEC);
    410   if (result != -1)
    411     {
    412       maybe_mark_cloexec (filedes[0]);
    413       maybe_mark_cloexec (filedes[1]);
    414     }
    415 #else
    416 #ifdef HAVE_PIPE
    417   result = pipe (filedes);
    418   if (result != -1)
    419     {
    420       mark_cloexec (filedes[0]);
    421       mark_cloexec (filedes[1]);
    422     }
    423 #else /* HAVE_PIPE */
    424   gdb_assert_not_reached ("pipe not available on this host");
    425 #endif /* HAVE_PIPE */
    426 #endif /* HAVE_PIPE2 */
    427 
    428   return result;
    429 }
    430 
    431 /* See gdbsupport/filestuff.h.  */
    432 
    433 bool
    434 is_regular_file (const char *name, int *errno_ptr)
    435 {
    436   struct stat st;
    437   const int status = stat (name, &st);
    438 
    439   /* Stat should never fail except when the file does not exist.
    440      If stat fails, analyze the source of error and return true
    441      unless the file does not exist, to avoid returning false results
    442      on obscure systems where stat does not work as expected.  */
    443 
    444   if (status != 0)
    445     {
    446       if (errno != ENOENT)
    447 	return true;
    448       *errno_ptr = ENOENT;
    449       return false;
    450     }
    451 
    452   if (S_ISREG (st.st_mode))
    453     return true;
    454 
    455   if (S_ISDIR (st.st_mode))
    456     *errno_ptr = EISDIR;
    457   else
    458     *errno_ptr = EINVAL;
    459   return false;
    460 }
    461 
    462 /* See gdbsupport/filestuff.h.  */
    463 
    464 bool
    465 mkdir_recursive (const char *dir)
    466 {
    467   auto holder = make_unique_xstrdup (dir);
    468   char * const start = holder.get ();
    469   char *component_start = start;
    470   char *component_end = start;
    471 
    472   while (1)
    473     {
    474       /* Find the beginning of the next component.  */
    475       while (*component_start == '/')
    476 	component_start++;
    477 
    478       /* Are we done?  */
    479       if (*component_start == '\0')
    480 	return true;
    481 
    482       /* Find the slash or null-terminator after this component.  */
    483       component_end = component_start;
    484       while (*component_end != '/' && *component_end != '\0')
    485 	component_end++;
    486 
    487       /* Temporarily replace the slash with a null terminator, so we can create
    488 	 the directory up to this component.  */
    489       char saved_char = *component_end;
    490       *component_end = '\0';
    491 
    492       /* If we get EEXIST and the existing path is a directory, then we're
    493 	 happy.  If it exists, but it's a regular file and this is not the last
    494 	 component, we'll fail at the next component.  If this is the last
    495 	 component, the caller will fail with ENOTDIR when trying to
    496 	 open/create a file under that path.  */
    497       if (mkdir (start, 0700) != 0)
    498 	if (errno != EEXIST)
    499 	  return false;
    500 
    501       /* Restore the overwritten char.  */
    502       *component_end = saved_char;
    503       component_start = component_end;
    504     }
    505 }
    506 
    507 /* See gdbsupport/filestuff.h.  */
    508 
    509 std::string
    510 read_remainder_of_file (FILE *file)
    511 {
    512   std::string res;
    513   for (;;)
    514     {
    515       std::string::size_type start_size = res.size ();
    516       constexpr int chunk_size = 1024;
    517 
    518       /* Resize to accommodate CHUNK_SIZE bytes.  */
    519       res.resize (start_size + chunk_size);
    520 
    521       int n = fread (&res[start_size], 1, chunk_size, file);
    522       if (n == chunk_size)
    523 	continue;
    524 
    525       gdb_assert (n < chunk_size);
    526 
    527       /* Less than CHUNK means EOF or error.  If it's an error, return
    528 	 no value.  */
    529       if (ferror (file))
    530 	return {};
    531 
    532       /* Resize the string according to the data we read.  */
    533       res.resize (start_size + n);
    534       break;
    535     }
    536 
    537   return res;
    538 }
    539 
    540 /* See gdbsupport/filestuff.h.  */
    541 
    542 std::optional<std::string>
    543 read_text_file_to_string (const char *path)
    544 {
    545   gdb_file_up file = gdb_fopen_cloexec (path, "r");
    546   if (file == nullptr)
    547     return {};
    548 
    549   return read_remainder_of_file (file.get ());
    550 }
    551