105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Duplicate an open file descriptor to a specified file descriptor. 205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang Copyright (C) 1999, 2004-2007, 2009-2012 Free Software Foundation, Inc. 405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 505436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is free software: you can redistribute it and/or modify 605436638acc7c010349a69c3395f1a57c642dc62Ying Wang it under the terms of the GNU General Public License as published by 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang the Free Software Foundation; either version 3 of the License, or 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang (at your option) any later version. 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is distributed in the hope that it will be useful, 1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang but WITHOUT ANY WARRANTY; without even the implied warranty of 1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang GNU General Public License for more details. 1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang You should have received a copy of the GNU General Public License 1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* written by Paul Eggert */ 1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h> 2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification. */ 2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <unistd.h> 2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <errno.h> 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <fcntl.h> 2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_DUP2 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# undef dup2 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Get declarations of the native Windows API functions. */ 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define WIN32_LEAN_AND_MEAN 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <windows.h> 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "msvc-inval.h" 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Get _get_osfhandle. */ 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "msvc-nothrow.h" 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wangms_windows_dup2 (int fd, int desired_fd) 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang int result; 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang dup2 (fd, fd) returns 0, but all further attempts to use fd in 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang future dup2 calls will hang. */ 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (fd == desired_fd) 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE) 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EBADF; 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return -1; 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return fd; 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Wine 1.0.1 return 0 when desired_fd is negative but not -1: 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang http://bugs.winehq.org/show_bug.cgi?id=21289 */ 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (desired_fd < 0) 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EBADF; 6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return -1; 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang TRY_MSVC_INVAL 7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = dup2 (fd, desired_fd); 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang CATCH_MSVC_INVAL 7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EBADF; 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = -1; 7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang DONE_MSVC_INVAL; 7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (result == 0) 8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = desired_fd; 8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return result; 8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define dup2 ms_windows_dup2 8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9005436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 9105436638acc7c010349a69c3395f1a57c642dc62Ying Wangrpl_dup2 (int fd, int desired_fd) 9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang int result; 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# ifdef F_GETFL 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang On Cygwin 1.5.x, dup2 (1, 1) returns 0. 9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ 9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (fd == desired_fd) 10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return fcntl (fd, F_GETFL) == -1 ? -1 : fd; 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = dup2 (fd, desired_fd); 10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (result == -1 && errno == EMFILE) 10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EBADF; 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if REPLACE_FCHDIR 10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (fd != desired_fd && result != -1) 11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = _gl_register_dup (fd, result); 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return result; 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else /* !HAVE_DUP2 */ 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* On older platforms, dup2 did not exist. */ 11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# ifndef F_DUPFD 12005436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int 12105436638acc7c010349a69c3395f1a57c642dc62Ying Wangdupfd (int fd, int desired_fd) 12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang int duplicated_fd = dup (fd); 12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (duplicated_fd < 0 || duplicated_fd == desired_fd) 12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return duplicated_fd; 12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang int r = dupfd (fd, desired_fd); 12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang int e = errno; 13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (duplicated_fd); 13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = e; 13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return r; 13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13705436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 13805436638acc7c010349a69c3395f1a57c642dc62Ying Wangdup2 (int fd, int desired_fd) 13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd; 14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (result == -1 || fd == desired_fd) 14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return result; 14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (desired_fd); 14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# ifdef F_DUPFD 14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = fcntl (fd, F_DUPFD, desired_fd); 14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if REPLACE_FCHDIR 14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (0 <= result) 14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = _gl_register_dup (fd, result); 14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else 15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = dupfd (fd, desired_fd); 15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (result == -1 && (errno == EMFILE || errno == EINVAL)) 15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EBADF; 15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return result; 15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif /* !HAVE_DUP2 */ 158