X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fpipe2.c;h=aca18e3b99f574ae1730fa6a2829296a00d1f9fd;hb=43593319b31e6b0175b8eec4433bac744959822d;hp=6ffb101f3d0ce6cdac672b2733a31ad631834257;hpb=0568a6e8985cc2ae9c57cb03fc81f5305458b7d2;p=gnulib.git diff --git a/lib/pipe2.c b/lib/pipe2.c index 6ffb101f3..aca18e3b9 100644 --- a/lib/pipe2.c +++ b/lib/pipe2.c @@ -1,5 +1,5 @@ /* Create a pipe, with specific opening flags. - Copyright (C) 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2009-2013 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 @@ -24,10 +23,14 @@ #include #include "binary-io.h" -#include "nonblocking.h" +#include "verify.h" + +#if GNULIB_defined_O_NONBLOCK +# include "nonblocking.h" +#endif #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* Native Woe32 API. */ +/* Native Windows API. */ # include @@ -36,6 +39,13 @@ int pipe2 (int fd[2], int flags) { + /* Mingw _pipe() corrupts fd on failure; also, if we succeed at + creating the pipe but later fail at changing fcntl, we want + to leave fd unchanged: http://austingroupbugs.net/view.php?id=467 */ + int tmp[2]; + tmp[0] = fd[0]; + tmp[1] = fd[1]; + #if HAVE_PIPE2 # undef pipe2 /* Try the system call first, if it exists. (We may be running with a glibc @@ -64,25 +74,32 @@ pipe2 (int fd[2], int flags) } #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* Native Woe32 API. */ +/* Native Windows API. */ + + if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0) + { + fd[0] = tmp[0]; + fd[1] = tmp[1]; + return -1; + } + /* O_NONBLOCK handling. + On native Windows platforms, O_NONBLOCK is defined by gnulib. Use the + functions defined by the gnulib module 'nonblocking'. */ +# if GNULIB_defined_O_NONBLOCK if (flags & O_NONBLOCK) { - int result = _pipe (fd, 4096, flags & ~O_NONBLOCK); - if (result != 0) - return result; if (set_nonblocking_flag (fd[0], true) != 0 || set_nonblocking_flag (fd[1], true) != 0) - { - int saved_errno = errno; - close (fd[0]); - close (fd[1]); - result = -1; - errno = saved_errno; - } - return result; + goto fail; } - return _pipe (fd, 4096, flags); +# else + { + verify (O_NONBLOCK == 0); + } +# endif + + return 0; #else /* Unix API. */ @@ -94,6 +111,8 @@ pipe2 (int fd[2], int flags) says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on both fd[0] and fd[1]. */ + /* O_NONBLOCK handling. + On Unix platforms, O_NONBLOCK is defined by the system. Use fcntl(). */ if (flags & O_NONBLOCK) { int fcntl_flags; @@ -119,26 +138,31 @@ pipe2 (int fd[2], int flags) # if O_BINARY if (flags & O_BINARY) { - setmode (fd[1], O_BINARY); - setmode (fd[0], O_BINARY); + set_binary_mode (fd[1], O_BINARY); + set_binary_mode (fd[0], O_BINARY); } else if (flags & O_TEXT) { - setmode (fd[1], O_TEXT); - setmode (fd[0], O_TEXT); + set_binary_mode (fd[1], O_TEXT); + set_binary_mode (fd[0], O_TEXT); } # endif return 0; +#endif + +#if GNULIB_defined_O_NONBLOCK || \ + !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) fail: { int saved_errno = errno; close (fd[0]); close (fd[1]); + fd[0] = tmp[0]; + fd[1] = tmp[1]; errno = saved_errno; return -1; } - #endif }