From 5f59a34ab747dde8ede7357f3431bf06bd6002fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 8 Mar 2026 17:28:33 +0100 Subject: New upstream version 1.4.2 --- tests/fcntl.c | 180 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 110 insertions(+), 70 deletions(-) (limited to 'tests/fcntl.c') diff --git a/tests/fcntl.c b/tests/fcntl.c index f47ebde1..1c0e52d2 100644 --- a/tests/fcntl.c +++ b/tests/fcntl.c @@ -1,6 +1,6 @@ /* Provide file descriptor control. - Copyright (C) 2009-2025 Free Software Foundation, Inc. + Copyright (C) 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 @@ -29,8 +29,8 @@ #include #ifdef __KLIBC__ -# define INCL_DOS -# include +# include +# include #endif #if defined _WIN32 && ! defined __CYGWIN__ @@ -56,19 +56,15 @@ dupfd (int oldfd, int newfd, int flags) { /* Mingw has no way to create an arbitrary fd. Iterate until all file descriptors less than newfd are filled up. */ - HANDLE curr_process = GetCurrentProcess (); - HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd); - unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT]; - unsigned int fds_to_close_bound = 0; - int result; - BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE; - int mode; if (newfd < 0 || getdtablesize () <= newfd) { errno = EINVAL; return -1; } + + HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd); + int mode; if (old_handle == INVALID_HANDLE_VALUE || (mode = _setmode (oldfd, O_BINARY)) == -1) { @@ -80,6 +76,11 @@ dupfd (int oldfd, int newfd, int flags) _setmode (oldfd, mode); flags |= mode; + HANDLE curr_process = GetCurrentProcess (); + BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE; + unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT]; + unsigned int fds_to_close_bound = 0; + int result; for (;;) { HANDLE new_handle; @@ -146,9 +147,8 @@ dupfd (int oldfd, int newfd, int flags) /* Close the previous fds that turned out to be too small. */ { int saved_errno = errno; - unsigned int duplicated_fd; - for (duplicated_fd = 0; + for (unsigned int duplicated_fd = 0; duplicated_fd < fds_to_close_bound * CHAR_BIT; duplicated_fd++) if ((fds_to_close[duplicated_fd / CHAR_BIT] @@ -206,8 +206,9 @@ fcntl (int fd, int action, /* arg */...) #endif { va_list arg; - int result = -1; va_start (arg, action); + + int result = -1; switch (action) { case F_DUPFD: @@ -433,7 +434,9 @@ fcntl (int fd, int action, /* arg */...) break; } } + va_end (arg); + return result; } @@ -540,78 +543,115 @@ rpl_fcntl_DUPFD_CLOEXEC (int fd, int target) #undef fcntl #ifdef __KLIBC__ - static int -klibc_fcntl (int fd, int action, /* arg */...) +klibc_dupdirfd (int fd, int minfd) { - va_list arg_ptr; - int arg; - struct stat sbuf; - int result; + int tempfd = open ("NUL", O_RDONLY); + if (tempfd == -1) + return -1; - va_start (arg_ptr, action); - arg = va_arg (arg_ptr, int); - result = fcntl (fd, action, arg); - /* EPERM for F_DUPFD, ENOTSUP for others */ - if (result == -1 && (errno == EPERM || errno == ENOTSUP) - && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) + if (tempfd >= minfd) { - ULONG ulMode; + close (tempfd); - switch (action) - { - case F_DUPFD: - /* Find available fd */ - while (fcntl (arg, F_GETFL) != -1 || errno != EBADF) - arg++; + char path[_MAX_PATH]; + if (__libc_Back_ioFHToPath (fd, path, sizeof (path))) + return -1; - result = dup2 (fd, arg); - break; + int dupfd = open (path, O_RDONLY); + if (dupfd == -1) + return -1; - /* Using underlying APIs is right ? */ - case F_GETFD: - if (DosQueryFHState (fd, &ulMode)) - break; + if (dupfd >= minfd) + return dupfd; - result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0; - break; - - case F_SETFD: - if (arg & ~FD_CLOEXEC) - break; - - if (DosQueryFHState (fd, &ulMode)) - break; - - if (arg & FD_CLOEXEC) - ulMode |= OPEN_FLAGS_NOINHERIT; - else - ulMode &= ~OPEN_FLAGS_NOINHERIT; + /* Lower FD was closed by other threads. Fill again. */ + tempfd = dupfd; + } - /* Filter supported flags. */ - ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR - | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); + int dupfd = klibc_dupdirfd (fd, minfd); - if (DosSetFHState (fd, ulMode)) - break; + close (tempfd); - result = 0; - break; + return dupfd; +} - case F_GETFL: - result = 0; - break; +static int +klibc_fcntl (int fd, int action, /* arg */...) +{ + va_list arg_ptr; + va_start (arg_ptr, action); - case F_SETFL: - if (arg != 0) - break; + int arg = va_arg (arg_ptr, int); + int result = fcntl (fd, action, arg); + /* EPERM for F_DUPFD, ENOTSUP for others */ + if (result == -1 && (errno == EPERM || errno == ENOTSUP)) + { + struct stat sbuf; + if (!fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) + { + switch (action) + { + case F_DUPFD: + result = klibc_dupdirfd (fd, arg); + break; + + case F_GETFD: + { + PLIBCFH pFH = __libc_FH (fd); + if (!pFH) + { + errno = EBADF; + break; + } + + result = (pFH->fFlags & ((FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT ) + | O_NOINHERIT)) ? FD_CLOEXEC : 0; + } + break; + + case F_SETFD: + { + if (arg & ~FD_CLOEXEC) + break; + + PLIBCFH pFH = __libc_FH (fd); + if (!pFH) + { + errno = EBADF; + break; + } + + unsigned fFlags = pFH->fFlags; + if (arg & FD_CLOEXEC) + fFlags |= (FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT) | O_NOINHERIT; + else + fFlags &= ~((FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT) | O_NOINHERIT); + + result = __libc_FHSetFlags (pFH, fd, fFlags); + if (result < 0) + { + errno = -result; + result = -1; + } + } + break; + + case F_GETFL: + result = 0; + break; + + case F_SETFL: + if (arg != 0) + break; - result = 0; - break; + result = 0; + break; - default: - errno = EINVAL; - break; + default: + errno = EINVAL; + break; + } } } -- cgit v1.2.3