X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fcommon%2Ffilestuff.c;h=c7b8c694055138cea1c66c89154f5251a70d2d50;hb=5b0e2db4fa08b43e9ff78d6e9a45d496522bd241;hp=c829a8928321eda3ed28e809a1a619603104d3ff;hpb=8d7493201cf01c9836403695f67f7e157341bfd5;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/common/filestuff.c b/gdb/common/filestuff.c index c829a89283..c7b8c69405 100644 --- a/gdb/common/filestuff.c +++ b/gdb/common/filestuff.c @@ -1,5 +1,5 @@ /* Low-level file-handling. - Copyright (C) 2012-2015 Free Software Foundation, Inc. + Copyright (C) 2012-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef USE_WIN32API #include @@ -35,6 +36,11 @@ #define HAVE_SOCKETS 1 #endif +#ifdef HAVE_KINFO_GETFILE +#include +#include +#endif + #ifdef HAVE_SYS_RESOURCE_H #include #endif /* HAVE_SYS_RESOURCE_H */ @@ -43,6 +49,10 @@ #define O_CLOEXEC 0 #endif +#ifndef O_NOINHERIT +#define O_NOINHERIT 0 +#endif + #ifndef SOCK_CLOEXEC #define SOCK_CLOEXEC 0 #endif @@ -79,7 +89,6 @@ fdwalk (int (*func) (void *, int), void *arg) { long fd; char *tail; - int result; errno = 0; fd = strtol (entry->d_name, &tail, 10); @@ -104,6 +113,25 @@ fdwalk (int (*func) (void *, int), void *arg) } /* We may fall through to the next case. */ #endif +#ifdef HAVE_KINFO_GETFILE + int nfd; + gdb::unique_xmalloc_ptr fdtbl + (kinfo_getfile (getpid (), &nfd)); + if (fdtbl != NULL) + { + for (int i = 0; i < nfd; i++) + { + if (fdtbl[i].kf_fd >= 0) + { + int result = func (arg, fdtbl[i].kf_fd); + if (result != 0) + return result; + } + } + return 0; + } + /* We may fall through to the next case. */ +#endif { int max, fd; @@ -146,11 +174,10 @@ fdwalk (int (*func) (void *, int), void *arg) -/* 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 open_fds; /* An fdwalk callback function used by notice_open_fds. It puts the given file descriptor into the vec. */ @@ -158,7 +185,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 +210,12 @@ mark_fd_no_cloexec (int fd) void unmark_fd_no_cloexec (int fd) { - int i, val; - - for (i = 0; VEC_iterate (int, open_fds, i, val); ++i) - { - if (fd == val) - { - VEC_unordered_remove (int, open_fds, i); - return; - } - } + auto it = std::remove (open_fds.begin (), open_fds.end (), fd); - 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 +224,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 +319,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; @@ -309,14 +328,16 @@ gdb_fopen_cloexec (const char *filename, const char *opentype) skip it. E.g., the Windows runtime issues an "Invalid parameter passed to C runtime function" OutputDebugString warning for unknown modes. Assume that if O_CLOEXEC is zero, then "e" isn't - supported. */ - static int fopen_e_ever_failed_einval = O_CLOEXEC == 0; + supported. On MinGW, O_CLOEXEC is an alias of O_NOINHERIT, and + "e" isn't supported. */ + static int fopen_e_ever_failed_einval = + O_CLOEXEC == 0 || O_CLOEXEC == O_NOINHERIT; if (!fopen_e_ever_failed_einval) { char *copy; - copy = alloca (strlen (opentype) + 2); + copy = (char *) alloca (strlen (opentype) + 2); strcpy (copy, opentype); /* This is a glibc extension but we try it unconditionally on this path. */ @@ -336,7 +357,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 @@ -405,23 +426,78 @@ gdb_pipe_cloexec (int filedes[2]) return result; } -/* Helper function which does the work for make_cleanup_close. */ +/* See common/filestuff.h. */ -static void -do_close_cleanup (void *arg) +bool +is_regular_file (const char *name, int *errno_ptr) { - int *fd = arg; + 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. */ - close (*fd); + 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 cleanup-utils.h. */ +/* See common/filestuff.h. */ -struct cleanup * -make_cleanup_close (int fd) +bool +mkdir_recursive (const char *dir) { - int *saved_fd = XNEW (int); + auto holder = make_unique_xstrdup (dir); + char * const start = holder.get (); + char *component_start = start; + char *component_end = start; - *saved_fd = fd; - return make_cleanup_dtor (do_close_cleanup, saved_fd, xfree); + 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; + } }