aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2017-08-30 12:00:26 +0200
committerMichael Albinus2017-08-30 12:00:26 +0200
commit9376ea3f6c736f62cc064088b2e020a9f89bae63 (patch)
tree0170a37cd464d0ec513c4a173bd9fd1e425646e0
parent9ef61c17af49886d150b938f51040ff3a1da1c80 (diff)
downloademacs-9376ea3f6c736f62cc064088b2e020a9f89bae63.tar.gz
emacs-9376ea3f6c736f62cc064088b2e020a9f89bae63.zip
Improve symlinks for Tramp
* lisp/files.el (files--splice-dirname-file): Quote whole file. * lisp/net/tramp-sh.el (tramp-sh-handle-make-symbolic-link): Do not expand TARGET, it could be remote. (tramp-sh-handle-file-truename): Check for cyclic symlink also in case of readlink. Quote result if it looks remote. (tramp-sh-handle-file-local-copy): Use `file-truename'. * test/lisp/net/tramp-tests.el (tramp-test08-file-local-copy) (tramp-test09-insert-file-contents): Test also file missing. (tramp-test21-file-links): Extend test.
-rw-r--r--lisp/files.el3
-rw-r--r--lisp/net/tramp-sh.el18
-rw-r--r--test/lisp/net/tramp-tests.el90
3 files changed, 91 insertions, 20 deletions
diff --git a/lisp/files.el b/lisp/files.el
index 7754be29643..8cec3d45dce 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -1165,7 +1165,8 @@ directory name and leading `~' and `/:' are not special in FILE."
1165 (if (eq (find-file-name-handler dirname 'file-symlink-p) 1165 (if (eq (find-file-name-handler dirname 'file-symlink-p)
1166 (find-file-name-handler file 'file-symlink-p)) 1166 (find-file-name-handler file 'file-symlink-p))
1167 file 1167 file
1168 (file-name-quote file)) 1168 ;; If `file' is remote, we want to quote it at the beginning.
1169 (let (file-name-handler-alist) (file-name-quote file)))
1169 (concat dirname file))) 1170 (concat dirname file)))
1170 1171
1171(defun file-truename (filename &optional counter prev-dirs) 1172(defun file-truename (filename &optional counter prev-dirs)
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 6494b0957bf..85966f122d2 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1086,7 +1086,7 @@ component is used as the target of the symlink."
1086 ;; If TARGET is a Tramp name, use just the localname component. 1086 ;; If TARGET is a Tramp name, use just the localname component.
1087 (when (and (tramp-tramp-file-p target) 1087 (when (and (tramp-tramp-file-p target)
1088 (tramp-file-name-equal-p 1088 (tramp-file-name-equal-p
1089 v (tramp-dissect-file-name (expand-file-name target)))) 1089 v (tramp-dissect-file-name target)))
1090 (setq target 1090 (setq target
1091 (tramp-file-name-localname 1091 (tramp-file-name-localname
1092 (tramp-dissect-file-name (expand-file-name target))))) 1092 (tramp-dissect-file-name (expand-file-name target)))))
@@ -1132,7 +1132,12 @@ component is used as the target of the symlink."
1132 (tramp-shell-quote-argument localname))) 1132 (tramp-shell-quote-argument localname)))
1133 (with-current-buffer (tramp-get-connection-buffer v) 1133 (with-current-buffer (tramp-get-connection-buffer v)
1134 (goto-char (point-min)) 1134 (goto-char (point-min))
1135 (setq result (buffer-substring (point-min) (point-at-eol))))) 1135 (setq result (buffer-substring (point-min) (point-at-eol))))
1136 (when (and (file-symlink-p filename)
1137 (string-equal result localname))
1138 (tramp-error
1139 v 'file-error
1140 "Apparent cycle of symbolic links for %s" filename)))
1136 1141
1137 ;; Use Perl implementation. 1142 ;; Use Perl implementation.
1138 ((and (tramp-get-remote-perl v) 1143 ((and (tramp-get-remote-perl v)
@@ -1214,8 +1219,11 @@ component is used as the target of the symlink."
1214 "/")) 1219 "/"))
1215 (when (string= "" result) 1220 (when (string= "" result)
1216 (setq result "/"))))) 1221 (setq result "/")))))
1217 1222 ;; If the resulting localname looks remote, we must quote it
1218 (when quoted (setq result (tramp-compat-file-name-quote result))) 1223 ;; for security reasons.
1224 (when (or quoted (file-remote-p result))
1225 (let (file-name-handler-alist)
1226 (setq result (tramp-compat-file-name-quote result))))
1219 (tramp-message v 4 "True name of `%s' is `%s'" localname result) 1227 (tramp-message v 4 "True name of `%s' is `%s'" localname result)
1220 result)))) 1228 result))))
1221 1229
@@ -3072,7 +3080,7 @@ the result will be a local, non-Tramp, file name."
3072(defun tramp-sh-handle-file-local-copy (filename) 3080(defun tramp-sh-handle-file-local-copy (filename)
3073 "Like `file-local-copy' for Tramp files." 3081 "Like `file-local-copy' for Tramp files."
3074 (with-parsed-tramp-file-name filename nil 3082 (with-parsed-tramp-file-name filename nil
3075 (unless (file-exists-p filename) 3083 (unless (file-exists-p (file-truename filename))
3076 (tramp-error 3084 (tramp-error
3077 v tramp-file-missing 3085 v tramp-file-missing
3078 "Cannot make local copy of non-existing file `%s'" filename)) 3086 "Cannot make local copy of non-existing file `%s'" filename))
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 201ac10dcc2..662163f3fec 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -1762,7 +1762,13 @@ This checks also `file-name-as-directory', `file-name-directory',
1762 (tramp-copy-size-limit 4) 1762 (tramp-copy-size-limit 4)
1763 (tramp-inline-compress-start-size 2)) 1763 (tramp-inline-compress-start-size 2))
1764 (delete-file tmp-name2) 1764 (delete-file tmp-name2)
1765 (should (setq tmp-name2 (file-local-copy tmp-name1))))) 1765 (should (setq tmp-name2 (file-local-copy tmp-name1))))
1766 ;; Error case.
1767 (delete-file tmp-name1)
1768 (delete-file tmp-name2)
1769 (should-error
1770 (setq tmp-name2 (file-local-copy tmp-name1))
1771 :type tramp-file-missing))
1766 1772
1767 ;; Cleanup. 1773 ;; Cleanup.
1768 (ignore-errors 1774 (ignore-errors
@@ -1776,19 +1782,23 @@ This checks also `file-name-as-directory', `file-name-directory',
1776 (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil))) 1782 (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
1777 (let ((tmp-name (tramp--test-make-temp-name nil quoted))) 1783 (let ((tmp-name (tramp--test-make-temp-name nil quoted)))
1778 (unwind-protect 1784 (unwind-protect
1779 (progn 1785 (with-temp-buffer
1780 (write-region "foo" nil tmp-name) 1786 (write-region "foo" nil tmp-name)
1781 (with-temp-buffer 1787 (insert-file-contents tmp-name)
1782 (insert-file-contents tmp-name) 1788 (should (string-equal (buffer-string) "foo"))
1783 (should (string-equal (buffer-string) "foo")) 1789 (insert-file-contents tmp-name)
1784 (insert-file-contents tmp-name) 1790 (should (string-equal (buffer-string) "foofoo"))
1785 (should (string-equal (buffer-string) "foofoo")) 1791 ;; Insert partly.
1786 ;; Insert partly. 1792 (insert-file-contents tmp-name nil 1 3)
1787 (insert-file-contents tmp-name nil 1 3) 1793 (should (string-equal (buffer-string) "oofoofoo"))
1788 (should (string-equal (buffer-string) "oofoofoo")) 1794 ;; Replace.
1789 ;; Replace. 1795 (insert-file-contents tmp-name nil nil nil 'replace)
1790 (insert-file-contents tmp-name nil nil nil 'replace) 1796 (should (string-equal (buffer-string) "foo"))
1791 (should (string-equal (buffer-string) "foo")))) 1797 ;; Error case.
1798 (delete-file tmp-name)
1799 (should-error
1800 (insert-file-contents tmp-name)
1801 :type tramp-file-missing))
1792 1802
1793 ;; Cleanup. 1803 ;; Cleanup.
1794 (ignore-errors (delete-file tmp-name)))))) 1804 (ignore-errors (delete-file tmp-name))))))
@@ -2681,6 +2691,16 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
2681 (should 2691 (should
2682 (string-equal (file-truename tmp-name1) (file-truename tmp-name2))) 2692 (string-equal (file-truename tmp-name1) (file-truename tmp-name2)))
2683 (should (file-equal-p tmp-name1 tmp-name2)) 2693 (should (file-equal-p tmp-name1 tmp-name2))
2694 ;; Symbolic links could look like a remote file name.
2695 ;; They must be quoted then.
2696 (delete-file tmp-name2)
2697 (make-symbolic-link "/penguin:motd:" tmp-name2)
2698 (should (file-symlink-p tmp-name2))
2699 (should
2700 (string-equal
2701 (file-truename tmp-name2)
2702 (tramp-compat-file-name-quote
2703 (concat (file-remote-p tmp-name2) "/penguin:motd:"))))
2684 ;; `tmp-name3' is a local file name. 2704 ;; `tmp-name3' is a local file name.
2685 (make-symbolic-link tmp-name1 tmp-name3) 2705 (make-symbolic-link tmp-name1 tmp-name3)
2686 (should (file-symlink-p tmp-name3)) 2706 (should (file-symlink-p tmp-name3))
@@ -2698,6 +2718,48 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
2698 (delete-file tmp-name2) 2718 (delete-file tmp-name2)
2699 (delete-file tmp-name3))) 2719 (delete-file tmp-name3)))
2700 2720
2721 ;; Symbolic links could be nested.
2722 (unwind-protect
2723 (tramp--test-ignore-make-symbolic-link-error
2724 (make-directory tmp-name1)
2725 (should (file-directory-p tmp-name1))
2726 (let* ((tramp-test-temporary-file-directory
2727 (file-truename tmp-name1))
2728 (tmp-name2 (tramp--test-make-temp-name nil quoted))
2729 (tmp-name3 tmp-name2)
2730 (number-nesting 50))
2731 (dotimes (_ number-nesting)
2732 (make-symbolic-link
2733 tmp-name3
2734 (setq tmp-name3 (tramp--test-make-temp-name nil quoted))))
2735 (should
2736 (string-equal
2737 (file-truename tmp-name2)
2738 (file-truename tmp-name3)))
2739 (should-error
2740 (with-temp-buffer (insert-file-contents tmp-name2))
2741 :type tramp-file-missing)
2742 (should-error
2743 (with-temp-buffer (insert-file-contents tmp-name3))
2744 :type tramp-file-missing)))
2745
2746 ;; Cleanup.
2747 (ignore-errors (delete-directory tmp-name1 'recursive)))
2748
2749 ;; Detect cyclic symbolic links.
2750 (unwind-protect
2751 (tramp--test-ignore-make-symbolic-link-error
2752 (make-symbolic-link tmp-name2 tmp-name1)
2753 (should (file-symlink-p tmp-name1))
2754 (make-symbolic-link tmp-name1 tmp-name2)
2755 (should (file-symlink-p tmp-name2))
2756 (should-error (file-truename tmp-name1) :type 'file-error))
2757
2758 ;; Cleanup.
2759 (ignore-errors
2760 (delete-file tmp-name1)
2761 (delete-file tmp-name2)))
2762
2701 ;; `file-truename' shall preserve trailing link of directories. 2763 ;; `file-truename' shall preserve trailing link of directories.
2702 (unless (file-symlink-p tramp-test-temporary-file-directory) 2764 (unless (file-symlink-p tramp-test-temporary-file-directory)
2703 (let* ((dir1 (directory-file-name tramp-test-temporary-file-directory)) 2765 (let* ((dir1 (directory-file-name tramp-test-temporary-file-directory))
@@ -4019,7 +4081,7 @@ process sentinels. They shall not disturb each other."
4019 ;; Create temporary buffers. The number of buffers 4081 ;; Create temporary buffers. The number of buffers
4020 ;; corresponds to the number of processes; it could be 4082 ;; corresponds to the number of processes; it could be
4021 ;; increased in order to make pressure on Tramp. 4083 ;; increased in order to make pressure on Tramp.
4022 (dotimes (_i number-proc) 4084 (dotimes (_ number-proc)
4023 (setq buffers (cons (generate-new-buffer "foo") buffers))) 4085 (setq buffers (cons (generate-new-buffer "foo") buffers)))
4024 4086
4025 ;; Open asynchronous processes. Set process filter and sentinel. 4087 ;; Open asynchronous processes. Set process filter and sentinel.