summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1996-07-07 01:59:24 +0000
committerMiles Bader <miles@gnu.org>1996-07-07 01:59:24 +0000
commit87d9ffbd255b2f04fffd4922be8efc28dccaf804 (patch)
treee3dd6aa0b05bde92e0df54cf3d630238694509b5 /src
parent9c49a43ad5982612d46f5d1e67c383c1030b700d (diff)
downloademacs-87d9ffbd255b2f04fffd4922be8efc28dccaf804.tar.gz
(normalize_filename): Always lower-case drive letters, even on systems
that preserve case in filenames. (sys_rename): Do not delete newname if only changing case. On Windows 95, use our version of mktemp (not the MSVC version) and give the temp name a long extension to ensure the final rename works as expected.
Diffstat (limited to 'src')
-rw-r--r--src/w32.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/src/w32.c b/src/w32.c
index 4c621fc8fa4..2f30e30b2ac 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -401,6 +401,17 @@ normalize_filename (fp, path_sep)
char sep;
char *elem;
+ /* Always lower-case drive letters a-z, even if the filesystem
+ preserves case in filenames.
+ This is so filenames can be compared by string comparison
+ functions that are case-sensitive. Even case-preserving filesystems
+ do not distinguish case in drive letters. */
+ if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
+ {
+ *fp += 'a' - 'A';
+ fp += 2;
+ }
+
if (NILP (Vwin32_downcase_file_names))
{
while (*fp)
@@ -1050,11 +1061,20 @@ int
sys_rename (const char * oldname, const char * newname)
{
char temp[MAX_PATH];
+ DWORD attr;
/* MoveFile on Win95 doesn't correctly change the short file name
- alias when oldname has a three char extension and newname has the
- same first three chars in its extension. To avoid problems, on
- Win95 we rename to a temporary name first. */
+ alias in a number of circumstances (it is not easy to predict when
+ just by looking at oldname and newname, unfortunately). In these
+ cases, renaming through a temporary name avoids the problem.
+
+ A second problem on Win95 is that renaming through a temp name when
+ newname is uppercase fails (the final long name ends up in
+ lowercase, although the short alias might be uppercase) UNLESS the
+ long temp name is not 8.3.
+
+ So, on Win95 we always rename through a temp name, and we make sure
+ the temp name has a long extension to ensure correct renaming. */
strcpy (temp, map_win32_filename (oldname, NULL));
@@ -1062,21 +1082,27 @@ sys_rename (const char * oldname, const char * newname)
{
char * p;
- unixtodos_filename (temp);
if (p = strrchr (temp, '\\'))
p++;
else
p = temp;
strcpy (p, "__XXXXXX");
- _mktemp (temp);
+ sys_mktemp (temp);
+ /* Force temp name to require a manufactured 8.3 alias - this
+ seems to make the second rename work properly. */
+ strcat (temp, ".long");
if (rename (map_win32_filename (oldname, NULL), temp) < 0)
return -1;
}
/* Emulate Unix behaviour - newname is deleted if it already exists
- (at least if it is a file; don't do this for directories). */
+ (at least if it is a file; don't do this for directories).
+ However, don't do this if we are just changing the case of the file
+ name - we will end up deleting the file we are trying to rename! */
newname = map_win32_filename (newname, NULL);
- if (GetFileAttributes (newname) != -1)
+ if (stricmp (newname, temp) != 0
+ && (attr = GetFileAttributes (newname)) != -1
+ && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
{
_chmod (newname, 0666);
_unlink (newname);