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