From ddd625ddd088a87d5598256d09b2036c63063386 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 21 Jul 2009 06:48:26 -0600 Subject: [PATCH] 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. Signed-off-by: Eric Blake --- ChangeLog | 15 +++++++++++++++ doc/posix-functions/dup2.texi | 8 ++++++++ lib/dup2.c | 29 +++++++++++++++++++++++------ lib/fchdir.c | 7 ++++++- lib/unistd.in.h | 11 ++++++++--- m4/dup2.m4 | 24 ++++++++++++++++++++++-- m4/unistd_h.m4 | 3 ++- modules/execute | 1 + modules/fseterr | 1 + modules/pipe | 1 + modules/posix_spawn-internal | 1 + modules/unistd | 1 + 12 files changed, 89 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 36248ab78..d87cc8e6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2009-07-21 Eric Blake + + 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 * modules/.gitattributes: New file. diff --git a/doc/posix-functions/dup2.texi b/doc/posix-functions/dup2.texi index 42d22e58e..bfaff38c1 100644 --- a/doc/posix-functions/dup2.texi +++ b/doc/posix-functions/dup2.texi @@ -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 diff --git a/lib/dup2.c b/lib/dup2.c index 09990823b..e5d3de47b 100644 --- a/lib/dup2.c +++ b/lib/dup2.c @@ -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 @@ -25,7 +26,22 @@ #include #include -#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 */ diff --git a/lib/fchdir.c b/lib/fchdir.c index 969e984c9..cc2fa63d7 100644 --- a/lib/fchdir.c +++ b/lib/fchdir.c @@ -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) { diff --git a/lib/unistd.in.h b/lib/unistd.in.h index cd3a60b7c..47d3096ad 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -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 . */ 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 diff --git a/m4/dup2.m4 b/m4/dup2.m4 index 054982359..2abc74cdc 100644 --- a/m4/dup2.m4 +++ b/m4/dup2.m4 @@ -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 +]], [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.]) ]) diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4 index ff9a4ea0a..96fddba7f 100644 --- a/m4/unistd_h.m4 +++ b/m4/unistd_h.m4 @@ -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]) diff --git a/modules/execute b/modules/execute index 6dddd3883..88c4fa4f9 100644 --- a/modules/execute +++ b/modules/execute @@ -8,6 +8,7 @@ lib/w32spawn.h m4/execute.m4 Depends-on: +dup2 error exit fatal-signal diff --git a/modules/fseterr b/modules/fseterr index 190cbd2df..60f92512e 100644 --- a/modules/fseterr +++ b/modules/fseterr @@ -7,6 +7,7 @@ lib/fseterr.c lib/stdio-impl.h Depends-on: +dup2 configure.ac: diff --git a/modules/pipe b/modules/pipe index 08c2f94a9..570d71d99 100644 --- a/modules/pipe +++ b/modules/pipe @@ -8,6 +8,7 @@ lib/w32spawn.h m4/pipe.m4 Depends-on: +dup2 environ error exit diff --git a/modules/posix_spawn-internal b/modules/posix_spawn-internal index 211cc22e4..da3ed2816 100644 --- a/modules/posix_spawn-internal +++ b/modules/posix_spawn-internal @@ -9,6 +9,7 @@ m4/posix_spawn.m4 Depends-on: spawn alloca-opt +dup2 errno open strchrnul diff --git a/modules/unistd b/modules/unistd index 1359c526d..7f7495d97 100644 --- a/modules/unistd +++ b/modules/unistd @@ -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' \ -- 2.11.0