]> code.delx.au - gnu-emacs/commitdiff
Improve special char handling in Tramp
authorMichael Albinus <michael.albinus@gmx.de>
Tue, 24 Mar 2015 19:05:00 +0000 (20:05 +0100)
committerMichael Albinus <michael.albinus@gmx.de>
Tue, 24 Mar 2015 19:05:00 +0000 (20:05 +0100)
* net/tramp-sh.el (tramp-do-file-attributes-with-ls)
(tramp-do-file-attributes-with-stat): Quote file names in output.
(tramp-do-directory-files-and-attributes-with-stat): Use "//" as marker.

lisp/ChangeLog
lisp/net/tramp-sh.el

index e91d2bc046450dc48b4f240d4cca23efd91ba4ae..3b8fa7d66c73c4abd94bdf1b166b7d94c01abf57 100644 (file)
@@ -1,3 +1,9 @@
+2015-03-24  Michael Albinus  <michael.albinus@gmx.de>
+
+       * net/tramp-sh.el (tramp-do-file-attributes-with-ls)
+       (tramp-do-file-attributes-with-stat): Quote file names in output.
+       (tramp-do-directory-files-and-attributes-with-stat): Use "//" as marker.
+
 2015-03-24  Daiki Ueno  <ueno@gnu.org>
 
        * epg.el (epg-start-generate-key): Fix typo in "gpg --gen-key"
index b82b4deb21a1df298a8da5017a1a2d9bf29af1dc..f59c5fbdf67eaf48e606ead732927fc2d334f2e1 100644 (file)
@@ -1175,15 +1175,19 @@ target of the symlink differ."
     (tramp-message vec 5 "file attributes with ls: %s" localname)
     (tramp-send-command
      vec
-     (format "(%s %s || %s -h %s) && %s %s %s"
+     (format "(%s %s || %s -h %s) && %s %s %s %s"
             (tramp-get-file-exists-command vec)
             (tramp-shell-quote-argument localname)
             (tramp-get-test-command vec)
             (tramp-shell-quote-argument localname)
             (tramp-get-ls-command vec)
+            ;; On systems which have no quoting style, file names
+            ;; with special characters could fail.
+            (if (tramp-get-ls-command-with-quoting-style vec)
+                "--quoting-style=c" "")
             (if (eq id-format 'integer) "-ildn" "-ild")
             (tramp-shell-quote-argument localname)))
-    ;; parse `ls -l' output ...
+    ;; Parse `ls -l' output ...
     (with-current-buffer (tramp-get-buffer vec)
       (when (> (buffer-size) 0)
         (goto-char (point-min))
@@ -1222,11 +1226,14 @@ target of the symlink differ."
         ;; From the file modes, figure out other stuff.
         (setq symlinkp (eq ?l (aref res-filemodes 0)))
         (setq dirp (eq ?d (aref res-filemodes 0)))
-        ;; if symlink, find out file name pointed to
+        ;; If symlink, find out file name pointed to.
         (when symlinkp
           (search-forward "-> ")
-          (setq res-symlink-target (buffer-substring (point) (point-at-eol))))
-        ;; return data gathered
+          (setq res-symlink-target
+               (if (tramp-get-ls-command-with-quoting-style vec)
+                   (read (current-buffer))
+                 (buffer-substring (point) (point-at-eol)))))
+        ;; Return data gathered.
         (list
          ;; 0. t for directory, string (name linked to) for symbolic
          ;; link, or nil.
@@ -1249,9 +1256,9 @@ target of the symlink differ."
          ;; 8. File modes, as a string of ten letters or dashes as in ls -l.
          res-filemodes
          ;; 9. t if file's gid would change if file were deleted and
-         ;; recreated.  Will be set in `tramp-convert-file-attributes'
+         ;; recreated.  Will be set in `tramp-convert-file-attributes'.
          t
-         ;; 10. inode number.
+         ;; 10. Inode number.
          res-inode
          ;; 11. Device number.  Will be replaced by a virtual device number.
          -1
@@ -1275,16 +1282,21 @@ target of the symlink differ."
   (tramp-send-command-and-read
    vec
    (format
-    ;; On Opsware, pdksh (which is the true name of ksh there) doesn't
-    ;; parse correctly the sequence "((".  Therefore, we add a space.
-    "( (%s %s || %s -h %s) && %s -c '((\"%%N\") %%h %s %s %%Xe0 %%Ye0 %%Ze0 %%se0 \"%%A\" t %%ie0 -1)' \"%s\" || echo nil)"
+    (concat
+     ;; On Opsware, pdksh (which is the true name of ksh there)
+     ;; doesn't parse correctly the sequence "((".  Therefore, we add
+     ;; a space.  Apostrophes in the stat output are masked as "//",
+     ;; in order to make a proper shell escape of them in file names.
+     "( (%s %s || %s -h %s) && (%s -c "
+     "'((//%%N//) %%h %s %s %%Xe0 %%Ye0 %%Ze0 %%se0 //%%A// t %%ie0 -1)' "
+     "%s | sed -e 's/\"/\\\\\"/g' -e 's/\\/\\//\"/g') || echo nil)")
     (tramp-get-file-exists-command vec)
     (tramp-shell-quote-argument localname)
     (tramp-get-test-command vec)
     (tramp-shell-quote-argument localname)
     (tramp-get-remote-stat vec)
-    (if (eq id-format 'integer) "%ue0" "\"%U\"")
-    (if (eq id-format 'integer) "%ge0" "\"%G\"")
+    (if (eq id-format 'integer) "%ue0" "//%U//")
+    (if (eq id-format 'integer) "%ge0" "//%G//")
     (tramp-shell-quote-argument localname))))
 
 (defun tramp-sh-handle-set-visited-file-modtime (&optional time-list)
@@ -1717,14 +1729,13 @@ be non-negative integers."
     (concat
      ;; We must care about file names with spaces, or starting with
      ;; "-"; this would confuse xargs.  "ls -aQ" might be a solution,
-     ;; but it does not work on all remote systems.  Therefore, we
-     ;; use \000 as file separator.
-     ;; Apostrophes in the stat output are masked as ?/ characters, in
-     ;; order to make a proper shell escape of them in file names.
+     ;; but it does not work on all remote systems.  Apostrophes in
+     ;; the stat output are masked as "//", in order to make a proper
+     ;; shell escape of them in file names.
      "cd %s && echo \"(\"; (%s %s -a | "
      "xargs %s -c "
-     "'(/%%n/ (/%%N/) %%h %s %s %%Xe0 %%Ye0 %%Ze0 %%se0 /%%A/ t %%ie0 -1)' "
-     "-- 2>/dev/null | sed -e 's/\"/\\\\\"/g' -e 's/\\//\"/g'); echo \")\"")
+     "'(//%%n// (//%%N//) %%h %s %s %%Xe0 %%Ye0 %%Ze0 %%se0 //%%A// t %%ie0 -1)' "
+     "-- 2>/dev/null | sed -e 's/\"/\\\\\"/g' -e 's/\\/\\//\"/g'); echo \")\"")
     (tramp-shell-quote-argument localname)
     (tramp-get-ls-command vec)
     ;; On systems which have no quoting style, file names with
@@ -1732,8 +1743,8 @@ be non-negative integers."
     (if (tramp-get-ls-command-with-quoting-style vec)
        "--quoting-style=shell" "")
     (tramp-get-remote-stat vec)
-    (if (eq id-format 'integer) "%ue0" "/%U/")
-    (if (eq id-format 'integer) "%ge0" "/%G/"))))
+    (if (eq id-format 'integer) "%ue0" "//%U//")
+    (if (eq id-format 'integer) "%ge0" "//%G//"))))
 
 ;; This function should return "foo/" for directories and "bar" for
 ;; files.