aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2017-08-26 15:09:55 +0200
committerMichael Albinus2017-08-26 15:09:55 +0200
commitcc7530cae09b0aa4d648d92ca0f82c81439a6b34 (patch)
treeda638672ca419b379a5df3e7675aaff852b986ea
parentdcc3ef3ee7b7cf2730378fca4c959f1fc799fbe2 (diff)
downloademacs-cc7530cae09b0aa4d648d92ca0f82c81439a6b34.tar.gz
emacs-cc7530cae09b0aa4d648d92ca0f82c81439a6b34.zip
Fix Tramp part of Bug#28156
* lisp/files.el (file-name-non-special): Use `file-name-quote' instead prefixing "/:", the file could already be quoted. * lisp/net/tramp.el (tramp-error): Handle null arguments. (tramp-handle-make-symbolic-link): * lisp/net/tramp-sh.el (tramp-sh-handle-make-symbolic-link) (tramp-sh-handle-add-name-to-file): * lisp/net/tramp-smb.el (tramp-smb-handle-add-name-to-file) (tramp-smb-handle-make-symbolic-link): Adapt implementation to stronger semantics in Emacs. (Bug#28156) * test/lisp/net/tramp-tests.el (tramp-test21-file-links): Extend test.
-rw-r--r--lisp/files.el2
-rw-r--r--lisp/net/tramp-sh.el129
-rw-r--r--lisp/net/tramp-smb.el115
-rw-r--r--lisp/net/tramp.el28
-rw-r--r--test/lisp/net/tramp-tests.el30
5 files changed, 173 insertions, 131 deletions
diff --git a/lisp/files.el b/lisp/files.el
index 77ebd94836e..ca3b055d7a6 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -6955,7 +6955,7 @@ only these files will be asked to be saved."
6955 (setq file-arg-indices (cdr file-arg-indices)))) 6955 (setq file-arg-indices (cdr file-arg-indices))))
6956 (pcase method 6956 (pcase method
6957 (`identity (car arguments)) 6957 (`identity (car arguments))
6958 (`add (concat "/:" (apply operation arguments))) 6958 (`add (file-name-quote (apply operation arguments)))
6959 (`insert-file-contents 6959 (`insert-file-contents
6960 (let ((visit (nth 1 arguments))) 6960 (let ((visit (nth 1 arguments)))
6961 (unwind-protect 6961 (unwind-protect
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 50b380100ba..6251248e282 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1057,62 +1057,61 @@ Operations not mentioned here will be handled by the normal Emacs functions.")
1057;;; File Name Handler Functions: 1057;;; File Name Handler Functions:
1058 1058
1059(defun tramp-sh-handle-make-symbolic-link 1059(defun tramp-sh-handle-make-symbolic-link
1060 (filename linkname &optional ok-if-already-exists) 1060 (target linkname &optional ok-if-already-exists)
1061 "Like `make-symbolic-link' for Tramp files. 1061 "Like `make-symbolic-link' for Tramp files.
1062If LINKNAME is a non-Tramp file, it is used verbatim as the target of 1062If TARGET is a non-Tramp file, it is used verbatim as the target
1063the symlink. If LINKNAME is a Tramp file, only the localname component is 1063of the symlink. If TARGET is a Tramp file, only the localname
1064used as the target of the symlink. 1064component is used as the target of the symlink."
1065 1065 (if (not (tramp-tramp-file-p (expand-file-name linkname)))
1066If LINKNAME is a Tramp file and the localname component is relative, then 1066 (tramp-run-real-handler
1067it is expanded first, before the localname component is taken. Note that 1067 'make-symbolic-link (list target linkname ok-if-already-exists))
1068this can give surprising results if the user/host for the source and 1068
1069target of the symlink differ." 1069 (with-parsed-tramp-file-name linkname nil
1070 (with-parsed-tramp-file-name linkname l 1070 (let ((ln (tramp-get-remote-ln v))
1071 (let ((ln (tramp-get-remote-ln l)) 1071 (cwd (tramp-run-real-handler
1072 (cwd (tramp-run-real-handler 1072 'file-name-directory (list localname))))
1073 'file-name-directory (list l-localname)))) 1073 (unless ln
1074 (unless ln 1074 (tramp-error
1075 (tramp-error 1075 v 'file-error
1076 l 'file-error 1076 "Making a symbolic link. ln(1) does not exist on the remote host."))
1077 "Making a symbolic link. ln(1) does not exist on the remote host.")) 1077
1078 1078 ;; Do the 'confirm if exists' thing.
1079 ;; Do the 'confirm if exists' thing. 1079 (when (file-exists-p linkname)
1080 (when (file-exists-p linkname) 1080 ;; What to do?
1081 ;; What to do? 1081 (if (or (null ok-if-already-exists) ; not allowed to exist
1082 (if (or (null ok-if-already-exists) ; not allowed to exist 1082 (and (numberp ok-if-already-exists)
1083 (and (numberp ok-if-already-exists) 1083 (not (yes-or-no-p
1084 (not (yes-or-no-p 1084 (format
1085 (format 1085 "File %s already exists; make it a link anyway? "
1086 "File %s already exists; make it a link anyway? " 1086 localname)))))
1087 l-localname))))) 1087 (tramp-error v 'file-already-exists localname)
1088 (tramp-error l 'file-already-exists l-localname) 1088 (delete-file linkname)))
1089 (delete-file linkname))) 1089
1090 1090 ;; If TARGET is a Tramp name, use just the localname component.
1091 ;; If FILENAME is a Tramp name, use just the localname component. 1091 (when (tramp-file-name-equal-p
1092 (when (tramp-tramp-file-p filename) 1092 v (tramp-dissect-file-name (expand-file-name target)))
1093 (setq filename 1093 (setq target
1094 (tramp-file-name-localname 1094 (tramp-file-name-localname
1095 (tramp-dissect-file-name (expand-file-name filename))))) 1095 (tramp-dissect-file-name (expand-file-name target)))))
1096 1096
1097 (tramp-flush-file-property l (file-name-directory l-localname)) 1097 (tramp-flush-file-property v (file-name-directory localname))
1098 (tramp-flush-file-property l l-localname) 1098 (tramp-flush-file-property v localname)
1099 1099
1100 ;; Right, they are on the same host, regardless of user, method, 1100 ;; Right, they are on the same host, regardless of user, method,
1101 ;; etc. We now make the link on the remote machine. This will 1101 ;; etc. We now make the link on the remote machine. This will
1102 ;; occur as the user that FILENAME belongs to. 1102 ;; occur as the user that TARGET belongs to.
1103 (and (tramp-send-command-and-check 1103 (and (tramp-send-command-and-check
1104 l (format "cd %s" (tramp-shell-quote-argument cwd))) 1104 v (format "cd %s" (tramp-shell-quote-argument cwd)))
1105 (tramp-send-command-and-check 1105 (tramp-send-command-and-check
1106 l (format 1106 v (format
1107 "%s -sf %s %s" 1107 "%s -sf %s %s" ln
1108 ln 1108 (tramp-shell-quote-argument target)
1109 (tramp-shell-quote-argument filename) 1109 ;; The command could exceed PATH_MAX, so we use
1110 ;; The command could exceed PATH_MAX, so we use 1110 ;; relative file names. However, relative file names
1111 ;; relative file names. However, relative file names 1111 ;; could start with "-". `tramp-shell-quote-argument'
1112 ;; could start with "-". `tramp-shell-quote-argument' 1112 ;; does not handle this, we must do it ourselves.
1113 ;; does not handle this, we must do it ourselves. 1113 (tramp-shell-quote-argument
1114 (tramp-shell-quote-argument 1114 (concat "./" (file-name-nondirectory localname))))))))))
1115 (concat "./" (file-name-nondirectory l-localname)))))))))
1116 1115
1117(defun tramp-sh-handle-file-truename (filename) 1116(defun tramp-sh-handle-file-truename (filename)
1118 "Like `file-truename' for Tramp files." 1117 "Like `file-truename' for Tramp files."
@@ -1918,14 +1917,18 @@ tramp-sh-handle-file-name-all-completions: internal error accessing `%s': `%s'"
1918 (with-parsed-tramp-file-name filename v1 1917 (with-parsed-tramp-file-name filename v1
1919 (with-parsed-tramp-file-name newname v2 1918 (with-parsed-tramp-file-name newname v2
1920 (let ((ln (when v1 (tramp-get-remote-ln v1)))) 1919 (let ((ln (when v1 (tramp-get-remote-ln v1))))
1921 (when (and (numberp ok-if-already-exists) 1920
1922 (file-exists-p newname) 1921 ;; Do the 'confirm if exists' thing.
1923 (yes-or-no-p 1922 (when (file-exists-p newname)
1924 (format 1923 ;; What to do?
1925 "File %s already exists; make it a new name anyway? " 1924 (if (or (null ok-if-already-exists) ; not allowed to exist
1926 newname))) 1925 (and (numberp ok-if-already-exists)
1927 (tramp-error v2 'file-already-exists newname)) 1926 (not (yes-or-no-p
1928 (when ok-if-already-exists (setq ln (concat ln " -f"))) 1927 (format
1928 "File %s already exists; make it a link anyway? "
1929 v2-localname)))))
1930 (tramp-error v2 'file-already-exists newname)
1931 (delete-file newname)))
1929 (tramp-flush-file-property v2 (file-name-directory v2-localname)) 1932 (tramp-flush-file-property v2 (file-name-directory v2-localname))
1930 (tramp-flush-file-property v2 v2-localname) 1933 (tramp-flush-file-property v2 v2-localname)
1931 (tramp-barf-unless-okay 1934 (tramp-barf-unless-okay
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 367beb823aa..f734b80d535 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -354,16 +354,17 @@ pass to the OPERATION."
354 (tramp-error 354 (tramp-error
355 v2 'file-error 355 v2 'file-error
356 "add-name-to-file: %s must not be a directory" filename)) 356 "add-name-to-file: %s must not be a directory" filename))
357 (when (and (not ok-if-already-exists) 357 ;; Do the 'confirm if exists' thing.
358 (file-exists-p newname) 358 (when (file-exists-p newname)
359 (not (numberp ok-if-already-exists)) 359 ;; What to do?
360 (y-or-n-p 360 (if (or (null ok-if-already-exists) ; not allowed to exist
361 (format 361 (and (numberp ok-if-already-exists)
362 "File %s already exists; make it a new name anyway? " 362 (not (yes-or-no-p
363 newname))) 363 (format
364 (tramp-error 364 "File %s already exists; make it a link anyway? "
365 v2 'file-error 365 v2-localname)))))
366 "add-name-to-file: file %s already exists" newname)) 366 (tramp-error v2 'file-already-exists newname)
367 (delete-file newname)))
367 ;; We must also flush the cache of the directory, because 368 ;; We must also flush the cache of the directory, because
368 ;; `file-attributes' reads the values from there. 369 ;; `file-attributes' reads the values from there.
369 (tramp-flush-file-property v2 (file-name-directory v2-localname)) 370 (tramp-flush-file-property v2 (file-name-directory v2-localname))
@@ -1095,54 +1096,56 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
1095 v 'file-error "Couldn't make directory %s" directory)))))) 1096 v 'file-error "Couldn't make directory %s" directory))))))
1096 1097
1097(defun tramp-smb-handle-make-symbolic-link 1098(defun tramp-smb-handle-make-symbolic-link
1098 (filename linkname &optional ok-if-already-exists) 1099 (target linkname &optional ok-if-already-exists)
1099 "Like `make-symbolic-link' for Tramp files. 1100 "Like `make-symbolic-link' for Tramp files.
1100If LINKNAME is a non-Tramp file, it is used verbatim as the target of 1101If TARGET is a non-Tramp file, it is used verbatim as the target
1101the symlink. If LINKNAME is a Tramp file, only the localname component is 1102of the symlink. If TARGET is a Tramp file, only the localname
1102used as the target of the symlink. 1103component is used as the target of the symlink."
1103 1104 (if (not (tramp-tramp-file-p (expand-file-name linkname)))
1104If LINKNAME is a Tramp file and the localname component is relative, then 1105 (tramp-run-real-handler
1105it is expanded first, before the localname component is taken. Note that 1106 'make-symbolic-link (list target linkname ok-if-already-exists))
1106this can give surprising results if the user/host for the source and 1107
1107target of the symlink differ." 1108 (unless (tramp-equal-remote target linkname)
1108 (unless (tramp-equal-remote filename linkname) 1109 (with-parsed-tramp-file-name
1109 (with-parsed-tramp-file-name 1110 (if (tramp-tramp-file-p target) target linkname) nil
1110 (if (tramp-tramp-file-p filename) filename linkname) nil
1111 (tramp-error
1112 v 'file-error
1113 "make-symbolic-link: %s"
1114 "only implemented for same method, same user, same host")))
1115 (with-parsed-tramp-file-name filename v1
1116 (with-parsed-tramp-file-name linkname v2
1117 (when (file-directory-p filename)
1118 (tramp-error
1119 v2 'file-error
1120 "make-symbolic-link: %s must not be a directory" filename))
1121 (when (and (not ok-if-already-exists)
1122 (file-exists-p linkname)
1123 (not (numberp ok-if-already-exists))
1124 (y-or-n-p
1125 (format
1126 "File %s already exists; make it a new name anyway? "
1127 linkname)))
1128 (tramp-error v2 'file-already-exists linkname))
1129 (unless (tramp-smb-get-cifs-capabilities v1)
1130 (tramp-error v2 'file-error "make-symbolic-link not supported"))
1131 ;; We must also flush the cache of the directory, because
1132 ;; `file-attributes' reads the values from there.
1133 (tramp-flush-file-property v2 (file-name-directory v2-localname))
1134 (tramp-flush-file-property v2 v2-localname)
1135 (unless
1136 (tramp-smb-send-command
1137 v1
1138 (format
1139 "symlink \"%s\" \"%s\""
1140 (tramp-smb-get-localname v1)
1141 (tramp-smb-get-localname v2)))
1142 (tramp-error 1111 (tramp-error
1143 v2 'file-error 1112 v 'file-error
1144 "error with make-symbolic-link, see buffer `%s' for details" 1113 "make-symbolic-link: %s"
1145 (buffer-name)))))) 1114 "only implemented for same method, same user, same host")))
1115 (with-parsed-tramp-file-name target v1
1116 (with-parsed-tramp-file-name linkname v2
1117 (when (file-directory-p target)
1118 (tramp-error
1119 v2 'file-error
1120 "make-symbolic-link: %s must not be a directory" target))
1121 ;; Do the 'confirm if exists' thing.
1122 (when (file-exists-p linkname)
1123 ;; What to do?
1124 (if (or (null ok-if-already-exists) ; not allowed to exist
1125 (and (numberp ok-if-already-exists)
1126 (not (yes-or-no-p
1127 (format
1128 "File %s already exists; make it a link anyway? "
1129 v2-localname)))))
1130 (tramp-error v2 'file-already-exists v2-localname)
1131 (delete-file linkname)))
1132 (unless (tramp-smb-get-cifs-capabilities v1)
1133 (tramp-error v2 'file-error "make-symbolic-link not supported"))
1134 ;; We must also flush the cache of the directory, because
1135 ;; `file-attributes' reads the values from there.
1136 (tramp-flush-file-property v2 (file-name-directory v2-localname))
1137 (tramp-flush-file-property v2 v2-localname)
1138 (unless
1139 (tramp-smb-send-command
1140 v1
1141 (format
1142 "symlink \"%s\" \"%s\""
1143 (tramp-smb-get-localname v1)
1144 (tramp-smb-get-localname v2)))
1145 (tramp-error
1146 v2 'file-error
1147 "error with make-symbolic-link, see buffer `%s' for details"
1148 (buffer-name)))))))
1146 1149
1147(defun tramp-smb-handle-process-file 1150(defun tramp-smb-handle-process-file
1148 (program &optional infile destination display &rest args) 1151 (program &optional infile destination display &rest args)
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index ef3e62ccce3..bb68b9e9645 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -1597,6 +1597,12 @@ signal identifier to be raised, remaining arguments passed to
1597`tramp-message'. Finally, signal SIGNAL is raised." 1597`tramp-message'. Finally, signal SIGNAL is raised."
1598 (let (tramp-message-show-message) 1598 (let (tramp-message-show-message)
1599 (tramp-backtrace vec-or-proc) 1599 (tramp-backtrace vec-or-proc)
1600 (unless arguments
1601 ;; FMT-STRING could be just a file name, as in
1602 ;; `file-already-exists' errors. It could contain the ?\%
1603 ;; character, as in smb domain spec.
1604 (setq arguments (list fmt-string)
1605 fmt-string "%s"))
1600 (when vec-or-proc 1606 (when vec-or-proc
1601 (tramp-message 1607 (tramp-message
1602 vec-or-proc 1 "%s" 1608 vec-or-proc 1 "%s"
@@ -2009,6 +2015,11 @@ ARGS are the arguments OPERATION has been called with."
2009 '(add-name-to-file copy-directory copy-file expand-file-name 2015 '(add-name-to-file copy-directory copy-file expand-file-name
2010 file-equal-p file-in-directory-p 2016 file-equal-p file-in-directory-p
2011 file-name-all-completions file-name-completion 2017 file-name-all-completions file-name-completion
2018 ;; Starting with Emacs 26.1, just the 2nd argument of
2019 ;; `make-symbolic-link' matters. For backward
2020 ;; compatibility, we still accept the first argument as
2021 ;; file name to be checked. Handled properly in
2022 ;; `tramp-handle-*-make-symbolic-link'.
2012 file-newer-than-file-p make-symbolic-link rename-file)) 2023 file-newer-than-file-p make-symbolic-link rename-file))
2013 (save-match-data 2024 (save-match-data
2014 (cond 2025 (cond
@@ -3262,11 +3273,18 @@ User is always nil."
3262 t))) 3273 t)))
3263 3274
3264(defun tramp-handle-make-symbolic-link 3275(defun tramp-handle-make-symbolic-link
3265 (filename linkname &optional _ok-if-already-exists) 3276 (target linkname &optional ok-if-already-exists)
3266 "Like `make-symbolic-link' for Tramp files." 3277 "Like `make-symbolic-link' for Tramp files.
3267 (with-parsed-tramp-file-name 3278This is the fallback implementation for backends which do not
3268 (if (tramp-tramp-file-p filename) filename linkname) nil 3279support symbolic links."
3269 (tramp-error v 'file-error "make-symbolic-link not supported"))) 3280 (if (tramp-tramp-file-p (expand-file-name linkname))
3281 (tramp-error
3282 (tramp-dissect-file-name (expand-file-name linkname)) 'file-error
3283 "make-symbolic-link not supported")
3284 ;; This is needed prior Emacs 26.1, where TARGET has also be
3285 ;; checked for a file name handler.
3286 (tramp-run-real-handler
3287 'make-symbolic-link (list target linkname ok-if-already-exists))))
3270 3288
3271(defun tramp-handle-shell-command 3289(defun tramp-handle-shell-command
3272 (command &optional output-buffer error-buffer) 3290 (command &optional output-buffer error-buffer)
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 55f4b52ccdf..3dbb522a7cd 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -2587,16 +2587,19 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
2587 (not (string-equal (error-message-string err) 2587 (not (string-equal (error-message-string err)
2588 "make-symbolic-link not supported"))))) 2588 "make-symbolic-link not supported")))))
2589 (should (file-symlink-p tmp-name2)) 2589 (should (file-symlink-p tmp-name2))
2590 (should-error (make-symbolic-link tmp-name1 tmp-name2)) 2590 (should-error (make-symbolic-link tmp-name1 tmp-name2)
2591 :type 'file-already-exists)
2591 (make-symbolic-link tmp-name1 tmp-name2 'ok-if-already-exists) 2592 (make-symbolic-link tmp-name1 tmp-name2 'ok-if-already-exists)
2592 (should (file-symlink-p tmp-name2)) 2593 (should (file-symlink-p tmp-name2))
2593 ;; `tmp-name3' is a local file name. 2594 ;; `tmp-name3' is a local file name.
2594 (should-error (make-symbolic-link tmp-name1 tmp-name3))) 2595 (make-symbolic-link tmp-name1 tmp-name3)
2596 (should (file-symlink-p tmp-name3)))
2595 2597
2596 ;; Cleanup. 2598 ;; Cleanup.
2597 (ignore-errors 2599 (ignore-errors
2598 (delete-file tmp-name1) 2600 (delete-file tmp-name1)
2599 (delete-file tmp-name2))) 2601 (delete-file tmp-name2)
2602 (delete-file tmp-name3)))
2600 2603
2601 ;; Check `add-name-to-file'. 2604 ;; Check `add-name-to-file'.
2602 (unwind-protect 2605 (unwind-protect
@@ -2605,7 +2608,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
2605 (should (file-exists-p tmp-name1)) 2608 (should (file-exists-p tmp-name1))
2606 (add-name-to-file tmp-name1 tmp-name2) 2609 (add-name-to-file tmp-name1 tmp-name2)
2607 (should-not (file-symlink-p tmp-name2)) 2610 (should-not (file-symlink-p tmp-name2))
2608 (should-error (add-name-to-file tmp-name1 tmp-name2)) 2611 (should-error (add-name-to-file tmp-name1 tmp-name2)
2612 :type 'file-already-exists)
2609 (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists) 2613 (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists)
2610 (should-not (file-symlink-p tmp-name2)) 2614 (should-not (file-symlink-p tmp-name2))
2611 ;; `tmp-name3' is a local file name. 2615 ;; `tmp-name3' is a local file name.
@@ -2626,10 +2630,24 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
2626 (should-not (string-equal tmp-name2 (file-truename tmp-name2))) 2630 (should-not (string-equal tmp-name2 (file-truename tmp-name2)))
2627 (should 2631 (should
2628 (string-equal (file-truename tmp-name1) (file-truename tmp-name2))) 2632 (string-equal (file-truename tmp-name1) (file-truename tmp-name2)))
2629 (should (file-equal-p tmp-name1 tmp-name2))) 2633 (should (file-equal-p tmp-name1 tmp-name2))
2634 ;; `tmp-name3' is a local file name.
2635 (make-symbolic-link tmp-name1 tmp-name3)
2636 (should (file-symlink-p tmp-name3))
2637 (should-not (string-equal tmp-name3 (file-truename tmp-name3)))
2638 ;; `file-truename' returns a quoted file name for `tmp-name3'.
2639 ;; We must unquote it.
2640 (should
2641 (string-equal
2642 (file-truename tmp-name1)
2643 (funcall
2644 'tramp-compat-file-name-unquote (file-truename tmp-name3)))))
2645
2646 ;; Cleanup.
2630 (ignore-errors 2647 (ignore-errors
2631 (delete-file tmp-name1) 2648 (delete-file tmp-name1)
2632 (delete-file tmp-name2))) 2649 (delete-file tmp-name2)
2650 (delete-file tmp-name3)))
2633 2651
2634 ;; `file-truename' shall preserve trailing link of directories. 2652 ;; `file-truename' shall preserve trailing link of directories.
2635 (unless (file-symlink-p tramp-test-temporary-file-directory) 2653 (unless (file-symlink-p tramp-test-temporary-file-directory)