Which optionally returns the original case of the last path component.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/ntdll/unix/file.c | 66 +++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 23 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index c033bb0..e649745 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -3113,13 +3113,13 @@ done: * Helper for nt_to_unix_file_name */ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer, int unix_len, int pos, - UINT disposition, BOOL is_unix ) + char **case_ret, UINT disposition, BOOL is_unix ) { static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, '/', 0 }; NTSTATUS status; int ret; struct stat st; - char *unix_name = *buffer; + char *unix_name = *buffer, file_case[MAX_DIR_ENTRY_LEN + 1]; const WCHAR *ptr, *end;
/* check syntax of individual components */ @@ -3157,6 +3157,12 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer for (p = unix_name + pos ; *p; p++) if (*p == '\') *p = '/'; if (!stat( unix_name, &st )) { + if (case_ret) + { + char *p = unix_name + pos + 1, *tmp = p; + while (*p) if (*p++ == '/' && *p) tmp = p; + *case_ret = strdup( tmp ); + } if (disposition == FILE_CREATE) return STATUS_OBJECT_NAME_COLLISION; return STATUS_SUCCESS; } @@ -3169,6 +3175,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
/* now do it component by component */
+ file_case[0] = 0; while (name_len) { const WCHAR *end, *next; @@ -3194,19 +3201,20 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer /* if this is the last element, not finding it is not necessarily fatal */ if (!name_len) { + ret = ntdll_wcstoumbs( name, end - name, file_case, MAX_DIR_ENTRY_LEN + 1, TRUE ); + if (ret < 0 || ret > MAX_DIR_ENTRY_LEN) ret = 0; + file_case[ret] = 0; + if (status == STATUS_OBJECT_PATH_NOT_FOUND) { status = STATUS_OBJECT_NAME_NOT_FOUND; - if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE) + if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE && ret) { - ret = ntdll_wcstoumbs( name, end - name, unix_name + pos + 1, MAX_DIR_ENTRY_LEN + 1, TRUE ); - if (ret > 0 && ret <= MAX_DIR_ENTRY_LEN) - { - unix_name[pos] = '/'; - unix_name[pos + 1 + ret] = 0; - status = STATUS_NO_SUCH_FILE; - break; - } + strcpy( unix_name + pos + 1, file_case ); + unix_name[pos] = '/'; + unix_name[pos + 1 + ret] = 0; + status = STATUS_NO_SUCH_FILE; + break; } } else if (status == STATUS_SUCCESS && disposition == FILE_CREATE) @@ -3221,6 +3229,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer name = next; }
+ if (case_ret) *case_ret = strdup( file_case ); return status; }
@@ -3229,7 +3238,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer * nt_to_unix_file_name_no_root */ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char **unix_name_ret, - UINT disposition ) + char **case_ret, UINT disposition ) { static const WCHAR unixW[] = {'u','n','i','x'}; static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 }; @@ -3245,6 +3254,7 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char name = nameW->Buffer; name_len = nameW->Length / sizeof(WCHAR);
+ if (case_ret) *case_ret = NULL; if (!name_len || name[0] != '\') return STATUS_OBJECT_PATH_SYNTAX_BAD;
if (!(pos = get_dos_prefix_len( nameW ))) @@ -3323,7 +3333,7 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char name += prefix_len; name_len -= prefix_len;
- status = lookup_unix_name( name, name_len, &unix_name, unix_len, pos, disposition, is_unix ); + status = lookup_unix_name( name, name_len, &unix_name, unix_len, pos, case_ret, disposition, is_unix ); if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE) { TRACE( "%s -> %s\n", debugstr_us(nameW), debugstr_a(unix_name) ); @@ -3339,15 +3349,9 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char
/****************************************************************************** - * nt_to_unix_file_name - * - * Convert a file name from NT namespace to Unix namespace. - * - * If disposition is not FILE_OPEN or FILE_OVERWRITE, the last path - * element doesn't have to exist; in that case STATUS_NO_SUCH_FILE is - * returned, but the unix name is still filled in properly. + * nt_to_unix_file_name_with_case */ -NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition ) +static NTSTATUS nt_to_unix_file_name_with_case( const OBJECT_ATTRIBUTES *attr, char **name_ret, char **case_ret, UINT disposition ) { enum server_fd_type type; int old_cwd, root_fd, needs_close; @@ -3357,11 +3361,12 @@ NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, U NTSTATUS status;
if (!attr->RootDirectory) /* without root dir fall back to normal lookup */ - return nt_to_unix_file_name_no_root( attr->ObjectName, name_ret, disposition ); + return nt_to_unix_file_name_no_root( attr->ObjectName, name_ret, case_ret, disposition );
name = attr->ObjectName->Buffer; name_len = attr->ObjectName->Length / sizeof(WCHAR);
+ if (case_ret) *case_ret = NULL; if (name_len && name[0] == '\') return STATUS_INVALID_PARAMETER;
unix_len = name_len * 3 + MAX_DIR_ENTRY_LEN + 3; @@ -3380,7 +3385,7 @@ NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, U mutex_lock( &dir_mutex ); if ((old_cwd = open( ".", O_RDONLY )) != -1 && fchdir( root_fd ) != -1) { - status = lookup_unix_name( name, name_len, &unix_name, unix_len, 1, disposition, FALSE ); + status = lookup_unix_name( name, name_len, &unix_name, unix_len, 1, case_ret, disposition, FALSE ); if (fchdir( old_cwd ) == -1) chdir( "/" ); } else status = errno_to_status( errno ); @@ -3405,6 +3410,21 @@ NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, U }
+/****************************************************************************** + * nt_to_unix_file_name + * + * Convert a file name from NT namespace to Unix namespace. + * + * If disposition is not FILE_OPEN or FILE_OVERWRITE, the last path + * element doesn't have to exist; in that case STATUS_NO_SUCH_FILE is + * returned, but the unix name is still filled in properly. + */ +NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition ) +{ + return nt_to_unix_file_name_with_case( attr, name_ret, NULL, disposition ); +} + + /****************************************************************************** * wine_nt_to_unix_file_name *
Renaming a file or directory from e.g. foobar to FooBar (or any other case change) should work, like on Windows, instead of being a no-op. Clobbering an existing file must also respect the new case.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46203 Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/kernel32/tests/file.c | 4 +- dlls/ntdll/tests/file.c | 4 +- dlls/ntdll/unix/file.c | 14 ++++-- server/fd.c | 100 +++++++++++++++++++++++++------------ server/protocol.def | 2 + 5 files changed, 84 insertions(+), 40 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 8560524..9ca56e1 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -2040,7 +2040,7 @@ static void test_MoveFileA(void) ok(hfile != INVALID_HANDLE_VALUE, "FindFirstFileA: failed, error %d\n", GetLastError()); if (hfile != INVALID_HANDLE_VALUE) { - todo_wine ok(!lstrcmpA(strrchr(tempdir, '\') + 1, find_data.cFileName), + ok(!lstrcmpA(strrchr(tempdir, '\') + 1, find_data.cFileName), "MoveFile failed to change casing on same file: got %s\n", find_data.cFileName); } CloseHandle(hfile); @@ -2085,7 +2085,7 @@ static void test_MoveFileA(void) ok(hfile != INVALID_HANDLE_VALUE, "FindFirstFileA: failed, error %d\n", GetLastError()); if (hfile != INVALID_HANDLE_VALUE) { - todo_wine ok(!lstrcmpA(strrchr(tempdir, '\') + 1, find_data.cFileName), + ok(!lstrcmpA(strrchr(tempdir, '\') + 1, find_data.cFileName), "MoveFile failed to change casing on same directory: got %s\n", find_data.cFileName); } CloseHandle(hfile); diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index b7b4636..591f425 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -2315,7 +2315,7 @@ static void test_file_link_information(void) ok(handle != INVALID_HANDLE_VALUE, "FindFirstFileW: failed, error %d\n", GetLastError()); if (handle != INVALID_HANDLE_VALUE) { - todo_wine ok(!lstrcmpW(wcsrchr(newpath, '\') + 1, find_data.cFileName), + ok(!lstrcmpW(wcsrchr(newpath, '\') + 1, find_data.cFileName), "Link did not change casing on existing target file: got %s\n", wine_dbgstr_w(find_data.cFileName)); }
@@ -2900,7 +2900,7 @@ static void test_file_link_information(void) ok(handle != INVALID_HANDLE_VALUE, "FindFirstFileW: failed, error %d\n", GetLastError()); if (handle != INVALID_HANDLE_VALUE) { - todo_wine ok(!lstrcmpW(wcsrchr(oldpath, '\') + 1, find_data.cFileName), + ok(!lstrcmpW(wcsrchr(oldpath, '\') + 1, find_data.cFileName), "Link did not change casing on same file: got %s\n", wine_dbgstr_w(find_data.cFileName)); }
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index e649745..9b106c7 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4547,8 +4547,8 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, { FILE_RENAME_INFORMATION *info = ptr; UNICODE_STRING name_str, redir; + char *unix_name, *file_case; OBJECT_ATTRIBUTES attr; - char *unix_name;
name_str.Buffer = info->FileName; name_str.Length = info->FileNameLength; @@ -4556,7 +4556,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, InitializeObjectAttributes( &attr, &name_str, OBJ_CASE_INSENSITIVE, info->RootDirectory, NULL ); get_redirect( &attr, &redir );
- io->u.Status = nt_to_unix_file_name( &attr, &unix_name, FILE_OPEN_IF ); + io->u.Status = nt_to_unix_file_name_with_case( &attr, &unix_name, &file_case, FILE_OPEN_IF ); if (io->u.Status == STATUS_SUCCESS || io->u.Status == STATUS_NO_SUCH_FILE) { SERVER_START_REQ( set_fd_name_info ) @@ -4564,15 +4564,18 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, req->handle = wine_server_obj_handle( handle ); req->rootdir = wine_server_obj_handle( attr.RootDirectory ); req->namelen = attr.ObjectName->Length; + req->caselen = file_case ? strlen( file_case ) : 0; req->link = FALSE; req->replace = info->ReplaceIfExists; wine_server_add_data( req, attr.ObjectName->Buffer, attr.ObjectName->Length ); + wine_server_add_data( req, file_case, req->caselen ); wine_server_add_data( req, unix_name, strlen(unix_name) ); io->u.Status = wine_server_call( req ); } SERVER_END_REQ;
free( unix_name ); + free( file_case ); } free( redir.Buffer ); } @@ -4584,8 +4587,8 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, { FILE_LINK_INFORMATION *info = ptr; UNICODE_STRING name_str, redir; + char *unix_name, *file_case; OBJECT_ATTRIBUTES attr; - char *unix_name;
name_str.Buffer = info->FileName; name_str.Length = info->FileNameLength; @@ -4593,7 +4596,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, InitializeObjectAttributes( &attr, &name_str, OBJ_CASE_INSENSITIVE, info->RootDirectory, NULL ); get_redirect( &attr, &redir );
- io->u.Status = nt_to_unix_file_name( &attr, &unix_name, FILE_OPEN_IF ); + io->u.Status = nt_to_unix_file_name_with_case( &attr, &unix_name, &file_case, FILE_OPEN_IF ); if (io->u.Status == STATUS_SUCCESS || io->u.Status == STATUS_NO_SUCH_FILE) { SERVER_START_REQ( set_fd_name_info ) @@ -4601,15 +4604,18 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, req->handle = wine_server_obj_handle( handle ); req->rootdir = wine_server_obj_handle( attr.RootDirectory ); req->namelen = attr.ObjectName->Length; + req->caselen = file_case ? strlen( file_case ) : 0; req->link = TRUE; req->replace = info->ReplaceIfExists; wine_server_add_data( req, attr.ObjectName->Buffer, attr.ObjectName->Length ); + wine_server_add_data( req, file_case, req->caselen ); wine_server_add_data( req, unix_name, strlen(unix_name) ); io->u.Status = wine_server_call( req ); } SERVER_END_REQ;
free( unix_name ); + free( file_case ); } free( redir.Buffer ); } diff --git a/server/fd.c b/server/fd.c index e7253ec..dcb7361 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2485,11 +2485,14 @@ static void set_fd_disposition( struct fd *fd, int unlink )
/* set new name for the fd */ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, data_size_t len, - struct unicode_str nt_name, int create_link, int replace ) + const char *file_case, data_size_t caselen, struct unicode_str nt_name, + int create_link, int replace ) { + size_t pathlen = 0, filenamelen; struct inode *inode; struct stat st, st2; - char *name; + int different_case; + char *name, *p;
if (!fd->inode || !fd->unix_name) { @@ -2523,6 +2526,22 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da name = combined_name; }
+ for (p = name; *p;) if (*p++ == '/' && *p) pathlen = p - name; + filenamelen = p - name - pathlen; + for (p = name + pathlen; filenamelen && p[filenamelen - 1] == '/'; filenamelen--) { } + different_case = caselen && (filenamelen != caselen || memcmp( p, file_case, caselen )); + + if (filenamelen < caselen) + { + p = realloc( name, pathlen + caselen + 1 ); + if (!p) + { + set_error( STATUS_NO_MEMORY ); + goto failed; + } + name = p; + } + /* when creating a hard link, source cannot be a dir */ if (create_link && !fstat( fd->unix_fd, &st ) && S_ISDIR( st.st_mode )) { @@ -2535,47 +2554,61 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da if (!fstat( fd->unix_fd, &st2 ) && st.st_ino == st2.st_ino && st.st_dev == st2.st_dev) { if (create_link && !replace) set_error( STATUS_OBJECT_NAME_COLLISION ); - free( name ); - return; - } + if (!different_case) + { + free( name ); + return; + }
- if (!replace) - { - set_error( STATUS_OBJECT_NAME_COLLISION ); - goto failed; + /* creating a link with a different case on itself renames the file */ + create_link = 0; } - - /* can't replace directories or special files */ - if (!S_ISREG( st.st_mode )) + else { - set_error( STATUS_ACCESS_DENIED ); - goto failed; - } + if (!replace) + { + set_error( STATUS_OBJECT_NAME_COLLISION ); + goto failed; + }
- /* can't replace an opened file */ - if ((inode = get_inode( st.st_dev, st.st_ino, -1 ))) - { - int is_empty = list_empty( &inode->open ); - release_object( inode ); - if (!is_empty) + /* can't replace directories or special files */ + if (!S_ISREG( st.st_mode )) { set_error( STATUS_ACCESS_DENIED ); goto failed; } - }
- /* link() expects that the target doesn't exist */ - /* rename() cannot replace files with directories */ - if (create_link || S_ISDIR( st2.st_mode )) - { - if (unlink( name )) + /* can't replace an opened file */ + if ((inode = get_inode( st.st_dev, st.st_ino, -1 ))) { - file_set_error(); - goto failed; + int is_empty = list_empty( &inode->open ); + release_object( inode ); + if (!is_empty) + { + set_error( STATUS_ACCESS_DENIED ); + goto failed; + } + } + + /* link() expects that the target doesn't exist */ + /* rename() cannot replace files with directories */ + if (create_link || S_ISDIR( st2.st_mode ) || different_case) + { + if (unlink( name )) + { + file_set_error(); + goto failed; + } } } }
+ if (different_case) + { + memcpy( name + pathlen, file_case, caselen ); + name[pathlen + caselen] = 0; + } + if (create_link) { if (link( fd->unix_name, name )) @@ -2876,16 +2909,19 @@ DECL_HANDLER(set_fd_disp_info) /* set fd name information */ DECL_HANDLER(set_fd_name_info) { + const char *fullname, *file_case; struct fd *fd, *root_fd = NULL; struct unicode_str nt_name;
- if (req->namelen > get_req_data_size()) + if (req->namelen > get_req_data_size() || get_req_data_size() - req->namelen < req->caselen) { set_error( STATUS_INVALID_PARAMETER ); return; } nt_name.str = get_req_data(); nt_name.len = (req->namelen / sizeof(WCHAR)) * sizeof(WCHAR); + file_case = (const char *)get_req_data() + req->namelen; + fullname = file_case + req->caselen;
if (req->rootdir) { @@ -2899,8 +2935,8 @@ DECL_HANDLER(set_fd_name_info)
if ((fd = get_handle_fd_obj( current->process, req->handle, 0 ))) { - set_fd_name( fd, root_fd, (const char *)get_req_data() + req->namelen, - get_req_data_size() - req->namelen, nt_name, req->link, req->replace ); + set_fd_name( fd, root_fd, fullname, (const char *)get_req_data() + get_req_data_size() - fullname, + file_case, req->caselen, nt_name, req->link, req->replace ); release_object( fd ); } if (root_fd) release_object( root_fd ); diff --git a/server/protocol.def b/server/protocol.def index 6d8208b..fdf491d 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3531,9 +3531,11 @@ struct handle_info obj_handle_t handle; /* handle to a file or directory */ obj_handle_t rootdir; /* root directory */ data_size_t namelen; /* length of NT name in bytes */ + data_size_t caselen; /* length of the actual case filename */ int link; /* link instead of renaming */ int replace; /* replace an existing file? */ VARARG(name,unicode_str,namelen); /* NT name */ + VARARG(actual_case,string,caselen); /* new file name's actual case (without path) */ VARARG(filename,string); /* new file name */ @END
On 5/20/21 5:35 PM, Gabriel Ivăncescu wrote:
Which optionally returns the original case of the last path component.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/ntdll/unix/file.c | 66 +++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 23 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index c033bb0..e649745 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -3113,13 +3113,13 @@ done:
- Helper for nt_to_unix_file_name
*/ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer, int unix_len, int pos,
UINT disposition, BOOL is_unix )
{ static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, '/', 0 }; NTSTATUS status; int ret; struct stat st;char **case_ret, UINT disposition, BOOL is_unix )
- char *unix_name = *buffer;
char *unix_name = *buffer, file_case[MAX_DIR_ENTRY_LEN + 1]; const WCHAR *ptr, *end;
/* check syntax of individual components */
@@ -3157,6 +3157,12 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer for (p = unix_name + pos ; *p; p++) if (*p == '\') *p = '/'; if (!stat( unix_name, &st )) {
if (case_ret)
{
char *p = unix_name + pos + 1, *tmp = p;
while (*p) if (*p++ == '/' && *p) tmp = p;
*case_ret = strdup( tmp );
} if (disposition == FILE_CREATE) return STATUS_OBJECT_NAME_COLLISION; return STATUS_SUCCESS; }
@@ -3169,6 +3175,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
/* now do it component by component */
- file_case[0] = 0; while (name_len) { const WCHAR *end, *next;
@@ -3194,19 +3201,20 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer /* if this is the last element, not finding it is not necessarily fatal */ if (!name_len) {
ret = ntdll_wcstoumbs( name, end - name, file_case, MAX_DIR_ENTRY_LEN + 1, TRUE );
if (ret < 0 || ret > MAX_DIR_ENTRY_LEN) ret = 0;
file_case[ret] = 0;
if (status == STATUS_OBJECT_PATH_NOT_FOUND) { status = STATUS_OBJECT_NAME_NOT_FOUND;
if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE)
if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE && ret) {
ret = ntdll_wcstoumbs( name, end - name, unix_name + pos + 1, MAX_DIR_ENTRY_LEN + 1, TRUE );
if (ret > 0 && ret <= MAX_DIR_ENTRY_LEN)
{
unix_name[pos] = '/';
unix_name[pos + 1 + ret] = 0;
status = STATUS_NO_SUCH_FILE;
break;
}
strcpy( unix_name + pos + 1, file_case );
unix_name[pos] = '/';
unix_name[pos + 1 + ret] = 0;
status = STATUS_NO_SUCH_FILE;
break; } } else if (status == STATUS_SUCCESS && disposition == FILE_CREATE)
@@ -3221,6 +3229,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer name = next; }
- if (case_ret) *case_ret = strdup( file_case ); return status; }
In addition to the comments I made on the previous version, I think this is also possibly leaking things in case_ret, depending on the status returned.
It may be better instead to take a bit of time considering a similar approach as for name_ret, where nt_to_unix_file_name(_no_root) would provide instead the case_ret / case_len buffer, returning it in the same way name_ret is.
Gabriel Ivăncescu gabrielopcode@gmail.com writes:
Which optionally returns the original case of the last path component.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/ntdll/unix/file.c | 66 +++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 23 deletions(-)
There doesn't seem to be any need for a new nt_to_unix_file_name helper. You can simply copy the last path component separately from the Unix name lookup, it doesn't require any file system access.
On 5/20/21 6:40 PM, Alexandre Julliard wrote:
Gabriel Ivăncescu gabrielopcode@gmail.com writes:
Which optionally returns the original case of the last path component.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/ntdll/unix/file.c | 66 +++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 23 deletions(-)
There doesn't seem to be any need for a new nt_to_unix_file_name helper. You can simply copy the last path component separately from the Unix name lookup, it doesn't require any file system access.
Sorry, I suggested that to take advantage of the lookup_unix_name path decomposition, and to handle the corner cases more easily.
On 20/05/2021 19:40, Alexandre Julliard wrote:
Gabriel Ivăncescu gabrielopcode@gmail.com writes:
Which optionally returns the original case of the last path component.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/ntdll/unix/file.c | 66 +++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 23 deletions(-)
There doesn't seem to be any need for a new nt_to_unix_file_name helper. You can simply copy the last path component separately from the Unix name lookup, it doesn't require any file system access.
So I should go with the previous approach then (obviously with fixes)?
Or, what if I just add an optional parameter to nt_to_unix_file_name to return the case of last path? Or is that not desirable either?
Gabriel Ivăncescu gabrielopcode@gmail.com writes:
On 20/05/2021 19:40, Alexandre Julliard wrote:
Gabriel Ivăncescu gabrielopcode@gmail.com writes:
Which optionally returns the original case of the last path component.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/ntdll/unix/file.c | 66 +++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 23 deletions(-)
There doesn't seem to be any need for a new nt_to_unix_file_name helper. You can simply copy the last path component separately from the Unix name lookup, it doesn't require any file system access.
So I should go with the previous approach then (obviously with fixes)?
Or, what if I just add an optional parameter to nt_to_unix_file_name to return the case of last path? Or is that not desirable either?
The nt_to_unix_file_name() functions are already complex enough, we shouldn't add more code to them if not absolutely necessary.