1 /* Duplicate an open file descriptor. 2 3 Copyright (C) 2011-2020 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 <https://www.gnu.org/licenses/>. */ 17 18 #include <config.h> 19 20 /* Specification. */ 21 #include <unistd.h> 22 23 #include <errno.h> 24 25 #if HAVE_MSVC_INVALID_PARAMETER_HANDLER 26 # include "msvc-inval.h" 27 #endif 28 29 #undef dup 30 31 #if defined _WIN32 && !defined __CYGWIN__ 32 # if HAVE_MSVC_INVALID_PARAMETER_HANDLER 33 static int dup_nothrow(int fd)34dup_nothrow (int fd) 35 { 36 int result; 37 38 TRY_MSVC_INVAL 39 { 40 result = _dup (fd); 41 } 42 CATCH_MSVC_INVAL 43 { 44 result = -1; 45 errno = EBADF; 46 } 47 DONE_MSVC_INVAL; 48 49 return result; 50 } 51 # else 52 # define dup_nothrow _dup 53 # endif 54 #elif defined __KLIBC__ 55 # include <fcntl.h> 56 # include <sys/stat.h> 57 58 # include <InnoTekLIBC/backend.h> 59 60 static int dup_nothrow(int fd)61dup_nothrow (int fd) 62 { 63 int dupfd; 64 struct stat sbuf; 65 66 dupfd = dup (fd); 67 if (dupfd == -1 && errno == ENOTSUP \ 68 && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) 69 { 70 char path[_MAX_PATH]; 71 72 /* Get a path from fd */ 73 if (!__libc_Back_ioFHToPath (fd, path, sizeof (path))) 74 dupfd = open (path, O_RDONLY); 75 } 76 77 return dupfd; 78 } 79 #else 80 # define dup_nothrow dup 81 #endif 82 83 int rpl_dup(int fd)84rpl_dup (int fd) 85 { 86 int result = dup_nothrow (fd); 87 #if REPLACE_FCHDIR 88 if (result >= 0) 89 result = _gl_register_dup (fd, result); 90 #endif 91 return result; 92 } 93