1/* Duplicate an open file descriptor to a specified file descriptor. 2 3 Copyright (C) 1999, 2004-2007, 2009-2010 Free Software Foundation, Inc. 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18/* written by Paul Eggert */ 19 20#include <config.h> 21 22/* Specification. */ 23#include <unistd.h> 24 25#include <errno.h> 26#include <fcntl.h> 27 28#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 29/* Get declarations of the Win32 API functions. */ 30# define WIN32_LEAN_AND_MEAN 31# include <windows.h> 32#endif 33 34#if HAVE_DUP2 35 36# undef dup2 37 38int 39rpl_dup2 (int fd, int desired_fd) 40{ 41 int result; 42# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 43 /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, 44 dup2 (fd, fd) returns 0, but all further attempts to use fd in 45 future dup2 calls will hang. */ 46 if (fd == desired_fd) 47 { 48 if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE) 49 { 50 errno = EBADF; 51 return -1; 52 } 53 return fd; 54 } 55 /* Wine 1.0.1 return 0 when desired_fd is negative but not -1: 56 http://bugs.winehq.org/show_bug.cgi?id=21289 */ 57 if (desired_fd < 0) 58 { 59 errno = EBADF; 60 return -1; 61 } 62# endif 63 result = dup2 (fd, desired_fd); 64# ifdef __linux__ 65 /* Correct a Linux return value. 66 <http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.30.y.git;a=commitdiff;h=2b79bc4f7ebbd5af3c8b867968f9f15602d5f802> 67 */ 68 if (fd == desired_fd && result == (unsigned int) -EBADF) 69 { 70 errno = EBADF; 71 result = -1; 72 } 73# endif 74 if (result == 0) 75 result = desired_fd; 76 /* Correct a cygwin 1.5.x errno value. */ 77 else if (result == -1 && errno == EMFILE) 78 errno = EBADF; 79# if REPLACE_FCHDIR 80 if (fd != desired_fd && result != -1) 81 result = _gl_register_dup (fd, result); 82# endif 83 return result; 84} 85 86#else /* !HAVE_DUP2 */ 87 88/* On older platforms, dup2 did not exist. */ 89 90# ifndef F_DUPFD 91static int 92dupfd (int fd, int desired_fd) 93{ 94 int duplicated_fd = dup (fd); 95 if (duplicated_fd < 0 || duplicated_fd == desired_fd) 96 return duplicated_fd; 97 else 98 { 99 int r = dupfd (fd, desired_fd); 100 int e = errno; 101 close (duplicated_fd); 102 errno = e; 103 return r; 104 } 105} 106# endif 107 108int 109dup2 (int fd, int desired_fd) 110{ 111 int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd; 112 if (result == -1 || fd == desired_fd) 113 return result; 114 close (desired_fd); 115# ifdef F_DUPFD 116 result = fcntl (fd, F_DUPFD, desired_fd); 117# if REPLACE_FCHDIR 118 if (0 <= result) 119 result = _gl_register_dup (fd, result); 120# endif 121# else 122 result = dupfd (fd, desired_fd); 123# endif 124 if (result == -1 && (errno == EMFILE || errno == EINVAL)) 125 errno = EBADF; 126 return result; 127} 128#endif /* !HAVE_DUP2 */ 129