Fix cross-filesystem directory trashing (Bug#58721)

* lisp/files.el (move-file-to-trash): When trashing a directory with
the same name as something that's already in the trash, copy it into
the trash folder and then delete it, rather than using rename-file.
This commit is contained in:
Mike Kupfer 2022-10-30 10:31:11 -07:00 committed by Eli Zaretskii
parent 3208a42c47
commit 95d827f21e

View file

@ -8596,10 +8596,27 @@ Otherwise, trash FILENAME using the freedesktop.org conventions,
(setq files-base (substring (file-name-nondirectory info-fn)
0 (- (length ".trashinfo"))))
(write-region nil nil info-fn nil 'quiet info-fn)))
;; Finally, try to move the file to the trashcan.
;; Finally, try to move the item to the trashcan. If
;; it's a file, just move it. Things are more
;; complicated for directories. If the target
;; directory already exists (due to uniquification)
;; and the trash directory is in a different
;; filesystem, rename-file will error out, even when
;; 'overwrite' is non-nil. Rather than worry about
;; whether we're crossing filesystems, just check if
;; we've moving a directory and the target directory
;; already exists. That handles both the
;; same-filesystem and cross-filesystem cases.
(let ((delete-by-moving-to-trash nil)
(new-fn (file-name-concat trash-files-dir files-base)))
(rename-file fn new-fn overwrite)))))))))
(if (or (not is-directory)
(not (file-exists-p new-fn)))
(rename-file fn new-fn overwrite)
(copy-directory fn
(file-name-as-directory new-fn)
t nil t)
(delete-directory fn t))))))))))
(defsubst file-attribute-type (attributes)