/* Low-level file-handling.
- Copyright (C) 2012-2018 Free Software Foundation, Inc.
+ Copyright (C) 2012-2019 Free Software Foundation, Inc.
This file is part of GDB.
#define HAVE_SOCKETS 1
#endif
+#ifdef HAVE_KINFO_GETFILE
+#include <sys/user.h>
+#include <libutil.h>
+#endif
+
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif /* HAVE_SYS_RESOURCE_H */
#define O_CLOEXEC 0
#endif
+#ifndef O_NOINHERIT
+#define O_NOINHERIT 0
+#endif
+
#ifndef SOCK_CLOEXEC
#define SOCK_CLOEXEC 0
#endif
{
long fd;
char *tail;
- int result;
errno = 0;
fd = strtol (entry->d_name, &tail, 10);
}
/* We may fall through to the next case. */
#endif
+#ifdef HAVE_KINFO_GETFILE
+ int nfd;
+ gdb::unique_xmalloc_ptr<struct kinfo_file[]> 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;
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)
{
return result;
}
-/* Helper function which does the work for make_cleanup_close. */
-
-static void
-do_close_cleanup (void *arg)
-{
- int *fd = (int *) arg;
-
- close (*fd);
-}
-
-/* See filestuff.h. */
-
-struct cleanup *
-make_cleanup_close (int fd)
-{
- int *saved_fd = XNEW (int);
-
- *saved_fd = fd;
- return make_cleanup_dtor (do_close_cleanup, saved_fd, xfree);
-}
-
/* See common/filestuff.h. */
bool
*errno_ptr = EINVAL;
return false;
}
+
+/* See common/filestuff.h. */
+
+bool
+mkdir_recursive (const char *dir)
+{
+ auto holder = make_unique_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;
+ }
+}