]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix bug #10284 with renaming a directory on MS-Windows.
authorLynX <_LynX@bk.ru>
Sat, 7 Jan 2012 09:50:57 +0000 (11:50 +0200)
committerEli Zaretskii <eliz@gnu.org>
Sat, 7 Jan 2012 09:50:57 +0000 (11:50 +0200)
 src/w32.c (sys_rename): Report EXDEV when rename of a directory
 fails because the target is on another logical disk.  (Bug#10284)

src/ChangeLog
src/w32.c

index 468e73c190b46da5f81f09c5dbe6cb85afacf0fe..3e0eed38cfbd4ade36eead2bfb96c9c85734e8e4 100644 (file)
@@ -1,3 +1,8 @@
+2012-01-07  LynX  <_LynX@bk.ru>  (tiny change)
+
+       * w32.c (sys_rename): Report EXDEV when rename of a directory
+       fails because the target is on another logical disk.  (Bug#10284)
+
 2012-01-07  David Benjamin  <davidben@mit.edu>  (tiny change)
 
        * xterm.c (x_embed_request_focus): New function.
index 3c2776689492eafb7063f0c516e7b232f35684a3..f610a36ecf464cc6d81bdc9dac586f7d2fdd2b88 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -2894,6 +2894,8 @@ sys_rename (const char * oldname, const char * newname)
 {
   BOOL result;
   char temp[MAX_PATH];
+  int newname_dev;
+  int oldname_dev;
 
   /* MoveFile on Windows 95 doesn't correctly change the short file name
      alias in a number of circumstances (it is not easy to predict when
@@ -2910,6 +2912,9 @@ sys_rename (const char * oldname, const char * newname)
 
   strcpy (temp, map_w32_filename (oldname, NULL));
 
+  /* volume_info is set indirectly by map_w32_filename.  */
+  oldname_dev = volume_info.serialnum;
+
   if (os_subtype == OS_WIN95)
     {
       char * o;
@@ -2953,13 +2958,38 @@ sys_rename (const char * oldname, const char * newname)
      all the permutations of shared or subst'd drives, etc.)  */
 
   newname = map_w32_filename (newname, NULL);
+
+  /* volume_info is set indirectly by map_w32_filename.  */
+  newname_dev = volume_info.serialnum;
+
   result = rename (temp, newname);
 
-  if (result < 0
-      && errno == EEXIST
-      && _chmod (newname, 0666) == 0
-      && _unlink (newname) == 0)
-    result = rename (temp, newname);
+  if (result < 0)
+    {
+
+      if (errno == EACCES
+         && newname_dev != oldname_dev)
+       {
+         /* The implementation of `rename' on Windows does not return
+            errno = EXDEV when you are moving a directory to a
+            different storage device (ex. logical disk).  It returns
+            EACCES instead.  So here we handle such situations and
+            return EXDEV.  */
+         DWORD attributes;
+
+         if ((attributes = GetFileAttributes (temp)) != -1
+             && attributes & FILE_ATTRIBUTE_DIRECTORY)
+           errno = EXDEV;
+       }
+      else if (errno == EEXIST)
+       {
+         if (_chmod (newname, 0666) != 0)
+           return result;
+         if (_unlink (newname) != 0)
+           return result;
+         result = rename (temp, newname);
+       }
+    }
 
   return result;
 }