Subject: Re: bug#28792: 26.0.60; Deleting to a custom trash directory in Dired gives error

From: Paul Eggert <[email-masked]>
Date: Thu, 12 Oct 2017 13:25:47 -0700

On 10/12/2017 08:27 AM, Andreas Schwab wrote:
> rename-file now refuses to copy directory across
> file systems unless the target name ends in a slash.

Thanks for the diagnosis. This is an unintended consequence of the 
race-condition patch for rename-file that I installed last month. I 
installed the attached patch into the emacs-26 branch to fix the bug.

>From 21df0eec6d056c88c7ffbd5a1c0f76661702d5cf Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Thu, 12 Oct 2017 13:08:53 -0700
Subject: [PATCH] Let rename-file rename dirs across filesystems

Problem diagnosed by Andreas Schwab (Bug#28792#65).
This fixes a bug that I introduced in
2017-09-10T22:39:24@[email-masked]
"Fix race with rename-file etc. with dir NEWNAME".
* src/fileio.c (Frename_file): Copy a source directory across
file system boundaries even if its name does not end in slash.
---
 src/fileio.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/src/fileio.c b/src/fileio.c
index 4bbcec6f17..e57bf46015 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2260,7 +2260,7 @@ This is what happens in interactive use with M-x.  */)
   (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists)
 {
   Lisp_Object handler;
-  Lisp_Object encoded_file, encoded_newname, symlink_target;
+  Lisp_Object encoded_file, encoded_newname;
 
   file = Fexpand_file_name (file, Qnil);
 
@@ -2334,12 +2334,22 @@ This is what happens in interactive use with M-x.  */)
   if (rename_errno != EXDEV)
     report_file_errno ("Renaming", list2 (file, newname), rename_errno);
 
+  struct stat file_st;
   bool dirp = !NILP (Fdirectory_name_p (file));
+  if (!dirp)
+    {
+      if (lstat (SSDATA (encoded_file), &file_st) != 0)
+	report_file_error ("Renaming", list2 (file, newname));
+      dirp = S_ISDIR (file_st.st_mode) != 0;
+    }
   if (dirp)
     call4 (Qcopy_directory, file, newname, Qt, Qnil);
   else
     {
-      symlink_target = Ffile_symlink_p (file);
+      Lisp_Object symlink_target
+	= (S_ISLNK (file_st.st_mode)
+	   ? emacs_readlinkat (AT_FDCWD, SSDATA (encoded_file))
+	   : Qnil);
       if (!NILP (symlink_target))
 	Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists);
       else
-- 
2.13.6