>From 21df0eec6d056c88c7ffbd5a1c0f76661702d5cf Mon Sep 17 00:00:00 2001 From: Paul Eggert 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@eggert@cs.ucla.edu "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