summaryrefslogtreecommitdiffstats
path: root/gl/fcntl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/fcntl.c')
-rw-r--r--gl/fcntl.c186
1 files changed, 110 insertions, 76 deletions
diff --git a/gl/fcntl.c b/gl/fcntl.c
index 7cd3a0f9..1c0e52d2 100644
--- a/gl/fcntl.c
+++ b/gl/fcntl.c
@@ -1,6 +1,6 @@
1/* Provide file descriptor control. 1/* Provide file descriptor control.
2 2
3 Copyright (C) 2009-2024 Free Software Foundation, Inc. 3 Copyright (C) 2009-2026 Free Software Foundation, Inc.
4 4
5 This file is free software: you can redistribute it and/or modify 5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as 6 it under the terms of the GNU Lesser General Public License as
@@ -29,8 +29,8 @@
29#include <unistd.h> 29#include <unistd.h>
30 30
31#ifdef __KLIBC__ 31#ifdef __KLIBC__
32# define INCL_DOS 32# include <emx/io.h>
33# include <os2.h> 33# include <InnoTekLIBC/backend.h>
34#endif 34#endif
35 35
36#if defined _WIN32 && ! defined __CYGWIN__ 36#if defined _WIN32 && ! defined __CYGWIN__
@@ -56,19 +56,15 @@ dupfd (int oldfd, int newfd, int flags)
56{ 56{
57 /* Mingw has no way to create an arbitrary fd. Iterate until all 57 /* Mingw has no way to create an arbitrary fd. Iterate until all
58 file descriptors less than newfd are filled up. */ 58 file descriptors less than newfd are filled up. */
59 HANDLE curr_process = GetCurrentProcess ();
60 HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd);
61 unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT];
62 unsigned int fds_to_close_bound = 0;
63 int result;
64 BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE;
65 int mode;
66 59
67 if (newfd < 0 || getdtablesize () <= newfd) 60 if (newfd < 0 || getdtablesize () <= newfd)
68 { 61 {
69 errno = EINVAL; 62 errno = EINVAL;
70 return -1; 63 return -1;
71 } 64 }
65
66 HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd);
67 int mode;
72 if (old_handle == INVALID_HANDLE_VALUE 68 if (old_handle == INVALID_HANDLE_VALUE
73 || (mode = _setmode (oldfd, O_BINARY)) == -1) 69 || (mode = _setmode (oldfd, O_BINARY)) == -1)
74 { 70 {
@@ -80,6 +76,11 @@ dupfd (int oldfd, int newfd, int flags)
80 _setmode (oldfd, mode); 76 _setmode (oldfd, mode);
81 flags |= mode; 77 flags |= mode;
82 78
79 HANDLE curr_process = GetCurrentProcess ();
80 BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE;
81 unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT];
82 unsigned int fds_to_close_bound = 0;
83 int result;
83 for (;;) 84 for (;;)
84 { 85 {
85 HANDLE new_handle; 86 HANDLE new_handle;
@@ -146,9 +147,8 @@ dupfd (int oldfd, int newfd, int flags)
146 /* Close the previous fds that turned out to be too small. */ 147 /* Close the previous fds that turned out to be too small. */
147 { 148 {
148 int saved_errno = errno; 149 int saved_errno = errno;
149 unsigned int duplicated_fd;
150 150
151 for (duplicated_fd = 0; 151 for (unsigned int duplicated_fd = 0;
152 duplicated_fd < fds_to_close_bound * CHAR_BIT; 152 duplicated_fd < fds_to_close_bound * CHAR_BIT;
153 duplicated_fd++) 153 duplicated_fd++)
154 if ((fds_to_close[duplicated_fd / CHAR_BIT] 154 if ((fds_to_close[duplicated_fd / CHAR_BIT]
@@ -206,8 +206,9 @@ fcntl (int fd, int action, /* arg */...)
206#endif 206#endif
207{ 207{
208 va_list arg; 208 va_list arg;
209 int result = -1;
210 va_start (arg, action); 209 va_start (arg, action);
210
211 int result = -1;
211 switch (action) 212 switch (action)
212 { 213 {
213 case F_DUPFD: 214 case F_DUPFD:
@@ -376,12 +377,6 @@ fcntl (int fd, int action, /* arg */...)
376 #ifdef F_NOTIFY /* Linux */ 377 #ifdef F_NOTIFY /* Linux */
377 case F_NOTIFY: 378 case F_NOTIFY:
378 #endif 379 #endif
379 #ifdef F_OPLKACK /* IRIX */
380 case F_OPLKACK:
381 #endif
382 #ifdef F_OPLKREG /* IRIX */
383 case F_OPLKREG:
384 #endif
385 #ifdef F_RDAHEAD /* macOS */ 380 #ifdef F_RDAHEAD /* macOS */
386 case F_RDAHEAD: 381 case F_RDAHEAD:
387 #endif 382 #endif
@@ -439,7 +434,9 @@ fcntl (int fd, int action, /* arg */...)
439 break; 434 break;
440 } 435 }
441 } 436 }
437
442 va_end (arg); 438 va_end (arg);
439
443 return result; 440 return result;
444} 441}
445 442
@@ -546,78 +543,115 @@ rpl_fcntl_DUPFD_CLOEXEC (int fd, int target)
546#undef fcntl 543#undef fcntl
547 544
548#ifdef __KLIBC__ 545#ifdef __KLIBC__
549
550static int 546static int
551klibc_fcntl (int fd, int action, /* arg */...) 547klibc_dupdirfd (int fd, int minfd)
552{ 548{
553 va_list arg_ptr; 549 int tempfd = open ("NUL", O_RDONLY);
554 int arg; 550 if (tempfd == -1)
555 struct stat sbuf; 551 return -1;
556 int result;
557 552
558 va_start (arg_ptr, action); 553 if (tempfd >= minfd)
559 arg = va_arg (arg_ptr, int);
560 result = fcntl (fd, action, arg);
561 /* EPERM for F_DUPFD, ENOTSUP for others */
562 if (result == -1 && (errno == EPERM || errno == ENOTSUP)
563 && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
564 { 554 {
565 ULONG ulMode; 555 close (tempfd);
566 556
567 switch (action) 557 char path[_MAX_PATH];
568 { 558 if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
569 case F_DUPFD: 559 return -1;
570 /* Find available fd */
571 while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
572 arg++;
573 560
574 result = dup2 (fd, arg); 561 int dupfd = open (path, O_RDONLY);
575 break; 562 if (dupfd == -1)
563 return -1;
576 564
577 /* Using underlying APIs is right ? */ 565 if (dupfd >= minfd)
578 case F_GETFD: 566 return dupfd;
579 if (DosQueryFHState (fd, &ulMode))
580 break;
581
582 result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
583 break;
584
585 case F_SETFD:
586 if (arg & ~FD_CLOEXEC)
587 break;
588 567
589 if (DosQueryFHState (fd, &ulMode)) 568 /* Lower FD was closed by other threads. Fill again. */
590 break; 569 tempfd = dupfd;
570 }
591 571
592 if (arg & FD_CLOEXEC) 572 int dupfd = klibc_dupdirfd (fd, minfd);
593 ulMode |= OPEN_FLAGS_NOINHERIT;
594 else
595 ulMode &= ~OPEN_FLAGS_NOINHERIT;
596 573
597 /* Filter supported flags. */ 574 close (tempfd);
598 ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
599 | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
600 575
601 if (DosSetFHState (fd, ulMode)) 576 return dupfd;
602 break; 577}
603
604 result = 0;
605 break;
606 578
607 case F_GETFL: 579static int
608 result = 0; 580klibc_fcntl (int fd, int action, /* arg */...)
609 break; 581{
582 va_list arg_ptr;
583 va_start (arg_ptr, action);
610 584
611 case F_SETFL: 585 int arg = va_arg (arg_ptr, int);
612 if (arg != 0) 586 int result = fcntl (fd, action, arg);
613 break; 587 /* EPERM for F_DUPFD, ENOTSUP for others */
588 if (result == -1 && (errno == EPERM || errno == ENOTSUP))
589 {
590 struct stat sbuf;
591 if (!fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
592 {
593 switch (action)
594 {
595 case F_DUPFD:
596 result = klibc_dupdirfd (fd, arg);
597 break;
598
599 case F_GETFD:
600 {
601 PLIBCFH pFH = __libc_FH (fd);
602 if (!pFH)
603 {
604 errno = EBADF;
605 break;
606 }
607
608 result = (pFH->fFlags & ((FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT )
609 | O_NOINHERIT)) ? FD_CLOEXEC : 0;
610 }
611 break;
612
613 case F_SETFD:
614 {
615 if (arg & ~FD_CLOEXEC)
616 break;
617
618 PLIBCFH pFH = __libc_FH (fd);
619 if (!pFH)
620 {
621 errno = EBADF;
622 break;
623 }
624
625 unsigned fFlags = pFH->fFlags;
626 if (arg & FD_CLOEXEC)
627 fFlags |= (FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT) | O_NOINHERIT;
628 else
629 fFlags &= ~((FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT) | O_NOINHERIT);
630
631 result = __libc_FHSetFlags (pFH, fd, fFlags);
632 if (result < 0)
633 {
634 errno = -result;
635 result = -1;
636 }
637 }
638 break;
639
640 case F_GETFL:
641 result = 0;
642 break;
643
644 case F_SETFL:
645 if (arg != 0)
646 break;
614 647
615 result = 0; 648 result = 0;
616 break; 649 break;
617 650
618 default: 651 default:
619 errno = EINVAL; 652 errno = EINVAL;
620 break; 653 break;
654 }
621 } 655 }
622 } 656 }
623 657