xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/filestuff.cc (revision 5ba1f45f2a09259cc846f20c7c5501604d633c90)
18dffb485Schristos /* Low-level file-handling.
2*5ba1f45fSchristos    Copyright (C) 2012-2024 Free Software Foundation, Inc.
38dffb485Schristos 
48dffb485Schristos    This file is part of GDB.
58dffb485Schristos 
68dffb485Schristos    This program is free software; you can redistribute it and/or modify
78dffb485Schristos    it under the terms of the GNU General Public License as published by
88dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
98dffb485Schristos    (at your option) any later version.
108dffb485Schristos 
118dffb485Schristos    This program is distributed in the hope that it will be useful,
128dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
138dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
148dffb485Schristos    GNU General Public License for more details.
158dffb485Schristos 
168dffb485Schristos    You should have received a copy of the GNU General Public License
178dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
188dffb485Schristos 
198dffb485Schristos #include "filestuff.h"
208dffb485Schristos #include "gdb_vecs.h"
218dffb485Schristos #include <fcntl.h>
228dffb485Schristos #include <unistd.h>
238dffb485Schristos #include <sys/types.h>
248dffb485Schristos #include <sys/stat.h>
258dffb485Schristos #include <algorithm>
268dffb485Schristos 
278dffb485Schristos #ifdef USE_WIN32API
288dffb485Schristos #include <winsock2.h>
298dffb485Schristos #include <windows.h>
308dffb485Schristos #define HAVE_SOCKETS 1
318dffb485Schristos #elif defined HAVE_SYS_SOCKET_H
328dffb485Schristos #include <sys/socket.h>
338dffb485Schristos /* Define HAVE_F_GETFD if we plan to use F_GETFD.  */
348dffb485Schristos #define HAVE_F_GETFD F_GETFD
358dffb485Schristos #define HAVE_SOCKETS 1
368dffb485Schristos #endif
378dffb485Schristos 
388dffb485Schristos #ifdef HAVE_KINFO_GETFILE
398dffb485Schristos #include <sys/user.h>
408dffb485Schristos #include <libutil.h>
418dffb485Schristos #endif
428dffb485Schristos 
438dffb485Schristos #ifdef HAVE_SYS_RESOURCE_H
448dffb485Schristos #include <sys/resource.h>
458dffb485Schristos #endif /* HAVE_SYS_RESOURCE_H */
468dffb485Schristos 
478dffb485Schristos #ifndef O_CLOEXEC
488dffb485Schristos #define O_CLOEXEC 0
498dffb485Schristos #endif
508dffb485Schristos 
518dffb485Schristos #ifndef O_NOINHERIT
528dffb485Schristos #define O_NOINHERIT 0
538dffb485Schristos #endif
548dffb485Schristos 
558dffb485Schristos #ifndef SOCK_CLOEXEC
568dffb485Schristos #define SOCK_CLOEXEC 0
578dffb485Schristos #endif
588dffb485Schristos 
598dffb485Schristos 
608dffb485Schristos 
618dffb485Schristos #ifndef HAVE_FDWALK
628dffb485Schristos 
638dffb485Schristos #include <dirent.h>
648dffb485Schristos 
658dffb485Schristos /* Replacement for fdwalk, if the system doesn't define it.  Walks all
668dffb485Schristos    open file descriptors (though this implementation may walk closed
678dffb485Schristos    ones as well, depending on the host platform's capabilities) and
688dffb485Schristos    call FUNC with ARG.  If FUNC returns non-zero, stops immediately
698dffb485Schristos    and returns the same value.  Otherwise, returns zero when
708dffb485Schristos    finished.  */
718dffb485Schristos 
728dffb485Schristos static int
738dffb485Schristos fdwalk (int (*func) (void *, int), void *arg)
748dffb485Schristos {
758dffb485Schristos   /* Checking __linux__ isn't great but it isn't clear what would be
768dffb485Schristos      better.  There doesn't seem to be a good way to check for this in
778dffb485Schristos      configure.  */
788dffb485Schristos #ifdef __linux__
798dffb485Schristos   DIR *dir;
808dffb485Schristos 
818dffb485Schristos   dir = opendir ("/proc/self/fd");
828dffb485Schristos   if (dir != NULL)
838dffb485Schristos     {
848dffb485Schristos       struct dirent *entry;
858dffb485Schristos       int result = 0;
868dffb485Schristos 
878dffb485Schristos       for (entry = readdir (dir); entry != NULL; entry = readdir (dir))
888dffb485Schristos 	{
898dffb485Schristos 	  long fd;
908dffb485Schristos 	  char *tail;
918dffb485Schristos 
928dffb485Schristos 	  errno = 0;
938dffb485Schristos 	  fd = strtol (entry->d_name, &tail, 10);
948dffb485Schristos 	  if (*tail != '\0' || errno != 0)
958dffb485Schristos 	    continue;
968dffb485Schristos 	  if ((int) fd != fd)
978dffb485Schristos 	    {
988dffb485Schristos 	      /* What can we do here really?  */
998dffb485Schristos 	      continue;
1008dffb485Schristos 	    }
1018dffb485Schristos 
1028dffb485Schristos 	  if (fd == dirfd (dir))
1038dffb485Schristos 	    continue;
1048dffb485Schristos 
1058dffb485Schristos 	  result = func (arg, fd);
1068dffb485Schristos 	  if (result != 0)
1078dffb485Schristos 	    break;
1088dffb485Schristos 	}
1098dffb485Schristos 
1108dffb485Schristos       closedir (dir);
1118dffb485Schristos       return result;
1128dffb485Schristos     }
1138dffb485Schristos   /* We may fall through to the next case.  */
1148dffb485Schristos #endif
1158dffb485Schristos #ifdef HAVE_KINFO_GETFILE
1168dffb485Schristos   int nfd;
1178dffb485Schristos   gdb::unique_xmalloc_ptr<struct kinfo_file[]> fdtbl
1188dffb485Schristos     (kinfo_getfile (getpid (), &nfd));
1198dffb485Schristos   if (fdtbl != NULL)
1208dffb485Schristos     {
1218dffb485Schristos       for (int i = 0; i < nfd; i++)
1228dffb485Schristos 	{
1238dffb485Schristos 	  if (fdtbl[i].kf_fd >= 0)
1248dffb485Schristos 	    {
1258dffb485Schristos 	      int result = func (arg, fdtbl[i].kf_fd);
1268dffb485Schristos 	      if (result != 0)
1278dffb485Schristos 		return result;
1288dffb485Schristos 	    }
1298dffb485Schristos 	}
1308dffb485Schristos       return 0;
1318dffb485Schristos     }
1328dffb485Schristos   /* We may fall through to the next case.  */
1338dffb485Schristos #endif
1348dffb485Schristos 
1358dffb485Schristos   {
1368dffb485Schristos     int max, fd;
1378dffb485Schristos 
1388dffb485Schristos #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1398dffb485Schristos     struct rlimit rlim;
1408dffb485Schristos 
1418dffb485Schristos     if (getrlimit (RLIMIT_NOFILE, &rlim) == 0 && rlim.rlim_max != RLIM_INFINITY)
1428dffb485Schristos       max = rlim.rlim_max;
1438dffb485Schristos     else
1448dffb485Schristos #endif
1458dffb485Schristos       {
1468dffb485Schristos #ifdef _SC_OPEN_MAX
1478dffb485Schristos 	max = sysconf (_SC_OPEN_MAX);
1488dffb485Schristos #else
1498dffb485Schristos 	/* Whoops.  */
1508dffb485Schristos 	return 0;
1518dffb485Schristos #endif /* _SC_OPEN_MAX */
1528dffb485Schristos       }
1538dffb485Schristos 
1548dffb485Schristos     for (fd = 0; fd < max; ++fd)
1558dffb485Schristos       {
1568dffb485Schristos 	struct stat sb;
1578dffb485Schristos 	int result;
1588dffb485Schristos 
1598dffb485Schristos 	/* Only call FUNC for open fds.  */
1608dffb485Schristos 	if (fstat (fd, &sb) == -1)
1618dffb485Schristos 	  continue;
1628dffb485Schristos 
1638dffb485Schristos 	result = func (arg, fd);
1648dffb485Schristos 	if (result != 0)
1658dffb485Schristos 	  return result;
1668dffb485Schristos       }
1678dffb485Schristos 
1688dffb485Schristos     return 0;
1698dffb485Schristos   }
1708dffb485Schristos }
1718dffb485Schristos 
1728dffb485Schristos #endif /* HAVE_FDWALK */
1738dffb485Schristos 
1748dffb485Schristos 
1758dffb485Schristos 
1768dffb485Schristos /* A vector holding all the fds open when notice_open_fds was called.  We
1778dffb485Schristos    don't use a hashtab because we don't expect there to be many open fds.  */
1788dffb485Schristos 
1798dffb485Schristos static std::vector<int> open_fds;
1808dffb485Schristos 
1818dffb485Schristos /* An fdwalk callback function used by notice_open_fds.  It puts the
1828dffb485Schristos    given file descriptor into the vec.  */
1838dffb485Schristos 
1848dffb485Schristos static int
1858dffb485Schristos do_mark_open_fd (void *ignore, int fd)
1868dffb485Schristos {
1878dffb485Schristos   open_fds.push_back (fd);
1888dffb485Schristos   return 0;
1898dffb485Schristos }
1908dffb485Schristos 
1918dffb485Schristos /* See filestuff.h.  */
1928dffb485Schristos 
1938dffb485Schristos void
1948dffb485Schristos notice_open_fds (void)
1958dffb485Schristos {
1968dffb485Schristos   fdwalk (do_mark_open_fd, NULL);
1978dffb485Schristos }
1988dffb485Schristos 
1998dffb485Schristos /* See filestuff.h.  */
2008dffb485Schristos 
2018dffb485Schristos void
2028dffb485Schristos mark_fd_no_cloexec (int fd)
2038dffb485Schristos {
2048dffb485Schristos   do_mark_open_fd (NULL, fd);
2058dffb485Schristos }
2068dffb485Schristos 
2078dffb485Schristos /* See filestuff.h.  */
2088dffb485Schristos 
2098dffb485Schristos void
2108dffb485Schristos unmark_fd_no_cloexec (int fd)
2118dffb485Schristos {
2128dffb485Schristos   auto it = std::remove (open_fds.begin (), open_fds.end (), fd);
2138dffb485Schristos 
2148dffb485Schristos   if (it != open_fds.end ())
2158dffb485Schristos     open_fds.erase (it);
2168dffb485Schristos   else
2174b169a6bSchristos     gdb_assert_not_reached ("fd not found in open_fds");
2188dffb485Schristos }
2198dffb485Schristos 
2208dffb485Schristos /* Helper function for close_most_fds that closes the file descriptor
2218dffb485Schristos    if appropriate.  */
2228dffb485Schristos 
2238dffb485Schristos static int
2248dffb485Schristos do_close (void *ignore, int fd)
2258dffb485Schristos {
2268dffb485Schristos   for (int val : open_fds)
2278dffb485Schristos     {
2288dffb485Schristos       if (fd == val)
2298dffb485Schristos 	{
2308dffb485Schristos 	  /* Keep this one open.  */
2318dffb485Schristos 	  return 0;
2328dffb485Schristos 	}
2338dffb485Schristos     }
2348dffb485Schristos 
2358dffb485Schristos   close (fd);
2368dffb485Schristos   return 0;
2378dffb485Schristos }
2388dffb485Schristos 
2398dffb485Schristos /* See filestuff.h.  */
2408dffb485Schristos 
2418dffb485Schristos void
2428dffb485Schristos close_most_fds (void)
2438dffb485Schristos {
2448dffb485Schristos   fdwalk (do_close, NULL);
2458dffb485Schristos }
2468dffb485Schristos 
2478dffb485Schristos 
2488dffb485Schristos 
2498dffb485Schristos /* This is a tri-state flag.  When zero it means we haven't yet tried
2508dffb485Schristos    O_CLOEXEC.  When positive it means that O_CLOEXEC works on this
2518dffb485Schristos    host.  When negative, it means that O_CLOEXEC doesn't work.  We
2528dffb485Schristos    track this state because, while gdb might have been compiled
2538dffb485Schristos    against a libc that supplies O_CLOEXEC, there is no guarantee that
2548dffb485Schristos    the kernel supports it.  */
2558dffb485Schristos 
2568dffb485Schristos static int trust_o_cloexec;
2578dffb485Schristos 
2588dffb485Schristos /* Mark FD as close-on-exec, ignoring errors.  Update
2598dffb485Schristos    TRUST_O_CLOEXEC.  */
2608dffb485Schristos 
2618dffb485Schristos static void
2628dffb485Schristos mark_cloexec (int fd)
2638dffb485Schristos {
2648dffb485Schristos #ifdef HAVE_F_GETFD
2658dffb485Schristos   int old = fcntl (fd, F_GETFD, 0);
2668dffb485Schristos 
2678dffb485Schristos   if (old != -1)
2688dffb485Schristos     {
2698dffb485Schristos       fcntl (fd, F_SETFD, old | FD_CLOEXEC);
2708dffb485Schristos 
2718dffb485Schristos       if (trust_o_cloexec == 0)
2728dffb485Schristos 	{
2738dffb485Schristos 	  if ((old & FD_CLOEXEC) != 0)
2748dffb485Schristos 	    trust_o_cloexec = 1;
2758dffb485Schristos 	  else
2768dffb485Schristos 	    trust_o_cloexec = -1;
2778dffb485Schristos 	}
2788dffb485Schristos     }
2798dffb485Schristos #endif /* HAVE_F_GETFD */
2808dffb485Schristos }
2818dffb485Schristos 
2828dffb485Schristos /* Depending on TRUST_O_CLOEXEC, mark FD as close-on-exec.  */
2838dffb485Schristos 
2848dffb485Schristos static void
2858dffb485Schristos maybe_mark_cloexec (int fd)
2868dffb485Schristos {
2878dffb485Schristos   if (trust_o_cloexec <= 0)
2888dffb485Schristos     mark_cloexec (fd);
2898dffb485Schristos }
2908dffb485Schristos 
2918dffb485Schristos #ifdef HAVE_SOCKETS
2928dffb485Schristos 
2938dffb485Schristos /* Like maybe_mark_cloexec, but for callers that use SOCK_CLOEXEC.  */
2948dffb485Schristos 
2958dffb485Schristos static void
2968dffb485Schristos socket_mark_cloexec (int fd)
2978dffb485Schristos {
2988dffb485Schristos   if (SOCK_CLOEXEC == 0 || trust_o_cloexec <= 0)
2998dffb485Schristos     mark_cloexec (fd);
3008dffb485Schristos }
3018dffb485Schristos 
3028dffb485Schristos #endif
3038dffb485Schristos 
3048dffb485Schristos 
3058dffb485Schristos 
3068dffb485Schristos /* See filestuff.h.  */
3078dffb485Schristos 
3084b169a6bSchristos scoped_fd
3098dffb485Schristos gdb_open_cloexec (const char *filename, int flags, unsigned long mode)
3108dffb485Schristos {
3114b169a6bSchristos   scoped_fd fd (open (filename, flags | O_CLOEXEC, mode));
3128dffb485Schristos 
3134b169a6bSchristos   if (fd.get () >= 0)
3144b169a6bSchristos     maybe_mark_cloexec (fd.get ());
3158dffb485Schristos 
3168dffb485Schristos   return fd;
3178dffb485Schristos }
3188dffb485Schristos 
3198dffb485Schristos /* See filestuff.h.  */
3208dffb485Schristos 
3218dffb485Schristos gdb_file_up
3228dffb485Schristos gdb_fopen_cloexec (const char *filename, const char *opentype)
3238dffb485Schristos {
3248dffb485Schristos   FILE *result;
3258dffb485Schristos   /* Probe for "e" support once.  But, if we can tell the operating
3268dffb485Schristos      system doesn't know about close on exec mode "e" without probing,
3278dffb485Schristos      skip it.  E.g., the Windows runtime issues an "Invalid parameter
3288dffb485Schristos      passed to C runtime function" OutputDebugString warning for
3298dffb485Schristos      unknown modes.  Assume that if O_CLOEXEC is zero, then "e" isn't
3308dffb485Schristos      supported.  On MinGW, O_CLOEXEC is an alias of O_NOINHERIT, and
3318dffb485Schristos      "e" isn't supported.  */
3328dffb485Schristos   static int fopen_e_ever_failed_einval =
3338dffb485Schristos     O_CLOEXEC == 0 || O_CLOEXEC == O_NOINHERIT;
3348dffb485Schristos 
3358dffb485Schristos   if (!fopen_e_ever_failed_einval)
3368dffb485Schristos     {
3378dffb485Schristos       char *copy;
3388dffb485Schristos 
3398dffb485Schristos       copy = (char *) alloca (strlen (opentype) + 2);
3408dffb485Schristos       strcpy (copy, opentype);
3418dffb485Schristos       /* This is a glibc extension but we try it unconditionally on
3428dffb485Schristos 	 this path.  */
3438dffb485Schristos       strcat (copy, "e");
3448dffb485Schristos       result = fopen (filename, copy);
3458dffb485Schristos 
3468dffb485Schristos       if (result == NULL && errno == EINVAL)
3478dffb485Schristos 	{
3488dffb485Schristos 	  result = fopen (filename, opentype);
3498dffb485Schristos 	  if (result != NULL)
3508dffb485Schristos 	    fopen_e_ever_failed_einval = 1;
3518dffb485Schristos 	}
3528dffb485Schristos     }
3538dffb485Schristos   else
3548dffb485Schristos     result = fopen (filename, opentype);
3558dffb485Schristos 
3568dffb485Schristos   if (result != NULL)
3578dffb485Schristos     maybe_mark_cloexec (fileno (result));
3588dffb485Schristos 
3598dffb485Schristos   return gdb_file_up (result);
3608dffb485Schristos }
3618dffb485Schristos 
3628dffb485Schristos #ifdef HAVE_SOCKETS
3638dffb485Schristos /* See filestuff.h.  */
3648dffb485Schristos 
3658dffb485Schristos int
3668dffb485Schristos gdb_socketpair_cloexec (int domain, int style, int protocol,
3678dffb485Schristos 			int filedes[2])
3688dffb485Schristos {
3698dffb485Schristos #ifdef HAVE_SOCKETPAIR
3708dffb485Schristos   int result = socketpair (domain, style | SOCK_CLOEXEC, protocol, filedes);
3718dffb485Schristos 
3728dffb485Schristos   if (result != -1)
3738dffb485Schristos     {
3748dffb485Schristos       socket_mark_cloexec (filedes[0]);
3758dffb485Schristos       socket_mark_cloexec (filedes[1]);
3768dffb485Schristos     }
3778dffb485Schristos 
3788dffb485Schristos   return result;
3798dffb485Schristos #else
3804b169a6bSchristos   gdb_assert_not_reached ("socketpair not available on this host");
3818dffb485Schristos #endif
3828dffb485Schristos }
3838dffb485Schristos 
3848dffb485Schristos /* See filestuff.h.  */
3858dffb485Schristos 
3868dffb485Schristos int
3878dffb485Schristos gdb_socket_cloexec (int domain, int style, int protocol)
3888dffb485Schristos {
3898dffb485Schristos   int result = socket (domain, style | SOCK_CLOEXEC, protocol);
3908dffb485Schristos 
3918dffb485Schristos   if (result != -1)
3928dffb485Schristos     socket_mark_cloexec (result);
3938dffb485Schristos 
3948dffb485Schristos   return result;
3958dffb485Schristos }
3968dffb485Schristos #endif
3978dffb485Schristos 
3988dffb485Schristos /* See filestuff.h.  */
3998dffb485Schristos 
4008dffb485Schristos int
4018dffb485Schristos gdb_pipe_cloexec (int filedes[2])
4028dffb485Schristos {
4038dffb485Schristos   int result;
4048dffb485Schristos 
4058dffb485Schristos #ifdef HAVE_PIPE2
4068dffb485Schristos   result = pipe2 (filedes, O_CLOEXEC);
4078dffb485Schristos   if (result != -1)
4088dffb485Schristos     {
4098dffb485Schristos       maybe_mark_cloexec (filedes[0]);
4108dffb485Schristos       maybe_mark_cloexec (filedes[1]);
4118dffb485Schristos     }
4128dffb485Schristos #else
4138dffb485Schristos #ifdef HAVE_PIPE
4148dffb485Schristos   result = pipe (filedes);
4158dffb485Schristos   if (result != -1)
4168dffb485Schristos     {
4178dffb485Schristos       mark_cloexec (filedes[0]);
4188dffb485Schristos       mark_cloexec (filedes[1]);
4198dffb485Schristos     }
4208dffb485Schristos #else /* HAVE_PIPE */
4214b169a6bSchristos   gdb_assert_not_reached ("pipe not available on this host");
4228dffb485Schristos #endif /* HAVE_PIPE */
4238dffb485Schristos #endif /* HAVE_PIPE2 */
4248dffb485Schristos 
4258dffb485Schristos   return result;
4268dffb485Schristos }
4278dffb485Schristos 
4288dffb485Schristos /* See gdbsupport/filestuff.h.  */
4298dffb485Schristos 
4308dffb485Schristos bool
4318dffb485Schristos is_regular_file (const char *name, int *errno_ptr)
4328dffb485Schristos {
4338dffb485Schristos   struct stat st;
4348dffb485Schristos   const int status = stat (name, &st);
4358dffb485Schristos 
4368dffb485Schristos   /* Stat should never fail except when the file does not exist.
4378dffb485Schristos      If stat fails, analyze the source of error and return true
4388dffb485Schristos      unless the file does not exist, to avoid returning false results
4398dffb485Schristos      on obscure systems where stat does not work as expected.  */
4408dffb485Schristos 
4418dffb485Schristos   if (status != 0)
4428dffb485Schristos     {
4438dffb485Schristos       if (errno != ENOENT)
4448dffb485Schristos 	return true;
4458dffb485Schristos       *errno_ptr = ENOENT;
4468dffb485Schristos       return false;
4478dffb485Schristos     }
4488dffb485Schristos 
4498dffb485Schristos   if (S_ISREG (st.st_mode))
4508dffb485Schristos     return true;
4518dffb485Schristos 
4528dffb485Schristos   if (S_ISDIR (st.st_mode))
4538dffb485Schristos     *errno_ptr = EISDIR;
4548dffb485Schristos   else
4558dffb485Schristos     *errno_ptr = EINVAL;
4568dffb485Schristos   return false;
4578dffb485Schristos }
4588dffb485Schristos 
4598dffb485Schristos /* See gdbsupport/filestuff.h.  */
4608dffb485Schristos 
4618dffb485Schristos bool
4628dffb485Schristos mkdir_recursive (const char *dir)
4638dffb485Schristos {
4648dffb485Schristos   auto holder = make_unique_xstrdup (dir);
4658dffb485Schristos   char * const start = holder.get ();
4668dffb485Schristos   char *component_start = start;
4678dffb485Schristos   char *component_end = start;
4688dffb485Schristos 
4698dffb485Schristos   while (1)
4708dffb485Schristos     {
4718dffb485Schristos       /* Find the beginning of the next component.  */
4728dffb485Schristos       while (*component_start == '/')
4738dffb485Schristos 	component_start++;
4748dffb485Schristos 
4758dffb485Schristos       /* Are we done?  */
4768dffb485Schristos       if (*component_start == '\0')
4778dffb485Schristos 	return true;
4788dffb485Schristos 
4798dffb485Schristos       /* Find the slash or null-terminator after this component.  */
4808dffb485Schristos       component_end = component_start;
4818dffb485Schristos       while (*component_end != '/' && *component_end != '\0')
4828dffb485Schristos 	component_end++;
4838dffb485Schristos 
4848dffb485Schristos       /* Temporarily replace the slash with a null terminator, so we can create
4858dffb485Schristos 	 the directory up to this component.  */
4868dffb485Schristos       char saved_char = *component_end;
4878dffb485Schristos       *component_end = '\0';
4888dffb485Schristos 
4898dffb485Schristos       /* If we get EEXIST and the existing path is a directory, then we're
4908dffb485Schristos 	 happy.  If it exists, but it's a regular file and this is not the last
4918dffb485Schristos 	 component, we'll fail at the next component.  If this is the last
4928dffb485Schristos 	 component, the caller will fail with ENOTDIR when trying to
4938dffb485Schristos 	 open/create a file under that path.  */
4948dffb485Schristos       if (mkdir (start, 0700) != 0)
4958dffb485Schristos 	if (errno != EEXIST)
4968dffb485Schristos 	  return false;
4978dffb485Schristos 
4988dffb485Schristos       /* Restore the overwritten char.  */
4998dffb485Schristos       *component_end = saved_char;
5008dffb485Schristos       component_start = component_end;
5018dffb485Schristos     }
5028dffb485Schristos }
5034b169a6bSchristos 
5044b169a6bSchristos /* See gdbsupport/filestuff.h.  */
5054b169a6bSchristos 
506*5ba1f45fSchristos std::string
507*5ba1f45fSchristos read_remainder_of_file (FILE *file)
5084b169a6bSchristos {
5094b169a6bSchristos   std::string res;
5104b169a6bSchristos   for (;;)
5114b169a6bSchristos     {
5124b169a6bSchristos       std::string::size_type start_size = res.size ();
5134b169a6bSchristos       constexpr int chunk_size = 1024;
5144b169a6bSchristos 
515*5ba1f45fSchristos       /* Resize to accommodate CHUNK_SIZE bytes.  */
5164b169a6bSchristos       res.resize (start_size + chunk_size);
5174b169a6bSchristos 
518*5ba1f45fSchristos       int n = fread (&res[start_size], 1, chunk_size, file);
5194b169a6bSchristos       if (n == chunk_size)
5204b169a6bSchristos 	continue;
5214b169a6bSchristos 
5224b169a6bSchristos       gdb_assert (n < chunk_size);
5234b169a6bSchristos 
5244b169a6bSchristos       /* Less than CHUNK means EOF or error.  If it's an error, return
5254b169a6bSchristos 	 no value.  */
526*5ba1f45fSchristos       if (ferror (file))
5274b169a6bSchristos 	return {};
5284b169a6bSchristos 
5294b169a6bSchristos       /* Resize the string according to the data we read.  */
5304b169a6bSchristos       res.resize (start_size + n);
5314b169a6bSchristos       break;
5324b169a6bSchristos     }
5334b169a6bSchristos 
5344b169a6bSchristos   return res;
5354b169a6bSchristos }
536*5ba1f45fSchristos 
537*5ba1f45fSchristos /* See gdbsupport/filestuff.h.  */
538*5ba1f45fSchristos 
539*5ba1f45fSchristos std::optional<std::string>
540*5ba1f45fSchristos read_text_file_to_string (const char *path)
541*5ba1f45fSchristos {
542*5ba1f45fSchristos   gdb_file_up file = gdb_fopen_cloexec (path, "r");
543*5ba1f45fSchristos   if (file == nullptr)
544*5ba1f45fSchristos     return {};
545*5ba1f45fSchristos 
546*5ba1f45fSchristos   return read_remainder_of_file (file.get ());
547*5ba1f45fSchristos }
548