diff options
| author | Jörg Frings-Fürst <debian@jff.email> | 2026-03-10 13:24:07 +0100 |
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff.email> | 2026-03-10 13:24:07 +0100 |
| commit | cfd1f17f1a85d95ea12bca8dae42add7dad1ad11 (patch) | |
| tree | 8016486f8ee7157213f2d09ff2491bfa9c94638a /tests/fcntl.c | |
| parent | 14e4d584d0121031ec40e6c35869745f1747ff29 (diff) | |
| parent | 1403307d6e2fb4e7b5d97a35f40d1e95134561ab (diff) | |
Merge branch 'release/debian/1.4.2-1'HEADdebian/1.4.2-1master
Diffstat (limited to 'tests/fcntl.c')
| -rw-r--r-- | tests/fcntl.c | 186 |
1 files changed, 110 insertions, 76 deletions
diff --git a/tests/fcntl.c b/tests/fcntl.c index 7cd3a0f9..1c0e52d2 100644 --- a/tests/fcntl.c +++ b/tests/fcntl.c @@ -1,6 +1,6 @@ /* Provide file descriptor control. - Copyright (C) 2009-2024 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 <unistd.h> #ifdef __KLIBC__ -# define INCL_DOS -# include <os2.h> +# include <emx/io.h> +# include <InnoTekLIBC/backend.h> #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: @@ -376,12 +377,6 @@ fcntl (int fd, int action, /* arg */...) #ifdef F_NOTIFY /* Linux */ case F_NOTIFY: #endif - #ifdef F_OPLKACK /* IRIX */ - case F_OPLKACK: - #endif - #ifdef F_OPLKREG /* IRIX */ - case F_OPLKREG: - #endif #ifdef F_RDAHEAD /* macOS */ case F_RDAHEAD: #endif @@ -439,7 +434,9 @@ fcntl (int fd, int action, /* arg */...) break; } } + va_end (arg); + return result; } @@ -546,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; - - result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0; - break; - - case F_SETFD: - if (arg & ~FD_CLOEXEC) - break; + if (dupfd >= minfd) + return dupfd; - if (DosQueryFHState (fd, &ulMode)) - break; + /* Lower FD was closed by other threads. Fill again. */ + tempfd = dupfd; + } - if (arg & FD_CLOEXEC) - ulMode |= OPEN_FLAGS_NOINHERIT; - else - ulMode &= ~OPEN_FLAGS_NOINHERIT; + int dupfd = klibc_dupdirfd (fd, minfd); - /* Filter supported flags. */ - ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR - | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); + close (tempfd); - if (DosSetFHState (fd, ulMode)) - break; - - 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; + } } } |
