diff options
| author | Michael Albinus | 2017-08-30 12:00:26 +0200 |
|---|---|---|
| committer | Michael Albinus | 2017-08-30 12:00:26 +0200 |
| commit | 9376ea3f6c736f62cc064088b2e020a9f89bae63 (patch) | |
| tree | 0170a37cd464d0ec513c4a173bd9fd1e425646e0 | |
| parent | 9ef61c17af49886d150b938f51040ff3a1da1c80 (diff) | |
| download | emacs-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.el | 3 | ||||
| -rw-r--r-- | lisp/net/tramp-sh.el | 18 | ||||
| -rw-r--r-- | test/lisp/net/tramp-tests.el | 90 |
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. |