X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fdup2.c;h=a4422bf3b8c3aed35e4f5bdf2cf734e0a1ce6056;hb=7ba06c8ff37d8725cb824c64b94be41b9294ffb7;hp=6d3e4fc530a21361855f6075d746bbae620d58c4;hpb=a62be9f4039b4499cfbb76e394cad2259d03fa84;p=gnulib.git diff --git a/lib/dup2.c b/lib/dup2.c index 6d3e4fc53..a4422bf3b 100644 --- a/lib/dup2.c +++ b/lib/dup2.c @@ -1,10 +1,11 @@ /* Duplicate an open file descriptor to a specified file descriptor. - Copyright (C) 1999, 2004 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + Copyright (C) 1999, 2004-2007, 2009-2010 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 2, or (at your option) - any later version. + 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 @@ -12,26 +13,81 @@ 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, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ /* written by Paul Eggert */ -#if HAVE_CONFIG_H -# include -#endif +#include + +/* Specification. */ +#include #include +#include -#if HAVE_FCNTL_H -# include +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Get declarations of the Win32 API functions. */ +# define WIN32_LEAN_AND_MEAN +# include #endif -#if HAVE_UNISTD_H -# include -#endif +#if HAVE_DUP2 + +# undef dup2 -#ifndef F_DUPFD +int +rpl_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. */ + if (fd == desired_fd) + { + if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return -1; + } + 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) + { + errno = EBADF; + return -1; + } +# endif + result = dup2 (fd, desired_fd); +# ifdef __linux__ + /* Correct a Linux return value. + + */ + if (fd == desired_fd && result == (unsigned int) -EBADF) + { + errno = EBADF; + result = -1; + } +# endif + if (result == 0) + result = desired_fd; + /* Correct a cygwin 1.5.x errno value. */ + else if (result == -1 && errno == EMFILE) + errno = EBADF; +# if REPLACE_FCHDIR + if (fd != desired_fd && result != -1) + result = _gl_register_dup (fd, result); +# endif + return result; +} + +#else /* !HAVE_DUP2 */ + +/* On older platforms, dup2 did not exist. */ + +# ifndef F_DUPFD static int dupfd (int fd, int desired_fd) { @@ -47,17 +103,26 @@ dupfd (int fd, int desired_fd) return r; } } -#endif +# endif int dup2 (int fd, int desired_fd) { - if (fd == desired_fd) - return fd; + int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd; + if (result == -1 || fd == desired_fd) + return result; close (desired_fd); -#ifdef F_DUPFD - return fcntl (fd, F_DUPFD, desired_fd); -#else - return dupfd (fd, desired_fd); -#endif +# ifdef F_DUPFD + result = fcntl (fd, F_DUPFD, desired_fd); +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif +# else + result = dupfd (fd, desired_fd); +# endif + if (result == -1 && (errno == EMFILE || errno == EINVAL)) + errno = EBADF; + return result; } +#endif /* !HAVE_DUP2 */