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