aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2017-08-03 16:18:45 -0700
committerPaul Eggert2017-08-03 16:19:21 -0700
commitddc1ff58dec92a782b233d97a254fc41c1c887eb (patch)
tree586afc017bdf34794c18763b946626433b626e4a
parentf465efe412607c6b931e3592e96200f2ff3b8d74 (diff)
downloademacs-ddc1ff58dec92a782b233d97a254fc41c1c887eb.tar.gz
emacs-ddc1ff58dec92a782b233d97a254fc41c1c887eb.zip
Port recent rename changes to RHEL 7 + NFS
Problem reported by Ted Zlatanov in: http://lists.gnu.org/archive/html/emacs-devel/2017-08/msg00082.html * src/fileio.c (Frename_file): On RHEL 7 + NFS, renameat2 can fail with errno == EINVAL when it is not supported. So treat that case like errno == ENOSYS. Also, when ok_if_already_exists is neither nil nor an integer, just call plain rename; this avoids an extra syscall to renameat2 when the latter fails with errno == EINVAL or ENOSYS or ENOENT.
-rw-r--r--src/fileio.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 0264c9fa1d8..db760d9b22d 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2344,23 +2344,38 @@ This is what happens in interactive use with M-x. */)
2344 encoded_file = ENCODE_FILE (file); 2344 encoded_file = ENCODE_FILE (file);
2345 encoded_newname = ENCODE_FILE (newname); 2345 encoded_newname = ENCODE_FILE (newname);
2346 2346
2347 if (renameat_noreplace (AT_FDCWD, SSDATA (encoded_file), 2347 /* If the filesystem is case-insensitive and the file names are
2348 AT_FDCWD, SSDATA (encoded_newname)) 2348 identical but for the case, don't worry whether the destination
2349 == 0) 2349 already exists: the caller simply wants to change the letter-case
2350 return Qnil; 2350 of the file name. */
2351 int rename_errno = errno; 2351 bool plain_rename
2352 = ((!NILP (ok_if_already_exists) && !INTEGERP (ok_if_already_exists))
2353 || (file_name_case_insensitive_p (SSDATA (encoded_file))
2354 && ! NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))));
2355
2356 int rename_errno;
2357 if (!plain_rename)
2358 {
2359 if (renameat_noreplace (AT_FDCWD, SSDATA (encoded_file),
2360 AT_FDCWD, SSDATA (encoded_newname))
2361 == 0)
2362 return Qnil;
2363
2364 rename_errno = errno;
2365 switch (rename_errno)
2366 {
2367 case EEXIST: case EINVAL: case ENOSYS:
2368 barf_or_query_if_file_exists (newname, rename_errno == EEXIST,
2369 "rename to it",
2370 INTEGERP (ok_if_already_exists),
2371 false);
2372 plain_rename = true;
2373 break;
2374 }
2375 }
2352 2376
2353 if (rename_errno == EEXIST || rename_errno == ENOSYS) 2377 if (plain_rename)
2354 { 2378 {
2355 /* If the filesystem is case-insensitive and the file names are
2356 identical but for the case, don't ask for confirmation: they
2357 simply want to change the letter-case of the file name. */
2358 if ((NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists))
2359 && (! file_name_case_insensitive_p (SSDATA (encoded_file))
2360 || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))))
2361 barf_or_query_if_file_exists (newname, rename_errno == EEXIST,
2362 "rename to it",
2363 INTEGERP (ok_if_already_exists), false);
2364 if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) == 0) 2379 if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) == 0)
2365 return Qnil; 2380 return Qnil;
2366 rename_errno = errno; 2381 rename_errno = errno;