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