X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fdup2.c;h=e00dc7b2e3c5f2789bc6a578a5f45be67871a2ef;hb=0e9ef9b9c9cd7036960656c797f0567b742e7b80;hp=fb3ffb0df07b386a634139b3256b7e0b1e2d095d;hpb=eeee74f5efe5e3c9f8f1198478b719921f29242c;p=gnulib.git diff --git a/lib/dup2.c b/lib/dup2.c index fb3ffb0df..e00dc7b2e 100644 --- a/lib/dup2.c +++ b/lib/dup2.c @@ -1,7 +1,6 @@ /* Duplicate an open file descriptor to a specified file descriptor. - Copyright (C) 1999, 2004, 2005, 2006, 2007, 2009 Free Software - Foundation, Inc. + Copyright (C) 1999, 2004-2007, 2009-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 @@ -32,7 +31,7 @@ # include #endif -#if REPLACE_DUP2 +#if HAVE_DUP2 # undef dup2 @@ -53,6 +52,17 @@ 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) + { + 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 (fd, desired_fd); # ifdef __linux__ @@ -70,10 +80,14 @@ rpl_dup2 (int fd, int 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 /* !REPLACE_DUP2 */ +#else /* !HAVE_DUP2 */ /* On older platforms, dup2 did not exist. */ @@ -98,13 +112,21 @@ dupfd (int fd, int desired_fd) 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); + result = fcntl (fd, F_DUPFD, desired_fd); +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif # else - return dupfd (fd, desired_fd); + result = dupfd (fd, desired_fd); # endif + if (result == -1 && (errno == EMFILE || errno == EINVAL)) + errno = EBADF; + return result; } -#endif /* !REPLACE_DUP2 */ +#endif /* !HAVE_DUP2 */