Do not reopen temporary files
[deliverable/binutils-gdb.git] / gdb / common / filestuff.c
index 798a411af3d43c4be58bf01c425d757ebb5b2f3f..d4bd1a8cb8cd5d5d182121258b2a646ee4bacae4 100644 (file)
@@ -1,5 +1,5 @@
 /* Low-level file-handling.
-   Copyright (C) 2012-2015 Free Software Foundation, Inc.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -23,6 +23,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <algorithm>
 
 #ifdef USE_WIN32API
 #include <winsock2.h>
@@ -79,7 +80,6 @@ fdwalk (int (*func) (void *, int), void *arg)
        {
          long fd;
          char *tail;
-         int result;
 
          errno = 0;
          fd = strtol (entry->d_name, &tail, 10);
@@ -146,11 +146,10 @@ fdwalk (int (*func) (void *, int), void *arg)
 
 \f
 
-/* A VEC holding all the fds open when notice_open_fds was called.  We
-   don't use a hashtab because libiberty isn't linked into gdbserver;
-   and anyway we don't expect there to be many open fds.  */
+/* A vector holding all the fds open when notice_open_fds was called.  We
+   don't use a hashtab because we don't expect there to be many open fds.  */
 
-static VEC (int) *open_fds;
+static std::vector<int> open_fds;
 
 /* An fdwalk callback function used by notice_open_fds.  It puts the
    given file descriptor into the vec.  */
@@ -158,7 +157,7 @@ static VEC (int) *open_fds;
 static int
 do_mark_open_fd (void *ignore, int fd)
 {
-  VEC_safe_push (int, open_fds, fd);
+  open_fds.push_back (fd);
   return 0;
 }
 
@@ -183,18 +182,12 @@ mark_fd_no_cloexec (int fd)
 void
 unmark_fd_no_cloexec (int fd)
 {
-  int i, val;
+  auto it = std::remove (open_fds.begin (), open_fds.end (), fd);
 
-  for (i = 0; VEC_iterate (int, open_fds, i, val); ++i)
-    {
-      if (fd == val)
-       {
-         VEC_unordered_remove (int, open_fds, i);
-         return;
-       }
-    }
-
-  gdb_assert_not_reached (_("fd not found in open_fds"));
+  if (it != open_fds.end ())
+    open_fds.erase (it);
+  else
+    gdb_assert_not_reached (_("fd not found in open_fds"));
 }
 
 /* Helper function for close_most_fds that closes the file descriptor
@@ -203,9 +196,7 @@ unmark_fd_no_cloexec (int fd)
 static int
 do_close (void *ignore, int fd)
 {
-  int i, val;
-
-  for (i = 0; VEC_iterate (int, open_fds, i, val); ++i)
+  for (int val : open_fds)
     {
       if (fd == val)
        {
@@ -300,7 +291,7 @@ gdb_open_cloexec (const char *filename, int flags, unsigned long mode)
 
 /* See filestuff.h.  */
 
-FILE *
+gdb_file_up
 gdb_fopen_cloexec (const char *filename, const char *opentype)
 {
   FILE *result;
@@ -336,7 +327,7 @@ gdb_fopen_cloexec (const char *filename, const char *opentype)
   if (result != NULL)
     maybe_mark_cloexec (fileno (result));
 
-  return result;
+  return gdb_file_up (result);
 }
 
 #ifdef HAVE_SOCKETS
@@ -415,7 +406,7 @@ do_close_cleanup (void *arg)
   close (*fd);
 }
 
-/* See cleanup-utils.h.  */
+/* See filestuff.h.  */
 
 struct cleanup *
 make_cleanup_close (int fd)
@@ -425,3 +416,79 @@ make_cleanup_close (int fd)
   *saved_fd = fd;
   return make_cleanup_dtor (do_close_cleanup, saved_fd, xfree);
 }
+
+/* See common/filestuff.h.  */
+
+bool
+is_regular_file (const char *name, int *errno_ptr)
+{
+  struct stat st;
+  const int status = stat (name, &st);
+
+  /* Stat should never fail except when the file does not exist.
+     If stat fails, analyze the source of error and return true
+     unless the file does not exist, to avoid returning false results
+     on obscure systems where stat does not work as expected.  */
+
+  if (status != 0)
+    {
+      if (errno != ENOENT)
+       return true;
+      *errno_ptr = ENOENT;
+      return false;
+    }
+
+  if (S_ISREG (st.st_mode))
+    return true;
+
+  if (S_ISDIR (st.st_mode))
+    *errno_ptr = EISDIR;
+  else
+    *errno_ptr = EINVAL;
+  return false;
+}
+
+/* See common/filestuff.h.  */
+
+bool
+mkdir_recursive (const char *dir)
+{
+  gdb::unique_xmalloc_ptr<char> holder (xstrdup (dir));
+  char * const start = holder.get ();
+  char *component_start = start;
+  char *component_end = start;
+
+  while (1)
+    {
+      /* Find the beginning of the next component.  */
+      while (*component_start == '/')
+       component_start++;
+
+      /* Are we done?  */
+      if (*component_start == '\0')
+       return true;
+
+      /* Find the slash or null-terminator after this component.  */
+      component_end = component_start;
+      while (*component_end != '/' && *component_end != '\0')
+       component_end++;
+
+      /* Temporarily replace the slash with a null terminator, so we can create
+         the directory up to this component.  */
+      char saved_char = *component_end;
+      *component_end = '\0';
+
+      /* If we get EEXIST and the existing path is a directory, then we're
+         happy.  If it exists, but it's a regular file and this is not the last
+         component, we'll fail at the next component.  If this is the last
+         component, the caller will fail with ENOTDIR when trying to
+         open/create a file under that path.  */
+      if (mkdir (start, 0700) != 0)
+       if (errno != EEXIST)
+         return false;
+
+      /* Restore the overwritten char.  */
+      *component_end = saved_char;
+      component_start = component_end;
+    }
+}
This page took 0.027971 seconds and 4 git commands to generate.