diff options
Diffstat (limited to 'gnulib/import/open.c')
-rw-r--r-- | gnulib/import/open.c | 70 |
1 files changed, 46 insertions, 24 deletions
diff --git a/gnulib/import/open.c b/gnulib/import/open.c index e9c3120..0c2742b 100644 --- a/gnulib/import/open.c +++ b/gnulib/import/open.c @@ -1,5 +1,5 @@ /* Open a descriptor to a file. - Copyright (C) 2007-2016 Free Software Foundation, Inc. + Copyright (C) 2007-2019 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 Bruno Haible <bruno@clisp.org>, 2007. */ @@ -38,6 +38,8 @@ orig_open (const char *filename, int flags, mode_t mode) this include because of the preliminary #include <fcntl.h> above. */ #include "fcntl.h" +#include "cloexec.h" + #include <errno.h> #include <stdarg.h> #include <string.h> @@ -52,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; @@ -77,28 +86,25 @@ open (const char *filename, int flags, ...) flags &= ~O_NONBLOCK; #endif -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +#if defined _WIN32 && ! defined __CYGWIN__ if (strcmp (filename, "/dev/null") == 0) filename = "NUL"; #endif #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 <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> - says that - "A pathname that contains at least one non-slash character and that - ends with one or more trailing slashes shall be resolved as if a - single dot character ( '.' ) were appended to the pathname." - and - "The special filename dot shall refer to the directory specified by - its predecessor." + /* Fail if one of O_CREAT, O_WRONLY, O_RDWR is specified and the filename + ends in a slash, as POSIX says such a filename must name a directory + <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>: + "A pathname that contains at least one non-<slash> character and that + ends with one or more trailing <slash> characters shall not be resolved + successfully unless the last pathname component before the trailing + <slash> characters names an existing directory" If the named file already exists as a directory, then - if O_CREAT is specified, open() must fail because of the semantics of O_CREAT, - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX - <http://www.opengroup.org/susv3/functions/open.html> says that it - fails with errno = EISDIR in this case. + <https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html> + says that it fails with errno = EISDIR in this case. If the named file does not exist or does not name a directory, then - if O_CREAT is specified, open() must fail since open() cannot create directories, @@ -115,7 +121,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 @@ -144,14 +168,12 @@ open (const char *filename, int flags, ...) #if OPEN_TRAILING_SLASH_BUG /* If the filename ends in a slash and fd does not refer to a directory, then fail. - Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> - says that - "A pathname that contains at least one non-slash character and that - ends with one or more trailing slashes shall be resolved as if a - single dot character ( '.' ) were appended to the pathname." - and - "The special filename dot shall refer to the directory specified by - its predecessor." + Rationale: POSIX says such a filename must name a directory + <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>: + "A pathname that contains at least one non-<slash> character and that + ends with one or more trailing <slash> characters shall not be resolved + successfully unless the last pathname component before the trailing + <slash> characters names an existing directory" If the named file without the slash is not a directory, open() must fail with ENOTDIR. */ if (fd >= 0) |