Cygwin: align renameat2 to Linux behaviour

In contrast to rename default behaviour, Linux' renameat2 returns -1
with errno set to EEXIST, if oldfile and newfile refer to the same
file, and the RENAME_NOREPLACE flag is set.

Follow suit, given this is a Linux-only function anyway.

Fixes: f665b1cef3 ("cygwin: Implement renameat2")
Reported-by: Bruno Haible <bruno@clisp.org>
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2023-04-18 18:18:27 +02:00
parent fa84aa4dd2
commit d30a5917a9
2 changed files with 17 additions and 5 deletions

View File

@ -21,3 +21,7 @@ Bug Fixes
- Fix error handling in readlinkat. - Fix error handling in readlinkat.
Addresses: https://cygwin.com/pipermail/cygwin/2023-April/253510.html Addresses: https://cygwin.com/pipermail/cygwin/2023-April/253510.html
- Fix return code and errno set by renameat2, if oldfile and newfile
refer to the same file, and the RENAME_NOREPLACE flag is set.
Addresses: https://cygwin.com/pipermail/cygwin/2023-April/253514.html

View File

@ -2108,6 +2108,14 @@ nt_path_has_executable_suffix (PUNICODE_STRING upath)
return false; return false;
} }
inline int
set_same_file_return (bool noreplace)
{
if (!noreplace)
return 0;
set_errno (EEXIST);
return -1;
}
/* If newpath names an existing file and the RENAME_NOREPLACE flag is /* If newpath names an existing file and the RENAME_NOREPLACE flag is
specified, fail with EEXIST. Exception: Don't fail if the purpose specified, fail with EEXIST. Exception: Don't fail if the purpose
of the rename is just to change the case of oldpath on a of the rename is just to change the case of oldpath on a
@ -2286,7 +2294,7 @@ rename2 (const char *oldpath, const char *newpath, unsigned int at2flags)
newpc.get_nt_native_path (), newpc.get_nt_native_path (),
FALSE)) FALSE))
{ {
res = 0; res = set_same_file_return (noreplace);
__leave; __leave;
} }
newpc.file_attributes (INVALID_FILE_ATTRIBUTES); newpc.file_attributes (INVALID_FILE_ATTRIBUTES);
@ -2301,7 +2309,7 @@ rename2 (const char *oldpath, const char *newpath, unsigned int at2flags)
if (newpc.get_nt_native_path ()->Length if (newpc.get_nt_native_path ()->Length
== oldpc.get_nt_native_path ()->Length) == oldpc.get_nt_native_path ()->Length)
{ {
res = 0; res = set_same_file_return (noreplace);
__leave; __leave;
} }
if (*(PWCHAR) ((PBYTE) newpc.get_nt_native_path ()->Buffer if (*(PWCHAR) ((PBYTE) newpc.get_nt_native_path ()->Buffer
@ -2321,7 +2329,7 @@ rename2 (const char *oldpath, const char *newpath, unsigned int at2flags)
newpc.get_nt_native_path (), newpc.get_nt_native_path (),
oldpc.objcaseinsensitive ())) oldpc.objcaseinsensitive ()))
{ {
res = 0; res = set_same_file_return (noreplace);
__leave; __leave;
} }
} }
@ -2350,7 +2358,7 @@ rename2 (const char *oldpath, const char *newpath, unsigned int at2flags)
newpc.get_nt_native_path (), newpc.get_nt_native_path (),
oldpc.objcaseinsensitive ())) oldpc.objcaseinsensitive ()))
{ {
res = 0; res = set_same_file_return (noreplace);
__leave; __leave;
} }
} }
@ -2571,7 +2579,7 @@ skip_pre_W10_checks:
{ {
debug_printf ("%s and %s are the same file", oldpath, newpath); debug_printf ("%s and %s are the same file", oldpath, newpath);
NtClose (nfh); NtClose (nfh);
res = 0; res = set_same_file_return (noreplace);
__leave; __leave;
} }
NtClose (nfh); NtClose (nfh);