Subject: bug#58721: 28.2; dired with delete-by-moving-to-trash can't trash directory twice

From: Gustavo Barros <[email-masked]>
Date: Thu, 27 Oct 2022 19:01:27 -0300

Hi Eli,

On Thu, 27 Oct 2022 at 16:04, Eli Zaretskii <[email-masked]> wrote:

> Perhaps step in Edebug through copy-directory, and see what's going on
> there?  AFAIU, the problem happens inside that function.

I think I was able to narrow it down a little.

The empty directory is indeed created, when the file already exists,
by the call to `make-temp-file' at:

    (when (file-exists-p
           (file-name-concat trash-files-dir files-base))
      (setq overwrite t
            files-base (file-name-nondirectory
                        (make-temp-file
                         (file-name-concat
                          trash-files-dir files-base)
                         is-directory))))

But, at the same time, the `overwrite' flag is set to t, in this case.
I'm not sure why the file is actually created, I suppose that it is to
"reserve" that name and ensure nothing else takes it in the meantime.

At the end of the function, the call is done to:

    (rename-file fn new-fn overwrite)

But, when the operation is crossing filesystems and the file is large
enough, the `rename-file' will fail with "file exists", despite the
`OK-IF-ALREADY-EXISTS' argument being `t'.

You can try that with:

    (make-directory "~/.local/share/Trash/files/org-mode-foo-bar")
    (rename-file "/tmp/org-mode"
"~/.local/share/Trash/files/org-mode-foo-bar" t)

Provided "crossing filesystems" and "large enough" we get (I do, at
least) "(file-already-exists "File exists" ..."

WDYT? Can you reproduce this?