diff options
| author | Paul Eggert | 2017-10-12 13:08:53 -0700 |
|---|---|---|
| committer | Paul Eggert | 2017-10-12 13:11:33 -0700 |
| commit | 2f4bd2fbdaccbaa61fe9b5adb56ba9e8f3d49505 (patch) | |
| tree | 71e75b38c66ba1554423ac7eccd911bc0b5adaef /src | |
| parent | 413978727c9fb1d26b64e81412434064d99ec568 (diff) | |
| download | emacs-2f4bd2fbdaccbaa61fe9b5adb56ba9e8f3d49505.tar.gz emacs-2f4bd2fbdaccbaa61fe9b5adb56ba9e8f3d49505.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileio.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/src/fileio.c b/src/fileio.c index 4bbcec6f178..e57bf46015c 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -2260,7 +2260,7 @@ This is what happens in interactive use with M-x. */) | |||
| 2260 | (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists) | 2260 | (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists) |
| 2261 | { | 2261 | { |
| 2262 | Lisp_Object handler; | 2262 | Lisp_Object handler; |
| 2263 | Lisp_Object encoded_file, encoded_newname, symlink_target; | 2263 | Lisp_Object encoded_file, encoded_newname; |
| 2264 | 2264 | ||
| 2265 | file = Fexpand_file_name (file, Qnil); | 2265 | file = Fexpand_file_name (file, Qnil); |
| 2266 | 2266 | ||
| @@ -2334,12 +2334,22 @@ This is what happens in interactive use with M-x. */) | |||
| 2334 | if (rename_errno != EXDEV) | 2334 | if (rename_errno != EXDEV) |
| 2335 | report_file_errno ("Renaming", list2 (file, newname), rename_errno); | 2335 | report_file_errno ("Renaming", list2 (file, newname), rename_errno); |
| 2336 | 2336 | ||
| 2337 | struct stat file_st; | ||
| 2337 | bool dirp = !NILP (Fdirectory_name_p (file)); | 2338 | bool dirp = !NILP (Fdirectory_name_p (file)); |
| 2339 | if (!dirp) | ||
| 2340 | { | ||
| 2341 | if (lstat (SSDATA (encoded_file), &file_st) != 0) | ||
| 2342 | report_file_error ("Renaming", list2 (file, newname)); | ||
| 2343 | dirp = S_ISDIR (file_st.st_mode) != 0; | ||
| 2344 | } | ||
| 2338 | if (dirp) | 2345 | if (dirp) |
| 2339 | call4 (Qcopy_directory, file, newname, Qt, Qnil); | 2346 | call4 (Qcopy_directory, file, newname, Qt, Qnil); |
| 2340 | else | 2347 | else |
| 2341 | { | 2348 | { |
| 2342 | symlink_target = Ffile_symlink_p (file); | 2349 | Lisp_Object symlink_target |
| 2350 | = (S_ISLNK (file_st.st_mode) | ||
| 2351 | ? emacs_readlinkat (AT_FDCWD, SSDATA (encoded_file)) | ||
| 2352 | : Qnil); | ||
| 2343 | if (!NILP (symlink_target)) | 2353 | if (!NILP (symlink_target)) |
| 2344 | Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists); | 2354 | Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists); |
| 2345 | else | 2355 | else |