aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2013-02-02 19:14:24 +0200
committerEli Zaretskii2013-02-02 19:14:24 +0200
commite7ac588e198385a9bc5a2338000ab6db69c2353c (patch)
treee25696520b4cc48bdf537afb8e9497663bd187b4 /src
parent85a83ea09dd2440187945ed4bb5f3f6fcebb9a71 (diff)
downloademacs-e7ac588e198385a9bc5a2338000ab6db69c2353c.tar.gz
emacs-e7ac588e198385a9bc5a2338000ab6db69c2353c.zip
Avoid encoding file names run through dostounix_filename on MS-Windows.
src/w32.c (normalize_filename): Accept an additional argument MULTIBYTE; if non-zero, traverse the file name by bytes and don't downcase it even if w32-downcase-file-names is non-nil. (dostounix_filename): Accept an additional argument MULTIBYTE and pass it to normalize_filename. (emacs_root_dir): Adjust. src/msdos.h (dostounix_filename): Adjust prototype. src/w32.h (dostounix_filename): Adjust prototype. src/msdos.c (dostounix_filename): Accept an additional argument and ignore it. (init_environment): Adjust callers of dostounix_filename. src/fileio.c (Ffile_name_directory, file_name_as_directory) (directory_file_name, Fexpand_file_name) (Fsubstitute_in_file_name): [DOS_NT] Adjust call to dostounix_filename. [WINDOWSNT]: Downcase file names if w32-downcase-file-names is non-nil. (Fsubstitute_in_file_name): [DOS_NT] Don't downcase environment variables, as egetenv is case-insensitive for DOS_NT. src/dired.c (file_name_completion): Don't call Fdirectory_file_name with an encoded file name. src/w32proc.c (Fw32_short_file_name, Fw32_long_file_name): Adjust calls to dostounix_filename. src/w32fns.c (Fx_file_dialog): Adjust call to dostounix_filename. src/unexw32.c (unexec): Adjust call to dostounix_filename. src/termcap.c (tgetent) [MSDOS]: Adjust call to dostounix_filename. src/emacs.c (decode_env_path) [DOS_NT]: Adjust call to dostounix_filename. src/callproc.c (Fcall_process) [MSDOS]: Adjust call to dostounix_filename.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog44
-rw-r--r--src/callproc.c2
-rw-r--r--src/dired.c4
-rw-r--r--src/emacs.c2
-rw-r--r--src/fileio.c125
-rw-r--r--src/msdos.c6
-rw-r--r--src/msdos.h2
-rw-r--r--src/termcap.c2
-rw-r--r--src/unexw32.c2
-rw-r--r--src/w32.c21
-rw-r--r--src/w32.h2
-rw-r--r--src/w32fns.c2
-rw-r--r--src/w32proc.c5
13 files changed, 128 insertions, 91 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 302010ec769..b90f18eba91 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,49 @@
12013-02-02 Eli Zaretskii <eliz@gnu.org> 12013-02-02 Eli Zaretskii <eliz@gnu.org>
2 2
3 Avoid encoding file names on MS-Windows when they need to be run
4 through dostounix_filename.
5 * w32.c (normalize_filename): Accept an additional argument
6 MULTIBYTE; if non-zero, traverse the file name by bytes and don't
7 downcase it even if w32-downcase-file-names is non-nil.
8 (dostounix_filename): Accept an additional argument MULTIBYTE and
9 pass it to normalize_filename.
10 (emacs_root_dir): Adjust.
11
12 * msdos.h (dostounix_filename): Adjust prototype.
13
14 * w32.h (dostounix_filename): Adjust prototype.
15
16 * msdos.c (dostounix_filename): Accept an additional argument and
17 ignore it.
18 (init_environment): Adjust callers of dostounix_filename.
19
20 * fileio.c (Ffile_name_directory, file_name_as_directory)
21 (directory_file_name, Fexpand_file_name)
22 (Fsubstitute_in_file_name): [DOS_NT] Adjust call to
23 dostounix_filename.
24 [WINDOWSNT]: Downcase file names if w32-downcase-file-names is
25 non-nil.
26 (Fsubstitute_in_file_name): [DOS_NT] Don't downcase environment
27 variables, as egetenv is case-insensitive for DOS_NT.
28
29 * dired.c (file_name_completion): Don't call Fdirectory_file_name
30 with an encoded file name.
31
32 * w32proc.c (Fw32_short_file_name, Fw32_long_file_name): Adjust
33 calls to dostounix_filename.
34
35 * w32fns.c (Fx_file_dialog): Adjust call to dostounix_filename.
36
37 * unexw32.c (unexec): Adjust call to dostounix_filename.
38
39 * termcap.c (tgetent) [MSDOS]: Adjust call to dostounix_filename.
40
41 * emacs.c (decode_env_path) [DOS_NT]: Adjust call to
42 dostounix_filename.
43
44 * callproc.c (Fcall_process) [MSDOS]: Adjust call to
45 dostounix_filename.
46
3 * callproc.c (Fcall_process): Make sure program name in PATH and 47 * callproc.c (Fcall_process): Make sure program name in PATH and
4 new_argv[0] is encoded, if needed. Otherwise, un-encoded string 48 new_argv[0] is encoded, if needed. Otherwise, un-encoded string
5 is passed to exec/spawnve, which fails unless the file-name 49 is passed to exec/spawnve, which fails unless the file-name
diff --git a/src/callproc.c b/src/callproc.c
index 9d81bb18295..ea79da7ff5a 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -487,7 +487,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
487 tempfile = alloca (20); 487 tempfile = alloca (20);
488 *tempfile = '\0'; 488 *tempfile = '\0';
489 } 489 }
490 dostounix_filename (tempfile); 490 dostounix_filename (tempfile, 0);
491 if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/') 491 if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/')
492 strcat (tempfile, "/"); 492 strcat (tempfile, "/");
493 strcat (tempfile, "detmp.XXX"); 493 strcat (tempfile, "detmp.XXX");
diff --git a/src/dired.c b/src/dired.c
index ed0571fe9fe..0e37568f211 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -484,9 +484,9 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
484 on the encoded file name. */ 484 on the encoded file name. */
485 encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file; 485 encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file;
486 486
487 encoded_dir = ENCODE_FILE (dirname); 487 encoded_dir = ENCODE_FILE (Fdirectory_file_name (dirname));
488 488
489 d = open_directory (SSDATA (Fdirectory_file_name (encoded_dir)), &fd); 489 d = open_directory (SSDATA (encoded_dir), &fd);
490 if (!d) 490 if (!d)
491 report_file_error ("Opening directory", Fcons (dirname, Qnil)); 491 report_file_error ("Opening directory", Fcons (dirname, Qnil));
492 492
diff --git a/src/emacs.c b/src/emacs.c
index 597fb2daf95..c351b1e9b9e 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -2152,7 +2152,7 @@ decode_env_path (const char *evarname, const char *defalt)
2152 { 2152 {
2153 char *path_copy = alloca (strlen (path) + 1); 2153 char *path_copy = alloca (strlen (path) + 1);
2154 strcpy (path_copy, path); 2154 strcpy (path_copy, path);
2155 dostounix_filename (path_copy); 2155 dostounix_filename (path_copy, 0);
2156 path = path_copy; 2156 path = path_copy;
2157 } 2157 }
2158#endif 2158#endif
diff --git a/src/fileio.c b/src/fileio.c
index fb6ecfedeb4..99c5f7a5837 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -383,11 +383,13 @@ Given a Unix syntax file name, returns a string ending in slash. */)
383 383
384 if (getdefdir (c_toupper (*beg) - 'A' + 1, r)) 384 if (getdefdir (c_toupper (*beg) - 'A' + 1, r))
385 { 385 {
386 if (!IS_DIRECTORY_SEP (res[strlen (res) - 1])) 386 size_t l = strlen (res);
387
388 if (l > 3 || !IS_DIRECTORY_SEP (res[l - 1]))
387 strcat (res, "/"); 389 strcat (res, "/");
388 beg = res; 390 beg = res;
389 p = beg + strlen (beg); 391 p = beg + strlen (beg);
390 dostounix_filename (beg); 392 dostounix_filename (beg, 0);
391 tem_fn = make_specified_string (beg, -1, p - beg, 393 tem_fn = make_specified_string (beg, -1, p - beg,
392 STRING_MULTIBYTE (filename)); 394 STRING_MULTIBYTE (filename));
393 } 395 }
@@ -397,13 +399,16 @@ Given a Unix syntax file name, returns a string ending in slash. */)
397 } 399 }
398 else if (STRING_MULTIBYTE (filename)) 400 else if (STRING_MULTIBYTE (filename))
399 { 401 {
400 tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg, 1)); 402 tem_fn = make_specified_string (beg, -1, p - beg, 1);
401 dostounix_filename (SSDATA (tem_fn)); 403 dostounix_filename (SSDATA (tem_fn), 1);
402 tem_fn = DECODE_FILE (tem_fn); 404#ifdef WINDOWSNT
405 if (!NILP (Vw32_downcase_file_names))
406 tem_fn = Fdowncase (tem_fn);
407#endif
403 } 408 }
404 else 409 else
405 { 410 {
406 dostounix_filename (beg); 411 dostounix_filename (beg, 0);
407 tem_fn = make_specified_string (beg, -1, p - beg, 0); 412 tem_fn = make_specified_string (beg, -1, p - beg, 0);
408 } 413 }
409 return tem_fn; 414 return tem_fn;
@@ -507,17 +512,7 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
507 srclen++; 512 srclen++;
508 } 513 }
509#ifdef DOS_NT 514#ifdef DOS_NT
510 if (multibyte) 515 dostounix_filename (dst, multibyte);
511 {
512 Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
513
514 tem_fn = ENCODE_FILE (tem_fn);
515 dostounix_filename (SSDATA (tem_fn));
516 tem_fn = DECODE_FILE (tem_fn);
517 memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
518 }
519 else
520 dostounix_filename (dst);
521#endif 516#endif
522 return srclen; 517 return srclen;
523} 518}
@@ -552,6 +547,10 @@ For a Unix-syntax file name, just appends a slash. */)
552 error ("Invalid handler in `file-name-handler-alist'"); 547 error ("Invalid handler in `file-name-handler-alist'");
553 } 548 }
554 549
550#ifdef WINDOWSNT
551 if (!NILP (Vw32_downcase_file_names))
552 file = Fdowncase (file);
553#endif
555 buf = alloca (SBYTES (file) + 10); 554 buf = alloca (SBYTES (file) + 10);
556 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), 555 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file),
557 STRING_MULTIBYTE (file)); 556 STRING_MULTIBYTE (file));
@@ -580,17 +579,7 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
580 srclen--; 579 srclen--;
581 } 580 }
582#ifdef DOS_NT 581#ifdef DOS_NT
583 if (multibyte) 582 dostounix_filename (dst, multibyte);
584 {
585 Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
586
587 tem_fn = ENCODE_FILE (tem_fn);
588 dostounix_filename (SSDATA (tem_fn));
589 tem_fn = DECODE_FILE (tem_fn);
590 memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
591 }
592 else
593 dostounix_filename (dst);
594#endif 583#endif
595 return srclen; 584 return srclen;
596} 585}
@@ -625,6 +614,10 @@ In Unix-syntax, this function just removes the final slash. */)
625 error ("Invalid handler in `file-name-handler-alist'"); 614 error ("Invalid handler in `file-name-handler-alist'");
626 } 615 }
627 616
617#ifdef WINDOWSNT
618 if (!NILP (Vw32_downcase_file_names))
619 directory = Fdowncase (directory);
620#endif
628 buf = alloca (SBYTES (directory) + 20); 621 buf = alloca (SBYTES (directory) + 20);
629 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), 622 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory),
630 STRING_MULTIBYTE (directory)); 623 STRING_MULTIBYTE (directory));
@@ -925,6 +918,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
925 } 918 }
926 } 919 }
927 920
921#ifdef WINDOWSNT
922 if (!NILP (Vw32_downcase_file_names))
923 default_directory = Fdowncase (default_directory);
924#endif
925
928 /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */ 926 /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */
929 nm = alloca (SBYTES (name) + 1); 927 nm = alloca (SBYTES (name) + 1);
930 memcpy (nm, SSDATA (name), SBYTES (name) + 1); 928 memcpy (nm, SSDATA (name), SBYTES (name) + 1);
@@ -1008,18 +1006,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1008#ifdef DOS_NT 1006#ifdef DOS_NT
1009 /* Make sure directories are all separated with /, but 1007 /* Make sure directories are all separated with /, but
1010 avoid allocation of a new string when not required. */ 1008 avoid allocation of a new string when not required. */
1011 if (multibyte) 1009 dostounix_filename (nm, multibyte);
1012 {
1013 Lisp_Object tem_name = make_specified_string (nm, -1, strlen (nm),
1014 multibyte);
1015
1016 tem_name = ENCODE_FILE (tem_name);
1017 dostounix_filename (SSDATA (tem_name));
1018 tem_name = DECODE_FILE (tem_name);
1019 memcpy (nm, SSDATA (tem_name), SBYTES (tem_name) + 1);
1020 }
1021 else
1022 dostounix_filename (nm);
1023#ifdef WINDOWSNT 1010#ifdef WINDOWSNT
1024 if (IS_DIRECTORY_SEP (nm[1])) 1011 if (IS_DIRECTORY_SEP (nm[1]))
1025 { 1012 {
@@ -1037,6 +1024,10 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1037 temp[0] = DRIVE_LETTER (drive); 1024 temp[0] = DRIVE_LETTER (drive);
1038 name = concat2 (build_string (temp), name); 1025 name = concat2 (build_string (temp), name);
1039 } 1026 }
1027#ifdef WINDOWSNT
1028 if (!NILP (Vw32_downcase_file_names))
1029 name = Fdowncase (name);
1030#endif
1040 return name; 1031 return name;
1041#else /* not DOS_NT */ 1032#else /* not DOS_NT */
1042 if (strcmp (nm, SSDATA (name)) == 0) 1033 if (strcmp (nm, SSDATA (name)) == 0)
@@ -1400,14 +1391,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1400 target[1] = ':'; 1391 target[1] = ':';
1401 } 1392 }
1402 result = make_specified_string (target, -1, o - target, multibyte); 1393 result = make_specified_string (target, -1, o - target, multibyte);
1403 if (multibyte) 1394 dostounix_filename (SSDATA (result), multibyte);
1404 { 1395#ifdef WINDOWSNT
1405 result = ENCODE_FILE (result); 1396 if (!NILP (Vw32_downcase_file_names))
1406 dostounix_filename (SSDATA (result)); 1397 result = Fdowncase (result);
1407 result = DECODE_FILE (result); 1398#endif
1408 }
1409 else
1410 dostounix_filename (SSDATA (result));
1411#else /* !DOS_NT */ 1399#else /* !DOS_NT */
1412 result = make_specified_string (target, -1, o - target, multibyte); 1400 result = make_specified_string (target, -1, o - target, multibyte);
1413#endif /* !DOS_NT */ 1401#endif /* !DOS_NT */
@@ -1689,24 +1677,8 @@ those `/' is discarded. */)
1689 memcpy (nm, SDATA (filename), SBYTES (filename) + 1); 1677 memcpy (nm, SDATA (filename), SBYTES (filename) + 1);
1690 1678
1691#ifdef DOS_NT 1679#ifdef DOS_NT
1692 if (multibyte) 1680 dostounix_filename (nm, multibyte);
1693 { 1681 substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
1694 Lisp_Object encoded_filename = ENCODE_FILE (filename);
1695 Lisp_Object tem_fn;
1696
1697 dostounix_filename (SDATA (encoded_filename));
1698 tem_fn = DECODE_FILE (encoded_filename);
1699 nm = alloca (SBYTES (tem_fn) + 1);
1700 memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1);
1701 substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
1702 if (substituted)
1703 filename = tem_fn;
1704 }
1705 else
1706 {
1707 dostounix_filename (nm);
1708 substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
1709 }
1710#endif 1682#endif
1711 endp = nm + SBYTES (filename); 1683 endp = nm + SBYTES (filename);
1712 1684
@@ -1780,7 +1752,13 @@ those `/' is discarded. */)
1780 } 1752 }
1781 1753
1782 if (!substituted) 1754 if (!substituted)
1783 return filename; 1755 {
1756#ifdef WINDOWSNT
1757 if (!NILP (Vw32_downcase_file_names))
1758 filename = Fdowncase (filename);
1759#endif
1760 return filename;
1761 }
1784 1762
1785 /* If substitution required, recopy the string and do it. */ 1763 /* If substitution required, recopy the string and do it. */
1786 /* Make space in stack frame for the new copy. */ 1764 /* Make space in stack frame for the new copy. */
@@ -1819,9 +1797,6 @@ those `/' is discarded. */)
1819 target = alloca (s - o + 1); 1797 target = alloca (s - o + 1);
1820 memcpy (target, o, s - o); 1798 memcpy (target, o, s - o);
1821 target[s - o] = 0; 1799 target[s - o] = 0;
1822#ifdef DOS_NT
1823 strupr (target); /* $home == $HOME etc. */
1824#endif /* DOS_NT */
1825 1800
1826 /* Get variable value. */ 1801 /* Get variable value. */
1827 o = egetenv (target); 1802 o = egetenv (target);
@@ -1858,6 +1833,16 @@ those `/' is discarded. */)
1858 need to quote some $ to $$ first. */ 1833 need to quote some $ to $$ first. */
1859 xnm = p; 1834 xnm = p;
1860 1835
1836#ifdef WINDOWSNT
1837 if (!NILP (Vw32_downcase_file_names))
1838 {
1839 Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte);
1840
1841 xname = Fdowncase (xname);
1842 return xname;
1843 }
1844 else
1845#endif
1861 return make_specified_string (xnm, -1, x - xnm, multibyte); 1846 return make_specified_string (xnm, -1, x - xnm, multibyte);
1862 1847
1863 badsubst: 1848 badsubst:
diff --git a/src/msdos.c b/src/msdos.c
index 5174bc4dfcd..1b2deaf7478 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -3339,7 +3339,7 @@ void msdos_downcase_filename (unsigned char *);
3339/* Destructively turn backslashes into slashes. */ 3339/* Destructively turn backslashes into slashes. */
3340 3340
3341void 3341void
3342dostounix_filename (char *p) 3342dostounix_filename (char *p, int ignore)
3343{ 3343{
3344 msdos_downcase_filename (p); 3344 msdos_downcase_filename (p);
3345 3345
@@ -3603,7 +3603,7 @@ init_environment (int argc, char **argv, int skip_args)
3603 if (!s) s = "c:/command.com"; 3603 if (!s) s = "c:/command.com";
3604 t = alloca (strlen (s) + 1); 3604 t = alloca (strlen (s) + 1);
3605 strcpy (t, s); 3605 strcpy (t, s);
3606 dostounix_filename (t); 3606 dostounix_filename (t, 0);
3607 setenv ("SHELL", t, 0); 3607 setenv ("SHELL", t, 0);
3608 3608
3609 /* PATH is also downcased and backslashes mirrored. */ 3609 /* PATH is also downcased and backslashes mirrored. */
@@ -3613,7 +3613,7 @@ init_environment (int argc, char **argv, int skip_args)
3613 /* Current directory is always considered part of MsDos's path but it is 3613 /* Current directory is always considered part of MsDos's path but it is
3614 not normally mentioned. Now it is. */ 3614 not normally mentioned. Now it is. */
3615 strcat (strcpy (t, ".;"), s); 3615 strcat (strcpy (t, ".;"), s);
3616 dostounix_filename (t); /* Not a single file name, but this should work. */ 3616 dostounix_filename (t, 0); /* Not a single file name, but this should work. */
3617 setenv ("PATH", t, 1); 3617 setenv ("PATH", t, 1);
3618 3618
3619 /* In some sense all dos users have root privileges, so... */ 3619 /* In some sense all dos users have root privileges, so... */
diff --git a/src/msdos.h b/src/msdos.h
index 57609d62218..ee0d49464ae 100644
--- a/src/msdos.h
+++ b/src/msdos.h
@@ -29,7 +29,7 @@ void dos_set_window_size (int *, int *);
29 29
30int getdefdir (int, char*); 30int getdefdir (int, char*);
31void unixtodos_filename (char *); 31void unixtodos_filename (char *);
32void dostounix_filename (char *); 32void dostounix_filename (char *, int);
33char *rootrelativepath (char *); 33char *rootrelativepath (char *);
34void init_environment (int, char **, int); 34void init_environment (int, char **, int);
35void internal_terminal_init (void); 35void internal_terminal_init (void);
diff --git a/src/termcap.c b/src/termcap.c
index 82c2b1fda07..99bbfce27f5 100644
--- a/src/termcap.c
+++ b/src/termcap.c
@@ -393,7 +393,7 @@ tgetent (char *bp, const char *name)
393 if (termcap_name && (*termcap_name == '\\' 393 if (termcap_name && (*termcap_name == '\\'
394 || *termcap_name == '/' 394 || *termcap_name == '/'
395 || termcap_name[1] == ':')) 395 || termcap_name[1] == ':'))
396 dostounix_filename (termcap_name); 396 dostounix_filename (termcap_name, 0);
397#endif 397#endif
398 398
399 filep = termcap_name && valid_filename_p (termcap_name); 399 filep = termcap_name && valid_filename_p (termcap_name);
diff --git a/src/unexw32.c b/src/unexw32.c
index 66071295727..e8b553a87d3 100644
--- a/src/unexw32.c
+++ b/src/unexw32.c
@@ -722,7 +722,7 @@ unexec (const char *new_name, const char *old_name)
722 /* Ignore old_name, and get our actual location from the OS. */ 722 /* Ignore old_name, and get our actual location from the OS. */
723 if (!GetModuleFileName (NULL, in_filename, MAX_PATH)) 723 if (!GetModuleFileName (NULL, in_filename, MAX_PATH))
724 abort (); 724 abort ();
725 dostounix_filename (in_filename); 725 dostounix_filename (in_filename, 0);
726 strcpy (out_filename, in_filename); 726 strcpy (out_filename, in_filename);
727 727
728 /* Change the base of the output filename to match the requested name. */ 728 /* Change the base of the output filename to match the requested name. */
diff --git a/src/w32.c b/src/w32.c
index 64e989a3b36..8b89bd3e660 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1598,12 +1598,17 @@ max_filename_mbslen (void)
1598 case path name components to lower case. */ 1598 case path name components to lower case. */
1599 1599
1600static void 1600static void
1601normalize_filename (register char *fp, char path_sep) 1601normalize_filename (register char *fp, char path_sep, int multibyte)
1602{ 1602{
1603 char sep; 1603 char sep;
1604 char *elem, *p2; 1604 char *elem, *p2;
1605 int dbcs_p = max_filename_mbslen () > 1; 1605 int dbcs_p = max_filename_mbslen () > 1;
1606 1606
1607 /* Multibyte file names are in the Emacs internal representation, so
1608 we can traverse them by bytes with no problems. */
1609 if (multibyte)
1610 dbcs_p = 0;
1611
1607 /* Always lower-case drive letters a-z, even if the filesystem 1612 /* Always lower-case drive letters a-z, even if the filesystem
1608 preserves case in filenames. 1613 preserves case in filenames.
1609 This is so filenames can be compared by string comparison 1614 This is so filenames can be compared by string comparison
@@ -1620,7 +1625,7 @@ normalize_filename (register char *fp, char path_sep)
1620 fp += 2; 1625 fp += 2;
1621 } 1626 }
1622 1627
1623 if (NILP (Vw32_downcase_file_names)) 1628 if (multibyte || NILP (Vw32_downcase_file_names))
1624 { 1629 {
1625 while (*fp) 1630 while (*fp)
1626 { 1631 {
@@ -1668,18 +1673,20 @@ normalize_filename (register char *fp, char path_sep)
1668 } while (*fp); 1673 } while (*fp);
1669} 1674}
1670 1675
1671/* Destructively turn backslashes into slashes. */ 1676/* Destructively turn backslashes into slashes. MULTIBYTE non-zero
1677 means the file name is a multibyte string in Emacs's internal
1678 representation. */
1672void 1679void
1673dostounix_filename (register char *p) 1680dostounix_filename (register char *p, int multibyte)
1674{ 1681{
1675 normalize_filename (p, '/'); 1682 normalize_filename (p, '/', multibyte);
1676} 1683}
1677 1684
1678/* Destructively turn slashes into backslashes. */ 1685/* Destructively turn slashes into backslashes. */
1679void 1686void
1680unixtodos_filename (register char *p) 1687unixtodos_filename (register char *p)
1681{ 1688{
1682 normalize_filename (p, '\\'); 1689 normalize_filename (p, '\\', 0);
1683} 1690}
1684 1691
1685/* Remove all CR's that are followed by a LF. 1692/* Remove all CR's that are followed by a LF.
@@ -2222,7 +2229,7 @@ emacs_root_dir (void)
2222 emacs_abort (); 2229 emacs_abort ();
2223 strcpy (root_dir, p); 2230 strcpy (root_dir, p);
2224 root_dir[parse_root (root_dir, NULL)] = '\0'; 2231 root_dir[parse_root (root_dir, NULL)] = '\0';
2225 dostounix_filename (root_dir); 2232 dostounix_filename (root_dir, 0);
2226 return root_dir; 2233 return root_dir;
2227} 2234}
2228 2235
diff --git a/src/w32.h b/src/w32.h
index 895e7f31d63..6bf165f52ba 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -180,7 +180,7 @@ extern void init_environment (char **);
180extern void check_windows_init_file (void); 180extern void check_windows_init_file (void);
181extern void syms_of_ntproc (void); 181extern void syms_of_ntproc (void);
182extern void syms_of_ntterm (void); 182extern void syms_of_ntterm (void);
183extern void dostounix_filename (register char *); 183extern void dostounix_filename (register char *, int);
184extern void unixtodos_filename (register char *); 184extern void unixtodos_filename (register char *);
185extern BOOL init_winsock (int load_now); 185extern BOOL init_winsock (int load_now);
186extern void srandom (int); 186extern void srandom (int);
diff --git a/src/w32fns.c b/src/w32fns.c
index 6c098cae3a3..0841ad3468e 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -6254,7 +6254,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
6254 /* we get one of the two final 0 bytes for free. */ 6254 /* we get one of the two final 0 bytes for free. */
6255 1 + sizeof (wchar_t) * wcslen (filename_buf))); 6255 1 + sizeof (wchar_t) * wcslen (filename_buf)));
6256#else /* !NTGUI_UNICODE */ 6256#else /* !NTGUI_UNICODE */
6257 dostounix_filename (filename_buf); 6257 dostounix_filename (filename_buf, 0);
6258 filename = DECODE_FILE (build_string (filename_buf)); 6258 filename = DECODE_FILE (build_string (filename_buf));
6259#endif /* NTGUI_UNICODE */ 6259#endif /* NTGUI_UNICODE */
6260 6260
diff --git a/src/w32proc.c b/src/w32proc.c
index 615e5329e8c..8bf57602927 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -2558,8 +2558,9 @@ All path elements in FILENAME are converted to their short names. */)
2558 if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0) 2558 if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0)
2559 return Qnil; 2559 return Qnil;
2560 2560
2561 dostounix_filename (shortname); 2561 dostounix_filename (shortname, 0);
2562 2562
2563 /* No need to DECODE_FILE, because 8.3 names are pure ASCII. */
2563 return build_string (shortname); 2564 return build_string (shortname);
2564} 2565}
2565 2566
@@ -2586,7 +2587,7 @@ All path elements in FILENAME are converted to their long names. */)
2586 if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH)) 2587 if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH))
2587 return Qnil; 2588 return Qnil;
2588 2589
2589 dostounix_filename (longname); 2590 dostounix_filename (longname, 0);
2590 2591
2591 /* If we were passed only a drive, make sure that a slash is not appended 2592 /* If we were passed only a drive, make sure that a slash is not appended
2592 for consistency with directories. Allow for drive mapping via SUBST 2593 for consistency with directories. Allow for drive mapping via SUBST