aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dup2.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dup2.c')
-rw-r--r--lib/dup2.c71
1 files changed, 48 insertions, 23 deletions
diff --git a/lib/dup2.c b/lib/dup2.c
index e00dc7b2e3c..790c98a2e84 100644
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -25,21 +25,26 @@
25#include <errno.h> 25#include <errno.h>
26#include <fcntl.h> 26#include <fcntl.h>
27 27
28#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
29/* Get declarations of the Win32 API functions. */
30# define WIN32_LEAN_AND_MEAN
31# include <windows.h>
32#endif
33
34#if HAVE_DUP2 28#if HAVE_DUP2
35 29
36# undef dup2 30# undef dup2
37 31
38int 32# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
39rpl_dup2 (int fd, int desired_fd) 33
34/* Get declarations of the Win32 API functions. */
35# define WIN32_LEAN_AND_MEAN
36# include <windows.h>
37
38# include "msvc-inval.h"
39
40/* Get _get_osfhandle. */
41# include "msvc-nothrow.h"
42
43static int
44ms_windows_dup2 (int fd, int desired_fd)
40{ 45{
41 int result; 46 int result;
42# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 47
43 /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, 48 /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open,
44 dup2 (fd, fd) returns 0, but all further attempts to use fd in 49 dup2 (fd, fd) returns 0, but all further attempts to use fd in
45 future dup2 calls will hang. */ 50 future dup2 calls will hang. */
@@ -52,6 +57,7 @@ rpl_dup2 (int fd, int desired_fd)
52 } 57 }
53 return fd; 58 return fd;
54 } 59 }
60
55 /* Wine 1.0.1 return 0 when desired_fd is negative but not -1: 61 /* Wine 1.0.1 return 0 when desired_fd is negative but not -1:
56 http://bugs.winehq.org/show_bug.cgi?id=21289 */ 62 http://bugs.winehq.org/show_bug.cgi?id=21289 */
57 if (desired_fd < 0) 63 if (desired_fd < 0)
@@ -59,26 +65,45 @@ rpl_dup2 (int fd, int desired_fd)
59 errno = EBADF; 65 errno = EBADF;
60 return -1; 66 return -1;
61 } 67 }
62# elif !defined __linux__ 68
63 /* On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ 69 TRY_MSVC_INVAL
64 if (fd == desired_fd) 70 {
65 return fcntl (fd, F_GETFL) == -1 ? -1 : fd; 71 result = dup2 (fd, desired_fd);
66# endif 72 }
67 result = dup2 (fd, desired_fd); 73 CATCH_MSVC_INVAL
68# ifdef __linux__
69 /* Correct a Linux return value.
70 <http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.30.y.git;a=commitdiff;h=2b79bc4f7ebbd5af3c8b867968f9f15602d5f802>
71 */
72 if (fd == desired_fd && result == (unsigned int) -EBADF)
73 { 74 {
74 errno = EBADF; 75 errno = EBADF;
75 result = -1; 76 result = -1;
76 } 77 }
77# endif 78 DONE_MSVC_INVAL;
79
78 if (result == 0) 80 if (result == 0)
79 result = desired_fd; 81 result = desired_fd;
80 /* Correct a cygwin 1.5.x errno value. */ 82
81 else if (result == -1 && errno == EMFILE) 83 return result;
84}
85
86# define dup2 ms_windows_dup2
87
88# endif
89
90int
91rpl_dup2 (int fd, int desired_fd)
92{
93 int result;
94
95# ifdef F_GETFL
96 /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF.
97 On Cygwin 1.5.x, dup2 (1, 1) returns 0.
98 On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */
99 if (fd == desired_fd)
100 return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
101# endif
102
103 result = dup2 (fd, desired_fd);
104
105 /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */
106 if (result == -1 && errno == EMFILE)
82 errno = EBADF; 107 errno = EBADF;
83# if REPLACE_FCHDIR 108# if REPLACE_FCHDIR
84 if (fd != desired_fd && result != -1) 109 if (fd != desired_fd && result != -1)