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_CLOEXEC - duplicate FD, with int ARG being the minimum
39 target fd. If successful, return the duplicate, which will not be
40 inheritable; otherwise return -1 and set errno. */
43 rpl_fcntl (int fd, int action, /* arg */...)
47 va_start (arg, action);
52 int target = va_arg (arg, int);
54 /* Try the system call first, if the headers claim it exists
55 (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
56 may be running with a glibc that has the macro but with an
57 older kernel that does not support it. Cache the
58 information on whether the system call really works, but
59 avoid caching failure if the corresponding F_DUPFD fails
60 for any reason. 0 = unknown, 1 = yes, -1 = no. */
61 static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
62 if (0 <= have_dupfd_cloexec)
64 result = fcntl (fd, action, target);
65 if (0 <= result || errno != EINVAL)
66 have_dupfd_cloexec = 1;
69 result = fcntl (fd, F_DUPFD, target);
72 have_dupfd_cloexec = -1;
76 result = fcntl (fd, F_DUPFD, target);
77 if (0 <= result && have_dupfd_cloexec == -1)
79 int flags = fcntl (result, F_GETFD);
80 if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
82 int saved_errno = errno;
90 result = _gl_register_dup (fd, result);
93 } /* F_DUPFD_CLOEXEC */
97 void *p = va_arg (arg, void *);
98 result = fcntl (fd, action, p);