msvcrt-B05: _dup/_dup2

Jaco Greeff jaco at puxedo.org
Tue Nov 5 05:23:01 CST 2002


Updated to make sure that the A?? patches applies cleanly to current CVS.

License:
LGPL

Changelog:
* dlls/msvcrt/msvcrt.spec, dlls/msvcrt/file.c: Jaco Greeff <jaco at puxedo.org>
- Full implementation of the _dup and _dup2 functions
-------------- next part --------------
diff -aurN msvcrt-B04/dlls/msvcrt/file.c msvcrt-B05/dlls/msvcrt/file.c
--- msvcrt-B04/dlls/msvcrt/file.c	Tue Nov  5 11:49:52 2002
+++ msvcrt-B05/dlls/msvcrt/file.c	Tue Nov  5 11:54:24 2002
@@ -146,6 +146,18 @@
     MSVCRT_fdstart = fd;
 }
 
+/* INTERNAL: mark the next free slot */
+static void msvcrt_next_free(int fd)
+{
+    /* locate next free slot as in msvcrt_alloc_fd */
+    if (fd == MSVCRT_fdend)
+        MSVCRT_fdstart = ++MSVCRT_fdend;
+    else
+        while((MSVCRT_fdstart < MSVCRT_fdend) &&
+              (MSVCRT_handles[MSVCRT_fdstart] != INVALID_HANDLE_VALUE))
+            MSVCRT_fdstart++;
+}
+
 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
 static int msvcrt_alloc_fd(HANDLE hand, int flag)
 {
@@ -160,17 +172,55 @@
   MSVCRT_handles[fd] = hand;
   MSVCRT_flags[fd] = flag;
 
-  /* locate next free slot */
-  if (fd == MSVCRT_fdend)
-    MSVCRT_fdstart = ++MSVCRT_fdend;
-  else
-    while(MSVCRT_fdstart < MSVCRT_fdend &&
-	  MSVCRT_handles[MSVCRT_fdstart] != INVALID_HANDLE_VALUE)
-      MSVCRT_fdstart++;
+  msvcrt_next_free(fd);
 
   return fd;
 }
 
+/* INTERNAL: duplicate an fd slot */
+static int msvcrt_dup_fd(int fd, int newfd)
+{
+    HANDLE newhand, hand = msvcrt_fdtoh(fd);
+
+    /* make sure we haven't exhausted our files
+     * and that the original fd it does have a valid
+     * handle assigned to it
+     */
+    if (newfd >= MSVCRT_MAX_FILES)
+    {
+        WARN("Files exhausted, increase MSVCRT_MAX_FILES\n");
+        return -1;
+    }
+    else if (hand == INVALID_HANDLE_VALUE)
+    {
+        TRACE("Invalid fd (%d), no associated handle\n", fd);
+        return -1;
+    }
+
+    /* Duplicate the file handle and flags for this fd,
+     * to allow us to have access to the same file as
+     * per the original 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
+     * associated with this entry, since the handle will
+     * refer to the original assigned entry.
+     */
+    MSVCRT_files[newfd] = NULL;
+    MSVCRT_tempfiles[newfd] = NULL;
+
+    return 0;
+}
+
 /* INTERNAL: Allocate a FILE* for an fd slot
  * This is done lazily to avoid memory wastage for low level open/write
  * usage when a FILE* is not requested (but may be later).
@@ -394,42 +444,56 @@
  */
 int _close(int fd)
 {
-  HANDLE hand = msvcrt_fdtoh(fd);
+    HANDLE hand = msvcrt_fdtoh(fd);
 
-  TRACE(":fd (%d) handle (%p)\n",fd,hand);
-  if (hand == INVALID_HANDLE_VALUE)
-    return -1;
-  /* flush stdio buffers */
-  if(MSVCRT_files[fd]) {
-  	if(MSVCRT_files[fd]->_flag & MSVCRT__IOWRT)
-		MSVCRT_fflush(MSVCRT_files[fd]);
+    TRACE("(fd == %d), handle == %p\n", fd, hand);
 
-  	if(MSVCRT_files[fd]->_flag & MSVCRT__IOMYBUF)
-		MSVCRT_free(MSVCRT_files[fd]->_base);
-  }
+    if (hand == INVALID_HANDLE_VALUE)
+        return -1;
 
-  /* Dont free std FILE*'s, they are not dynamic */
-  if (fd > 2 && MSVCRT_files[fd])
-    MSVCRT_free(MSVCRT_files[fd]);
+    /* flush stdio buffers */
+    if (MSVCRT_files[fd])
+    {
+        if (MSVCRT_files[fd]->_flag & MSVCRT__IOWRT)
+            MSVCRT_fflush(MSVCRT_files[fd]);
+        if (MSVCRT_files[fd]->_flag & MSVCRT__IOMYBUF)
+        {
+            MSVCRT_free(MSVCRT_files[fd]->_base);
+            MSVCRT_files[fd]->_base = NULL;
+        }
+    }
 
-  msvcrt_free_fd(fd);
+    /* Dont free std FILE*'s, they are not dynamic */
+    if (fd > 2 && MSVCRT_files[fd])
+    {
+        MSVCRT_free(MSVCRT_files[fd]);
+        MSVCRT_files[fd] = NULL;
+    }
 
-  if (!CloseHandle(hand))
-  {
-    WARN(":failed-last error (%ld)\n",GetLastError());
-    MSVCRT__set_errno(GetLastError());
-    return -1;
-  }
-  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;
-  }
+    msvcrt_free_fd(fd);
 
-  TRACE(":ok\n");
-  return 0;
+    /* 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;
 }
 
 /*********************************************************************
@@ -629,6 +693,45 @@
     MSVCRT_rewind(file);
 
   return file;
+}
+
+/*********************************************************************
+ *      _dup (MSVCRT.@)
+ */
+int _dup(int fd)
+{
+    int newfd = MSVCRT_fdstart;
+
+    TRACE("(fd == %d)\n", fd);
+
+    if (msvcrt_dup_fd(fd, newfd) == -1)
+        return -1;
+    msvcrt_next_free(newfd);
+
+    return newfd;
+}
+
+/*********************************************************************
+ *      _dup2 (MSVCRT.@)
+ */
+int _dup2(int fd1, int fd2)
+{
+    TRACE("(fd1 == %d, fd2 == %d)\n", fd1, fd2);
+
+    /* Close the file associated with fd2, before
+     * assigning duplicating it with values from fd1
+     */
+    _close(fd2);
+    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;
 }
 
 /*********************************************************************
diff -aurN msvcrt-B04/dlls/msvcrt/msvcrt.spec msvcrt-B05/dlls/msvcrt/msvcrt.spec
--- msvcrt-B04/dlls/msvcrt/msvcrt.spec	Tue Nov  5 11:49:35 2002
+++ msvcrt-B05/dlls/msvcrt/msvcrt.spec	Tue Nov  5 11:54:18 2002
@@ -195,8 +195,8 @@
 @ cdecl _cwait(ptr long long) _cwait
 @ stub _daylight
 @ stub _dstbias
-@ stub _dup #(long)
-@ stub _dup2 #(long long)
+@ cdecl _dup(long) _dup
+@ cdecl _dup2(long long) _dup2
 @ cdecl _ecvt( double long ptr ptr) ecvt
 @ cdecl _endthread () _endthread
 @ cdecl _endthreadex(long) _endthreadex


More information about the wine-patches mailing list