X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fdup3.c;h=5af40b24070439c8bbe44a9f09aa79bc189096d0;hb=cd56634a4a8179fd5a4419fbb3e27211b042ab1c;hp=906594e46978bc2b5e3e29f6fd5833c7d3273eba;hpb=049bfdaa5dfee0ab9b45c089a078db7db595c28c;p=gnulib.git diff --git a/lib/dup3.c b/lib/dup3.c index 906594e46..5af40b240 100644 --- a/lib/dup3.c +++ b/lib/dup3.c @@ -1,5 +1,5 @@ /* Copy a file descriptor, applying specific flags. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009-2014 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 @@ -12,8 +12,7 @@ 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + with this program; if not, see . */ #include @@ -26,30 +25,15 @@ #include "binary-io.h" -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* Native Woe32 API. */ - -/* Get declarations of the Win32 API functions. */ -# define WIN32_LEAN_AND_MEAN -# include - -/* Upper bound on getdtablesize(). See lib/getdtablesize.c. */ -# define OPEN_MAX_MAX 0x10000 - -#else -/* Unix API. */ - -# ifndef O_CLOEXEC -# define O_CLOEXEC 0 -# endif - -#endif - int dup3 (int oldfd, int newfd, int flags) { #if HAVE_DUP3 # undef dup3 +# if HAVE_SETDTABLESIZE + /* Avoid a cygwin crasher. */ + setdtablesize (newfd + 1); +# endif /* Try the system call first, if it exists. (We may be running with a glibc that has the function but with an older kernel that lacks it.) */ { @@ -57,18 +41,22 @@ dup3 (int oldfd, int newfd, int flags) static int have_dup3_really; /* 0 = unknown, 1 = yes, -1 = no */ if (have_dup3_really >= 0) { - int result = dup3 (oldfd, newfd, flags); - if (!(result < 0 && errno == ENOSYS)) - { - have_dup3_really = 1; - return result; - } - have_dup3_really = -1; + int result = dup3 (oldfd, newfd, flags); + if (!(result < 0 && errno == ENOSYS)) + { + have_dup3_really = 1; +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (oldfd, newfd); +# endif + return result; + } + have_dup3_really = -1; } } #endif - if (oldfd < 0 || newfd < 0 || newfd >= getdtablesize ()) + if (newfd < 0 || newfd >= getdtablesize () || fcntl (oldfd, F_GETFD) == -1) { errno = EBADF; return -1; @@ -89,131 +77,28 @@ dup3 (int oldfd, int newfd, int flags) return -1; } -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* Native Woe32 API. */ - if (flags & O_CLOEXEC) { - /* Neither dup() nor dup2() can create a file descriptor with - O_CLOEXEC = O_NOINHERIT set. We need to use the low-level function - _open_osfhandle for this. 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; - - if (old_handle == INVALID_HANDLE_VALUE) - { - /* oldfd is not open, or is an unassigned standard file - descriptor. */ - errno = EBADF; - return -1; - } - close (newfd); - - 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 */ - FALSE, /* InheritHandle */ - DUPLICATE_SAME_ACCESS)) /* Options */ - { - errno = EBADF; /* arbitrary */ - result = -1; - break; - } - duplicated_fd = _open_osfhandle ((long) new_handle, flags); - if (duplicated_fd < 0) - { - CloseHandle (new_handle); - result = -1; - break; - } - if (duplicated_fd > newfd) - /* Shouldn't happen, since newfd is still closed. */ - abort (); - if (duplicated_fd == newfd) - { - result = newfd; - break; - } - - /* Set the bit duplicated_fd in fds_to_close[]. */ - index = (unsigned int) duplicated_fd / CHAR_BIT; - if (index >= fds_to_close_bound) - { - if (index >= sizeof (fds_to_close)) - /* 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; - } - - return result; + result = fcntl (oldfd, F_DUPFD_CLOEXEC, newfd); + if (newfd < result) + { + close (result); + errno = EIO; + result = -1; + } + if (result < 0) + return -1; } - - if (dup2 (oldfd, newfd) < 0) - return -1; - -#else -/* Unix API. */ - - if (dup2 (oldfd, newfd) < 0) + else if (dup2 (oldfd, newfd) < 0) return -1; - /* POSIX - says that initially, the FD_CLOEXEC flag is cleared on newfd. */ - - if (flags & O_CLOEXEC) - { - int fcntl_flags; - - if ((fcntl_flags = fcntl (newfd, F_GETFD, 0)) < 0 - || fcntl (newfd, F_SETFD, fcntl_flags | FD_CLOEXEC) == -1) - { - int saved_errno = errno; - close (newfd); - errno = saved_errno; - return -1; - } - } - -#endif - #if O_BINARY if (flags & O_BINARY) - setmode (newfd, O_BINARY); + set_binary_mode (newfd, O_BINARY); else if (flags & O_TEXT) - setmode (newfd, O_TEXT); + set_binary_mode (newfd, O_TEXT); #endif return newfd;