summaryrefslogtreecommitdiffstats
path: root/libgnu/openat.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgnu/openat.c')
-rw-r--r--libgnu/openat.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/libgnu/openat.c b/libgnu/openat.c
index e739b714..341c5113 100644
--- a/libgnu/openat.c
+++ b/libgnu/openat.c
@@ -1,5 +1,5 @@
/* provide a replacement openat function
- Copyright (C) 2004-2017 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -12,7 +12,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
@@ -41,6 +41,8 @@ orig_openat (int fd, char const *filename, int flags, mode_t mode)
#include "openat.h"
+#include "cloexec.h"
+
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
@@ -50,10 +52,18 @@ orig_openat (int fd, char const *filename, int flags, mode_t mode)
#if HAVE_OPENAT
-/* Like openat, but work around Solaris 9 bugs with trailing slash. */
+/* Like openat, but support O_CLOEXEC and work around Solaris 9 bugs
+ with trailing slash. */
int
rpl_openat (int dfd, char const *filename, int flags, ...)
{
+ /* 0 = unknown, 1 = yes, -1 = no. */
+#if GNULIB_defined_O_CLOEXEC
+ int have_cloexec = -1;
+#else
+ static int have_cloexec;
+#endif
+
mode_t mode;
int fd;
@@ -103,7 +113,25 @@ rpl_openat (int dfd, char const *filename, int flags, ...)
}
# endif
- fd = orig_openat (dfd, filename, flags, mode);
+ fd = orig_openat (dfd, filename,
+ flags & ~(have_cloexec <= 0 ? O_CLOEXEC : 0), mode);
+
+ if (flags & O_CLOEXEC)
+ {
+ if (! have_cloexec)
+ {
+ if (0 <= fd)
+ have_cloexec = 1;
+ else if (errno == EINVAL)
+ {
+ fd = orig_openat (dfd, filename, flags & ~O_CLOEXEC, mode);
+ have_cloexec = -1;
+ }
+ }
+ if (have_cloexec < 0 && 0 <= fd)
+ set_cloexec_flag (fd, true);
+ }
+
# if OPEN_TRAILING_SLASH_BUG
/* If the filename ends in a slash and fd does not refer to a directory,
@@ -146,7 +174,7 @@ rpl_openat (int dfd, char const *filename, int flags, ...)
# include "save-cwd.h"
/* Replacement for Solaris' openat function.
- <http://www.google.com/search?q=openat+site:docs.sun.com>
+ <https://www.google.com/search?q=openat+site:docs.oracle.com>
First, try to simulate it via open ("/proc/self/fd/FD/FILE").
Failing that, simulate it by doing save_cwd/fchdir/open/restore_cwd.
If either the save_cwd or the restore_cwd fails (relatively unlikely),