dup2: work around mingw and cygwin 1.5 bug
authorEric Blake <ebb9@byu.net>
Tue, 21 Jul 2009 12:48:26 +0000 (06:48 -0600)
committerEric Blake <ebb9@byu.net>
Tue, 21 Jul 2009 13:08:06 +0000 (07:08 -0600)
* m4/dup2.m4 (gl_FUNC_DUP2): Detect mingw bug.
* m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Add witness.
* modules/unistd (Makefile.am): Substitute it.
* lib/unistd.in.h (dup2): Declare the replacement.
* lib/dup2.c (dup2) [REPLACE_DUP2]: Implement it.
* doc/posix-functions/dup2.texi (dup2): Document the bugs.
* lib/fchdir.c (rpl_dup2): Don't collide with mingw replacement.
* modules/execute (Depends-on): Add dup2.
* modules/fseterr (Depends-on): Likewise.
* modules/pipe (Depends-on): Likewise.
* modules/posix_spawn-internal (Depends-on): Likewise.

Signed-off-by: Eric Blake <ebb9@byu.net>
12 files changed:
ChangeLog
doc/posix-functions/dup2.texi
lib/dup2.c
lib/fchdir.c
lib/unistd.in.h
m4/dup2.m4
m4/unistd_h.m4
modules/execute
modules/fseterr
modules/pipe
modules/posix_spawn-internal
modules/unistd

index 36248ab..d87cc8e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2009-07-21  Eric Blake  <ebb9@byu.net>
+
+       dup2: work around mingw and cygwin 1.5 bug
+       * m4/dup2.m4 (gl_FUNC_DUP2): Detect mingw bug.
+       * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Add witness.
+       * modules/unistd (Makefile.am): Substitute it.
+       * lib/unistd.in.h (dup2): Declare the replacement.
+       * lib/dup2.c (dup2) [REPLACE_DUP2]: Implement it.
+       * doc/posix-functions/dup2.texi (dup2): Document the bugs.
+       * lib/fchdir.c (rpl_dup2): Don't collide with mingw replacement.
+       * modules/execute (Depends-on): Add dup2.
+       * modules/fseterr (Depends-on): Likewise.
+       * modules/pipe (Depends-on): Likewise.
+       * modules/posix_spawn-internal (Depends-on): Likewise.
+
 2009-07-21  Bruno Haible  <bruno@clisp.org>
 
        * modules/.gitattributes: New file.
index 42d22e5..bfaff38 100644 (file)
@@ -9,6 +9,14 @@ Gnulib module: dup2
 Portability problems fixed by Gnulib:
 @itemize
 @item
+This function always returns 0 for success on some platforms:
+mingw.
+
+@item
+This function returns 0 for dup2 (1, 1) on some platforms:
+Cygwin 1.5.x.
+
+@item
 This function is missing on some older platforms.
 @end itemize
 
index 0999082..e5d3de4 100644 (file)
@@ -1,6 +1,7 @@
 /* Duplicate an open file descriptor to a specified file descriptor.
 
-   Copyright (C) 1999, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2004, 2005, 2006, 2007, 2009 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
 #include <errno.h>
 #include <fcntl.h>
 
-#ifndef F_DUPFD
+#if REPLACE_DUP2
+/* On mingw, dup2 exists, but always returns 0 for success.  */
+int
+dup2 (int fd, int desired_fd)
+#undef dup2
+{
+  int result = dup2 (fd, desired_fd);
+  if (result == 0)
+    result = desired_fd;
+  return result;
+}
+
+#else /* !REPLACE_DUP2 */
+/* On older platforms, dup2 did not exist.  */
+
+# ifndef F_DUPFD
 static int
 dupfd (int fd, int desired_fd)
 {
@@ -41,7 +57,7 @@ dupfd (int fd, int desired_fd)
       return r;
     }
 }
-#endif
+# endif
 
 int
 dup2 (int fd, int desired_fd)
@@ -49,9 +65,10 @@ dup2 (int fd, int desired_fd)
   if (fd == desired_fd)
     return fd;
   close (desired_fd);
-#ifdef F_DUPFD
+# ifdef F_DUPFD
   return fcntl (fd, F_DUPFD, desired_fd);
-#else
+# else
   return dupfd (fd, desired_fd);
-#endif
+# endif
 }
+#endif /* !REPLACE_DUP2 */
index 969e984..cc2fa63 100644 (file)
@@ -1,5 +1,5 @@
 /* fchdir replacement.
-   Copyright (C) 2006-2008 Free Software Foundation, Inc.
+   Copyright (C) 2006-2009 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
@@ -177,6 +177,11 @@ rpl_dup2 (int oldfd, int newfd)
 #undef dup2
 {
   int retval = dup2 (oldfd, newfd);
+#if REPLACE_DUP2
+  /* Inline mingw replacement from dup2.c.  */
+  if (retval == 0)
+    retval = newfd;
+#endif
 
   if (retval >= 0 && oldfd >= 0 && newfd >= 0 && newfd != oldfd)
     {
index cd3a60b..47d3096 100644 (file)
@@ -150,10 +150,13 @@ extern int close (int);
 
 
 #if @GNULIB_DUP2@
-# if !@HAVE_DUP2@
+# if @REPLACE_DUP2@
+#  define dup2 rpl_dup2
+# endif
+# if !@HAVE_DUP2@ || @REPLACE_DUP2@
 /* Copy the file descriptor OLDFD into file descriptor NEWFD.  Do nothing if
    NEWFD = OLDFD, otherwise close NEWFD first if it is open.
-   Return 0 if successful, otherwise -1 and errno set.
+   Return newfd if successful, otherwise -1 and errno set.
    See the POSIX:2001 specification
    <http://www.opengroup.org/susv3xsh/dup2.html>.  */
 extern int dup2 (int oldfd, int newfd);
@@ -214,8 +217,10 @@ extern int fchdir (int /*fd*/);
 
 #  define dup rpl_dup
 extern int dup (int);
-#  define dup2 rpl_dup2
+#  if !@REPLACE_DUP2@
+#   define dup2 rpl_dup2
 extern int dup2 (int, int);
+#  endif
 
 # endif
 #elif defined GNULIB_POSIXCHECK
index 0549823..2abc74c 100644 (file)
@@ -1,5 +1,5 @@
-#serial 5
-dnl Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
+#serial 6
+dnl Copyright (C) 2002, 2005, 2007, 2009 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.
@@ -7,9 +7,29 @@ dnl with or without modifications, as long as this notice is preserved.
 AC_DEFUN([gl_FUNC_DUP2],
 [
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
   AC_CHECK_FUNCS_ONCE([dup2])
   if test $ac_cv_func_dup2 = no; then
     HAVE_DUP2=0
     AC_LIBOBJ([dup2])
+  else
+    AC_CACHE_CHECK([whether dup2 works], [gl_cv_func_dup2_works],
+      [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <unistd.h>
+]], [return 1 - dup2 (1, 1);])],
+       [gl_cv_func_dup2_works=yes], [gl_cv_func_dup2_works=no],
+       [case "$host_os" in
+          mingw*) # on this platform, dup2 always returns 0 for success
+            gl_cv_func_dup2_works=no;;
+          cygwin*) # on cygwin 1.5.x, dup2(1,1) returns 0
+            gl_cv_func_dup2_works=no;;
+          *) gl_cv_func_dup2_works=yes;;
+        esac])])
+    if test "$gl_cv_func_dup2_works" = no; then
+      REPLACE_DUP2=1
+      AC_LIBOBJ([dup2])
+    fi
   fi
+  AC_DEFINE_UNQUOTED([REPLACE_DUP2], [$REPLACE_DUP2],
+    [Define to 1 if dup2 returns 0 instead of the target fd.])
 ])
index ff9a4ea..96fddba 100644 (file)
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 17
+# unistd_h.m4 serial 18
 dnl Copyright (C) 2006-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -73,6 +73,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   HAVE_SYS_PARAM_H=0;     AC_SUBST([HAVE_SYS_PARAM_H])
   REPLACE_CHOWN=0;        AC_SUBST([REPLACE_CHOWN])
   REPLACE_CLOSE=0;        AC_SUBST([REPLACE_CLOSE])
+  REPLACE_DUP2=0;         AC_SUBST([REPLACE_DUP2])
   REPLACE_FCHDIR=0;       AC_SUBST([REPLACE_FCHDIR])
   REPLACE_GETCWD=0;       AC_SUBST([REPLACE_GETCWD])
   REPLACE_GETPAGESIZE=0;  AC_SUBST([REPLACE_GETPAGESIZE])
index 6dddd38..88c4fa4 100644 (file)
@@ -8,6 +8,7 @@ lib/w32spawn.h
 m4/execute.m4
 
 Depends-on:
+dup2
 error
 exit
 fatal-signal
index 190cbd2..60f9251 100644 (file)
@@ -7,6 +7,7 @@ lib/fseterr.c
 lib/stdio-impl.h
 
 Depends-on:
+dup2
 
 configure.ac:
 
index 08c2f94..570d71d 100644 (file)
@@ -8,6 +8,7 @@ lib/w32spawn.h
 m4/pipe.m4
 
 Depends-on:
+dup2
 environ
 error
 exit
index 211cc22..da3ed28 100644 (file)
@@ -9,6 +9,7 @@ m4/posix_spawn.m4
 Depends-on:
 spawn
 alloca-opt
+dup2
 errno
 open
 strchrnul
index 1359c52..7f7495d 100644 (file)
@@ -64,6 +64,7 @@ unistd.h: unistd.in.h
              -e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \
              -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \
              -e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \
+             -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \
              -e 's|@''REPLACE_FCHDIR''@|$(REPLACE_FCHDIR)|g' \
              -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
              -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \