diff options
Diffstat (limited to 'winsup/cygwin/dtable.cc')
-rw-r--r-- | winsup/cygwin/dtable.cc | 37 |
1 files changed, 19 insertions, 18 deletions
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"); + debug_printf ("newfh->io_handle %p, oldfh->io_handle %p", + newfh->get_io_handle (), fds[oldfd]->get_io_handle ()); - if (newfd < 0) + if (!not_open (newfd)) + _close (newfd); + else if ((size_t) newfd < size) + /* nothing to do */; + else if (find_unused_handle (newfd) < 0) { - syscall_printf ("new fd out of bounds: %d", newfd); - set_errno (EBADF); + newfh->close (); + res = -1; goto done; } - if ((size_t) newfd >= size) - { - int inc_size = NOFILE_INCR * ((newfd + NOFILE_INCR - 1) / NOFILE_INCR) - - size; - extend (inc_size); - } - - if (!not_open (newfd)) - _close (newfd); fds[newfd] = newfh; - ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup"); - MALLOC_CHECK; - 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; |