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 HAVE_MSVC_INVALID_PARAMETER_HANDLER 32 static int 33 dup_nothrow (int fd) 34 { 35 int result; 36 37 TRY_MSVC_INVAL 38 { 39 result = dup (fd); 40 } 41 CATCH_MSVC_INVAL 42 { 43 result = -1; 44 errno = EBADF; 45 } 46 DONE_MSVC_INVAL; 47 48 return result; 49 } 50 #elif defined __KLIBC__ 51 # include <fcntl.h> 52 # include <sys/stat.h> 53 54 # include <InnoTekLIBC/backend.h> 55 56 static int 57 dup_nothrow (int fd) 58 { 59 int dupfd; 60 struct stat sbuf; 61 62 dupfd = dup (fd); 63 if (dupfd == -1 && errno == ENOTSUP \ 64 && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) 65 { 66 char path[_MAX_PATH]; 67 68 /* Get a path from fd */ 69 if (!__libc_Back_ioFHToPath (fd, path, sizeof (path))) 70 dupfd = open (path, O_RDONLY); 71 } 72 73 return dupfd; 74 } 75 #else 76 # define dup_nothrow dup 77 #endif 78 79 int 80 rpl_dup (int fd) 81 { 82 int result = dup_nothrow (fd); 83 #if REPLACE_FCHDIR 84 if (result >= 0) 85 result = _gl_register_dup (fd, result); 86 #endif 87 return result; 88 } 89