aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2025-03-16 14:17:38 +0100
committerMichael Albinus2025-03-16 14:17:38 +0100
commitb8104dadbf285d12c356d4cddd28ac3eaf05f263 (patch)
treefdee9ed3209a12b0957d4a7699db51e0e2d05e8e
parent03e33cbef3e33aa1ec843388d1671f7116a7347b (diff)
downloademacs-b8104dadbf285d12c356d4cddd28ac3eaf05f263.tar.gz
emacs-b8104dadbf285d12c356d4cddd28ac3eaf05f263.zip
Tramp: Handle symlinks to non-existing targets better
* lisp/net/tramp-gvfs.el (tramp-gvfs-do-copy-or-rename-file): Don't use the truename. * lisp/net/tramp-sh.el (tramp-do-copy-or-rename-file): Refactor. Handle symlinks. (Bug#76678) * lisp/net/tramp-smb.el (tramp-smb-errors): Add string. (tramp-smb-handle-copy-file, tramp-smb-handle-rename-file): Refactor. * lisp/net/tramp-sudoedit.el (tramp-sudoedit-do-copy-or-rename-file): Don't use the truename. Handle symlinks. * lisp/net/tramp.el (tramp-barf-if-file-missing): Accept also symlinks. (tramp-skeleton-file-exists-p): Handle non-existing symlink targets. (tramp-skeleton-set-file-modes-times-uid-gid): Fix typo. * test/lisp/net/tramp-tests.el (vc-handled-backends): Suppress only if noninteractive. (tramp-test11-copy-file, tramp-test12-rename-file) (tramp-test18-file-attributes, tramp-test21-file-links) (tramp--test-check-files): Adapt tests.
-rw-r--r--lisp/net/tramp-adb.el2
-rw-r--r--lisp/net/tramp-cmds.el1
-rw-r--r--lisp/net/tramp-gvfs.el6
-rw-r--r--lisp/net/tramp-sh.el234
-rw-r--r--lisp/net/tramp-smb.el191
-rw-r--r--lisp/net/tramp-sudoedit.el152
-rw-r--r--lisp/net/tramp.el21
-rw-r--r--test/lisp/net/tramp-tests.el89
8 files changed, 385 insertions, 311 deletions
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index f3b4e547692..fb54abfa0c6 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -997,7 +997,7 @@ error and non-nil on success."
997 ;; <https://android.stackexchange.com/questions/226638/how-to-use-multibyte-file-names-in-adb-shell/232379#232379> 997 ;; <https://android.stackexchange.com/questions/226638/how-to-use-multibyte-file-names-in-adb-shell/232379#232379>
998 ;; mksh uses UTF-8 internally, but is currently limited to the 998 ;; mksh uses UTF-8 internally, but is currently limited to the
999 ;; BMP (basic multilingua plane), which means U+0000 to 999 ;; BMP (basic multilingua plane), which means U+0000 to
1000 ;; U+FFFD. If you want to use SMP codepoints (U-00010000 to 1000 ;; U+FFFD. If you want to use SMP codepoints (U-00010000 to
1001 ;; U-0010FFFD) on the input line, you currently have to disable 1001 ;; U-0010FFFD) on the input line, you currently have to disable
1002 ;; the UTF-8 mode (sorry). 1002 ;; the UTF-8 mode (sorry).
1003 (tramp-adb-execute-adb-command vec "shell" command) 1003 (tramp-adb-execute-adb-command vec "shell" command)
diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el
index 0118ed7ab4c..0d90382b2d3 100644
--- a/lisp/net/tramp-cmds.el
+++ b/lisp/net/tramp-cmds.el
@@ -738,6 +738,7 @@ By default this is done using the \"sudo\" Tramp method.
738YOu can customize `tramp-file-name-with-method' to change this. 738YOu can customize `tramp-file-name-with-method' to change this.
739 739
740Interactively, with a prefix argument, prompt for a different method." 740Interactively, with a prefix argument, prompt for a different method."
741 ;; (declare (completion tramp-dired-buffer-command-completion-p))
741 (interactive) 742 (interactive)
742 (with-tramp-file-name-with-method 743 (with-tramp-file-name-with-method
743 (find-file (tramp-file-name-with-sudo (dired-get-file-for-visit))))) 744 (find-file (tramp-file-name-with-sudo (dired-get-file-for-visit)))))
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 2f0593b0a93..eff7a2d9ff8 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1044,7 +1044,9 @@ file names."
1044 (unless (memq op '(copy rename)) 1044 (unless (memq op '(copy rename))
1045 (error "Unknown operation `%s', must be `copy' or `rename'" op)) 1045 (error "Unknown operation `%s', must be `copy' or `rename'" op))
1046 1046
1047 (setq filename (file-truename filename)) 1047 ;; We cannot use `file-truename', this would fail for symlinks with
1048 ;; non-existing target.
1049 (setq filename (expand-file-name filename))
1048 (if (file-directory-p filename) 1050 (if (file-directory-p filename)
1049 (progn 1051 (progn
1050 (copy-directory filename newname keep-date t) 1052 (copy-directory filename newname keep-date t)
@@ -2217,7 +2219,7 @@ connection if a previous connection has died for some reason."
2217 method '(("smb" . "smb-share") 2219 method '(("smb" . "smb-share")
2218 ("davs" . "dav") 2220 ("davs" . "dav")
2219 ("nextcloud" . "dav") 2221 ("nextcloud" . "dav")
2220 ("afp". "afp-volume") 2222 ("afp" . "afp-volume")
2221 ("gdrive" . "google-drive"))) 2223 ("gdrive" . "google-drive")))
2222 method) 2224 method)
2223 tramp-gvfs-mounttypes) 2225 tramp-gvfs-mounttypes)
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 84b0d97cd20..2b113ba1acf 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2128,123 +2128,129 @@ file names."
2128 (progn 2128 (progn
2129 (copy-directory filename newname keep-date t) 2129 (copy-directory filename newname keep-date t)
2130 (when (eq op 'rename) (delete-directory filename 'recursive))) 2130 (when (eq op 'rename) (delete-directory filename 'recursive)))
2131 (if (file-symlink-p filename)
2132 (progn
2133 (make-symbolic-link
2134 (file-symlink-p filename) newname ok-if-already-exists)
2135 (when (eq op 'rename) (delete-file filename)))
2136
2137 ;; FIXME: This should be optimized. Computing `file-attributes'
2138 ;; checks already, whether the file exists.
2139 (let ((t1 (tramp-tramp-file-p filename))
2140 (t2 (tramp-tramp-file-p newname))
2141 (length (or (file-attribute-size
2142 (file-attributes (file-truename filename)))
2143 ;; `filename' doesn't exist, for example due
2144 ;; to non-existent symlink target.
2145 0))
2146 (file-times (file-attribute-modification-time
2147 (file-attributes filename)))
2148 (file-modes (tramp-default-file-modes filename))
2149 (msg-operation (if (eq op 'copy) "Copying" "Renaming"))
2150 copy-keep-date)
2151
2152 (with-parsed-tramp-file-name (if t1 filename newname) nil
2153 (tramp-barf-if-file-missing v filename
2154 (when (and (not ok-if-already-exists) (file-exists-p newname))
2155 (tramp-error v 'file-already-exists newname))
2156 (when (and (file-directory-p newname)
2157 (not (directory-name-p newname)))
2158 (tramp-error v 'file-error "File is a directory %s" newname))
2131 2159
2132 ;; FIXME: This should be optimized. Computing `file-attributes' 2160 (with-tramp-progress-reporter
2133 ;; checks already, whether the file exists. 2161 v 0 (format "%s %s to %s" msg-operation filename newname)
2134 (let ((t1 (tramp-tramp-file-p filename))
2135 (t2 (tramp-tramp-file-p newname))
2136 (length (file-attribute-size
2137 (file-attributes (file-truename filename))))
2138 (file-times (file-attribute-modification-time
2139 (file-attributes filename)))
2140 (file-modes (tramp-default-file-modes filename))
2141 (msg-operation (if (eq op 'copy) "Copying" "Renaming"))
2142 copy-keep-date)
2143
2144 (with-parsed-tramp-file-name (if t1 filename newname) nil
2145 (unless length
2146 (tramp-error v 'file-missing filename))
2147 (tramp-barf-if-file-missing v filename
2148 (when (and (not ok-if-already-exists) (file-exists-p newname))
2149 (tramp-error v 'file-already-exists newname))
2150 (when (and (file-directory-p newname)
2151 (not (directory-name-p newname)))
2152 (tramp-error v 'file-error "File is a directory %s" newname))
2153
2154 (with-tramp-progress-reporter
2155 v 0 (format "%s %s to %s" msg-operation filename newname)
2156 2162
2157 (cond
2158 ;; Both are Tramp files.
2159 ((and t1 t2)
2160 (with-parsed-tramp-file-name filename v1
2161 (with-parsed-tramp-file-name newname v2
2162 (cond
2163 ;; Shortcut: if method, host, user are the same for
2164 ;; both files, we invoke `cp' or `mv' on the remote
2165 ;; host directly.
2166 ((tramp-equal-remote filename newname)
2167 (setq copy-keep-date
2168 (or (eq op 'rename) keep-date preserve-uid-gid))
2169 (tramp-do-copy-or-rename-file-directly
2170 op filename newname
2171 ok-if-already-exists keep-date preserve-uid-gid))
2172
2173 ;; Try out-of-band operation.
2174 ((and
2175 (tramp-method-out-of-band-p v1 length)
2176 (tramp-method-out-of-band-p v2 length))
2177 (setq copy-keep-date
2178 (tramp-get-method-parameter v 'tramp-copy-keep-date))
2179 (tramp-do-copy-or-rename-file-out-of-band
2180 op filename newname ok-if-already-exists keep-date))
2181
2182 ;; No shortcut was possible. So we copy the file
2183 ;; first. If the operation was `rename', we go
2184 ;; back and delete the original file (if the copy
2185 ;; was successful). The approach is simple-minded:
2186 ;; we create a new buffer, insert the contents of
2187 ;; the source file into it, then write out the
2188 ;; buffer to the target file. The advantage is
2189 ;; that it doesn't matter which file name handlers
2190 ;; are used for the source and target file.
2191 (t
2192 (tramp-do-copy-or-rename-file-via-buffer
2193 op filename newname ok-if-already-exists keep-date))))))
2194
2195 ;; One file is a Tramp file, the other one is local.
2196 ((or t1 t2)
2197 (cond 2163 (cond
2198 ;; Fast track on local machine. 2164 ;; Both are Tramp files.
2199 ((tramp-local-host-p v) 2165 ((and t1 t2)
2200 (setq copy-keep-date 2166 (with-parsed-tramp-file-name filename v1
2201 (or (eq op 'rename) keep-date preserve-uid-gid)) 2167 (with-parsed-tramp-file-name newname v2
2202 (tramp-do-copy-or-rename-file-directly 2168 (cond
2203 op filename newname 2169 ;; Shortcut: if method, host, user are the same
2204 ok-if-already-exists keep-date preserve-uid-gid)) 2170 ;; for both files, we invoke `cp' or `mv' on the
2205 2171 ;; remote host directly.
2206 ;; If the Tramp file has an out-of-band method, the 2172 ((tramp-equal-remote filename newname)
2207 ;; corresponding copy-program can be invoked. 2173 (setq copy-keep-date
2208 ((tramp-method-out-of-band-p v length) 2174 (or (eq op 'rename) keep-date preserve-uid-gid))
2209 (setq copy-keep-date 2175 (tramp-do-copy-or-rename-file-directly
2210 (tramp-get-method-parameter v 'tramp-copy-keep-date)) 2176 op filename newname
2211 (tramp-do-copy-or-rename-file-out-of-band 2177 ok-if-already-exists keep-date preserve-uid-gid))
2212 op filename newname ok-if-already-exists keep-date)) 2178
2179 ;; Try out-of-band operation.
2180 ((and
2181 (tramp-method-out-of-band-p v1 length)
2182 (tramp-method-out-of-band-p v2 length))
2183 (setq copy-keep-date
2184 (tramp-get-method-parameter v 'tramp-copy-keep-date))
2185 (tramp-do-copy-or-rename-file-out-of-band
2186 op filename newname ok-if-already-exists keep-date))
2187
2188 ;; No shortcut was possible. So we copy the file
2189 ;; first. If the operation was `rename', we go
2190 ;; back and delete the original file (if the copy
2191 ;; was successful). The approach is simple-minded:
2192 ;; we create a new buffer, insert the contents of
2193 ;; the source file into it, then write out the
2194 ;; buffer to the target file. The advantage is
2195 ;; that it doesn't matter which file name handlers
2196 ;; are used for the source and target file.
2197 (t
2198 (tramp-do-copy-or-rename-file-via-buffer
2199 op filename newname ok-if-already-exists keep-date))))))
2200
2201 ;; One file is a Tramp file, the other one is local.
2202 ((or t1 t2)
2203 (cond
2204 ;; Fast track on local machine.
2205 ((tramp-local-host-p v)
2206 (setq copy-keep-date
2207 (or (eq op 'rename) keep-date preserve-uid-gid))
2208 (tramp-do-copy-or-rename-file-directly
2209 op filename newname
2210 ok-if-already-exists keep-date preserve-uid-gid))
2211
2212 ;; If the Tramp file has an out-of-band method, the
2213 ;; corresponding copy-program can be invoked.
2214 ((tramp-method-out-of-band-p v length)
2215 (setq copy-keep-date
2216 (tramp-get-method-parameter v 'tramp-copy-keep-date))
2217 (tramp-do-copy-or-rename-file-out-of-band
2218 op filename newname ok-if-already-exists keep-date))
2219
2220 ;; Use the inline method via a Tramp buffer.
2221 (t (tramp-do-copy-or-rename-file-via-buffer
2222 op filename newname ok-if-already-exists keep-date))))
2223
2224 (t
2225 ;; One of them must be a Tramp file.
2226 (error "Tramp implementation says this cannot happen")))
2227
2228 ;; In case of `rename', we must flush the cache of the source file.
2229 (when (and t1 (eq op 'rename))
2230 (with-parsed-tramp-file-name filename v1
2231 (tramp-flush-file-properties v1 v1-localname)))
2232
2233 ;; NEWNAME has wrong cached values.
2234 (when t2
2235 (with-parsed-tramp-file-name newname v2
2236 (tramp-flush-file-properties v2 v2-localname)))
2213 2237
2214 ;; Use the inline method via a Tramp buffer. 2238 ;; Handle `preserve-extended-attributes'. We ignore
2215 (t (tramp-do-copy-or-rename-file-via-buffer 2239 ;; possible errors, because ACL strings could be
2216 op filename newname ok-if-already-exists keep-date)))) 2240 ;; incompatible.
2241 (when-let* ((attributes (and preserve-extended-attributes
2242 (file-extended-attributes filename))))
2243 (ignore-errors
2244 (set-file-extended-attributes newname attributes)))
2217 2245
2218 (t 2246 ;; KEEP-DATE handling.
2219 ;; One of them must be a Tramp file. 2247 (when (and keep-date (not copy-keep-date))
2220 (error "Tramp implementation says this cannot happen"))) 2248 (set-file-times
2221 2249 newname file-times (unless ok-if-already-exists 'nofollow)))
2222 ;; In case of `rename', we must flush the cache of the source file. 2250
2223 (when (and t1 (eq op 'rename)) 2251 ;; Set the mode.
2224 (with-parsed-tramp-file-name filename v1 2252 (unless (and keep-date copy-keep-date)
2225 (tramp-flush-file-properties v1 v1-localname))) 2253 (set-file-modes newname file-modes)))))))))
2226
2227 ;; NEWNAME has wrong cached values.
2228 (when t2
2229 (with-parsed-tramp-file-name newname v2
2230 (tramp-flush-file-properties v2 v2-localname)))
2231
2232 ;; Handle `preserve-extended-attributes'. We ignore
2233 ;; possible errors, because ACL strings could be
2234 ;; incompatible.
2235 (when-let* ((attributes (and preserve-extended-attributes
2236 (file-extended-attributes filename))))
2237 (ignore-errors
2238 (set-file-extended-attributes newname attributes)))
2239
2240 ;; KEEP-DATE handling.
2241 (when (and keep-date (not copy-keep-date))
2242 (set-file-times
2243 newname file-times (unless ok-if-already-exists 'nofollow)))
2244
2245 ;; Set the mode.
2246 (unless (and keep-date copy-keep-date)
2247 (set-file-modes newname file-modes))))))))
2248 2254
2249(defun tramp-do-copy-or-rename-file-via-buffer 2255(defun tramp-do-copy-or-rename-file-via-buffer
2250 (op filename newname _ok-if-already-exists _keep-date) 2256 (op filename newname _ok-if-already-exists _keep-date)
@@ -3119,7 +3125,7 @@ will be used."
3119 ;; character to read. When a process does 3125 ;; character to read. When a process does
3120 ;; not read from stdin, like magit, it 3126 ;; not read from stdin, like magit, it
3121 ;; should set a timeout 3127 ;; should set a timeout
3122 ;; instead. See`tramp-pipe-stty-settings'. 3128 ;; instead. See `tramp-pipe-stty-settings'.
3123 ;; (Bug#62093) 3129 ;; (Bug#62093)
3124 ;; FIXME: Shall we rather use "stty raw"? 3130 ;; FIXME: Shall we rather use "stty raw"?
3125 (tramp-send-command 3131 (tramp-send-command
@@ -5631,7 +5637,7 @@ Nonexistent directories are removed from spec."
5631 (lambda (x) (not (tramp-get-file-property vec x "file-directory-p"))) 5637 (lambda (x) (not (tramp-get-file-property vec x "file-directory-p")))
5632 remote-path)))))) 5638 remote-path))))))
5633 5639
5634;; The PIPE_BUF in POSIX [1] can be as low as 512 [2]. Here are the values 5640;; The PIPE_BUF in POSIX [1] can be as low as 512 [2]. Here are the values
5635;; on various platforms: 5641;; on various platforms:
5636;; - 512 on macOS, FreeBSD, NetBSD, OpenBSD, MirBSD, native Windows. 5642;; - 512 on macOS, FreeBSD, NetBSD, OpenBSD, MirBSD, native Windows.
5637;; - 4 KiB on Linux, OSF/1, Cygwin, Haiku. 5643;; - 4 KiB on Linux, OSF/1, Cygwin, Haiku.
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 64bde348775..aeb7c01c03f 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -114,6 +114,7 @@ this variable \"client min protocol=NT1\"."
114 "Read from server failed, maybe it closed the connection" 114 "Read from server failed, maybe it closed the connection"
115 "Call timed out: server did not respond" 115 "Call timed out: server did not respond"
116 (: (+ (not blank)) ": command not found") 116 (: (+ (not blank)) ": command not found")
117 (: (+ (not blank)) " does not exist")
117 "Server doesn't support UNIX CIFS calls" 118 "Server doesn't support UNIX CIFS calls"
118 (| ;; Samba. 119 (| ;; Samba.
119 "ERRDOS" 120 "ERRDOS"
@@ -596,66 +597,63 @@ KEEP-DATE has no effect in case NEWNAME resides on an SMB server.
596PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." 597PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
597 (setq filename (expand-file-name filename) 598 (setq filename (expand-file-name filename)
598 newname (expand-file-name newname)) 599 newname (expand-file-name newname))
599 (with-tramp-progress-reporter
600 (tramp-dissect-file-name
601 (if (tramp-tramp-file-p filename) filename newname))
602 0 (format "Copying %s to %s" filename newname)
603 600
604 (if (file-directory-p filename) 601 (with-parsed-tramp-file-name
605 (copy-directory filename newname keep-date 'parents 'copy-contents) 602 (if (tramp-tramp-file-p filename) filename newname) nil
603 (with-tramp-progress-reporter
604 v 0 (format "Copying %s to %s" filename newname)
605
606 (if (file-directory-p filename)
607 (copy-directory filename newname keep-date 'parents 'copy-contents)
608
609 (tramp-barf-if-file-missing v filename
610 ;; `file-local-copy' returns a file name also for a local
611 ;; file with `jka-compr-handler', so we cannot trust its
612 ;; result as indication for a remote file name.
613 (if-let* ((tmpfile
614 (and (tramp-tramp-file-p filename)
615 (file-local-copy filename))))
616 ;; Remote filename.
617 (condition-case err
618 (rename-file tmpfile newname ok-if-already-exists)
619 ((error quit)
620 (delete-file tmpfile)
621 (signal (car err) (cdr err))))
622
623 ;; Remote newname.
624 (when (and (file-directory-p newname)
625 (directory-name-p newname))
626 (setq newname
627 (expand-file-name
628 (file-name-nondirectory filename) newname)))
629
630 (when (and (not ok-if-already-exists) (file-exists-p newname))
631 (tramp-error v 'file-already-exists newname))
632 (when (and (file-directory-p newname)
633 (not (directory-name-p newname)))
634 (tramp-error v 'file-error "File is a directory %s" newname))
635
636 (unless (tramp-smb-get-share v)
637 (tramp-error
638 v 'file-error "Target `%s' must contain a share name" newname))
639 (unless (tramp-smb-send-command
640 v (format "put %s %s"
641 (tramp-smb-shell-quote-argument filename)
642 (tramp-smb-shell-quote-localname v)))
643 (tramp-error
644 v 'file-error "Cannot copy `%s' to `%s'" filename newname))
606 645
607 (unless (file-exists-p filename) 646 ;; When newname did exist, we have wrong cached values.
608 (tramp-error 647 (when (tramp-tramp-file-p newname)
609 (tramp-dissect-file-name 648 (with-parsed-tramp-file-name newname v2
610 (if (tramp-tramp-file-p filename) filename newname)) 649 (tramp-flush-file-properties v2 v2-localname))))))
611 'file-missing filename)) 650
612 651 ;; KEEP-DATE handling.
613 ;; `file-local-copy' returns a file name also for a local file 652 (when keep-date
614 ;; with `jka-compr-handler', so we cannot trust its result as 653 (set-file-times
615 ;; indication for a remote file name. 654 newname
616 (if-let* ((tmpfile 655 (file-attribute-modification-time (file-attributes filename))
617 (and (tramp-tramp-file-p filename) (file-local-copy filename)))) 656 (unless ok-if-already-exists 'nofollow))))))
618 ;; Remote filename.
619 (condition-case err
620 (rename-file tmpfile newname ok-if-already-exists)
621 ((error quit)
622 (delete-file tmpfile)
623 (signal (car err) (cdr err))))
624
625 ;; Remote newname.
626 (when (and (file-directory-p newname)
627 (directory-name-p newname))
628 (setq newname
629 (expand-file-name (file-name-nondirectory filename) newname)))
630
631 (with-parsed-tramp-file-name newname nil
632 (when (and (not ok-if-already-exists) (file-exists-p newname))
633 (tramp-error v 'file-already-exists newname))
634 (when (and (file-directory-p newname)
635 (not (directory-name-p newname)))
636 (tramp-error v 'file-error "File is a directory %s" newname))
637
638 (unless (tramp-smb-get-share v)
639 (tramp-error
640 v 'file-error "Target `%s' must contain a share name" newname))
641 (unless (tramp-smb-send-command
642 v (format "put %s %s"
643 (tramp-smb-shell-quote-argument filename)
644 (tramp-smb-shell-quote-localname v)))
645 (tramp-error
646 v 'file-error "Cannot copy `%s' to `%s'" filename newname))
647
648 ;; When newname did exist, we have wrong cached values.
649 (when (tramp-tramp-file-p newname)
650 (with-parsed-tramp-file-name newname v2
651 (tramp-flush-file-properties v2 v2-localname))))))
652
653 ;; KEEP-DATE handling.
654 (when keep-date
655 (set-file-times
656 newname
657 (file-attribute-modification-time (file-attributes filename))
658 (unless ok-if-already-exists 'nofollow)))))
659 657
660(defun tramp-smb-handle-delete-directory (directory &optional recursive trash) 658(defun tramp-smb-handle-delete-directory (directory &optional recursive trash)
661 "Like `delete-directory' for Tramp files." 659 "Like `delete-directory' for Tramp files."
@@ -1306,46 +1304,45 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
1306 1304
1307 (with-parsed-tramp-file-name 1305 (with-parsed-tramp-file-name
1308 (if (tramp-tramp-file-p filename) filename newname) nil 1306 (if (tramp-tramp-file-p filename) filename newname) nil
1309 (unless (file-exists-p filename) 1307 (tramp-barf-if-file-missing v filename
1310 (tramp-error v 'file-missing filename)) 1308 (when (and (not ok-if-already-exists) (file-exists-p newname))
1311 (when (and (not ok-if-already-exists) (file-exists-p newname)) 1309 (tramp-error v 'file-already-exists newname))
1312 (tramp-error v 'file-already-exists newname)) 1310 (when (and (file-directory-p newname)
1313 (when (and (file-directory-p newname) 1311 (not (directory-name-p newname)))
1314 (not (directory-name-p newname))) 1312 (tramp-error v 'file-error "File is a directory %s" newname))
1315 (tramp-error v 'file-error "File is a directory %s" newname))
1316 1313
1317 (with-tramp-progress-reporter 1314 (with-tramp-progress-reporter
1318 v 0 (format "Renaming %s to %s" filename newname) 1315 v 0 (format "Renaming %s to %s" filename newname)
1319 1316
1320 (if (and (not (file-exists-p newname)) 1317 (if (and (not (file-exists-p newname))
1321 (tramp-equal-remote filename newname) 1318 (tramp-equal-remote filename newname)
1322 (string-equal 1319 (string-equal
1323 (tramp-smb-get-share (tramp-dissect-file-name filename)) 1320 (tramp-smb-get-share (tramp-dissect-file-name filename))
1324 (tramp-smb-get-share (tramp-dissect-file-name newname)))) 1321 (tramp-smb-get-share (tramp-dissect-file-name newname))))
1325 ;; We can rename directly. 1322 ;; We can rename directly.
1326 (with-parsed-tramp-file-name filename v1 1323 (with-parsed-tramp-file-name filename v1
1327 (with-parsed-tramp-file-name newname v2 1324 (with-parsed-tramp-file-name newname v2
1328 1325
1329 ;; We must also flush the cache of the directory, because 1326 ;; We must also flush the cache of the directory, because
1330 ;; `file-attributes' reads the values from there. 1327 ;; `file-attributes' reads the values from there.
1331 (tramp-flush-file-properties v1 v1-localname) 1328 (tramp-flush-file-properties v1 v1-localname)
1332 (tramp-flush-file-properties v2 v2-localname) 1329 (tramp-flush-file-properties v2 v2-localname)
1333 (unless (tramp-smb-get-share v2) 1330 (unless (tramp-smb-get-share v2)
1334 (tramp-error 1331 (tramp-error
1335 v2 'file-error 1332 v2 'file-error
1336 "Target `%s' must contain a share name" newname)) 1333 "Target `%s' must contain a share name" newname))
1337 (unless (tramp-smb-send-command 1334 (unless (tramp-smb-send-command
1338 v2 (format "rename %s %s" 1335 v2 (format "rename %s %s"
1339 (tramp-smb-shell-quote-localname v1) 1336 (tramp-smb-shell-quote-localname v1)
1340 (tramp-smb-shell-quote-localname v2))) 1337 (tramp-smb-shell-quote-localname v2)))
1341 (tramp-error v2 'file-error "Cannot rename `%s'" filename)))) 1338 (tramp-error v2 'file-error "Cannot rename `%s'" filename))))
1342 1339
1343 ;; We must rename via copy. 1340 ;; We must rename via copy.
1344 (copy-file 1341 (copy-file
1345 filename newname ok-if-already-exists 'keep-time 'preserve-uid-gid) 1342 filename newname ok-if-already-exists 'keep-time 'preserve-uid-gid)
1346 (if (file-directory-p filename) 1343 (if (file-directory-p filename)
1347 (delete-directory filename 'recursive) 1344 (delete-directory filename 'recursive)
1348 (delete-file filename)))))) 1345 (delete-file filename)))))))
1349 1346
1350(defun tramp-smb-action-set-acl (proc vec) 1347(defun tramp-smb-action-set-acl (proc vec)
1351 "Set ACL data." 1348 "Set ACL data."
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index 0202f933b74..517bd85736a 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -244,84 +244,88 @@ absolute file names."
244 (unless (memq op '(copy rename)) 244 (unless (memq op '(copy rename))
245 (error "Unknown operation `%s', must be `copy' or `rename'" op)) 245 (error "Unknown operation `%s', must be `copy' or `rename'" op))
246 246
247 (setq filename (file-truename filename))
248 (if (file-directory-p filename) 247 (if (file-directory-p filename)
249 (progn 248 (progn
250 (copy-directory filename newname keep-date t) 249 (copy-directory filename newname keep-date t)
251 (when (eq op 'rename) (delete-directory filename 'recursive))) 250 (when (eq op 'rename) (delete-directory filename 'recursive)))
252 251 (if (file-symlink-p filename)
253 ;; FIXME: This should be optimized. Computing `file-attributes' 252 (progn
254 ;; checks already, whether the file exists. 253 (make-symbolic-link
255 (let ((t1 (tramp-sudoedit-file-name-p filename)) 254 (file-symlink-p filename) newname ok-if-already-exists)
256 (t2 (tramp-sudoedit-file-name-p newname)) 255 (when (eq op 'rename) (delete-file filename)))
257 (file-times (file-attribute-modification-time 256
258 (file-attributes filename))) 257 ;; FIXME: This should be optimized. Computing `file-attributes'
259 (file-modes (tramp-default-file-modes filename)) 258 ;; checks already, whether the file exists.
260 (attributes (and preserve-extended-attributes 259 (let ((t1 (tramp-sudoedit-file-name-p filename))
261 (file-extended-attributes filename))) 260 (t2 (tramp-sudoedit-file-name-p newname))
262 (sudoedit-operation 261 (file-times (file-attribute-modification-time
263 (cond 262 (file-attributes filename)))
264 ((and (eq op 'copy) preserve-uid-gid) '("cp" "-f" "-p")) 263 (file-modes (tramp-default-file-modes filename))
265 ((eq op 'copy) '("cp" "-f")) 264 (attributes (and preserve-extended-attributes
266 ((eq op 'rename) '("mv" "-f")))) 265 (file-extended-attributes filename)))
267 (msg-operation (if (eq op 'copy) "Copying" "Renaming"))) 266 (sudoedit-operation
268 267 (cond
269 (with-parsed-tramp-file-name (if t1 filename newname) nil 268 ((and (eq op 'copy) preserve-uid-gid) '("cp" "-f" "-p"))
270 (tramp-barf-if-file-missing v filename 269 ((eq op 'copy) '("cp" "-f"))
271 (when (and (not ok-if-already-exists) (file-exists-p newname)) 270 ((eq op 'rename) '("mv" "-f"))))
272 (tramp-error v 'file-already-exists newname)) 271 (msg-operation (if (eq op 'copy) "Copying" "Renaming")))
273 (when (and (file-directory-p newname) 272
274 (not (directory-name-p newname))) 273 (with-parsed-tramp-file-name (if t1 filename newname) nil
275 (tramp-error v 'file-error "File is a directory %s" newname)) 274 (tramp-barf-if-file-missing v filename
276 275 (when (and (not ok-if-already-exists) (file-exists-p newname))
277 (if (or (and (tramp-tramp-file-p filename) (not t1)) 276 (tramp-error v 'file-already-exists newname))
278 (and (tramp-tramp-file-p newname) (not t2))) 277 (when (and (file-directory-p newname)
279 ;; We cannot copy or rename directly. 278 (not (directory-name-p newname)))
280 (let ((tmpfile (tramp-compat-make-temp-file filename))) 279 (tramp-error v 'file-error "File is a directory %s" newname))
281 (if (eq op 'copy) 280
282 (copy-file filename tmpfile t) 281 (if (or (and (tramp-tramp-file-p filename) (not t1))
283 (rename-file filename tmpfile t)) 282 (and (tramp-tramp-file-p newname) (not t2)))
284 (rename-file tmpfile newname ok-if-already-exists)) 283 ;; We cannot copy or rename directly.
285 284 (let ((tmpfile (tramp-compat-make-temp-file filename)))
286 ;; Direct action. 285 (if (eq op 'copy)
287 (with-tramp-progress-reporter 286 (copy-file filename tmpfile t)
288 v 0 (format "%s %s to %s" msg-operation filename newname) 287 (rename-file filename tmpfile t))
289 (unless (tramp-sudoedit-send-command 288 (rename-file tmpfile newname ok-if-already-exists))
290 v sudoedit-operation 289
291 (tramp-unquote-file-local-name filename) 290 ;; Direct action.
292 (tramp-unquote-file-local-name newname)) 291 (with-tramp-progress-reporter
293 (tramp-error 292 v 0 (format "%s %s to %s" msg-operation filename newname)
294 v 'file-error 293 (unless (tramp-sudoedit-send-command
295 "Error %s `%s' `%s'" msg-operation filename newname)))) 294 v sudoedit-operation
296 295 (tramp-unquote-file-local-name filename)
297 ;; When `newname' is local, we must change the ownership to 296 (tramp-unquote-file-local-name newname))
298 ;; the local user. 297 (tramp-error
299 (unless (tramp-tramp-file-p newname) 298 v 'file-error
300 (tramp-set-file-uid-gid 299 "Error %s `%s' `%s'" msg-operation filename newname))))
301 (concat (file-remote-p filename) newname) 300
302 (tramp-get-local-uid 'integer) 301 ;; When `newname' is local, we must change the ownership
303 (tramp-get-local-gid 'integer))) 302 ;; to the local user.
304 303 (unless (tramp-tramp-file-p newname)
305 ;; Set the time and mode. Mask possible errors. 304 (tramp-set-file-uid-gid
306 (when keep-date 305 (concat (file-remote-p filename) newname)
307 (ignore-errors 306 (tramp-get-local-uid 'integer)
308 (set-file-times 307 (tramp-get-local-gid 'integer)))
309 newname file-times (unless ok-if-already-exists 'nofollow)) 308
310 (set-file-modes newname file-modes))) 309 ;; Set the time and mode. Mask possible errors.
311 310 (when keep-date
312 ;; Handle `preserve-extended-attributes'. We ignore possible 311 (ignore-errors
313 ;; errors, because ACL strings could be incompatible. 312 (set-file-times
314 (when attributes 313 newname file-times (unless ok-if-already-exists 'nofollow))
315 (ignore-errors 314 (set-file-modes newname file-modes)))
316 (set-file-extended-attributes newname attributes))) 315
317 316 ;; Handle `preserve-extended-attributes'. We ignore possible
318 (when (and t1 (eq op 'rename)) 317 ;; errors, because ACL strings could be incompatible.
319 (with-parsed-tramp-file-name filename v1 318 (when attributes
320 (tramp-flush-file-properties v1 v1-localname))) 319 (ignore-errors
321 320 (set-file-extended-attributes newname attributes)))
322 (when t2 321
323 (with-parsed-tramp-file-name newname v2 322 (when (and t1 (eq op 'rename))
324 (tramp-flush-file-properties v2 v2-localname)))))))) 323 (with-parsed-tramp-file-name filename v1
324 (tramp-flush-file-properties v1 v1-localname)))
325
326 (when t2
327 (with-parsed-tramp-file-name newname v2
328 (tramp-flush-file-properties v2 v2-localname)))))))))
325 329
326(defun tramp-sudoedit-handle-copy-file 330(defun tramp-sudoedit-handle-copy-file
327 (filename newname &optional ok-if-already-exists keep-date 331 (filename newname &optional ok-if-already-exists keep-date
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 190e1871234..6f2d891db5d 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -2107,7 +2107,7 @@ does not exist, otherwise propagate the error."
2107 `(condition-case ,err 2107 `(condition-case ,err
2108 (progn ,@body) 2108 (progn ,@body)
2109 (error 2109 (error
2110 (if (not (file-exists-p ,filename)) 2110 (if (not (or (file-exists-p ,filename) (file-symlink-p ,filename)))
2111 (tramp-error ,vec 'file-missing ,filename) 2111 (tramp-error ,vec 'file-missing ,filename)
2112 (signal (car ,err) (cdr ,err))))))) 2112 (signal (car ,err) (cdr ,err)))))))
2113 2113
@@ -3576,12 +3576,17 @@ BODY is the backend specific code."
3576 (when (tramp-connectable-p ,filename) 3576 (when (tramp-connectable-p ,filename)
3577 (with-parsed-tramp-file-name (expand-file-name ,filename) nil 3577 (with-parsed-tramp-file-name (expand-file-name ,filename) nil
3578 (with-tramp-file-property v localname "file-exists-p" 3578 (with-tramp-file-property v localname "file-exists-p"
3579 ;; Examine `file-attributes' cache to see if request can 3579 (cond
3580 ;; be satisfied without remote operation. 3580 ;; Examine `file-attributes' cache to see if request can
3581 (if (tramp-file-property-p v localname "file-attributes") 3581 ;; be satisfied without remote operation.
3582 (not 3582 ((and-let*
3583 (null (tramp-get-file-property v localname "file-attributes"))) 3583 (((tramp-file-property-p v localname "file-attributes"))
3584 ,@body)))))) 3584 (fa (tramp-get-file-property v localname "file-attributes"))
3585 ((not (stringp (car fa)))))))
3586 ;; Symlink to a non-existing target counts as nil.
3587 ((file-symlink-p ,filename)
3588 (file-exists-p (file-truename ,filename)))
3589 (t ,@body)))))))
3585 3590
3586(defmacro tramp-skeleton-file-local-copy (filename &rest body) 3591(defmacro tramp-skeleton-file-local-copy (filename &rest body)
3587 "Skeleton for `tramp-*-handle-file-local-copy'. 3592 "Skeleton for `tramp-*-handle-file-local-copy'.
@@ -3846,7 +3851,7 @@ BODY is the backend specific code."
3846 ;; We cannot add "file-attributes", "file-executable-p", 3851 ;; We cannot add "file-attributes", "file-executable-p",
3847 ;; "file-ownership-preserved-p", "file-readable-p", 3852 ;; "file-ownership-preserved-p", "file-readable-p",
3848 ;; "file-writable-p". 3853 ;; "file-writable-p".
3849 '("file-directory-p" "file-exists-p" "file-symlinkp" "file-truename") 3854 '("file-directory-p" "file-exists-p" "file-symlink-p" "file-truename")
3850 (tramp-flush-file-properties v localname)) 3855 (tramp-flush-file-properties v localname))
3851 (condition-case err 3856 (condition-case err
3852 (progn ,@body) 3857 (progn ,@body)
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 1efafb68fbc..ccb3731fc09 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -153,7 +153,7 @@
153 tramp-error-show-message-timeout nil 153 tramp-error-show-message-timeout nil
154 tramp-persistency-file-name nil 154 tramp-persistency-file-name nil
155 tramp-verbose 0 155 tramp-verbose 0
156 vc-handled-backends nil) 156 vc-handled-backends (unless noninteractive vc-handled-backends))
157 157
158(defconst tramp-test-name-prefix "tramp-test" 158(defconst tramp-test-name-prefix "tramp-test"
159 "Prefix to use for temporary test files.") 159 "Prefix to use for temporary test files.")
@@ -2871,7 +2871,9 @@ This checks also `file-name-as-directory', `file-name-directory',
2871 (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil))) 2871 (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
2872 (let ((tmp-name1 (tramp--test-make-temp-name nil quoted)) 2872 (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
2873 (tmp-name2 (tramp--test-make-temp-name nil quoted)) 2873 (tmp-name2 (tramp--test-make-temp-name nil quoted))
2874 (tmp-name3 (tramp--test-make-temp-name 'local quoted))) 2874 (tmp-name3 (tramp--test-make-temp-name 'local quoted))
2875 (tmp-name4
2876 (file-name-nondirectory (tramp--test-make-temp-name 'local quoted))))
2875 (dolist (source-target 2877 (dolist (source-target
2876 `(;; Copy on remote side. 2878 `(;; Copy on remote side.
2877 (,tmp-name1 . ,tmp-name2) 2879 (,tmp-name1 . ,tmp-name2)
@@ -2879,8 +2881,12 @@ This checks also `file-name-as-directory', `file-name-directory',
2879 (,tmp-name1 . ,tmp-name3) 2881 (,tmp-name1 . ,tmp-name3)
2880 ;; Copy from local side to remote side. 2882 ;; Copy from local side to remote side.
2881 (,tmp-name3 . ,tmp-name1))) 2883 (,tmp-name3 . ,tmp-name1)))
2882 (let ((source (car source-target)) 2884 (let* ((source (car source-target))
2883 (target (cdr source-target))) 2885 (source-link
2886 (expand-file-name tmp-name4 (file-name-directory source)))
2887 (target (cdr source-target))
2888 (target-link
2889 (expand-file-name tmp-name4 (file-name-directory target))))
2884 2890
2885 ;; Copy simple file. 2891 ;; Copy simple file.
2886 (unwind-protect 2892 (unwind-protect
@@ -2905,6 +2911,26 @@ This checks also `file-name-as-directory', `file-name-directory',
2905 (ignore-errors (delete-file source)) 2911 (ignore-errors (delete-file source))
2906 (ignore-errors (delete-file target))) 2912 (ignore-errors (delete-file target)))
2907 2913
2914 ;; Copy symlinked file.
2915 (unwind-protect
2916 (tramp--test-ignore-make-symbolic-link-error
2917 (write-region "foo" nil source-link)
2918 (should (file-exists-p source-link))
2919 (make-symbolic-link tmp-name4 source)
2920 (should (file-exists-p source))
2921 (should (string-equal (file-symlink-p source) tmp-name4))
2922 (copy-file source target)
2923 ;; Some backends like tramp-gvfs.el do not create the
2924 ;; link on the target.
2925 (when (file-symlink-p target)
2926 (should (string-equal (file-symlink-p target) tmp-name4))))
2927
2928 ;; Cleanup.
2929 (ignore-errors (delete-file source))
2930 (ignore-errors (delete-file source-link))
2931 (ignore-errors (delete-file target))
2932 (ignore-errors (delete-file target-link)))
2933
2908 ;; Copy file to directory. 2934 ;; Copy file to directory.
2909 (unwind-protect 2935 (unwind-protect
2910 ;; This doesn't work on FTP. 2936 ;; This doesn't work on FTP.
@@ -2980,7 +3006,9 @@ This checks also `file-name-as-directory', `file-name-directory',
2980 (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil))) 3006 (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
2981 (let ((tmp-name1 (tramp--test-make-temp-name nil quoted)) 3007 (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
2982 (tmp-name2 (tramp--test-make-temp-name nil quoted)) 3008 (tmp-name2 (tramp--test-make-temp-name nil quoted))
2983 (tmp-name3 (tramp--test-make-temp-name 'local quoted))) 3009 (tmp-name3 (tramp--test-make-temp-name 'local quoted))
3010 (tmp-name4
3011 (file-name-nondirectory (tramp--test-make-temp-name 'local quoted))))
2984 (dolist (source-target 3012 (dolist (source-target
2985 `(;; Rename on remote side. 3013 `(;; Rename on remote side.
2986 (,tmp-name1 . ,tmp-name2) 3014 (,tmp-name1 . ,tmp-name2)
@@ -2988,8 +3016,12 @@ This checks also `file-name-as-directory', `file-name-directory',
2988 (,tmp-name1 . ,tmp-name3) 3016 (,tmp-name1 . ,tmp-name3)
2989 ;; Rename from local side to remote side. 3017 ;; Rename from local side to remote side.
2990 (,tmp-name3 . ,tmp-name1))) 3018 (,tmp-name3 . ,tmp-name1)))
2991 (let ((source (car source-target)) 3019 (let* ((source (car source-target))
2992 (target (cdr source-target))) 3020 (source-link
3021 (expand-file-name tmp-name4 (file-name-directory source)))
3022 (target (cdr source-target))
3023 (target-link
3024 (expand-file-name tmp-name4 (file-name-directory target))))
2993 3025
2994 ;; Rename simple file. 3026 ;; Rename simple file.
2995 (unwind-protect 3027 (unwind-protect
@@ -3018,6 +3050,27 @@ This checks also `file-name-as-directory', `file-name-directory',
3018 (ignore-errors (delete-file source)) 3050 (ignore-errors (delete-file source))
3019 (ignore-errors (delete-file target))) 3051 (ignore-errors (delete-file target)))
3020 3052
3053 ;; Rename symlinked file.
3054 (unwind-protect
3055 (tramp--test-ignore-make-symbolic-link-error
3056 (write-region "foo" nil source-link)
3057 (should (file-exists-p source-link))
3058 (make-symbolic-link tmp-name4 source)
3059 (should (file-exists-p source))
3060 (should (string-equal (file-symlink-p source) tmp-name4))
3061 (rename-file source target)
3062 (should-not (file-exists-p source))
3063 ;; Some backends like tramp-gvfs.el do not create the
3064 ;; link on the target.
3065 (when (file-symlink-p target)
3066 (should (string-equal (file-symlink-p target) tmp-name4))))
3067
3068 ;; Cleanup.
3069 (ignore-errors (delete-file source))
3070 (ignore-errors (delete-file source-link))
3071 (ignore-errors (delete-file target))
3072 (ignore-errors (delete-file target-link)))
3073
3021 ;; Rename file to directory. 3074 ;; Rename file to directory.
3022 (unwind-protect 3075 (unwind-protect
3023 (progn 3076 (progn
@@ -3814,6 +3867,18 @@ This tests also `access-file', `file-readable-p',
3814 (if quoted #'file-name-quote #'identity) 3867 (if quoted #'file-name-quote #'identity)
3815 (file-attribute-type attr)) 3868 (file-attribute-type attr))
3816 (file-remote-p (file-truename tmp-name1) 'localname))) 3869 (file-remote-p (file-truename tmp-name1) 'localname)))
3870 (delete-file tmp-name2)
3871
3872 ;; A non-existent link target makes the file unaccessible.
3873 (make-symbolic-link "error" tmp-name2)
3874 (should (file-symlink-p tmp-name2))
3875 (should-error
3876 (access-file tmp-name2 "error")
3877 :type 'file-missing)
3878 ;; `file-ownership-preserved-p' should return t for
3879 ;; symlinked files to a non-existing target.
3880 (when test-file-ownership-preserved-p
3881 (should (file-ownership-preserved-p tmp-name2 'group)))
3817 (delete-file tmp-name2)) 3882 (delete-file tmp-name2))
3818 3883
3819 ;; Check, that "//" in symlinks are handled properly. 3884 ;; Check, that "//" in symlinks are handled properly.
@@ -4463,13 +4528,11 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
4463 (make-symbolic-link tmp-name1 tmp-name2) 4528 (make-symbolic-link tmp-name1 tmp-name2)
4464 (should (file-symlink-p tmp-name1)) 4529 (should (file-symlink-p tmp-name1))
4465 (should (file-symlink-p tmp-name2)) 4530 (should (file-symlink-p tmp-name2))
4466 (should-not (file-regular-p tmp-name1))
4467 (should-not (file-regular-p tmp-name2))
4468 (should-error 4531 (should-error
4469 (file-truename tmp-name1) 4532 (file-regular-p tmp-name1)
4470 :type 'file-error) 4533 :type 'file-error)
4471 (should-error 4534 (should-error
4472 (file-truename tmp-name2) 4535 (file-regular-p tmp-name2)
4473 :type 'file-error)))) 4536 :type 'file-error))))
4474 4537
4475 ;; Cleanup. 4538 ;; Cleanup.
@@ -7390,10 +7453,6 @@ This requires restrictions of file name syntax."
7390 (if quoted #'file-name-quote #'identity) 7453 (if quoted #'file-name-quote #'identity)
7391 (file-attribute-type (file-attributes file3))) 7454 (file-attribute-type (file-attributes file3)))
7392 (file-remote-p (file-truename file1) 'localname))) 7455 (file-remote-p (file-truename file1) 'localname)))
7393 ;; Check file contents.
7394 (with-temp-buffer
7395 (insert-file-contents file3)
7396 (should (string-equal (buffer-string) elt)))
7397 (delete-file file3)))) 7456 (delete-file file3))))
7398 7457
7399 ;; Check file names. 7458 ;; Check file names.