From 4c78be52dfa2f8991e763e501c5c8e5b232d6d0a Mon Sep 17 00:00:00 2001
From: Christopher Faylor <me@cgf.cx>
Date: Mon, 24 Jun 2002 20:05:52 +0000
Subject: [PATCH] * dtable.cc (fhandler_base::dup2): Cleanup.  Ensure that lock
 is turned off in error condition.

---
 winsup/cygwin/ChangeLog |  5 +++++
 winsup/cygwin/dtable.cc | 41 +++++++++++++++++++++--------------------
 2 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 6ff5adfda..0be5f97ff 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,8 @@
+2002-06-24  Christopher Faylor  <cgf@redhat.com>
+
+	* dtable.cc (fhandler_base::dup2): Cleanup.  Ensure that lock is turned
+	off in error condition.
+
 2002-06-24  Corinna Vinschen  <corinna@vinschen.de>
 
 	* uinfo.cc (internal_getlogin): Set myself->uid and myself->gid instead
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index b94e9cf38..95225bb49 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -433,6 +433,7 @@ dtable::dup2 (int oldfd, int newfd)
 
   MALLOC_CHECK;
   debug_printf ("dup2 (%d, %d)", oldfd, newfd);
+  SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup");
 
   if (not_open (oldfd))
     {
@@ -441,6 +442,13 @@ dtable::dup2 (int oldfd, int newfd)
       goto done;
     }
 
+  if (newfd < 0)
+    {
+      syscall_printf ("new fd out of bounds: %d", newfd);
+      set_errno (EBADF);
+      goto done;
+    }
+
   if (newfd == oldfd)
     {
       res = 0;
@@ -453,35 +461,28 @@ dtable::dup2 (int oldfd, int newfd)
       goto done;
     }
 
-  debug_printf ("newfh->io_handle %p, oldfh->io_handle %p", newfh->get_io_handle (), fds[oldfd]->get_io_handle ());
-  SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup");
-
-  if (newfd < 0)
-    {
-      syscall_printf ("new fd out of bounds: %d", newfd);
-      set_errno (EBADF);
-      goto done;
-    }
-
-  if ((size_t) newfd >= size)
-   {
-     int inc_size = NOFILE_INCR * ((newfd + NOFILE_INCR - 1) / NOFILE_INCR) -
-		    size;
-     extend (inc_size);
-   }
+  debug_printf ("newfh->io_handle %p, oldfh->io_handle %p",
+		newfh->get_io_handle (), fds[oldfd]->get_io_handle ());
 
   if (!not_open (newfd))
     _close (newfd);
-  fds[newfd] = newfh;
+  else if ((size_t) newfd < size)
+    /* nothing to do */;
+  else if (find_unused_handle (newfd) < 0)
+    {
+      newfh->close ();
+      res = -1;
+      goto done;
+    }
 
-  ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup");
-  MALLOC_CHECK;
+  fds[newfd] = newfh;
 
   if ((res = newfd) <= 2)
     set_std_handle (res);
 
-  MALLOC_CHECK;
 done:
+  MALLOC_CHECK;
+  ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup");
   syscall_printf ("%d = dup2 (%d, %d)", res, oldfd, newfd);
 
   return res;