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) {