mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-27 04:52:05 +08:00
5e8754f90a
This reverts commit 7a6dbc2fdb
("Update
gnulib to current upstream master"). It is needed because the gnulib
update caused problems with people using old GCC compilers (version
4.8, for example), which support C99 but don't default to using it.
Unfortunately this broke GDB for these users. A more detailed report
of what happened can be found at:
https://lists.gnu.org/archive/html/bug-gnulib/2018-08/msg00157.html
The reason for updating our gnulib copy was to fix PR gdb/23558.
Reverting this patch reintroduces the bug, so in order to fix it I
will submit a subsequent patch which cherry-picks the fix from gnulib.
gdb/ChangeLog:
2018-09-10 Sergio Durigan Junior <sergiodj@redhat.com>
Revert:
2018-08-29 Sergio Durigan Junior <sergiodj@redhat.com>
PR gdb/23555
PR gdb/23558
* gnulib/aclocal.m4: Regenerate.
* gnulib/config.in: Regenerate.
* gnulib/configure: Regenerate.
* gnulib/import/Makefile.am: Update.
* gnulib/import/Makefile.in: Update.
* gnulib/import/extra/snippet/_Noreturn.h: Rename to...
* gnulib/import/_Noreturn.h: ... this.
* gnulib/import/alloca.in.h: Update.
* gnulib/import/extra/snippet/arg-nonnull.h: Rename to...
* gnulib/import/arg-nonnull.h: ... this.
* gnulib/import/assure.h: Update.
* gnulib/import/at-func.c: Update.
* gnulib/import/basename-lgpl.c: Update.
* gnulib/import/extra/snippet/c++defs.h: Rename to...
* gnulib/import/c++defs.h: ... this.
* gnulib/import/canonicalize-lgpl.c: Update.
* gnulib/import/cdefs.h: Update.
* gnulib/import/chdir-long.c: Update.
* gnulib/import/chdir-long.h: Update.
* gnulib/import/cloexec.c: Update.
* gnulib/import/cloexec.h: Update.
* gnulib/import/close.c: Update.
* gnulib/import/closedir.c: Update.
* gnulib/import/config.charset: Update.
* gnulib/import/dirent-private.h: Update.
* gnulib/import/dirent.in.h: Update.
* gnulib/import/dirfd.c: Update.
* gnulib/import/dirname-lgpl.c: Update.
* gnulib/import/dirname.h: Update.
* gnulib/import/dosname.h: Update.
* gnulib/import/dup-safer-flag.c: Update.
* gnulib/import/dup-safer.c: Update.
* gnulib/import/dup.c: Update.
* gnulib/import/dup2.c: Update.
* gnulib/import/errno.in.h: Update.
* gnulib/import/error.c: Update.
* gnulib/import/error.h: Update.
* gnulib/import/exitfail.c: Update.
* gnulib/import/exitfail.h: Update.
* gnulib/import/extra/update-copyright: Update.
* gnulib/import/fchdir.c: Update.
* gnulib/import/fcntl.c: Update.
* gnulib/import/fcntl.in.h: Update.
* gnulib/import/fd-hook.c: Update.
* gnulib/import/fd-hook.h: Update.
* gnulib/import/fd-safer-flag.c: Update.
* gnulib/import/fd-safer.c: Update.
* gnulib/import/fdopendir.c: Update.
* gnulib/import/filename.h: Update.
* gnulib/import/filenamecat-lgpl.c: Update.
* gnulib/import/filenamecat.h: Update.
* gnulib/import/flexmember.h: Update.
* gnulib/import/float+.h: Update.
* gnulib/import/float.c: Update.
* gnulib/import/float.in.h: Update.
* gnulib/import/fnmatch.c: Update.
* gnulib/import/fnmatch.in.h: Update.
* gnulib/import/fnmatch_loop.c: Update.
* gnulib/import/fpucw.h: Update.
* gnulib/import/frexp.c: Update.
* gnulib/import/frexpl.c: Update.
* gnulib/import/fstat.c: Update.
* gnulib/import/fstatat.c: Update.
* gnulib/import/getcwd-lgpl.c: Update.
* gnulib/import/getcwd.c: Update.
* gnulib/import/getdtablesize.c: Update.
* gnulib/import/getlogin_r.c: Update.
* gnulib/import/getprogname.c: Update.
* gnulib/import/getprogname.h: Update.
* gnulib/import/gettext.h: Update.
* gnulib/import/gettimeofday.c: Update.
* gnulib/import/glob-libc.h: Update.
* gnulib/import/glob.c: Update.
* gnulib/import/glob.in.h: Update.
* gnulib/import/glob_internal.h: Update.
* gnulib/import/glob_pattern_p.c: Update.
* gnulib/import/globfree.c: Update.
* gnulib/import/hard-locale.c: Update.
* gnulib/import/hard-locale.h: Update.
* gnulib/import/intprops.h: Update.
* gnulib/import/inttypes.in.h: Update.
* gnulib/import/isnan.c: Update.
* gnulib/import/isnand-nolibm.h: Update.
* gnulib/import/isnand.c: Update.
* gnulib/import/isnanl-nolibm.h: Update.
* gnulib/import/isnanl.c: Update.
* gnulib/import/itold.c: Update.
* gnulib/import/libc-config.h: Update.
* gnulib/import/limits.in.h: Update.
* gnulib/import/localcharset.c: Update.
* gnulib/import/localcharset.h: Update.
* gnulib/import/localtime-buffer.c: Update.
* gnulib/import/localtime-buffer.h: Update.
* gnulib/import/lstat.c: Update.
* gnulib/import/m4/00gnulib.m4: Update.
* gnulib/import/m4/__inline.m4: Update.
* gnulib/import/m4/absolute-header.m4: Update.
* gnulib/import/m4/alloca.m4: Update.
* gnulib/import/m4/builtin-expect.m4: Update.
* gnulib/import/m4/canonicalize.m4: Update.
* gnulib/import/m4/chdir-long.m4: Update.
* gnulib/import/m4/close.m4: Update.
* gnulib/import/m4/closedir.m4: Update.
* gnulib/import/m4/configmake.m4: Update.
* gnulib/import/m4/d-ino.m4: Update.
* gnulib/import/m4/d-type.m4: Update.
* gnulib/import/m4/dirent_h.m4: Update.
* gnulib/import/m4/dirfd.m4: Update.
* gnulib/import/m4/dirname.m4: Update.
* gnulib/import/m4/double-slash-root.m4: Update.
* gnulib/import/m4/dup.m4: Update.
* gnulib/import/m4/dup2.m4: Update.
* gnulib/import/m4/eealloc.m4: Update.
* gnulib/import/m4/environ.m4: Update.
* gnulib/import/m4/errno_h.m4: Update.
* gnulib/import/m4/error.m4: Update.
* gnulib/import/m4/exponentd.m4: Update.
* gnulib/import/m4/exponentl.m4: Update.
* gnulib/import/m4/extensions.m4: Update.
* gnulib/import/m4/extern-inline.m4: Update.
* gnulib/import/m4/fchdir.m4: Update.
* gnulib/import/m4/fcntl-o.m4: Update.
* gnulib/import/m4/fcntl.m4: Update.
* gnulib/import/m4/fcntl_h.m4: Update.
* gnulib/import/m4/fdopendir.m4: Update.
* gnulib/import/m4/filenamecat.m4: Update.
* gnulib/import/m4/flexmember.m4: Update.
* gnulib/import/m4/float_h.m4: Update.
* gnulib/import/m4/fnmatch.m4: Update.
* gnulib/import/m4/fnmatch_h.m4: Update.
* gnulib/import/m4/fpieee.m4: Update.
* gnulib/import/m4/frexp.m4: Update.
* gnulib/import/m4/frexpl.m4: Update.
* gnulib/import/m4/fstat.m4: Update.
* gnulib/import/m4/fstatat.m4: Update.
* gnulib/import/m4/getcwd-abort-bug.m4: Update.
* gnulib/import/m4/getcwd-path-max.m4: Update.
* gnulib/import/m4/getcwd.m4: Update.
* gnulib/import/m4/getdtablesize.m4: Update.
* gnulib/import/m4/getlogin.m4: Update.
* gnulib/import/m4/getlogin_r.m4: Update.
* gnulib/import/m4/getpagesize.m4: Update.
* gnulib/import/m4/getprogname.m4: Update.
* gnulib/import/m4/gettimeofday.m4: Update.
* gnulib/import/m4/glibc21.m4: Update.
* gnulib/import/m4/glob.m4: Update.
* gnulib/import/m4/glob_h.m4: Update.
* gnulib/import/m4/gnulib-cache.m4: Update.
* gnulib/import/m4/gnulib-common.m4: Update.
* gnulib/import/m4/gnulib-comp.m4: Update.
* gnulib/import/m4/gnulib-tool.m4: Update.
* gnulib/import/m4/hard-locale.m4: Update.
* gnulib/import/m4/include_next.m4: Update.
* gnulib/import/m4/inttypes-pri.m4: Update.
* gnulib/import/m4/inttypes.m4: Update.
* gnulib/import/m4/isnand.m4: Update.
* gnulib/import/m4/isnanl.m4: Update.
* gnulib/import/m4/largefile.m4: Update.
* gnulib/import/m4/limits-h.m4: Update.
* gnulib/import/m4/localcharset.m4: Update.
* gnulib/import/m4/locale-fr.m4: Update.
* gnulib/import/m4/locale-ja.m4: Update.
* gnulib/import/m4/locale-zh.m4: Update.
* gnulib/import/m4/localtime-buffer.m4: Update.
* gnulib/import/m4/longlong.m4: Update.
* gnulib/import/m4/lstat.m4: Update.
* gnulib/import/m4/malloc.m4: Update.
* gnulib/import/m4/malloca.m4: Update.
* gnulib/import/m4/math_h.m4: Update.
* gnulib/import/m4/mbrtowc.m4: Update.
* gnulib/import/m4/mbsinit.m4: Update.
* gnulib/import/m4/mbsrtowcs.m4: Update.
* gnulib/import/m4/mbstate_t.m4: Update.
* gnulib/import/m4/memchr.m4: Update.
* gnulib/import/m4/memmem.m4: Update.
* gnulib/import/m4/mempcpy.m4: Update.
* gnulib/import/m4/memrchr.m4: Update.
* gnulib/import/m4/mkdir.m4: Update.
* gnulib/import/m4/mkstemp.m4: Update.
* gnulib/import/m4/mmap-anon.m4: Update.
* gnulib/import/m4/mode_t.m4: Update.
* gnulib/import/m4/msvc-inval.m4: Update.
* gnulib/import/m4/msvc-nothrow.m4: Update.
* gnulib/import/m4/multiarch.m4: Update.
* gnulib/import/m4/nocrash.m4: Update.
* gnulib/import/m4/off_t.m4: Update.
* gnulib/import/m4/onceonly.m4: Update.
* gnulib/import/m4/open-cloexec.m4: Update.
* gnulib/import/m4/open.m4: Update.
* gnulib/import/m4/openat.m4: Update.
* gnulib/import/m4/opendir.m4: Update.
* gnulib/import/m4/pathmax.m4: Update.
* gnulib/import/m4/rawmemchr.m4: Update.
* gnulib/import/m4/readdir.m4: Update.
* gnulib/import/m4/readlink.m4: Update.
* gnulib/import/m4/realloc.m4: Update.
* gnulib/import/m4/rename.m4: Update.
* gnulib/import/m4/rewinddir.m4: Update.
* gnulib/import/m4/rmdir.m4: Update.
* gnulib/import/m4/save-cwd.m4: Update.
* gnulib/import/m4/secure_getenv.m4: Update.
* gnulib/import/m4/setenv.m4: Update.
* gnulib/import/m4/signal_h.m4: Update.
* gnulib/import/m4/ssize_t.m4: Update.
* gnulib/import/m4/stat-time.m4: Update.
* gnulib/import/m4/stat.m4: Update.
* gnulib/import/m4/std-gnu11.m4: Update.
* gnulib/import/m4/stdbool.m4: Update.
* gnulib/import/m4/stddef_h.m4: Update.
* gnulib/import/m4/stdint.m4: Update.
* gnulib/import/m4/stdio_h.m4: Update.
* gnulib/import/m4/stdlib_h.m4: Update.
* gnulib/import/m4/strchrnul.m4: Update.
* gnulib/import/m4/strdup.m4: Update.
* gnulib/import/m4/strerror.m4: Update.
* gnulib/import/m4/string_h.m4: Update.
* gnulib/import/m4/strstr.m4: Update.
* gnulib/import/m4/strtok_r.m4: Update.
* gnulib/import/m4/sys_socket_h.m4: Update.
* gnulib/import/m4/sys_stat_h.m4: Update.
* gnulib/import/m4/sys_time_h.m4: Update.
* gnulib/import/m4/sys_types_h.m4: Update.
* gnulib/import/m4/tempname.m4: Update.
* gnulib/import/m4/time_h.m4: Update.
* gnulib/import/m4/unistd-safer.m4: Update.
* gnulib/import/m4/unistd_h.m4: Update.
* gnulib/import/m4/warn-on-use.m4: Update.
* gnulib/import/m4/wchar_h.m4: Update.
* gnulib/import/m4/wchar_t.m4: Update.
* gnulib/import/m4/wctype_h.m4: Update.
* gnulib/import/m4/wint_t.m4: Update.
* gnulib/import/malloc.c: Update.
* gnulib/import/malloc/scratch_buffer.h: Update.
* gnulib/import/malloc/scratch_buffer_grow.c: Update.
* gnulib/import/malloc/scratch_buffer_grow_preserve.c: Update.
* gnulib/import/malloc/scratch_buffer_set_array_size.c: Update.
* gnulib/import/malloca.c: Update.
* gnulib/import/malloca.h: Update.
* gnulib/import/malloca.valgrind: Update.
* gnulib/import/math.in.h: Update.
* gnulib/import/mbrtowc.c: Update.
* gnulib/import/mbsinit.c: Update.
* gnulib/import/mbsrtowcs-impl.h: Update.
* gnulib/import/mbsrtowcs-state.c: Update.
* gnulib/import/mbsrtowcs.c: Update.
* gnulib/import/memchr.c: Update.
* gnulib/import/memmem.c: Update.
* gnulib/import/mempcpy.c: Update.
* gnulib/import/memrchr.c: Update.
* gnulib/import/mkdir.c: Update.
* gnulib/import/mkstemp.c: Update.
* gnulib/import/msvc-inval.c: Update.
* gnulib/import/msvc-inval.h: Update.
* gnulib/import/msvc-nothrow.c: Update.
* gnulib/import/msvc-nothrow.h: Update.
* gnulib/import/open.c: Update.
* gnulib/import/openat-die.c: Update.
* gnulib/import/openat-priv.h: Update.
* gnulib/import/openat-proc.c: Update.
* gnulib/import/openat.c: Update.
* gnulib/import/openat.h: Update.
* gnulib/import/opendir.c: Update.
* gnulib/import/pathmax.h: Update.
* gnulib/import/pipe-safer.c: Update.
* gnulib/import/rawmemchr.c: Update.
* gnulib/import/readdir.c: Update.
* gnulib/import/readlink.c: Update.
* gnulib/import/realloc.c: Update.
* gnulib/import/ref-add.sin: Update.
* gnulib/import/ref-del.sin: Update.
* gnulib/import/rename.c: Update.
* gnulib/import/rewinddir.c: Update.
* gnulib/import/rmdir.c: Update.
* gnulib/import/same-inode.h: Update.
* gnulib/import/save-cwd.c: Update.
* gnulib/import/save-cwd.h: Update.
* gnulib/import/scratch_buffer.h: Update.
* gnulib/import/secure_getenv.c: Update.
* gnulib/import/setenv.c: Update.
* gnulib/import/signal.in.h: Update.
* gnulib/import/stat-time.c: Update.
* gnulib/import/stat-time.h: Update.
* gnulib/import/stat-w32.c: Update.
* gnulib/import/stat-w32.h: Update.
* gnulib/import/stat.c: Update.
* gnulib/import/stdbool.in.h: Update.
* gnulib/import/stddef.in.h: Update.
* gnulib/import/stdint.in.h: Update.
* gnulib/import/stdio.in.h: Update.
* gnulib/import/stdlib.in.h: Update.
* gnulib/import/str-two-way.h: Update.
* gnulib/import/strchrnul.c: Update.
* gnulib/import/strdup.c: Update.
* gnulib/import/streq.h: Update.
* gnulib/import/strerror-override.c: Update.
* gnulib/import/strerror-override.h: Update.
* gnulib/import/strerror.c: Update.
* gnulib/import/string.in.h: Update.
* gnulib/import/stripslash.c: Update.
* gnulib/import/strnlen1.c: Update.
* gnulib/import/strnlen1.h: Update.
* gnulib/import/strstr.c: Update.
* gnulib/import/strtok_r.c: Update.
* gnulib/import/sys_stat.in.h: Update.
* gnulib/import/sys_time.in.h: Update.
* gnulib/import/sys_types.in.h: Update.
* gnulib/import/tempname.c: Update.
* gnulib/import/tempname.h: Update.
* gnulib/import/time.in.h: Update.
* gnulib/import/unistd--.h: Update.
* gnulib/import/unistd-safer.h: Update.
* gnulib/import/unistd.in.h: Update.
* gnulib/import/unsetenv.c: Update.
* gnulib/import/verify.h: Update.
* gnulib/import/extra/snippet/warn-on-use.h: Update.
* gnulib/import/wchar.in.h: Update.
* gnulib/import/wctype.in.h: Update.
* gnulib/import/xalloc-oversized.h: Update.
* gnulib/update-gnulib.sh (GNULIB_COMMIT_SHA1): Set to
"53e2c179f26a890fa6685af4b6c1397ee370433b".
415 lines
12 KiB
C
415 lines
12 KiB
C
/* Provide file descriptor control.
|
|
|
|
Copyright (C) 2009-2016 Free Software Foundation, Inc.
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
/* Written by Eric Blake <ebb9@byu.net>. */
|
|
|
|
#include <config.h>
|
|
|
|
/* Specification. */
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <stdarg.h>
|
|
#include <unistd.h>
|
|
|
|
#if !HAVE_FCNTL
|
|
# define rpl_fcntl fcntl
|
|
#endif
|
|
#undef fcntl
|
|
|
|
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
|
|
/* Get declarations of the native Windows API functions. */
|
|
# define WIN32_LEAN_AND_MEAN
|
|
# include <windows.h>
|
|
|
|
/* Get _get_osfhandle. */
|
|
# include "msvc-nothrow.h"
|
|
|
|
/* Upper bound on getdtablesize(). See lib/getdtablesize.c. */
|
|
# define OPEN_MAX_MAX 0x10000
|
|
|
|
/* Duplicate OLDFD into the first available slot of at least NEWFD,
|
|
which must be positive, with FLAGS determining whether the duplicate
|
|
will be inheritable. */
|
|
static int
|
|
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;
|
|
}
|
|
if (old_handle == INVALID_HANDLE_VALUE
|
|
|| (mode = setmode (oldfd, O_BINARY)) == -1)
|
|
{
|
|
/* oldfd is not open, or is an unassigned standard file
|
|
descriptor. */
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
setmode (oldfd, mode);
|
|
flags |= mode;
|
|
|
|
for (;;)
|
|
{
|
|
HANDLE new_handle;
|
|
int duplicated_fd;
|
|
unsigned int index;
|
|
|
|
if (!DuplicateHandle (curr_process, /* SourceProcessHandle */
|
|
old_handle, /* SourceHandle */
|
|
curr_process, /* TargetProcessHandle */
|
|
(PHANDLE) &new_handle, /* TargetHandle */
|
|
(DWORD) 0, /* DesiredAccess */
|
|
inherit, /* InheritHandle */
|
|
DUPLICATE_SAME_ACCESS)) /* Options */
|
|
{
|
|
switch (GetLastError ())
|
|
{
|
|
case ERROR_TOO_MANY_OPEN_FILES:
|
|
errno = EMFILE;
|
|
break;
|
|
case ERROR_INVALID_HANDLE:
|
|
case ERROR_INVALID_TARGET_HANDLE:
|
|
case ERROR_DIRECT_ACCESS_HANDLE:
|
|
errno = EBADF;
|
|
break;
|
|
case ERROR_INVALID_PARAMETER:
|
|
case ERROR_INVALID_FUNCTION:
|
|
case ERROR_INVALID_ACCESS:
|
|
errno = EINVAL;
|
|
break;
|
|
default:
|
|
errno = EACCES;
|
|
break;
|
|
}
|
|
result = -1;
|
|
break;
|
|
}
|
|
duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags);
|
|
if (duplicated_fd < 0)
|
|
{
|
|
CloseHandle (new_handle);
|
|
result = -1;
|
|
break;
|
|
}
|
|
if (newfd <= duplicated_fd)
|
|
{
|
|
result = duplicated_fd;
|
|
break;
|
|
}
|
|
|
|
/* Set the bit duplicated_fd in fds_to_close[]. */
|
|
index = (unsigned int) duplicated_fd / CHAR_BIT;
|
|
if (fds_to_close_bound <= index)
|
|
{
|
|
if (sizeof fds_to_close <= index)
|
|
/* Need to increase OPEN_MAX_MAX. */
|
|
abort ();
|
|
memset (fds_to_close + fds_to_close_bound, '\0',
|
|
index + 1 - fds_to_close_bound);
|
|
fds_to_close_bound = index + 1;
|
|
}
|
|
fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT);
|
|
}
|
|
|
|
/* Close the previous fds that turned out to be too small. */
|
|
{
|
|
int saved_errno = errno;
|
|
unsigned int duplicated_fd;
|
|
|
|
for (duplicated_fd = 0;
|
|
duplicated_fd < fds_to_close_bound * CHAR_BIT;
|
|
duplicated_fd++)
|
|
if ((fds_to_close[duplicated_fd / CHAR_BIT]
|
|
>> (duplicated_fd % CHAR_BIT))
|
|
& 1)
|
|
close (duplicated_fd);
|
|
|
|
errno = saved_errno;
|
|
}
|
|
|
|
# if REPLACE_FCHDIR
|
|
if (0 <= result)
|
|
result = _gl_register_dup (oldfd, result);
|
|
# endif
|
|
return result;
|
|
}
|
|
#endif /* W32 */
|
|
|
|
#ifdef __KLIBC__
|
|
|
|
# define INCL_DOS
|
|
# include <os2.h>
|
|
|
|
static int
|
|
klibc_fcntl (int fd, int action, /* arg */...)
|
|
{
|
|
va_list arg_ptr;
|
|
int arg;
|
|
struct stat sbuf;
|
|
int result = -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))
|
|
{
|
|
ULONG ulMode;
|
|
|
|
switch (action)
|
|
{
|
|
case F_DUPFD:
|
|
/* Find available fd */
|
|
while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
|
|
arg++;
|
|
|
|
result = dup2 (fd, arg);
|
|
break;
|
|
|
|
/* 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 (DosQueryFHState (fd, &ulMode))
|
|
break;
|
|
|
|
if (arg & FD_CLOEXEC)
|
|
ulMode |= OPEN_FLAGS_NOINHERIT;
|
|
else
|
|
ulMode &= ~OPEN_FLAGS_NOINHERIT;
|
|
|
|
/* Filter supported flags. */
|
|
ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
|
|
| OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
|
|
|
|
if (DosSetFHState (fd, ulMode))
|
|
break;
|
|
|
|
result = 0;
|
|
break;
|
|
|
|
case F_GETFL:
|
|
result = 0;
|
|
break;
|
|
|
|
case F_SETFL:
|
|
if (arg != 0)
|
|
break;
|
|
|
|
result = 0;
|
|
break;
|
|
|
|
default :
|
|
errno = EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
va_end (arg_ptr);
|
|
|
|
return result;
|
|
}
|
|
|
|
# define fcntl klibc_fcntl
|
|
#endif
|
|
|
|
/* Perform the specified ACTION on the file descriptor FD, possibly
|
|
using the argument ARG further described below. This replacement
|
|
handles the following actions, and forwards all others on to the
|
|
native fcntl. An unrecognized ACTION returns -1 with errno set to
|
|
EINVAL.
|
|
|
|
F_DUPFD - duplicate FD, with int ARG being the minimum target fd.
|
|
If successful, return the duplicate, which will be inheritable;
|
|
otherwise return -1 and set errno.
|
|
|
|
F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum
|
|
target fd. If successful, return the duplicate, which will not be
|
|
inheritable; otherwise return -1 and set errno.
|
|
|
|
F_GETFD - ARG need not be present. If successful, return a
|
|
non-negative value containing the descriptor flags of FD (only
|
|
FD_CLOEXEC is portable, but other flags may be present); otherwise
|
|
return -1 and set errno. */
|
|
|
|
int
|
|
rpl_fcntl (int fd, int action, /* arg */...)
|
|
{
|
|
va_list arg;
|
|
int result = -1;
|
|
va_start (arg, action);
|
|
switch (action)
|
|
{
|
|
|
|
#if !HAVE_FCNTL
|
|
case F_DUPFD:
|
|
{
|
|
int target = va_arg (arg, int);
|
|
result = dupfd (fd, target, 0);
|
|
break;
|
|
}
|
|
#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
|
|
case F_DUPFD:
|
|
{
|
|
int target = va_arg (arg, int);
|
|
/* Detect invalid target; needed for cygwin 1.5.x. */
|
|
if (target < 0 || getdtablesize () <= target)
|
|
errno = EINVAL;
|
|
else
|
|
{
|
|
/* Haiku alpha 2 loses fd flags on original. */
|
|
int flags = fcntl (fd, F_GETFD);
|
|
if (flags < 0)
|
|
{
|
|
result = -1;
|
|
break;
|
|
}
|
|
result = fcntl (fd, action, target);
|
|
if (0 <= result && fcntl (fd, F_SETFD, flags) == -1)
|
|
{
|
|
int saved_errno = errno;
|
|
close (result);
|
|
result = -1;
|
|
errno = saved_errno;
|
|
}
|
|
# if REPLACE_FCHDIR
|
|
if (0 <= result)
|
|
result = _gl_register_dup (fd, result);
|
|
# endif
|
|
}
|
|
break;
|
|
} /* F_DUPFD */
|
|
#endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */
|
|
|
|
case F_DUPFD_CLOEXEC:
|
|
{
|
|
int target = va_arg (arg, int);
|
|
|
|
#if !HAVE_FCNTL
|
|
result = dupfd (fd, target, O_CLOEXEC);
|
|
break;
|
|
#else /* HAVE_FCNTL */
|
|
/* Try the system call first, if the headers claim it exists
|
|
(that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
|
|
may be running with a glibc that has the macro but with an
|
|
older kernel that does not support it. Cache the
|
|
information on whether the system call really works, but
|
|
avoid caching failure if the corresponding F_DUPFD fails
|
|
for any reason. 0 = unknown, 1 = yes, -1 = no. */
|
|
static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
|
|
if (0 <= have_dupfd_cloexec)
|
|
{
|
|
result = fcntl (fd, action, target);
|
|
if (0 <= result || errno != EINVAL)
|
|
{
|
|
have_dupfd_cloexec = 1;
|
|
# if REPLACE_FCHDIR
|
|
if (0 <= result)
|
|
result = _gl_register_dup (fd, result);
|
|
# endif
|
|
}
|
|
else
|
|
{
|
|
result = rpl_fcntl (fd, F_DUPFD, target);
|
|
if (result < 0)
|
|
break;
|
|
have_dupfd_cloexec = -1;
|
|
}
|
|
}
|
|
else
|
|
result = rpl_fcntl (fd, F_DUPFD, target);
|
|
if (0 <= result && have_dupfd_cloexec == -1)
|
|
{
|
|
int flags = fcntl (result, F_GETFD);
|
|
if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
|
|
{
|
|
int saved_errno = errno;
|
|
close (result);
|
|
errno = saved_errno;
|
|
result = -1;
|
|
}
|
|
}
|
|
break;
|
|
#endif /* HAVE_FCNTL */
|
|
} /* F_DUPFD_CLOEXEC */
|
|
|
|
#if !HAVE_FCNTL
|
|
case F_GETFD:
|
|
{
|
|
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
|
|
HANDLE handle = (HANDLE) _get_osfhandle (fd);
|
|
DWORD flags;
|
|
if (handle == INVALID_HANDLE_VALUE
|
|
|| GetHandleInformation (handle, &flags) == 0)
|
|
errno = EBADF;
|
|
else
|
|
result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC;
|
|
# else /* !W32 */
|
|
/* Use dup2 to reject invalid file descriptors. No way to
|
|
access this information, so punt. */
|
|
if (0 <= dup2 (fd, fd))
|
|
result = 0;
|
|
# endif /* !W32 */
|
|
break;
|
|
} /* F_GETFD */
|
|
#endif /* !HAVE_FCNTL */
|
|
|
|
/* Implementing F_SETFD on mingw is not trivial - there is no
|
|
API for changing the O_NOINHERIT bit on an fd, and merely
|
|
changing the HANDLE_FLAG_INHERIT bit on the underlying handle
|
|
can lead to odd state. It may be possible by duplicating the
|
|
handle, using _open_osfhandle with the right flags, then
|
|
using dup2 to move the duplicate onto the original, but that
|
|
is not supported for now. */
|
|
|
|
default:
|
|
{
|
|
#if HAVE_FCNTL
|
|
void *p = va_arg (arg, void *);
|
|
result = fcntl (fd, action, p);
|
|
#else
|
|
errno = EINVAL;
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
va_end (arg);
|
|
return result;
|
|
}
|