On 10/8/20 9:55 AM, Gabriel Ivăncescu wrote:
Renaming a file or directory from e.g. foobar to FooBar (or any other caps-only change) should work and capitalize it, like on Windows, instead of being a no-op.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46203 Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/ntdll/unix/file.c | 48 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index afb552b..639ea6c 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4326,9 +4326,10 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, if (len >= sizeof(FILE_RENAME_INFORMATION)) { FILE_RENAME_INFORMATION *info = ptr;
char *unix_name, *src_unix; UNICODE_STRING name_str; OBJECT_ATTRIBUTES attr;
char *unix_name;
size_t unix_name_len; name_str.Buffer = info->FileName; name_str.Length = info->FileNameLength;@@ -4343,13 +4344,56 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, if (io->u.Status != STATUS_SUCCESS && io->u.Status != STATUS_NO_SUCH_FILE) break;
unix_name_len = strlen(unix_name);/* When it's renaming to the same file, preserve the case sensitivity of the lastcomponent, so that renaming a\b\c\foobar to a\b\c\Foobar works correctly. */if (io->u.Status != STATUS_NO_SUCH_FILE && !server_get_unix_name(handle, &src_unix)){char *name = realpath(unix_name, NULL);if (name && !strcmp(name, src_unix)){
Do we even need to make either of these checks?
(What happens if you try to clobber an existing file with different casing?)
size_t nt_filename_len, pathlen;const WCHAR *nt_filename;char *tmp;INT maxsz;for (pathlen = name_str.Length / sizeof(WCHAR); pathlen; pathlen--)if (name_str.Buffer[pathlen - 1] == '\\')break;
wcsrchr()?
nt_filename = name_str.Buffer + pathlen;nt_filename_len = name_str.Length / sizeof(WCHAR) - pathlen;/* Build it from path + filename (the latter converted from nt_filename) */for (pathlen = unix_name_len; pathlen; pathlen--)if (unix_name[pathlen - 1] == '/')break;tmp = unix_name;maxsz = pathlen + nt_filename_len * 3 + 1;if (unix_name_len + 1 < maxsz) tmp = realloc(tmp, maxsz);
This reallocation strategy is very weird.
if (tmp){unix_name = tmp;unix_name_len = pathlen;unix_name_len += ntdll_wcstoumbs(nt_filename, nt_filename_len,unix_name + pathlen, maxsz - pathlen, TRUE);unix_name[unix_name_len] = '\0';}}free(src_unix);free(name);}SERVER_START_REQ( set_fd_name_info ) { req->handle = wine_server_obj_handle( handle ); req->rootdir = wine_server_obj_handle( attr.RootDirectory ); req->link = FALSE; req->replace = info->ReplaceIfExists;
wine_server_add_data( req, unix_name, strlen(unix_name) );
wine_server_add_data( req, unix_name, unix_name_len ); io->u.Status = wine_server_call( req ); } SERVER_END_REQ;