X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fdup2.c;h=f128e7a63cd49ed58ecdcd0ce430beb8e17f6ecf;hb=fdd1b511c5c12912aae79b58e0c5f6ffa0492d6e;hp=e2a44734e47508a30416f390401f99db8500b87e;hpb=9b604b4cbfad7422bacc1c723df1d027b6a7c738;p=gnulib.git diff --git a/lib/dup2.c b/lib/dup2.c index e2a44734e..f128e7a63 100644 --- a/lib/dup2.c +++ b/lib/dup2.c @@ -1,6 +1,6 @@ /* Duplicate an open file descriptor to a specified file descriptor. - Copyright (C) 1999, 2004-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1999, 2004-2007, 2009-2013 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,48 +25,26 @@ #include #include -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* Get declarations of the Win32 API functions. */ -# define WIN32_LEAN_AND_MEAN -# include -/* Get _get_osfhandle. */ -# include "msvc-nothrow.h" -#endif - -#include "msvc-inval.h" - #if HAVE_DUP2 # undef dup2 -# if HAVE_MSVC_INVALID_PARAMETER_HANDLER -static inline int -dup2_nothrow (int fd, int desired_fd) -{ - int result; +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - TRY_MSVC_INVAL - { - result = dup2 (fd, desired_fd); - } - CATCH_MSVC_INVAL - { - result = -1; - errno = EBADF; - } - DONE_MSVC_INVAL; +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include - return result; -} -# else -# define dup2_nothrow dup2 -# endif +# include "msvc-inval.h" -int -rpl_dup2 (int fd, int desired_fd) +/* Get _get_osfhandle. */ +# include "msvc-nothrow.h" + +static int +ms_windows_dup2 (int fd, int desired_fd) { int result; -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, dup2 (fd, fd) returns 0, but all further attempts to use fd in future dup2 calls will hang. */ @@ -79,6 +57,7 @@ rpl_dup2 (int fd, int desired_fd) } return fd; } + /* Wine 1.0.1 return 0 when desired_fd is negative but not -1: http://bugs.winehq.org/show_bug.cgi?id=21289 */ if (desired_fd < 0) @@ -86,28 +65,52 @@ rpl_dup2 (int fd, int desired_fd) errno = EBADF; return -1; } -# elif !defined __linux__ - /* On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ - if (fd == desired_fd) - return fcntl (fd, F_GETFL) == -1 ? -1 : fd; -# endif - - result = dup2_nothrow (fd, desired_fd); -# ifdef __linux__ - /* Correct a Linux return value. - - */ - if (fd == desired_fd && result == (unsigned int) -EBADF) + TRY_MSVC_INVAL + { + result = dup2 (fd, desired_fd); + } + CATCH_MSVC_INVAL { errno = EBADF; result = -1; } -# endif + DONE_MSVC_INVAL; + if (result == 0) result = desired_fd; - /* Correct a cygwin 1.5.x errno value. */ - else if (result == -1 && errno == EMFILE) + + return result; +} + +# define dup2 ms_windows_dup2 + +# endif + +int +rpl_dup2 (int fd, int desired_fd) +{ + int result; + +# ifdef F_GETFL + /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. + On Cygwin 1.5.x, dup2 (1, 1) returns 0. + On Cygwin 1.7.17, dup2 (1, -1) dumps core. + On Cygwin 1.7.25, dup2 (1, 256) can dump core. + On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ +# if HAVE_SETDTABLESIZE + setdtablesize (desired_fd + 1); +# endif + if (desired_fd < 0) + fd = desired_fd; + if (fd == desired_fd) + return fcntl (fd, F_GETFL) == -1 ? -1 : fd; +# endif + + result = dup2 (fd, desired_fd); + + /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ + if (result == -1 && errno == EMFILE) errno = EBADF; # if REPLACE_FCHDIR if (fd != desired_fd && result != -1)