Improved MoveFileEx() Patch

Martin Wilck Martin.Wilck at Fujitsu-Siemens.com
Fri Sep 13 09:50:47 CDT 2002


Patch: MoveFileEx.diff
Martin Wilck <Martin.Wilck at fujitsu-siemens.com>
Patch against: CVS 2002-09-13

** This patch obsoletes my earlier MoveFileEx() patch: ** 
http://www.winehq.com/hypermail/wine-patches/2002/09/0114.html

Modified files:
        - wine/files:        file.c

MoveFileEx(): 
        - return correct error codes
        - Fix behaviour if files are on different Wine drives.
          * delete source if copy successful
          * try rename() - files may be on the same Unix file system
        - Try copy/delete if rename() fails: files may be on the same DOS drive,
          but on different Unix file systems

Index: files/file.c
===================================================================
RCS file: /home/wine/wine/files/file.c,v
retrieving revision 1.160
diff -u -r1.160 file.c
--- files/file.c	12 Sep 2002 22:28:01 -0000	1.160
+++ files/file.c	13 Sep 2002 14:26:47 -0000
@@ -2579,6 +2579,7 @@
 {
     DOS_FULL_NAME full_name1, full_name2;
     HANDLE hFile;
+    DWORD attr = INVALID_FILE_ATTRIBUTES;
 
     TRACE("(%s,%s,%04lx)\n", debugstr_w(fn1), debugstr_w(fn2), flag);
 
@@ -2619,8 +2620,7 @@
                 /* target exists, check if we may overwrite */
                 if (!(flag & MOVEFILE_REPLACE_EXISTING))
                 {
-                    /* FIXME: Use right error code */
-                    SetLastError( ERROR_ACCESS_DENIED );
+                    SetLastError( ERROR_FILE_EXISTS );
                     return FALSE;
                 }
             }
@@ -2647,17 +2647,17 @@
             return FILE_AddBootRenameEntry( fn1, fn2, flag );
         }
 
+        attr = GetFileAttributesA( full_name1.long_name );
+        if ( attr == INVALID_FILE_ATTRIBUTES ) return FALSE;
+
         /* check if we are allowed to rename the source */
         hFile = FILE_CreateFile( full_name1.long_name, 0, 0,
                                  NULL, OPEN_EXISTING, 0, 0, TRUE,
                                  GetDriveTypeW( full_name1.short_name ) );
         if (!hFile)
         {
-            DWORD attr;
-
             if (GetLastError() != ERROR_ACCESS_DENIED) return FALSE;
-            attr = GetFileAttributesA( full_name1.long_name );
-            if (attr == (DWORD)-1 || !(attr & FILE_ATTRIBUTE_DIRECTORY)) return FALSE;
+            if ( !(attr & FILE_ATTRIBUTE_DIRECTORY) ) return FALSE;
             /* if it's a directory we can continue */
         }
         else CloseHandle(hFile);
@@ -2672,20 +2672,36 @@
 
         if (full_name1.drive != full_name2.drive)
         {
-            /* use copy, if allowed */
             if (!(flag & MOVEFILE_COPY_ALLOWED))
             {
-                /* FIXME: Use right error code */
-                SetLastError( ERROR_FILE_EXISTS );
+                SetLastError( ERROR_NOT_SAME_DEVICE );
+                return FALSE;
+            }
+            else if ( attr & FILE_ATTRIBUTE_DIRECTORY )
+            {
+                /* Strange, but that's what Windows returns */
+                SetLastError ( ERROR_ACCESS_DENIED );
                 return FALSE;
             }
-            return CopyFileW( fn1, fn2, !(flag & MOVEFILE_REPLACE_EXISTING) );
         }
         if (rename( full_name1.long_name, full_name2.long_name ) == -1)
-	{
-            FILE_SetDosError();
-            return FALSE;
-	}
+            /* Try copy/delete unless it's a directory. */
+            /* FIXME: This does not handle the (unlikely) case that the two locations
+               are on the same Wine drive, but on different Unix file systems. */
+        {
+            if ( attr & FILE_ATTRIBUTE_DIRECTORY )
+            {
+                FILE_SetDosError();
+                return FALSE;
+            }
+            else
+            {
+                if ( ! CopyFileW( fn1, fn2, !(flag & MOVEFILE_REPLACE_EXISTING) ))
+                    return FALSE;
+                if ( ! DeleteFileW ( fn1 ) )
+                    return FALSE;
+            }
+        }
         if (is_executable( full_name1.long_name ) != is_executable( full_name2.long_name ))
         {
             struct stat fstat;
-- 
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1	    mailto:Martin.Wilck at Fujitsu-Siemens.com
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy








More information about the wine-patches mailing list