16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Duplicate an open file descriptor to a specified file descriptor. 26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Copyright (C) 1999, 2004-2007, 2009-2012 Free Software Foundation, Inc. 46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn This program is free software: you can redistribute it and/or modify 66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn it under the terms of the GNU General Public License as published by 76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn the Free Software Foundation; either version 3 of the License, or 86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (at your option) any later version. 96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn This program is distributed in the hope that it will be useful, 116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn but WITHOUT ANY WARRANTY; without even the implied warranty of 126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn GNU General Public License for more details. 146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn You should have received a copy of the GNU General Public License 166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn along with this program. If not, see <http://www.gnu.org/licenses/>. */ 176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* written by Paul Eggert */ 196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <config.h> 216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Specification. */ 236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <unistd.h> 246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <errno.h> 266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <fcntl.h> 276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if HAVE_DUP2 296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# undef dup2 316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Get declarations of the native Windows API functions. */ 356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# define WIN32_LEAN_AND_MEAN 366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# include <windows.h> 376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# include "msvc-inval.h" 396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Get _get_osfhandle. */ 416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# include "msvc-nothrow.h" 426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennms_windows_dup2 (int fd, int desired_fd) 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int result; 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dup2 (fd, fd) returns 0, but all further attempts to use fd in 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn future dup2 calls will hang. */ 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (fd == desired_fd) 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE) 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn errno = EBADF; 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return -1; 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return fd; 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* Wine 1.0.1 return 0 when desired_fd is negative but not -1: 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn http://bugs.winehq.org/show_bug.cgi?id=21289 */ 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (desired_fd < 0) 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn errno = EBADF; 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return -1; 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn TRY_MSVC_INVAL 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = dup2 (fd, desired_fd); 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CATCH_MSVC_INVAL 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn errno = EBADF; 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = -1; 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn DONE_MSVC_INVAL; 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (result == 0) 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = desired_fd; 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return result; 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# define dup2 ms_windows_dup2 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# endif 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennrpl_dup2 (int fd, int desired_fd) 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int result; 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# ifdef F_GETFL 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn On Cygwin 1.5.x, dup2 (1, 1) returns 0. 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (fd == desired_fd) 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return fcntl (fd, F_GETFL) == -1 ? -1 : fd; 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# endif 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = dup2 (fd, desired_fd); 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (result == -1 && errno == EMFILE) 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn errno = EBADF; 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# if REPLACE_FCHDIR 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (fd != desired_fd && result != -1) 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = _gl_register_dup (fd, result); 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# endif 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return result; 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else /* !HAVE_DUP2 */ 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* On older platforms, dup2 did not exist. */ 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# ifndef F_DUPFD 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renndupfd (int fd, int desired_fd) 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int duplicated_fd = dup (fd); 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (duplicated_fd < 0 || duplicated_fd == desired_fd) 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return duplicated_fd; 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int r = dupfd (fd, desired_fd); 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int e = errno; 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn close (duplicated_fd); 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn errno = e; 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return r; 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# endif 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renndup2 (int fd, int desired_fd) 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd; 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (result == -1 || fd == desired_fd) 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return result; 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn close (desired_fd); 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# ifdef F_DUPFD 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = fcntl (fd, F_DUPFD, desired_fd); 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# if REPLACE_FCHDIR 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (0 <= result) 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = _gl_register_dup (fd, result); 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# endif 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# else 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = dupfd (fd, desired_fd); 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn# endif 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (result == -1 && (errno == EMFILE || errno == EINVAL)) 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn errno = EBADF; 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return result; 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif /* !HAVE_DUP2 */ 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn