msvcrt-A12: _dup/_dup2 HANDLE duplication
Jaco Greeff
jaco at puxedo.org
Mon Nov 4 09:16:31 CST 2002
This patch in the msvcrt-A?? series makes sure that we duplicate the
associated HANDLE inside the _dup and _dup2 functions. This leads to the
correct implementation and cleans up the hacked _close function
considderably.
License:
LGPL
Changelog:
* dlls/msvcrt/file.c: Jaco Greeff <jaco at puxedo.org>
- Correctly duplicate the low-level file handle inside the _dup and
_dup2 calls
--[ inline patch ]--
diff -aurN msvcrt-A11/dlls/msvcrt/file.c msvcrt-A12/dlls/msvcrt/file.c
--- msvcrt-A11/dlls/msvcrt/file.c Mon Nov 4 15:06:39 2002
+++ msvcrt-A12/dlls/msvcrt/file.c Mon Nov 4 17:11:35 2002
@@ -178,12 +178,9 @@
}
/* INTERNAL: duplicate an fd slot */
-static int msvcrt_dup_fd(int fd)
+static int msvcrt_dup_fd(int fd, int newfd)
{
- HANDLE hand = msvcrt_fdtoh(fd);
- int newfd = MSVCRT_fdstart;
-
- TRACE("(fd == %d), handle == %p\n", fd, hand);
+ HANDLE newhand, hand = msvcrt_fdtoh(fd);
/* make sure we haven't exhausted our files
* and that the original fd it does have a valid
@@ -204,7 +201,14 @@
* to allow us to have access to the same file as
* per the original fd
*/
- MSVCRT_handles[newfd] = MSVCRT_handles[fd];
+ if (!DuplicateHandle(GetCurrentProcess(), hand,
+ GetCurrentProcess(), &newhand,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ TRACE("Unable to duplicate source handle\n");
+ return -1;
+ }
+ MSVCRT_handles[newfd] = newhand;
MSVCRT_flags[newfd] = MSVCRT_flags[fd];
/* We don't have a specific MSVCRT_FILE or temp file
@@ -214,9 +218,7 @@
MSVCRT_files[newfd] = NULL;
MSVCRT_tempfiles[newfd] = NULL;
- msvcrt_next_free(newfd);
-
- return newfd;
+ return 0;
}
/* INTERNAL: Allocate a FILE* for an fd slot
@@ -442,7 +444,6 @@
*/
int _close(int fd)
{
- int i, closed = 0;
HANDLE hand = msvcrt_fdtoh(fd);
TRACE("(fd == %d), handle == %p\n", fd, hand);
@@ -450,61 +451,47 @@
if (hand == INVALID_HANDLE_VALUE)
return -1;
- /* The handle we are trying to close might have been
- * _dup'ed, in which case we will need to clean all
- * occurances of the specific handle in our internal
- * tables. Hence we run through all and see if the
- * handles match, if they do, we clean up
- */
- for (i = 0; i < MSVCRT_MAX_FILES; i++)
+ /* flush stdio buffers */
+ if (MSVCRT_files[fd])
{
- /* Ok, this is one occurace, clean it up */
- if (MSVCRT_handles[i] == hand)
+ if (MSVCRT_files[fd]->_flag & MSVCRT__IOWRT)
+ MSVCRT_fflush(MSVCRT_files[fd]);
+ if (MSVCRT_files[fd]->_flag & MSVCRT__IOMYBUF)
{
- /* flush stdio buffers */
- if (MSVCRT_files[i])
- {
- if (MSVCRT_files[i]->_flag & MSVCRT__IOWRT)
- MSVCRT_fflush(MSVCRT_files[i]);
- if (MSVCRT_files[fd]->_flag & MSVCRT__IOMYBUF)
- {
- MSVCRT_free(MSVCRT_files[i]->_base);
- MSVCRT_files[i]->_base = NULL;
- }
- }
-
- /* Dont free std FILE*'s, they are not dynamic */
- if (i > 2 && MSVCRT_files[i])
- {
- MSVCRT_free(MSVCRT_files[i]);
- MSVCRT_files[i] = NULL;
- }
-
- msvcrt_free_fd(i);
-
- /* If we haven't close the handle, do so once, and
- * only once. This makes sure we don't close already
- * closed occurances, which will fail
- */
- if ((!closed) && (!CloseHandle(hand)))
- {
- WARN(":failed-last error (%ld)\n" ,GetLastError());
- MSVCRT__set_errno(GetLastError());
- return -1;
- }
- MSVCRT_handles[i] = INVALID_HANDLE_VALUE;
- closed = 1;
-
- if (MSVCRT_tempfiles[i])
- {
- TRACE("deleting temporary file '%s'\n",
MSVCRT_tempfiles[i]);
- _unlink(MSVCRT_tempfiles[i]);
- MSVCRT_free(MSVCRT_tempfiles[i]);
- MSVCRT_tempfiles[i] = NULL;
- }
+ MSVCRT_free(MSVCRT_files[fd]->_base);
+ MSVCRT_files[fd]->_base = NULL;
}
}
+ /* Dont free std FILE*'s, they are not dynamic */
+ if (fd > 2 && MSVCRT_files[fd])
+ {
+ MSVCRT_free(MSVCRT_files[fd]);
+ MSVCRT_files[fd] = NULL;
+ }
+
+ msvcrt_free_fd(fd);
+
+ /* If we haven't close the handle, do so once, and
+ * only once. This makes sure we don't close already
+ * closed occurances, which will fail
+ */
+ if (!CloseHandle(hand))
+ {
+ WARN(":failed-last error (%ld)\n" ,GetLastError());
+ MSVCRT__set_errno(GetLastError());
+ return -1;
+ }
+ MSVCRT_handles[fd] = INVALID_HANDLE_VALUE;
+
+ if (MSVCRT_tempfiles[fd])
+ {
+ TRACE("deleting temporary file '%s'\n", MSVCRT_tempfiles[fd]);
+ _unlink(MSVCRT_tempfiles[fd]);
+ MSVCRT_free(MSVCRT_tempfiles[fd]);
+ MSVCRT_tempfiles[fd] = NULL;
+ }
+
TRACE(":ok\n");
return 0;
}
@@ -713,8 +700,15 @@
*/
int _dup(int fd)
{
+ int newfd = MSVCRT_fdstart;
+
TRACE("(fd == %d)\n", fd);
- return msvcrt_dup_fd(fd);
+
+ if (msvcrt_dup_fd(fd, newfd) == -1)
+ return -1;
+ msvcrt_next_free(newfd);
+
+ return newfd;
}
/*********************************************************************
@@ -722,44 +716,21 @@
*/
int _dup2(int fd1, int fd2)
{
- HANDLE hand = msvcrt_fdtoh(fd1);
-
TRACE("(fd1 == %d, fd2 == %d)\n", fd1, fd2);
- /* Make sure that the handle for fd1 is valid and
- * that fd2 is a valid file descriptor
- */
- if (hand == INVALID_HANDLE_VALUE)
- {
- TRACE("Invalid fd == %d, no associated handle\n", fd1);
- return -1;
- }
- else if ((fd2 < 0) || (fd2 >= MSVCRT_fdend))
- {
- TRACE("Invalid fd == %d\n", fd2);
- return -1;
- }
-
/* Close the file associated with fd2, before
- * assigning it another value from fd1
+ * assigning duplicating it with values from fd1
*/
_close(fd2);
-
- /* Duplicate the file handle and flags for fd2,
- * to allow us to have access to the same file as
- * per the original fd1
- */
- MSVCRT_handles[fd2] = MSVCRT_handles[fd1];
- MSVCRT_flags[fd2] = MSVCRT_flags[fd1];
- MSVCRT_files[fd2] = NULL;
- MSVCRT_tempfiles[fd2] = NULL;
+ if (msvcrt_dup_fd(fd1, fd2) == -1)
+ return -1;
/* If fd2 was marked as the first free file descriptor,
* re-allocate it as not to be used
*/
if (fd2 == MSVCRT_fdstart)
msvcrt_next_free(fd2);
-
+
return 0;
}
More information about the wine-patches
mailing list