1 /* Provide file descriptor control.
3 Copyright (C) 2009 Free Software Foundation, Inc.
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.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* Written by Eric Blake <ebb9@byu.net>. */
29 # error not ported to mingw yet
33 /* Perform the specified ACTION on the file descriptor FD, possibly
34 using the argument ARG further described below. This replacement
35 handles the following actions, and forwards all others on to the
38 F_DUPFD - duplicate FD, with int ARG being the minimum target fd.
39 If successful, return the duplicate, which will be inheritable;
40 otherwise return -1 and set errno.
42 F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum
43 target fd. If successful, return the duplicate, which will not be
44 inheritable; otherwise return -1 and set errno. */
47 rpl_fcntl (int fd, int action, /* arg */...)
51 va_start (arg, action);
55 #if FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
58 int target = va_arg (arg, int);
59 /* Detect invalid target; needed for cygwin 1.5.x. */
60 if (target < 0 || getdtablesize () <= target)
64 result = fcntl (fd, action, target);
67 result = _gl_register_dup (fd, result);
72 #endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */
76 int target = va_arg (arg, int);
78 /* Try the system call first, if the headers claim it exists
79 (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
80 may be running with a glibc that has the macro but with an
81 older kernel that does not support it. Cache the
82 information on whether the system call really works, but
83 avoid caching failure if the corresponding F_DUPFD fails
84 for any reason. 0 = unknown, 1 = yes, -1 = no. */
85 static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
86 if (0 <= have_dupfd_cloexec)
88 result = fcntl (fd, action, target);
89 if (0 <= result || errno != EINVAL)
91 have_dupfd_cloexec = 1;
94 result = _gl_register_dup (fd, result);
99 result = rpl_fcntl (fd, F_DUPFD, target);
102 have_dupfd_cloexec = -1;
106 result = rpl_fcntl (fd, F_DUPFD, target);
107 if (0 <= result && have_dupfd_cloexec == -1)
109 int flags = fcntl (result, F_GETFD);
110 if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
112 int saved_errno = errno;
119 } /* F_DUPFD_CLOEXEC */
123 void *p = va_arg (arg, void *);
124 result = fcntl (fd, action, p);