X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=lib%2Fopenat.c;h=341c5113818af03a243f3192dda470bce11bbeb2;hb=92249085071a973e2c0621b0415b93d2e48bb00d;hp=f2eac868d447c9829100f003345cc4d6c31ef785;hpb=dc0ab95dbae38577efebe2283fc9b76e92ef4233;p=debian%2Fgzip
diff --git a/lib/openat.c b/lib/openat.c
index f2eac86..341c511 100644
--- a/lib/openat.c
+++ b/lib/openat.c
@@ -1,5 +1,5 @@
/* provide a replacement openat function
- Copyright (C) 2004-2010 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,31 +12,58 @@
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 . */
+ along with this program. If not, see . */
/* written by Jim Meyering */
+/* If the user's config.h happens to include , let it include only
+ the system's here, so that orig_openat doesn't recurse to
+ rpl_openat. */
+#define __need_system_fcntl_h
#include
+/* Get the original definition of open. It might be defined as a macro. */
+#include
+#include
+#undef __need_system_fcntl_h
+
+#if HAVE_OPENAT
+static int
+orig_openat (int fd, char const *filename, int flags, mode_t mode)
+{
+ return openat (fd, filename, flags, mode);
+}
+#endif
+
+/* Write "fcntl.h" here, not , otherwise OSF/1 5.1 DTK cc eliminates
+ this include because of the preliminary #include above. */
+#include "fcntl.h"
+
#include "openat.h"
+#include "cloexec.h"
+
#include
+#include
#include
#include
#include
-
-#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
-#include "openat-priv.h"
-#include "save-cwd.h"
+#include
#if HAVE_OPENAT
-# undef 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;
@@ -53,7 +80,7 @@ rpl_openat (int dfd, char const *filename, int flags, ...)
va_end (arg);
}
-#if OPEN_TRAILING_SLASH_BUG
+# if OPEN_TRAILING_SLASH_BUG
/* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR
is specified, then fail.
Rationale: POSIX
@@ -84,11 +111,29 @@ rpl_openat (int dfd, char const *filename, int flags, ...)
return -1;
}
}
-#endif
+# endif
- fd = openat (dfd, filename, flags, mode);
+ fd = orig_openat (dfd, filename,
+ flags & ~(have_cloexec <= 0 ? O_CLOEXEC : 0), mode);
-#if OPEN_TRAILING_SLASH_BUG
+ 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,
then fail.
Rationale: POSIX
@@ -117,15 +162,19 @@ rpl_openat (int dfd, char const *filename, int flags, ...)
}
}
}
-#endif
+# endif
return fd;
}
#else /* !HAVE_OPENAT */
+# include "dosname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
+# include "openat-priv.h"
+# include "save-cwd.h"
+
/* Replacement for Solaris' openat function.
-
+
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),
@@ -159,7 +208,7 @@ openat (int fd, char const *file, int flags, ...)
directory argument.
If a previous attempt to restore the current working directory
- failed, then we must not even try to access a `.'-relative name.
+ failed, then we must not even try to access a '.'-relative name.
It is the caller's responsibility not to call this function
in that case. */
@@ -244,7 +293,7 @@ bool
openat_needs_fchdir (void)
{
bool needs_fchdir = true;
- int fd = open ("/", O_RDONLY);
+ int fd = open ("/", O_SEARCH);
if (0 <= fd)
{