diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/cloexec.c | 83 | ||||
| -rw-r--r-- | lib/cloexec.h | 38 | ||||
| -rw-r--r-- | lib/fcntl.in.h | 5 | ||||
| -rw-r--r-- | lib/gnulib.mk.in | 33 | ||||
| -rw-r--r-- | lib/open.c | 208 | ||||
| -rw-r--r-- | lib/stdio.in.h | 4 | ||||
| -rw-r--r-- | lib/stdlib.in.h | 17 |
7 files changed, 384 insertions, 4 deletions
diff --git a/lib/cloexec.c b/lib/cloexec.c new file mode 100644 index 00000000000..e34aef87976 --- /dev/null +++ b/lib/cloexec.c | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | /* cloexec.c - set or clear the close-on-exec descriptor flag | ||
| 2 | |||
| 3 | Copyright (C) 1991, 2004-2006, 2009-2017 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This program is free software: you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 3 of the License, or | ||
| 8 | (at your option) any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 17 | |||
| 18 | The code is taken from glibc/manual/llio.texi */ | ||
| 19 | |||
| 20 | #include <config.h> | ||
| 21 | |||
| 22 | #include "cloexec.h" | ||
| 23 | |||
| 24 | #include <errno.h> | ||
| 25 | #include <fcntl.h> | ||
| 26 | #include <unistd.h> | ||
| 27 | |||
| 28 | /* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, | ||
| 29 | or clear the flag if VALUE is false. | ||
| 30 | Return 0 on success, or -1 on error with 'errno' set. | ||
| 31 | |||
| 32 | Note that on MingW, this function does NOT protect DESC from being | ||
| 33 | inherited into spawned children. Instead, either use dup_cloexec | ||
| 34 | followed by closing the original DESC, or use interfaces such as | ||
| 35 | open or pipe2 that accept flags like O_CLOEXEC to create DESC | ||
| 36 | non-inheritable in the first place. */ | ||
| 37 | |||
| 38 | int | ||
| 39 | set_cloexec_flag (int desc, bool value) | ||
| 40 | { | ||
| 41 | #ifdef F_SETFD | ||
| 42 | |||
| 43 | int flags = fcntl (desc, F_GETFD, 0); | ||
| 44 | |||
| 45 | if (0 <= flags) | ||
| 46 | { | ||
| 47 | int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC); | ||
| 48 | |||
| 49 | if (flags == newflags | ||
| 50 | || fcntl (desc, F_SETFD, newflags) != -1) | ||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | return -1; | ||
| 55 | |||
| 56 | #else /* !F_SETFD */ | ||
| 57 | |||
| 58 | /* Use dup2 to reject invalid file descriptors; the cloexec flag | ||
| 59 | will be unaffected. */ | ||
| 60 | if (desc < 0) | ||
| 61 | { | ||
| 62 | errno = EBADF; | ||
| 63 | return -1; | ||
| 64 | } | ||
| 65 | if (dup2 (desc, desc) < 0) | ||
| 66 | /* errno is EBADF here. */ | ||
| 67 | return -1; | ||
| 68 | |||
| 69 | /* There is nothing we can do on this kind of platform. Punt. */ | ||
| 70 | return 0; | ||
| 71 | #endif /* !F_SETFD */ | ||
| 72 | } | ||
| 73 | |||
| 74 | |||
| 75 | /* Duplicates a file handle FD, while marking the copy to be closed | ||
| 76 | prior to exec or spawn. Returns -1 and sets errno if FD could not | ||
| 77 | be duplicated. */ | ||
| 78 | |||
| 79 | int | ||
| 80 | dup_cloexec (int fd) | ||
| 81 | { | ||
| 82 | return fcntl (fd, F_DUPFD_CLOEXEC, 0); | ||
| 83 | } | ||
diff --git a/lib/cloexec.h b/lib/cloexec.h new file mode 100644 index 00000000000..cdaf422226d --- /dev/null +++ b/lib/cloexec.h | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | /* cloexec.c - set or clear the close-on-exec descriptor flag | ||
| 2 | |||
| 3 | Copyright (C) 2004, 2009-2017 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This program is free software: you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 3 of the License, or | ||
| 8 | (at your option) any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 17 | |||
| 18 | */ | ||
| 19 | |||
| 20 | #include <stdbool.h> | ||
| 21 | |||
| 22 | /* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, | ||
| 23 | or clear the flag if VALUE is false. | ||
| 24 | Return 0 on success, or -1 on error with 'errno' set. | ||
| 25 | |||
| 26 | Note that on MingW, this function does NOT protect DESC from being | ||
| 27 | inherited into spawned children. Instead, either use dup_cloexec | ||
| 28 | followed by closing the original DESC, or use interfaces such as | ||
| 29 | open or pipe2 that accept flags like O_CLOEXEC to create DESC | ||
| 30 | non-inheritable in the first place. */ | ||
| 31 | |||
| 32 | int set_cloexec_flag (int desc, bool value); | ||
| 33 | |||
| 34 | /* Duplicates a file handle FD, while marking the copy to be closed | ||
| 35 | prior to exec or spawn. Returns -1 and sets errno if FD could not | ||
| 36 | be duplicated. */ | ||
| 37 | |||
| 38 | int dup_cloexec (int fd); | ||
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h index 4a1d40af6df..076d1ac34a7 100644 --- a/lib/fcntl.in.h +++ b/lib/fcntl.in.h | |||
| @@ -213,7 +213,10 @@ _GL_WARN_ON_USE (openat, "openat is not portable - " | |||
| 213 | #endif | 213 | #endif |
| 214 | 214 | ||
| 215 | #ifndef O_CLOEXEC | 215 | #ifndef O_CLOEXEC |
| 216 | # define O_CLOEXEC 0 | 216 | # define O_CLOEXEC 0x40000000 /* Try to not collide with system O_* flags. */ |
| 217 | # define GNULIB_defined_O_CLOEXEC 1 | ||
| 218 | #else | ||
| 219 | # define GNULIB_defined_O_CLOEXEC 0 | ||
| 217 | #endif | 220 | #endif |
| 218 | 221 | ||
| 219 | #ifndef O_DIRECT | 222 | #ifndef O_DIRECT |
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 30986b4ed7f..b6eb0f69539 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | # the same distribution terms as the rest of that program. | 21 | # the same distribution terms as the rest of that program. |
| 22 | # | 22 | # |
| 23 | # Generated by gnulib-tool. | 23 | # Generated by gnulib-tool. |
| 24 | # Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoastr dtotimespec dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime nstrftime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax symlink sys_stat sys_time tempname time time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimens vla warnings | 24 | # Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoastr dtotimespec dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime nstrftime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax symlink sys_stat sys_time tempname time time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimens vla warnings |
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | MOSTLYCLEANFILES += core *.stackdump | 27 | MOSTLYCLEANFILES += core *.stackdump |
| @@ -255,6 +255,7 @@ GNULIB_READ = @GNULIB_READ@ | |||
| 255 | GNULIB_READDIR = @GNULIB_READDIR@ | 255 | GNULIB_READDIR = @GNULIB_READDIR@ |
| 256 | GNULIB_READLINK = @GNULIB_READLINK@ | 256 | GNULIB_READLINK = @GNULIB_READLINK@ |
| 257 | GNULIB_READLINKAT = @GNULIB_READLINKAT@ | 257 | GNULIB_READLINKAT = @GNULIB_READLINKAT@ |
| 258 | GNULIB_REALLOCARRAY = @GNULIB_REALLOCARRAY@ | ||
| 258 | GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ | 259 | GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ |
| 259 | GNULIB_REALPATH = @GNULIB_REALPATH@ | 260 | GNULIB_REALPATH = @GNULIB_REALPATH@ |
| 260 | GNULIB_REMOVE = @GNULIB_REMOVE@ | 261 | GNULIB_REMOVE = @GNULIB_REMOVE@ |
| @@ -465,6 +466,7 @@ HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@ | |||
| 465 | HAVE_READDIR = @HAVE_READDIR@ | 466 | HAVE_READDIR = @HAVE_READDIR@ |
| 466 | HAVE_READLINK = @HAVE_READLINK@ | 467 | HAVE_READLINK = @HAVE_READLINK@ |
| 467 | HAVE_READLINKAT = @HAVE_READLINKAT@ | 468 | HAVE_READLINKAT = @HAVE_READLINKAT@ |
| 469 | HAVE_REALLOCARRAY = @HAVE_REALLOCARRAY@ | ||
| 468 | HAVE_REALPATH = @HAVE_REALPATH@ | 470 | HAVE_REALPATH = @HAVE_REALPATH@ |
| 469 | HAVE_RENAMEAT = @HAVE_RENAMEAT@ | 471 | HAVE_RENAMEAT = @HAVE_RENAMEAT@ |
| 470 | HAVE_REWINDDIR = @HAVE_REWINDDIR@ | 472 | HAVE_REWINDDIR = @HAVE_REWINDDIR@ |
| @@ -898,11 +900,13 @@ gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c = @gl_GNULIB_ENABLED_6099e973 | |||
| 898 | gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec = @gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec@ | 900 | gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec = @gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec@ |
| 899 | gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1 = @gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1@ | 901 | gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1 = @gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1@ |
| 900 | gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36 = @gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36@ | 902 | gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36 = @gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36@ |
| 903 | gl_GNULIB_ENABLED_cloexec = @gl_GNULIB_ENABLED_cloexec@ | ||
| 901 | gl_GNULIB_ENABLED_dirfd = @gl_GNULIB_ENABLED_dirfd@ | 904 | gl_GNULIB_ENABLED_dirfd = @gl_GNULIB_ENABLED_dirfd@ |
| 902 | gl_GNULIB_ENABLED_dosname = @gl_GNULIB_ENABLED_dosname@ | 905 | gl_GNULIB_ENABLED_dosname = @gl_GNULIB_ENABLED_dosname@ |
| 903 | gl_GNULIB_ENABLED_euidaccess = @gl_GNULIB_ENABLED_euidaccess@ | 906 | gl_GNULIB_ENABLED_euidaccess = @gl_GNULIB_ENABLED_euidaccess@ |
| 904 | gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@ | 907 | gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@ |
| 905 | gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@ | 908 | gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@ |
| 909 | gl_GNULIB_ENABLED_open = @gl_GNULIB_ENABLED_open@ | ||
| 906 | gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@ | 910 | gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@ |
| 907 | gl_LIBOBJS = @gl_LIBOBJS@ | 911 | gl_LIBOBJS = @gl_LIBOBJS@ |
| 908 | gl_LTLIBOBJS = @gl_LTLIBOBJS@ | 912 | gl_LTLIBOBJS = @gl_LTLIBOBJS@ |
| @@ -1085,6 +1089,18 @@ EXTRA_DIST += careadlinkat.h | |||
| 1085 | endif | 1089 | endif |
| 1086 | ## end gnulib module careadlinkat | 1090 | ## end gnulib module careadlinkat |
| 1087 | 1091 | ||
| 1092 | ## begin gnulib module cloexec | ||
| 1093 | ifeq (,$(OMIT_GNULIB_MODULE_cloexec)) | ||
| 1094 | |||
| 1095 | ifneq (,$(gl_GNULIB_ENABLED_cloexec)) | ||
| 1096 | libgnu_a_SOURCES += cloexec.c | ||
| 1097 | |||
| 1098 | endif | ||
| 1099 | EXTRA_DIST += cloexec.h | ||
| 1100 | |||
| 1101 | endif | ||
| 1102 | ## end gnulib module cloexec | ||
| 1103 | |||
| 1088 | ## begin gnulib module close-stream | 1104 | ## begin gnulib module close-stream |
| 1089 | ifeq (,$(OMIT_GNULIB_MODULE_close-stream)) | 1105 | ifeq (,$(OMIT_GNULIB_MODULE_close-stream)) |
| 1090 | 1106 | ||
| @@ -1817,6 +1833,19 @@ EXTRA_DIST += strftime.h | |||
| 1817 | endif | 1833 | endif |
| 1818 | ## end gnulib module nstrftime | 1834 | ## end gnulib module nstrftime |
| 1819 | 1835 | ||
| 1836 | ## begin gnulib module open | ||
| 1837 | ifeq (,$(OMIT_GNULIB_MODULE_open)) | ||
| 1838 | |||
| 1839 | ifneq (,$(gl_GNULIB_ENABLED_open)) | ||
| 1840 | |||
| 1841 | endif | ||
| 1842 | EXTRA_DIST += open.c | ||
| 1843 | |||
| 1844 | EXTRA_libgnu_a_SOURCES += open.c | ||
| 1845 | |||
| 1846 | endif | ||
| 1847 | ## end gnulib module open | ||
| 1848 | |||
| 1820 | ## begin gnulib module openat-h | 1849 | ## begin gnulib module openat-h |
| 1821 | ifeq (,$(OMIT_GNULIB_MODULE_openat-h)) | 1850 | ifeq (,$(OMIT_GNULIB_MODULE_openat-h)) |
| 1822 | 1851 | ||
| @@ -2311,6 +2340,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ | |||
| 2311 | -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \ | 2340 | -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \ |
| 2312 | -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \ | 2341 | -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \ |
| 2313 | -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \ | 2342 | -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \ |
| 2343 | -e 's/@''GNULIB_REALLOCARRAY''@/$(GNULIB_REALLOCARRAY)/g' \ | ||
| 2314 | -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \ | 2344 | -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \ |
| 2315 | -e 's/@''GNULIB_RPMATCH''@/$(GNULIB_RPMATCH)/g' \ | 2345 | -e 's/@''GNULIB_RPMATCH''@/$(GNULIB_RPMATCH)/g' \ |
| 2316 | -e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \ | 2346 | -e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \ |
| @@ -2341,6 +2371,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ | |||
| 2341 | -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|g' \ | 2371 | -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|g' \ |
| 2342 | -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \ | 2372 | -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \ |
| 2343 | -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \ | 2373 | -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \ |
| 2374 | -e 's|@''HAVE_REALLOCARRAY''@|$(HAVE_REALLOCARRAY)|g' \ | ||
| 2344 | -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \ | 2375 | -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \ |
| 2345 | -e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \ | 2376 | -e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \ |
| 2346 | -e 's|@''HAVE_SECURE_GETENV''@|$(HAVE_SECURE_GETENV)|g' \ | 2377 | -e 's|@''HAVE_SECURE_GETENV''@|$(HAVE_SECURE_GETENV)|g' \ |
diff --git a/lib/open.c b/lib/open.c new file mode 100644 index 00000000000..c62f02b1452 --- /dev/null +++ b/lib/open.c | |||
| @@ -0,0 +1,208 @@ | |||
| 1 | /* Open a descriptor to a file. | ||
| 2 | Copyright (C) 2007-2017 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 3 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | ||
| 16 | |||
| 17 | /* Written by Bruno Haible <bruno@clisp.org>, 2007. */ | ||
| 18 | |||
| 19 | /* If the user's config.h happens to include <fcntl.h>, let it include only | ||
| 20 | the system's <fcntl.h> here, so that orig_open doesn't recurse to | ||
| 21 | rpl_open. */ | ||
| 22 | #define __need_system_fcntl_h | ||
| 23 | #include <config.h> | ||
| 24 | |||
| 25 | /* Get the original definition of open. It might be defined as a macro. */ | ||
| 26 | #include <fcntl.h> | ||
| 27 | #include <sys/types.h> | ||
| 28 | #undef __need_system_fcntl_h | ||
| 29 | |||
| 30 | static int | ||
| 31 | orig_open (const char *filename, int flags, mode_t mode) | ||
| 32 | { | ||
| 33 | return open (filename, flags, mode); | ||
| 34 | } | ||
| 35 | |||
| 36 | /* Specification. */ | ||
| 37 | /* Write "fcntl.h" here, not <fcntl.h>, otherwise OSF/1 5.1 DTK cc eliminates | ||
| 38 | this include because of the preliminary #include <fcntl.h> above. */ | ||
| 39 | #include "fcntl.h" | ||
| 40 | |||
| 41 | #include "cloexec.h" | ||
| 42 | |||
| 43 | #include <errno.h> | ||
| 44 | #include <stdarg.h> | ||
| 45 | #include <string.h> | ||
| 46 | #include <sys/types.h> | ||
| 47 | #include <sys/stat.h> | ||
| 48 | #include <unistd.h> | ||
| 49 | |||
| 50 | #ifndef REPLACE_OPEN_DIRECTORY | ||
| 51 | # define REPLACE_OPEN_DIRECTORY 0 | ||
| 52 | #endif | ||
| 53 | |||
| 54 | int | ||
| 55 | open (const char *filename, int flags, ...) | ||
| 56 | { | ||
| 57 | /* 0 = unknown, 1 = yes, -1 = no. */ | ||
| 58 | #if GNULIB_defined_O_CLOEXEC | ||
| 59 | int have_cloexec = -1; | ||
| 60 | #else | ||
| 61 | static int have_cloexec; | ||
| 62 | #endif | ||
| 63 | |||
| 64 | mode_t mode; | ||
| 65 | int fd; | ||
| 66 | |||
| 67 | mode = 0; | ||
| 68 | if (flags & O_CREAT) | ||
| 69 | { | ||
| 70 | va_list arg; | ||
| 71 | va_start (arg, flags); | ||
| 72 | |||
| 73 | /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 | ||
| 74 | creates crashing code when 'mode_t' is smaller than 'int'. */ | ||
| 75 | mode = va_arg (arg, PROMOTED_MODE_T); | ||
| 76 | |||
| 77 | va_end (arg); | ||
| 78 | } | ||
| 79 | |||
| 80 | #if GNULIB_defined_O_NONBLOCK | ||
| 81 | /* The only known platform that lacks O_NONBLOCK is mingw, but it | ||
| 82 | also lacks named pipes and Unix sockets, which are the only two | ||
| 83 | file types that require non-blocking handling in open(). | ||
| 84 | Therefore, it is safe to ignore O_NONBLOCK here. It is handy | ||
| 85 | that mingw also lacks openat(), so that is also covered here. */ | ||
| 86 | flags &= ~O_NONBLOCK; | ||
| 87 | #endif | ||
| 88 | |||
| 89 | #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | ||
| 90 | if (strcmp (filename, "/dev/null") == 0) | ||
| 91 | filename = "NUL"; | ||
| 92 | #endif | ||
| 93 | |||
| 94 | #if OPEN_TRAILING_SLASH_BUG | ||
| 95 | /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR | ||
| 96 | is specified, then fail. | ||
| 97 | Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> | ||
| 98 | says that | ||
| 99 | "A pathname that contains at least one non-slash character and that | ||
| 100 | ends with one or more trailing slashes shall be resolved as if a | ||
| 101 | single dot character ( '.' ) were appended to the pathname." | ||
| 102 | and | ||
| 103 | "The special filename dot shall refer to the directory specified by | ||
| 104 | its predecessor." | ||
| 105 | If the named file already exists as a directory, then | ||
| 106 | - if O_CREAT is specified, open() must fail because of the semantics | ||
| 107 | of O_CREAT, | ||
| 108 | - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX | ||
| 109 | <http://www.opengroup.org/susv3/functions/open.html> says that it | ||
| 110 | fails with errno = EISDIR in this case. | ||
| 111 | If the named file does not exist or does not name a directory, then | ||
| 112 | - if O_CREAT is specified, open() must fail since open() cannot create | ||
| 113 | directories, | ||
| 114 | - if O_WRONLY or O_RDWR is specified, open() must fail because the | ||
| 115 | file does not contain a '.' directory. */ | ||
| 116 | if (flags & (O_CREAT | O_WRONLY | O_RDWR)) | ||
| 117 | { | ||
| 118 | size_t len = strlen (filename); | ||
| 119 | if (len > 0 && filename[len - 1] == '/') | ||
| 120 | { | ||
| 121 | errno = EISDIR; | ||
| 122 | return -1; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | #endif | ||
| 126 | |||
| 127 | fd = orig_open (filename, | ||
| 128 | flags & ~(have_cloexec <= 0 ? O_CLOEXEC : 0), mode); | ||
| 129 | |||
| 130 | if (flags & O_CLOEXEC) | ||
| 131 | { | ||
| 132 | if (! have_cloexec) | ||
| 133 | { | ||
| 134 | if (0 <= fd) | ||
| 135 | have_cloexec = 1; | ||
| 136 | else if (errno == EINVAL) | ||
| 137 | { | ||
| 138 | fd = orig_open (filename, flags & ~O_CLOEXEC, mode); | ||
| 139 | have_cloexec = -1; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | if (have_cloexec < 0 && 0 <= fd) | ||
| 143 | set_cloexec_flag (fd, true); | ||
| 144 | } | ||
| 145 | |||
| 146 | |||
| 147 | #if REPLACE_FCHDIR | ||
| 148 | /* Implementing fchdir and fdopendir requires the ability to open a | ||
| 149 | directory file descriptor. If open doesn't support that (as on | ||
| 150 | mingw), we use a dummy file that behaves the same as directories | ||
| 151 | on Linux (ie. always reports EOF on attempts to read()), and | ||
| 152 | override fstat() in fchdir.c to hide the fact that we have a | ||
| 153 | dummy. */ | ||
| 154 | if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES | ||
| 155 | && ((flags & O_ACCMODE) == O_RDONLY | ||
| 156 | || (O_SEARCH != O_RDONLY && (flags & O_ACCMODE) == O_SEARCH))) | ||
| 157 | { | ||
| 158 | struct stat statbuf; | ||
| 159 | if (stat (filename, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) | ||
| 160 | { | ||
| 161 | /* Maximum recursion depth of 1. */ | ||
| 162 | fd = open ("/dev/null", flags, mode); | ||
| 163 | if (0 <= fd) | ||
| 164 | fd = _gl_register_fd (fd, filename); | ||
| 165 | } | ||
| 166 | else | ||
| 167 | errno = EACCES; | ||
| 168 | } | ||
| 169 | #endif | ||
| 170 | |||
| 171 | #if OPEN_TRAILING_SLASH_BUG | ||
| 172 | /* If the filename ends in a slash and fd does not refer to a directory, | ||
| 173 | then fail. | ||
| 174 | Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> | ||
| 175 | says that | ||
| 176 | "A pathname that contains at least one non-slash character and that | ||
| 177 | ends with one or more trailing slashes shall be resolved as if a | ||
| 178 | single dot character ( '.' ) were appended to the pathname." | ||
| 179 | and | ||
| 180 | "The special filename dot shall refer to the directory specified by | ||
| 181 | its predecessor." | ||
| 182 | If the named file without the slash is not a directory, open() must fail | ||
| 183 | with ENOTDIR. */ | ||
| 184 | if (fd >= 0) | ||
| 185 | { | ||
| 186 | /* We know len is positive, since open did not fail with ENOENT. */ | ||
| 187 | size_t len = strlen (filename); | ||
| 188 | if (filename[len - 1] == '/') | ||
| 189 | { | ||
| 190 | struct stat statbuf; | ||
| 191 | |||
| 192 | if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) | ||
| 193 | { | ||
| 194 | close (fd); | ||
| 195 | errno = ENOTDIR; | ||
| 196 | return -1; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | } | ||
| 200 | #endif | ||
| 201 | |||
| 202 | #if REPLACE_FCHDIR | ||
| 203 | if (!REPLACE_OPEN_DIRECTORY && 0 <= fd) | ||
| 204 | fd = _gl_register_fd (fd, filename); | ||
| 205 | #endif | ||
| 206 | |||
| 207 | return fd; | ||
| 208 | } | ||
diff --git a/lib/stdio.in.h b/lib/stdio.in.h index d706377f984..b714c54a544 100644 --- a/lib/stdio.in.h +++ b/lib/stdio.in.h | |||
| @@ -111,9 +111,9 @@ | |||
| 111 | #define _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM(formatstring_parameter, first_argument) \ | 111 | #define _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM(formatstring_parameter, first_argument) \ |
| 112 | _GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument)) | 112 | _GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument)) |
| 113 | 113 | ||
| 114 | /* Solaris 10 declares renameat in <unistd.h>, not in <stdio.h>. */ | 114 | /* Solaris 10 and NetBSD 7.0 declare renameat in <unistd.h>, not in <stdio.h>. */ |
| 115 | /* But in any case avoid namespace pollution on glibc systems. */ | 115 | /* But in any case avoid namespace pollution on glibc systems. */ |
| 116 | #if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && defined __sun \ | 116 | #if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && (defined __sun || defined __NetBSD__) \ |
| 117 | && ! defined __GLIBC__ | 117 | && ! defined __GLIBC__ |
| 118 | # include <unistd.h> | 118 | # include <unistd.h> |
| 119 | #endif | 119 | #endif |
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index b5cf9d36958..c6e68fddc48 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h | |||
| @@ -765,6 +765,23 @@ _GL_WARN_ON_USE (realloc, "realloc is not POSIX compliant everywhere - " | |||
| 765 | "use gnulib module realloc-posix for portability"); | 765 | "use gnulib module realloc-posix for portability"); |
| 766 | #endif | 766 | #endif |
| 767 | 767 | ||
| 768 | |||
| 769 | #if @GNULIB_REALLOCARRAY@ | ||
| 770 | # if ! @HAVE_REALLOCARRAY@ | ||
| 771 | _GL_FUNCDECL_SYS (reallocarray, void *, | ||
| 772 | (void *ptr, size_t nmemb, size_t size)); | ||
| 773 | # endif | ||
| 774 | _GL_CXXALIAS_SYS (reallocarray, void *, | ||
| 775 | (void *ptr, size_t nmemb, size_t size)); | ||
| 776 | _GL_CXXALIASWARN (reallocarray); | ||
| 777 | #elif defined GNULIB_POSIXCHECK | ||
| 778 | # undef reallocarray | ||
| 779 | # if HAVE_RAW_DECL_REALLOCARRAY | ||
| 780 | _GL_WARN_ON_USE (reallocarray, "reallocarray is not portable - " | ||
| 781 | "use gnulib module reallocarray for portability"); | ||
| 782 | # endif | ||
| 783 | #endif | ||
| 784 | |||
| 768 | #if @GNULIB_REALPATH@ | 785 | #if @GNULIB_REALPATH@ |
| 769 | # if @REPLACE_REALPATH@ | 786 | # if @REPLACE_REALPATH@ |
| 770 | # if !(defined __cplusplus && defined GNULIB_NAMESPACE) | 787 | # if !(defined __cplusplus && defined GNULIB_NAMESPACE) |