diff options
| author | Jörg Frings-Fürst <debian@jff.email> | 2026-03-08 17:28:33 +0100 |
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff.email> | 2026-03-08 17:28:33 +0100 |
| commit | 5f59a34ab747dde8ede7357f3431bf06bd6002fe (patch) | |
| tree | 056a4477fd870d454d5be5868cddab829a47f4d2 /tests/dup2.c | |
| parent | 27dae84ed92f1ef0300263091972338d12e78348 (diff) | |
New upstream version 1.4.2upstream/1.4.2upstream
Diffstat (limited to 'tests/dup2.c')
| -rw-r--r-- | tests/dup2.c | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/tests/dup2.c b/tests/dup2.c index 69b37196..b9a55263 100644 --- a/tests/dup2.c +++ b/tests/dup2.c @@ -1,6 +1,6 @@ /* Duplicate an open file descriptor to a specified file descriptor. - Copyright (C) 1999, 2004-2007, 2009-2025 Free Software Foundation, Inc. + Copyright (C) 1999, 2004-2007, 2009-2026 Free Software Foundation, Inc. This file is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -70,8 +70,6 @@ dup2_nothrow (int fd, int desired_fd) static int ms_windows_dup2 (int fd, int desired_fd) { - int result; - /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, dup2 (fd, fd) returns 0, but all further attempts to use fd in future dup2 calls will hang. */ @@ -93,7 +91,7 @@ ms_windows_dup2 (int fd, int desired_fd) return -1; } - result = dup2_nothrow (fd, desired_fd); + int result = dup2_nothrow (fd, desired_fd); if (result == 0) result = desired_fd; @@ -110,14 +108,11 @@ ms_windows_dup2 (int fd, int desired_fd) static int klibc_dup2dirfd (int fd, int desired_fd) { - int tempfd; - int dupfd; - - tempfd = open ("NUL", O_RDONLY); - if (tempfd == -1) - return -1; + int tempfd = open ("NUL", O_RDONLY); + if (tempfd < 0) + return tempfd; - if (tempfd == desired_fd) + if (tempfd >= desired_fd) { close (tempfd); @@ -125,10 +120,32 @@ klibc_dup2dirfd (int fd, int desired_fd) if (__libc_Back_ioFHToPath (fd, path, sizeof (path))) return -1; - return open(path, O_RDONLY); + for (;;) + { + close (desired_fd); + + int dupfd = open (path, O_RDONLY); + if (dupfd < 0) + return dupfd; + + if (dupfd == desired_fd) + return dupfd; + + /* If lower FD was closed by other threads, fill again. */ + if (dupfd < desired_fd) + { + tempfd = dupfd; + break; + } + + /* desired_fd was opened by other threads. Try again. */ + /* FIXME: Closing desired_fd opened by other threads may lead to + unexpected behavior. */ + close (dupfd); + } } - dupfd = klibc_dup2dirfd (fd, desired_fd); + int dupfd = klibc_dup2dirfd (fd, desired_fd); close (tempfd); @@ -138,16 +155,16 @@ klibc_dup2dirfd (int fd, int desired_fd) static int klibc_dup2 (int fd, int desired_fd) { - int dupfd; - struct stat sbuf; - - dupfd = dup2 (fd, desired_fd); - if (dupfd == -1 && errno == ENOTSUP \ - && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) + int dupfd = dup2 (fd, desired_fd); + if (dupfd < 0 && errno == ENOTSUP) { - close (desired_fd); + struct stat sbuf; + if (!fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) + { + close (desired_fd); - return klibc_dup2dirfd (fd, desired_fd); + return klibc_dup2dirfd (fd, desired_fd); + } } return dupfd; @@ -159,8 +176,6 @@ klibc_dup2 (int fd, int desired_fd) int rpl_dup2 (int fd, int desired_fd) { - int result; - #ifdef F_GETFL /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. On Cygwin 1.5.x, dup2 (1, 1) returns 0. @@ -176,13 +191,14 @@ rpl_dup2 (int fd, int desired_fd) return fcntl (fd, F_GETFL) == -1 ? -1 : fd; #endif - result = dup2 (fd, desired_fd); + int result = dup2 (fd, desired_fd); /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ - if (result == -1 && errno == EMFILE) + if (result < 0 && errno == EMFILE) errno = EBADF; + #if REPLACE_FCHDIR - if (fd != desired_fd && result != -1) + if (! (result < 0 || fd == desired_fd)) result = _gl_register_dup (fd, result); #endif return result; |
