X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=lib%2Fopen.c;h=792e258ba0b09199346fc053356c6cf3e3b6d73a;hb=HEAD;hp=f612b802d2185505b2aa19cc72290ab790190cba;hpb=dc0ab95dbae38577efebe2283fc9b76e92ef4233;p=debian%2Fgzip
diff --git a/lib/open.c b/lib/open.c
index f612b80..792e258 100644
--- a/lib/open.c
+++ b/lib/open.c
@@ -1,5 +1,5 @@
/* Open a descriptor to a file.
- Copyright (C) 2007-2010 Free Software Foundation, Inc.
+ Copyright (C) 2007-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,26 +12,33 @@
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 Bruno Haible , 2007. */
+/* If the user's config.h happens to include , let it include only
+ the system's here, so that orig_open doesn't recurse to
+ rpl_open. */
+#define __need_system_fcntl_h
#include
/* Get the original definition of open. It might be defined as a macro. */
-#define __need_system_fcntl_h
#include
-#undef __need_system_fcntl_h
#include
+#undef __need_system_fcntl_h
-static inline int
+static int
orig_open (const char *filename, int flags, mode_t mode)
{
return open (filename, flags, mode);
}
/* Specification. */
-#include
+/* 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 "cloexec.h"
#include
#include
@@ -47,6 +54,13 @@ orig_open (const char *filename, int flags, mode_t mode)
int
open (const char *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;
@@ -63,7 +77,16 @@ open (const char *filename, int flags, ...)
va_end (arg);
}
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if GNULIB_defined_O_NONBLOCK
+ /* The only known platform that lacks O_NONBLOCK is mingw, but it
+ also lacks named pipes and Unix sockets, which are the only two
+ file types that require non-blocking handling in open().
+ Therefore, it is safe to ignore O_NONBLOCK here. It is handy
+ that mingw also lacks openat(), so that is also covered here. */
+ flags &= ~O_NONBLOCK;
+#endif
+
+#if defined _WIN32 && ! defined __CYGWIN__
if (strcmp (filename, "/dev/null") == 0)
filename = "NUL";
#endif
@@ -101,7 +124,25 @@ open (const char *filename, int flags, ...)
}
#endif
- fd = orig_open (filename, flags, mode);
+ fd = orig_open (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_open (filename, flags & ~O_CLOEXEC, mode);
+ have_cloexec = -1;
+ }
+ }
+ if (have_cloexec < 0 && 0 <= fd)
+ set_cloexec_flag (fd, true);
+ }
+
#if REPLACE_FCHDIR
/* Implementing fchdir and fdopendir requires the ability to open a
@@ -111,7 +152,8 @@ open (const char *filename, int flags, ...)
override fstat() in fchdir.c to hide the fact that we have a
dummy. */
if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES
- && (flags & O_ACCMODE) == O_RDONLY)
+ && ((flags & O_ACCMODE) == O_RDONLY
+ || (O_SEARCH != O_RDONLY && (flags & O_ACCMODE) == O_SEARCH)))
{
struct stat statbuf;
if (stat (filename, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))