From 9df7fd21fac8a3af186c9c560ff0da10f007ccc5 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sun, 18 Sep 2011 10:34:24 +0200
Subject: [PATCH] dup2: Support for MSVC.

* lib/dup2.c: Include msvc-inval.h.
(rpl_dup2): Handle invalid parameter notifications during dup2 and
_get_osfhandle calls.
* modules/dup2 (Depends-on): Add msvc-inval.
* doc/posix-functions/dup2.texi: Mention problem on MSVC.
---
 ChangeLog                     |  7 +++++++
 doc/posix-functions/dup2.texi |  4 ++++
 lib/dup2.c                    | 29 +++++++++++++++++++++++++++--
 modules/dup2                  |  1 +
 4 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ce725eb6e2..bd98467e63 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2011-09-18  Bruno Haible  <bruno@clisp.org>
 
+	dup2: Support for MSVC.
+	* lib/dup2.c: Include msvc-inval.h.
+	(rpl_dup2): Handle invalid parameter notifications during dup2 and
+	_get_osfhandle calls.
+	* modules/dup2 (Depends-on): Add msvc-inval.
+	* doc/posix-functions/dup2.texi: Mention problem on MSVC.
+
 	New module 'msvc-inval'.
 	* lib/msvc-inval.h: New file.
 	* lib/msvc-inval.c: New file.
diff --git a/doc/posix-functions/dup2.texi b/doc/posix-functions/dup2.texi
index 8ba64bda74..012bb7f0e0 100644
--- a/doc/posix-functions/dup2.texi
+++ b/doc/posix-functions/dup2.texi
@@ -16,6 +16,10 @@ mingw, MSVC 9.
 This function can hang when duplicating an fd to itself on some platforms:
 mingw, MSVC 9.
 
+@item
+This function crashes when invoked with invalid arguments on some platforms:
+MSVC 9.
+
 @item
 This function resets the @code{FD_CLOEXEC} flag when duplicating an fd
 to itself on some platforms:
diff --git a/lib/dup2.c b/lib/dup2.c
index e00dc7b2e3..09ae49fb3f 100644
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -31,6 +31,8 @@
 # include <windows.h>
 #endif
 
+#include "msvc-inval.h"
+
 #if HAVE_DUP2
 
 # undef dup2
@@ -45,7 +47,19 @@ rpl_dup2 (int fd, int desired_fd)
      future dup2 calls will hang.  */
   if (fd == desired_fd)
     {
-      if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE)
+      HANDLE handle;
+
+      TRY_MSVC_INVAL
+        {
+          handle = (HANDLE) _get_osfhandle (fd);
+        }
+      CATCH_MSVC_INVAL
+        {
+          handle = INVALID_HANDLE_VALUE;
+        }
+      DONE_MSVC_INVAL
+
+      if (handle == INVALID_HANDLE_VALUE)
         {
           errno = EBADF;
           return -1;
@@ -64,7 +78,18 @@ rpl_dup2 (int fd, int desired_fd)
   if (fd == desired_fd)
     return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
 # endif
-  result = dup2 (fd, desired_fd);
+
+  TRY_MSVC_INVAL
+    {
+      result = dup2 (fd, desired_fd);
+    }
+  CATCH_MSVC_INVAL
+    {
+      result = -1;
+      errno = EBADF;
+    }
+  DONE_MSVC_INVAL
+
 # ifdef __linux__
   /* Correct a Linux return value.
      <http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.30.y.git;a=commitdiff;h=2b79bc4f7ebbd5af3c8b867968f9f15602d5f802>
diff --git a/modules/dup2 b/modules/dup2
index f9a1ee3f37..a94dc17162 100644
--- a/modules/dup2
+++ b/modules/dup2
@@ -8,6 +8,7 @@ m4/dup2.m4
 Depends-on:
 unistd
 dup2-obsolete
+msvc-inval      [test $HAVE_DUP2 = 0 || test $REPLACE_DUP2 = 1]
 
 configure.ac:
 gl_FUNC_DUP2
-- 
2.39.5