From 4810e2dc1d9b1bf84da97d7869f7ad8743b3b3c4 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 24 Sep 2011 02:08:13 +0200 Subject: [PATCH] New module 'dup'. * lib/unistd.in.h (dup): Declare only if the 'dup' module is in use. Allow replacement. * lib/dup.c: New file. * lib/fchdir.c (rpl_dup): Remove function. * m4/dup.m4: New file. * m4/fchdir.m4 (gl_FUNC_FCHDIR): Don't set REPLACE_DUP here. * m4/unistd_h.m4 (gl_UNISTD_H): Test whether 'dup' is declared. (gl_UNISTD_H_DEFAULTS): Initialize GNULIB_DUP. * modules/unistd (Makefile.am): Substitute GNULIB_DUP. * modules/dup: New file. * tests/test-unistd-c++.cc: Check the signature of 'dup' only if the 'dup' module is in use. * modules/fdopendir (Depends-on): Add dup. * modules/fdutimensat-tests (Depends-on): Likewise. * modules/fts (Depends-on): Likewise. * modules/futimens-tests (Depends-on): Likewise. * modules/posix_spawnp-tests (Depends-on): Likewise. * modules/unistd-safer-tests (Depends-on): Likewise. * modules/utimens-tests (Depends-on): Likewise. * doc/posix-functions/dup.texi: Mention the new module and the problem on MSVC. --- ChangeLog | 25 ++++++++++++++++++ doc/posix-functions/dup.texi | 5 +++- lib/dup.c | 61 ++++++++++++++++++++++++++++++++++++++++++++ lib/fchdir.c | 13 ---------- lib/unistd.in.h | 20 ++++++++++----- m4/dup.m4 | 52 +++++++++++++++++++++++++++++++++++++ m4/fchdir.m4 | 3 +-- m4/unistd_h.m4 | 5 ++-- modules/dup | 29 +++++++++++++++++++++ modules/fdopendir | 1 + modules/fdutimensat-tests | 1 + modules/fts | 1 + modules/futimens-tests | 1 + modules/posix_spawnp-tests | 1 + modules/unistd | 1 + modules/unistd-safer-tests | 1 + modules/utimens-tests | 1 + tests/test-unistd-c++.cc | 2 ++ 18 files changed, 199 insertions(+), 24 deletions(-) create mode 100644 lib/dup.c create mode 100644 m4/dup.m4 create mode 100644 modules/dup diff --git a/ChangeLog b/ChangeLog index ae72da716..a81731ea5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,30 @@ 2011-09-23 Bruno Haible + New module 'dup'. + * lib/unistd.in.h (dup): Declare only if the 'dup' module is in use. + Allow replacement. + * lib/dup.c: New file. + * lib/fchdir.c (rpl_dup): Remove function. + * m4/dup.m4: New file. + * m4/fchdir.m4 (gl_FUNC_FCHDIR): Don't set REPLACE_DUP here. + * m4/unistd_h.m4 (gl_UNISTD_H): Test whether 'dup' is declared. + (gl_UNISTD_H_DEFAULTS): Initialize GNULIB_DUP. + * modules/unistd (Makefile.am): Substitute GNULIB_DUP. + * modules/dup: New file. + * tests/test-unistd-c++.cc: Check the signature of 'dup' only if the + 'dup' module is in use. + * modules/fdopendir (Depends-on): Add dup. + * modules/fdutimensat-tests (Depends-on): Likewise. + * modules/fts (Depends-on): Likewise. + * modules/futimens-tests (Depends-on): Likewise. + * modules/posix_spawnp-tests (Depends-on): Likewise. + * modules/unistd-safer-tests (Depends-on): Likewise. + * modules/utimens-tests (Depends-on): Likewise. + * doc/posix-functions/dup.texi: Mention the new module and the problem + on MSVC. + +2011-09-23 Bruno Haible + getdtablesize: Support for MSVC 9. * lib/getdtablesize.c: Include msvc-inval.h. (_setmaxstdio_nothrow): New function. diff --git a/doc/posix-functions/dup.texi b/doc/posix-functions/dup.texi index b67fc1f54..3b4c63f22 100644 --- a/doc/posix-functions/dup.texi +++ b/doc/posix-functions/dup.texi @@ -4,10 +4,13 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/dup.html} -Gnulib module: --- +Gnulib module: dup Portability problems fixed by Gnulib: @itemize +@item +This function crashes when invoked with invalid arguments on some platforms: +MSVC 9. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/dup.c b/lib/dup.c new file mode 100644 index 000000000..4a75a0cf6 --- /dev/null +++ b/lib/dup.c @@ -0,0 +1,61 @@ +/* Duplicate an open file descriptor. + + Copyright (C) 2011 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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 . */ + +#include + +/* Specification. */ +#include + +#include + +#include "msvc-inval.h" + +#undef dup + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static inline int +dup_nothrow (int fd) +{ + int result; + + TRY_MSVC_INVAL + { + result = dup (fd); + } + CATCH_MSVC_INVAL + { + result = -1; + errno = EBADF; + } + DONE_MSVC_INVAL; + + return result; +} +#else +# define dup_nothrow dup +#endif + +int +rpl_dup (int fd) +{ + int result = dup_nothrow (fd); +#if REPLACE_FCHDIR + if (result >= 0) + result = _gl_register_dup (fd, result); +#endif + return result; +} diff --git a/lib/fchdir.c b/lib/fchdir.c index e13ba2249..63c287b20 100644 --- a/lib/fchdir.c +++ b/lib/fchdir.c @@ -211,19 +211,6 @@ rpl_fstat (int fd, struct stat *statbuf) } #endif -/* Override dup(), to keep track of open file descriptors. */ - -int -rpl_dup (int oldfd) -#undef dup -{ - int newfd = dup (oldfd); - - if (0 <= newfd) - newfd = _gl_register_dup (oldfd, newfd); - return newfd; -} - /* Implement fchdir() in terms of chdir(). */ diff --git a/lib/unistd.in.h b/lib/unistd.in.h index bb514dbff..60a7530b4 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -301,16 +301,24 @@ _GL_WARN_ON_USE (close, "close does not portably work on sockets - " #endif -#if @REPLACE_DUP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define dup rpl_dup -# endif +#if @GNULIB_DUP@ +# if @REPLACE_DUP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dup rpl_dup +# endif _GL_FUNCDECL_RPL (dup, int, (int oldfd)); _GL_CXXALIAS_RPL (dup, int, (int oldfd)); -#else +# else _GL_CXXALIAS_SYS (dup, int, (int oldfd)); -#endif +# endif _GL_CXXALIASWARN (dup); +#elif defined GNULIB_POSIXCHECK +# undef dup +# if HAVE_RAW_DECL_DUP +_GL_WARN_ON_USE (dup, "dup is unportable - " + "use gnulib module dup for portability"); +# endif +#endif #if @GNULIB_DUP2@ diff --git a/m4/dup.m4 b/m4/dup.m4 new file mode 100644 index 000000000..8f2ec8f7b --- /dev/null +++ b/m4/dup.m4 @@ -0,0 +1,52 @@ +# dup.m4 serial 1 +dnl Copyright (C) 2011 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_DUP], +[ + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_CHECK_HEADERS_ONCE([unistd.h]) + AC_CACHE_CHECK([whether dup supports bad arguments], [gl_cv_func_dup_works], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ +#if HAVE_UNISTD_H +# include +#else +# include +#endif +#include +]], + [[if (dup (-1) != -1) + return 1; + if (errno != EBADF) + return 2; + return 0; + ]])], + [gl_cv_func_dup_works=yes], + [gl_cv_func_dup_works=no], + [case "$host_os" in + mingw*) gl_cv_func_dup_works="guessing no" ;; + *) gl_cv_func_dup_works="guessing yes" ;; + esac + ]) + ]) + case "$gl_cv_func_dup_works" in + *no) REPLACE_DUP=1 ;; + esac + dnl Replace dup() for supporting the gnulib-defined fchdir() function, + dnl to keep fchdir's bookkeeping up-to-date. + m4_ifdef([gl_FUNC_FCHDIR], [ + gl_TEST_FCHDIR + if test $HAVE_FCHDIR = 0; then + REPLACE_DUP=1 + fi + ]) +]) + +# Prerequisites of lib/dup.c. +AC_DEFUN([gl_PREREQ_DUP], [ + AC_REQUIRE([AC_C_INLINE]) +]) diff --git a/m4/fchdir.m4 b/m4/fchdir.m4 index e742a0732..602aad925 100644 --- a/m4/fchdir.m4 +++ b/m4/fchdir.m4 @@ -1,4 +1,4 @@ -# fchdir.m4 serial 18 +# fchdir.m4 serial 19 dnl Copyright (C) 2006-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -24,7 +24,6 @@ AC_DEFUN([gl_FUNC_FCHDIR], dnl We must also replace anything that can manipulate a directory fd, dnl to keep our bookkeeping up-to-date. We don't have to replace dnl fstatat, since no platform has fstatat but lacks fchdir. - REPLACE_DUP=1 AC_CACHE_CHECK([whether open can visit directories], [gl_cv_func_open_directory_works], [AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4 index 79ae9e966..57c8094e4 100644 --- a/m4/unistd_h.m4 +++ b/m4/unistd_h.m4 @@ -1,4 +1,4 @@ -# unistd_h.m4 serial 60 +# unistd_h.m4 serial 61 dnl Copyright (C) 2006-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -39,7 +39,7 @@ AC_DEFUN([gl_UNISTD_H], # include # endif #endif - ]], [chdir chown dup2 dup3 environ euidaccess faccessat fchdir fchownat + ]], [chdir chown dup dup2 dup3 environ euidaccess faccessat fchdir fchownat fdatasync fsync ftruncate getcwd getdomainname getdtablesize getgroups gethostname getlogin getlogin_r getpagesize getusershell setusershell endusershell group_member lchown link linkat lseek pipe pipe2 pread pwrite @@ -61,6 +61,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], GNULIB_CHDIR=0; AC_SUBST([GNULIB_CHDIR]) GNULIB_CHOWN=0; AC_SUBST([GNULIB_CHOWN]) GNULIB_CLOSE=0; AC_SUBST([GNULIB_CLOSE]) + GNULIB_DUP=0; AC_SUBST([GNULIB_DUP]) GNULIB_DUP2=0; AC_SUBST([GNULIB_DUP2]) GNULIB_DUP3=0; AC_SUBST([GNULIB_DUP3]) GNULIB_ENVIRON=0; AC_SUBST([GNULIB_ENVIRON]) diff --git a/modules/dup b/modules/dup new file mode 100644 index 000000000..85f295dd9 --- /dev/null +++ b/modules/dup @@ -0,0 +1,29 @@ +Description: +dup() function: duplicate an open file descriptor. + +Files: +lib/dup.c +m4/dup.m4 + +Depends-on: +unistd +msvc-inval [test $REPLACE_DUP = 1] + +configure.ac: +gl_FUNC_DUP +if test $REPLACE_DUP = 1; then + AC_LIBOBJ([dup]) + gl_PREREQ_DUP +fi +gl_UNISTD_MODULE_INDICATOR([dup]) + +Makefile.am: + +Include: + + +License: +LGPLv2+ + +Maintainer: +Bruno Haible diff --git a/modules/fdopendir b/modules/fdopendir index 41695b99a..94168faa0 100644 --- a/modules/fdopendir +++ b/modules/fdopendir @@ -10,6 +10,7 @@ m4/fdopendir.m4 Depends-on: dirent extensions +dup [test $HAVE_FDOPENDIR = 0] errno [test $HAVE_FDOPENDIR = 0] fchdir [test $HAVE_FDOPENDIR = 0] openat-die [test $HAVE_FDOPENDIR = 0] diff --git a/modules/fdutimensat-tests b/modules/fdutimensat-tests index 446762bc1..8c1dc3909 100644 --- a/modules/fdutimensat-tests +++ b/modules/fdutimensat-tests @@ -10,6 +10,7 @@ tests/macros.h Depends-on: ignore-value timespec +dup usleep utimecmp diff --git a/modules/fts b/modules/fts index 9869c941d..8aae6d89f 100644 --- a/modules/fts +++ b/modules/fts @@ -14,6 +14,7 @@ cycle-check d-ino d-type dirent-safer +dup fchdir fcntl-h fcntl-safer diff --git a/modules/futimens-tests b/modules/futimens-tests index 356f67e2d..bfd65f6b9 100644 --- a/modules/futimens-tests +++ b/modules/futimens-tests @@ -9,6 +9,7 @@ tests/macros.h Depends-on: ignore-value timespec +dup usleep utimecmp diff --git a/modules/posix_spawnp-tests b/modules/posix_spawnp-tests index 49465d856..6363585d2 100644 --- a/modules/posix_spawnp-tests +++ b/modules/posix_spawnp-tests @@ -19,6 +19,7 @@ sigprocmask stdbool unistd sys_wait +dup configure.ac: AC_EGREP_CPP([notposix], [[ diff --git a/modules/unistd b/modules/unistd index 3d3173450..633ba3198 100644 --- a/modules/unistd +++ b/modules/unistd @@ -33,6 +33,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \ -e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \ -e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \ + -e 's/@''GNULIB_DUP''@/$(GNULIB_DUP)/g' \ -e 's/@''GNULIB_DUP2''@/$(GNULIB_DUP2)/g' \ -e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \ -e 's/@''GNULIB_ENVIRON''@/$(GNULIB_ENVIRON)/g' \ diff --git a/modules/unistd-safer-tests b/modules/unistd-safer-tests index d8519a656..03e753c45 100644 --- a/modules/unistd-safer-tests +++ b/modules/unistd-safer-tests @@ -5,6 +5,7 @@ tests/macros.h Depends-on: binary-io cloexec +dup fd-safer-flag msvc-nothrow stdbool diff --git a/modules/utimens-tests b/modules/utimens-tests index 7335c5df5..4d5d1f576 100644 --- a/modules/utimens-tests +++ b/modules/utimens-tests @@ -8,6 +8,7 @@ tests/test-utimens.c tests/macros.h Depends-on: +dup ignore-value symlink timespec diff --git a/tests/test-unistd-c++.cc b/tests/test-unistd-c++.cc index b82b0e81d..e9244b32e 100644 --- a/tests/test-unistd-c++.cc +++ b/tests/test-unistd-c++.cc @@ -36,7 +36,9 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::chown, int, (const char *, uid_t, gid_t)); SIGNATURE_CHECK (GNULIB_NAMESPACE::close, int, (int)); #endif +#if GNULIB_TEST_DUP SIGNATURE_CHECK (GNULIB_NAMESPACE::dup, int, (int)); +#endif #if GNULIB_TEST_DUP2 SIGNATURE_CHECK (GNULIB_NAMESPACE::dup2, int, (int, int)); -- 2.11.0