strtoumax: fix typo in previous commit.
[gnulib.git] / lib / pipe2.c
index f50dae6..aca18e3 100644 (file)
@@ -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 <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
@@ -31,7 +30,7 @@
 #endif
 
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-/* Native Woe32 API.  */
+/* Native Windows API.  */
 
 # include <io.h>
 
 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
@@ -68,10 +74,14 @@ 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)
-    return -1;
+    {
+      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
@@ -84,7 +94,9 @@ pipe2 (int fd[2], int flags)
         goto fail;
     }
 # else
-  verify (O_NONBLOCK == 0);
+  {
+    verify (O_NONBLOCK == 0);
+  }
 # endif
 
   return 0;
@@ -126,13 +138,13 @@ 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
 
@@ -140,12 +152,17 @@ pipe2 (int fd[2], int flags)
 
 #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
 }