[PATCH] [cmd, try2] move filename . deletes file

Jason Edmeades jason at edmeades.me.uk
Tue Jun 11 16:27:58 CDT 2013


move is not tollerent of the source and destination being the same
and happily removes the destination (after prompting) ready to
move the file, only to appear shocked that the file is no longer
there...

This was sent originally where I compared filenames, and was given
feedback to use a better system of equality. This now uses something
the MSDN implies is the best way to tell for equivalent destinations

[Fixes bug 28582]
-------------- next part --------------
From 03a16b8b3d0032a6365c69bfec699d399f89394b Mon Sep 17 00:00:00 2001
From: Jason Edmeades <jason at edmeades.me.uk>
Date: Tue, 11 Jun 2013 21:52:07 +0100
Subject: [PATCH] [cmd, try2] move filename . deletes file

move is not tollerent of the source and destination being the same
and happily removes the destination (after prompting) ready to
move the file, only to appear shocked that the file is no longer
there...

This was sent originally where I compared filenames, and was given
feedback to use a better system of equality. This now uses something
the MSDN implies is the best way to tell for equivalent destinations

[Fixes bug 28582]
---
 programs/cmd/builtins.c |   81 ++++++++++++++++++++++++++++++++---------------
 1 file changed, 56 insertions(+), 25 deletions(-)

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index aa1e7d4..80cf955 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -2858,6 +2858,7 @@ void WCMD_move (void)
     WCHAR  src[MAX_PATH];
     DWORD attribs;
     BOOL ok = TRUE;
+    BOOL samelocation = FALSE;
 
     WINE_TRACE("Processing file '%s'\n", wine_dbgstr_w(fd.cFileName));
 
@@ -2886,41 +2887,71 @@ void WCMD_move (void)
       BOOL force = FALSE;
       WCHAR copycmd[MAXSTRING];
       DWORD len;
-
-      /* /-Y has the highest priority, then /Y and finally the COPYCMD env. variable */
-      if (strstrW (quals, parmNoY))
-        force = FALSE;
-      else if (strstrW (quals, parmY))
-        force = TRUE;
-      else {
-        static const WCHAR copyCmdW[] = {'C','O','P','Y','C','M','D','\0'};
-        len = GetEnvironmentVariableW(copyCmdW, copycmd, sizeof(copycmd)/sizeof(WCHAR));
-        force = (len && len < (sizeof(copycmd)/sizeof(WCHAR))
-                     && ! lstrcmpiW (copycmd, parmY));
+      HANDLE h1, h2;
+      BY_HANDLE_FILE_INFORMATION bh1, bh2;
+
+      /* If the source and destination are the same, then we can */
+      /* short cut and assume success without doing anything.    */
+      /* Ignore any failure, and proceed with default processing */
+      h1 = CreateFileW(src, 0,
+                       FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
+                       NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+      h2 = CreateFileW(dest, 0,
+                       FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
+                       NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+      if (h1 != INVALID_HANDLE_VALUE && GetFileInformationByHandle(h1, &bh1) &&
+          h2 != INVALID_HANDLE_VALUE && GetFileInformationByHandle(h2, &bh2)) {
+
+        if (bh1.dwVolumeSerialNumber == bh2.dwVolumeSerialNumber &&
+            bh1.nFileIndexHigh == bh2.nFileIndexHigh &&
+            bh1.nFileIndexLow == bh2.nFileIndexLow) {
+          WINE_TRACE("Src and Dest are the same\n");
+          samelocation = TRUE;
+        }
       }
+      CloseHandle(h1);
+      CloseHandle(h2);
+
+      if (!samelocation) {
+        /* /-Y has the highest priority, then /Y and finally the COPYCMD env. variable */
+        if (strstrW (quals, parmNoY))
+          force = FALSE;
+        else if (strstrW (quals, parmY))
+          force = TRUE;
+        else {
+          static const WCHAR copyCmdW[] = {'C','O','P','Y','C','M','D','\0'};
+          len = GetEnvironmentVariableW(copyCmdW, copycmd, sizeof(copycmd)/sizeof(WCHAR));
+          force = (len && len < (sizeof(copycmd)/sizeof(WCHAR))
+                       && ! lstrcmpiW (copycmd, parmY));
+        }
 
-      /* Prompt if overwriting */
-      if (!force) {
-        WCHAR* question;
+        /* Prompt if overwriting */
+        if (!force) {
+          WCHAR* question;
 
-        /* Ask for confirmation */
-        question = WCMD_format_string(WCMD_LoadMessage(WCMD_OVERWRITE), dest);
-        ok = WCMD_ask_confirm(question, FALSE, NULL);
-        LocalFree(question);
+          /* Ask for confirmation */
+          question = WCMD_format_string(WCMD_LoadMessage(WCMD_OVERWRITE), dest);
+          ok = WCMD_ask_confirm(question, FALSE, NULL);
+          LocalFree(question);
 
-        /* So delete the destination prior to the move */
-        if (ok) {
-          if (!DeleteFileW(dest)) {
-            WCMD_print_error ();
-            errorlevel = 1;
-            ok = FALSE;
+          /* So delete the destination prior to the move */
+          if (ok) {
+            if (!DeleteFileW(dest)) {
+              WCMD_print_error ();
+              errorlevel = 1;
+              ok = FALSE;
+            }
           }
         }
       }
     }
 
     if (ok) {
-      status = MoveFileW(src, dest);
+      if (!samelocation) {
+        status = MoveFileW(src, dest);
+      } else {
+        status = 0; /* Nothing to do, assume success */
+      }
     } else {
       status = 1; /* Anything other than 0 to prevent error msg below */
     }
-- 
1.7.9.5


More information about the wine-patches mailing list