]> code.delx.au - gnu-emacs/commitdiff
Avoid encoding file names run through dostounix_filename on MS-Windows.
authorEli Zaretskii <eliz@gnu.org>
Sat, 2 Feb 2013 17:14:24 +0000 (19:14 +0200)
committerEli Zaretskii <eliz@gnu.org>
Sat, 2 Feb 2013 17:14:24 +0000 (19:14 +0200)
 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.

13 files changed:
src/ChangeLog
src/callproc.c
src/dired.c
src/emacs.c
src/fileio.c
src/msdos.c
src/msdos.h
src/termcap.c
src/unexw32.c
src/w32.c
src/w32.h
src/w32fns.c
src/w32proc.c

index 302010ec76956fdeb86b92542e2db33af1d8a3a9..b90f18eba910757736258510876ef2b10be3a7a7 100644 (file)
@@ -1,5 +1,49 @@
 2013-02-02  Eli Zaretskii  <eliz@gnu.org>
 
+       Avoid encoding file names on MS-Windows when they need to be run
+       through dostounix_filename.
+       * 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.
+
+       * msdos.h (dostounix_filename): Adjust prototype.
+
+       * w32.h (dostounix_filename): Adjust prototype.
+
+       * msdos.c (dostounix_filename): Accept an additional argument and
+       ignore it.
+       (init_environment): Adjust callers of dostounix_filename.
+
+       * 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.
+
+       * dired.c (file_name_completion): Don't call Fdirectory_file_name
+       with an encoded file name.
+
+       * w32proc.c (Fw32_short_file_name, Fw32_long_file_name): Adjust
+       calls to dostounix_filename.
+
+       * w32fns.c (Fx_file_dialog): Adjust call to dostounix_filename.
+
+       * unexw32.c (unexec): Adjust call to dostounix_filename.
+
+       * termcap.c (tgetent) [MSDOS]: Adjust call to dostounix_filename.
+
+       * emacs.c (decode_env_path) [DOS_NT]: Adjust call to
+       dostounix_filename.
+
+       * callproc.c (Fcall_process) [MSDOS]: Adjust call to
+       dostounix_filename.
+
        * callproc.c (Fcall_process): Make sure program name in PATH and
        new_argv[0] is encoded, if needed.  Otherwise, un-encoded string
        is passed to exec/spawnve, which fails unless the file-name
index 9d81bb18295a9681c349f8d4a7213a9496b55884..ea79da7ff5a2e95cd38d1d355aec88c00860ad4b 100644 (file)
@@ -487,7 +487,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
          tempfile = alloca (20);
          *tempfile = '\0';
        }
-      dostounix_filename (tempfile);
+      dostounix_filename (tempfile, 0);
       if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/')
        strcat (tempfile, "/");
       strcat (tempfile, "detmp.XXX");
index ed0571fe9fe7b876726f2ae3248eca297f1a0b22..0e37568f211c8572cb7d9f6805de5119826463fd 100644 (file)
@@ -484,9 +484,9 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
      on the encoded file name.  */
   encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file;
 
-  encoded_dir = ENCODE_FILE (dirname);
+  encoded_dir = ENCODE_FILE (Fdirectory_file_name (dirname));
 
-  d = open_directory (SSDATA (Fdirectory_file_name (encoded_dir)), &fd);
+  d = open_directory (SSDATA (encoded_dir), &fd);
   if (!d)
     report_file_error ("Opening directory", Fcons (dirname, Qnil));
 
index 597fb2daf95d23bb607791cb311b78e3ecdd9b8d..c351b1e9b9e4b18a01fcbb972f85bd2a0e90f0fd 100644 (file)
@@ -2152,7 +2152,7 @@ decode_env_path (const char *evarname, const char *defalt)
     {
       char *path_copy = alloca (strlen (path) + 1);
       strcpy (path_copy, path);
-      dostounix_filename (path_copy);
+      dostounix_filename (path_copy, 0);
       path = path_copy;
     }
 #endif
index fb6ecfedeb44f3c6ddce6905ed847df8f22c8511..99c5f7a5837230c0599052781ec22ccdecf3779e 100644 (file)
@@ -383,11 +383,13 @@ Given a Unix syntax file name, returns a string ending in slash.  */)
 
       if (getdefdir (c_toupper (*beg) - 'A' + 1, r))
        {
-         if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
+         size_t l = strlen (res);
+
+         if (l > 3 || !IS_DIRECTORY_SEP (res[l - 1]))
            strcat (res, "/");
          beg = res;
          p = beg + strlen (beg);
-         dostounix_filename (beg);
+         dostounix_filename (beg, 0);
          tem_fn = make_specified_string (beg, -1, p - beg,
                                          STRING_MULTIBYTE (filename));
        }
@@ -397,13 +399,16 @@ Given a Unix syntax file name, returns a string ending in slash.  */)
     }
   else if (STRING_MULTIBYTE (filename))
     {
-      tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg, 1));
-      dostounix_filename (SSDATA (tem_fn));
-      tem_fn = DECODE_FILE (tem_fn);
+      tem_fn = make_specified_string (beg, -1, p - beg, 1);
+      dostounix_filename (SSDATA (tem_fn), 1);
+#ifdef WINDOWSNT
+      if (!NILP (Vw32_downcase_file_names))
+       tem_fn = Fdowncase (tem_fn);
+#endif
     }
   else
     {
-      dostounix_filename (beg);
+      dostounix_filename (beg, 0);
       tem_fn = make_specified_string (beg, -1, p - beg, 0);
     }
   return tem_fn;
@@ -507,17 +512,7 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
       srclen++;
     }
 #ifdef DOS_NT
-  if (multibyte)
-    {
-      Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
-
-      tem_fn = ENCODE_FILE (tem_fn);
-      dostounix_filename (SSDATA (tem_fn));
-      tem_fn = DECODE_FILE (tem_fn);
-      memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
-    }
-  else
-    dostounix_filename (dst);
+  dostounix_filename (dst, multibyte);
 #endif
   return srclen;
 }
@@ -552,6 +547,10 @@ For a Unix-syntax file name, just appends a slash.  */)
       error ("Invalid handler in `file-name-handler-alist'");
     }
 
+#ifdef WINDOWSNT
+  if (!NILP (Vw32_downcase_file_names))
+    file = Fdowncase (file);
+#endif
   buf = alloca (SBYTES (file) + 10);
   length = file_name_as_directory (buf, SSDATA (file), SBYTES (file),
                                   STRING_MULTIBYTE (file));
@@ -580,17 +579,7 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
       srclen--;
     }
 #ifdef DOS_NT
-  if (multibyte)
-    {
-      Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
-
-      tem_fn = ENCODE_FILE (tem_fn);
-      dostounix_filename (SSDATA (tem_fn));
-      tem_fn = DECODE_FILE (tem_fn);
-      memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
-    }
-  else
-    dostounix_filename (dst);
+  dostounix_filename (dst, multibyte);
 #endif
   return srclen;
 }
@@ -625,6 +614,10 @@ In Unix-syntax, this function just removes the final slash.  */)
       error ("Invalid handler in `file-name-handler-alist'");
     }
 
+#ifdef WINDOWSNT
+  if (!NILP (Vw32_downcase_file_names))
+    directory = Fdowncase (directory);
+#endif
   buf = alloca (SBYTES (directory) + 20);
   length = directory_file_name (buf, SSDATA (directory), SBYTES (directory),
                                STRING_MULTIBYTE (directory));
@@ -925,6 +918,11 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
        }
     }
 
+#ifdef WINDOWSNT
+  if (!NILP (Vw32_downcase_file_names))
+    default_directory = Fdowncase (default_directory);
+#endif
+
   /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below.  */
   nm = alloca (SBYTES (name) + 1);
   memcpy (nm, SSDATA (name), SBYTES (name) + 1);
@@ -1008,18 +1006,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
 #ifdef DOS_NT
          /* Make sure directories are all separated with /, but
             avoid allocation of a new string when not required. */
-         if (multibyte)
-           {
-             Lisp_Object tem_name = make_specified_string (nm, -1, strlen (nm),
-                                                           multibyte);
-
-             tem_name = ENCODE_FILE (tem_name);
-             dostounix_filename (SSDATA (tem_name));
-             tem_name = DECODE_FILE (tem_name);
-             memcpy (nm, SSDATA (tem_name), SBYTES (tem_name) + 1);
-           }
-         else
-           dostounix_filename (nm);
+         dostounix_filename (nm, multibyte);
 #ifdef WINDOWSNT
          if (IS_DIRECTORY_SEP (nm[1]))
            {
@@ -1037,6 +1024,10 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
              temp[0] = DRIVE_LETTER (drive);
              name = concat2 (build_string (temp), name);
            }
+#ifdef WINDOWSNT
+         if (!NILP (Vw32_downcase_file_names))
+           name = Fdowncase (name);
+#endif
          return name;
 #else /* not DOS_NT */
          if (strcmp (nm, SSDATA (name)) == 0)
@@ -1400,14 +1391,11 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
        target[1] = ':';
       }
     result = make_specified_string (target, -1, o - target, multibyte);
-    if (multibyte)
-      {
-       result = ENCODE_FILE (result);
-       dostounix_filename (SSDATA (result));
-       result = DECODE_FILE (result);
-      }
-    else
-      dostounix_filename (SSDATA (result));
+    dostounix_filename (SSDATA (result), multibyte);
+#ifdef WINDOWSNT
+    if (!NILP (Vw32_downcase_file_names))
+      result = Fdowncase (result);
+#endif
 #else  /* !DOS_NT */
     result = make_specified_string (target, -1, o - target, multibyte);
 #endif /* !DOS_NT */
@@ -1689,24 +1677,8 @@ those `/' is discarded.  */)
   memcpy (nm, SDATA (filename), SBYTES (filename) + 1);
 
 #ifdef DOS_NT
-  if (multibyte)
-    {
-      Lisp_Object encoded_filename = ENCODE_FILE (filename);
-      Lisp_Object tem_fn;
-
-      dostounix_filename (SDATA (encoded_filename));
-      tem_fn = DECODE_FILE (encoded_filename);
-      nm = alloca (SBYTES (tem_fn) + 1);
-      memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1);
-      substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
-      if (substituted)
-       filename = tem_fn;
-    }
-  else
-    {
-      dostounix_filename (nm);
-      substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
-    }
+  dostounix_filename (nm, multibyte);
+  substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
 #endif
   endp = nm + SBYTES (filename);
 
@@ -1780,7 +1752,13 @@ those `/' is discarded.  */)
       }
 
   if (!substituted)
-    return filename;
+    {
+#ifdef WINDOWSNT
+      if (!NILP (Vw32_downcase_file_names))
+       filename = Fdowncase (filename);
+#endif
+      return filename;
+    }
 
   /* If substitution required, recopy the string and do it.  */
   /* Make space in stack frame for the new copy.  */
@@ -1819,9 +1797,6 @@ those `/' is discarded.  */)
        target = alloca (s - o + 1);
        memcpy (target, o, s - o);
        target[s - o] = 0;
-#ifdef DOS_NT
-       strupr (target); /* $home == $HOME etc.  */
-#endif /* DOS_NT */
 
        /* Get variable value.  */
        o = egetenv (target);
@@ -1858,6 +1833,16 @@ those `/' is discarded.  */)
        need to quote some $ to $$ first.  */
     xnm = p;
 
+#ifdef WINDOWSNT
+  if (!NILP (Vw32_downcase_file_names))
+    {
+      Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte);
+
+      xname = Fdowncase (xname);
+      return xname;
+    }
+  else
+#endif
   return make_specified_string (xnm, -1, x - xnm, multibyte);
 
  badsubst:
index 5174bc4dfcd8b6ad5aeed063cb852d5c62199f11..1b2deaf7478c2a91795930250f6cb4ecb07ed3d7 100644 (file)
@@ -3339,7 +3339,7 @@ void msdos_downcase_filename (unsigned char *);
 /* Destructively turn backslashes into slashes.  */
 
 void
-dostounix_filename (char *p)
+dostounix_filename (char *p, int ignore)
 {
   msdos_downcase_filename (p);
 
@@ -3603,7 +3603,7 @@ init_environment (int argc, char **argv, int skip_args)
   if (!s) s = "c:/command.com";
   t = alloca (strlen (s) + 1);
   strcpy (t, s);
-  dostounix_filename (t);
+  dostounix_filename (t, 0);
   setenv ("SHELL", t, 0);
 
   /* PATH is also downcased and backslashes mirrored.  */
@@ -3613,7 +3613,7 @@ init_environment (int argc, char **argv, int skip_args)
   /* Current directory is always considered part of MsDos's path but it is
      not normally mentioned.  Now it is.  */
   strcat (strcpy (t, ".;"), s);
-  dostounix_filename (t); /* Not a single file name, but this should work.  */
+  dostounix_filename (t, 0); /* Not a single file name, but this should work.  */
   setenv ("PATH", t, 1);
 
   /* In some sense all dos users have root privileges, so...  */
index 57609d622188adcd002a363a968bbd0db061dd6d..ee0d49464ae22bcff3de5ba9b69d050f62dc25ac 100644 (file)
@@ -29,7 +29,7 @@ void dos_set_window_size (int *, int *);
 
 int getdefdir (int, char*);
 void unixtodos_filename (char *);
-void dostounix_filename (char *);
+void dostounix_filename (char *, int);
 char *rootrelativepath (char *);
 void init_environment (int, char **, int);
 void internal_terminal_init (void);
index 82c2b1fda0734ded92a77b0fc86056568bb7abc6..99bbfce27f5e26cb849723f5530ab5bfa840fd52 100644 (file)
@@ -393,7 +393,7 @@ tgetent (char *bp, const char *name)
   if (termcap_name && (*termcap_name == '\\'
                       || *termcap_name == '/'
                       || termcap_name[1] == ':'))
-    dostounix_filename (termcap_name);
+    dostounix_filename (termcap_name, 0);
 #endif
 
   filep = termcap_name && valid_filename_p (termcap_name);
index 66071295727c892f11f9d77d4f60df642bc34455..e8b553a87d3123cf2a41217b68e00249d1fb860a 100644 (file)
@@ -722,7 +722,7 @@ unexec (const char *new_name, const char *old_name)
   /* Ignore old_name, and get our actual location from the OS.  */
   if (!GetModuleFileName (NULL, in_filename, MAX_PATH))
     abort ();
-  dostounix_filename (in_filename);
+  dostounix_filename (in_filename, 0);
   strcpy (out_filename, in_filename);
 
   /* Change the base of the output filename to match the requested name.  */
index 64e989a3b3606b4b3813bb7d8ecd6617f8b739d1..8b89bd3e660e5e0599baadc04cceb4439fa3d0ce 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -1598,12 +1598,17 @@ max_filename_mbslen (void)
    case path name components to lower case.  */
 
 static void
-normalize_filename (register char *fp, char path_sep)
+normalize_filename (register char *fp, char path_sep, int multibyte)
 {
   char sep;
   char *elem, *p2;
   int dbcs_p = max_filename_mbslen () > 1;
 
+  /* Multibyte file names are in the Emacs internal representation, so
+     we can traverse them by bytes with no problems.  */
+  if (multibyte)
+    dbcs_p = 0;
+
   /* 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
@@ -1620,7 +1625,7 @@ normalize_filename (register char *fp, char path_sep)
       fp += 2;
     }
 
-  if (NILP (Vw32_downcase_file_names))
+  if (multibyte || NILP (Vw32_downcase_file_names))
     {
       while (*fp)
        {
@@ -1668,18 +1673,20 @@ normalize_filename (register char *fp, char path_sep)
   } while (*fp);
 }
 
-/* Destructively turn backslashes into slashes.  */
+/* Destructively turn backslashes into slashes.  MULTIBYTE non-zero
+   means the file name is a multibyte string in Emacs's internal
+   representation.  */
 void
-dostounix_filename (register char *p)
+dostounix_filename (register char *p, int multibyte)
 {
-  normalize_filename (p, '/');
+  normalize_filename (p, '/', multibyte);
 }
 
 /* Destructively turn slashes into backslashes.  */
 void
 unixtodos_filename (register char *p)
 {
-  normalize_filename (p, '\\');
+  normalize_filename (p, '\\', 0);
 }
 
 /* Remove all CR's that are followed by a LF.
@@ -2222,7 +2229,7 @@ emacs_root_dir (void)
     emacs_abort ();
   strcpy (root_dir, p);
   root_dir[parse_root (root_dir, NULL)] = '\0';
-  dostounix_filename (root_dir);
+  dostounix_filename (root_dir, 0);
   return root_dir;
 }
 
index 895e7f31d63c31030a18fc7bd3d4c8af2cf84658..6bf165f52bae465392badd84942800917287c362 100644 (file)
--- a/src/w32.h
+++ b/src/w32.h
@@ -180,7 +180,7 @@ extern void init_environment (char **);
 extern void check_windows_init_file (void);
 extern void syms_of_ntproc (void);
 extern void syms_of_ntterm (void);
-extern void dostounix_filename (register char *);
+extern void dostounix_filename (register char *, int);
 extern void unixtodos_filename (register char *);
 extern BOOL init_winsock (int load_now);
 extern void srandom (int);
index 6c098cae3a3066a835cf5d9207e2e74c92c8931b..0841ad3468ede1f2060e4e2f3e4edc7248f0ebde 100644 (file)
@@ -6254,7 +6254,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.  */)
             /* we get one of the two final 0 bytes for free. */
             1 + sizeof (wchar_t) * wcslen (filename_buf)));
 #else /* !NTGUI_UNICODE */
-        dostounix_filename (filename_buf);
+        dostounix_filename (filename_buf, 0);
         filename = DECODE_FILE (build_string (filename_buf));
 #endif /* NTGUI_UNICODE */
 
index 615e5329e8cf8eea2dd1d8bc58269000b05e79d8..8bf57602927e60ab0c35ee251ae44dbd6f492c62 100644 (file)
@@ -2558,8 +2558,9 @@ All path elements in FILENAME are converted to their short names.  */)
   if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0)
     return Qnil;
 
-  dostounix_filename (shortname);
+  dostounix_filename (shortname, 0);
 
+  /* No need to DECODE_FILE, because 8.3 names are pure ASCII.   */
   return build_string (shortname);
 }
 
@@ -2586,7 +2587,7 @@ All path elements in FILENAME are converted to their long names.  */)
   if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH))
     return Qnil;
 
-  dostounix_filename (longname);
+  dostounix_filename (longname, 0);
 
   /* If we were passed only a drive, make sure that a slash is not appended
      for consistency with directories.  Allow for drive mapping via SUBST