changeset 15760:45b9be95a543

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.
author Bruno Haible <bruno@clisp.org>
date Sat, 24 Sep 2011 02:08:13 +0200
parents 4583838a5587
children 19b1b0022807
files ChangeLog doc/posix-functions/dup.texi lib/dup.c lib/fchdir.c lib/unistd.in.h m4/dup.m4 m4/fchdir.m4 m4/unistd_h.m4 modules/dup modules/fdopendir modules/fdutimensat-tests modules/fts modules/futimens-tests modules/posix_spawnp-tests modules/unistd modules/unistd-safer-tests modules/utimens-tests tests/test-unistd-c++.cc
diffstat 18 files changed, 199 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2011-09-23  Bruno Haible  <bruno@clisp.org>
+
+	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  <bruno@clisp.org>
 
 	getdtablesize: Support for MSVC 9.
--- 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:
new file mode 100644
--- /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 <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+
+#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;
+}
--- a/lib/fchdir.c
+++ b/lib/fchdir.c
@@ -211,19 +211,6 @@
 }
 #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().  */
 
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -301,16 +301,24 @@
 #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
+_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
-_GL_CXXALIASWARN (dup);
 
 
 #if @GNULIB_DUP2@
new file mode 100644
--- /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 <unistd.h>
+#else
+# include <io.h>
+#endif
+#include <errno.h>
+]],
+          [[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])
+])
--- 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 @@
     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 <fcntl.h>
--- 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 @@
 #  include <io.h>
 # 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 @@
   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])
new file mode 100644
--- /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:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible
--- a/modules/fdopendir
+++ b/modules/fdopendir
@@ -10,6 +10,7 @@
 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]
--- a/modules/fdutimensat-tests
+++ b/modules/fdutimensat-tests
@@ -10,6 +10,7 @@
 Depends-on:
 ignore-value
 timespec
+dup
 usleep
 utimecmp
 
--- a/modules/fts
+++ b/modules/fts
@@ -14,6 +14,7 @@
 d-ino
 d-type
 dirent-safer
+dup
 fchdir
 fcntl-h
 fcntl-safer
--- a/modules/futimens-tests
+++ b/modules/futimens-tests
@@ -9,6 +9,7 @@
 Depends-on:
 ignore-value
 timespec
+dup
 usleep
 utimecmp
 
--- a/modules/posix_spawnp-tests
+++ b/modules/posix_spawnp-tests
@@ -19,6 +19,7 @@
 stdbool
 unistd
 sys_wait
+dup
 
 configure.ac:
 AC_EGREP_CPP([notposix], [[
--- a/modules/unistd
+++ b/modules/unistd
@@ -33,6 +33,7 @@
 	      -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' \
--- a/modules/unistd-safer-tests
+++ b/modules/unistd-safer-tests
@@ -5,6 +5,7 @@
 Depends-on:
 binary-io
 cloexec
+dup
 fd-safer-flag
 msvc-nothrow
 stdbool
--- a/modules/utimens-tests
+++ b/modules/utimens-tests
@@ -8,6 +8,7 @@
 tests/macros.h
 
 Depends-on:
+dup
 ignore-value
 symlink
 timespec
--- a/tests/test-unistd-c++.cc
+++ b/tests/test-unistd-c++.cc
@@ -36,7 +36,9 @@
 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));