diff options
author | LynX <[email protected]> | 2012-01-07 11:50:57 +0200 |
---|---|---|
committer | Eli Zaretskii <[email protected]> | 2012-01-07 11:50:57 +0200 |
commit | 069d2b507080e2cb2b4f9ed112c9b7d8c3f2dc22 (patch) | |
tree | ccd1ba62708aec369c08772c2d92c65eec4717ca /src/w32.c | |
parent | e490b28922e17178224c6842b40429675b751cc8 (diff) |
Fix bug #10284 with renaming a directory on MS-Windows.
src/w32.c (sys_rename): Report EXDEV when rename of a directory
fails because the target is on another logical disk. (Bug#10284)
Diffstat (limited to 'src/w32.c')
-rw-r--r-- | src/w32.c | 40 |
1 files changed, 35 insertions, 5 deletions
@@ -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; } |