diff options
| author | Paul Eggert | 2017-08-03 16:18:45 -0700 |
|---|---|---|
| committer | Paul Eggert | 2017-08-03 16:19:21 -0700 |
| commit | ddc1ff58dec92a782b233d97a254fc41c1c887eb (patch) | |
| tree | 586afc017bdf34794c18763b946626433b626e4a | |
| parent | f465efe412607c6b931e3592e96200f2ff3b8d74 (diff) | |
| download | emacs-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.c | 45 |
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; |