From: Brendan Shanks bshanks@codeweavers.com
--- dlls/ntdll/unix/file.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index f3c8039be2b..a475fcc3225 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -2877,7 +2877,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, PIO_APC_ROUTI * The file found is appended to unix_name at pos. * There must be at least MAX_DIR_ENTRY_LEN+2 chars available at pos. */ -static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, int length, +static NTSTATUS find_file_in_dir( int root_fd, char *unix_name, int pos, const WCHAR *name, int length, BOOLEAN check_case ) { WCHAR buffer[MAX_DIR_ENTRY_LEN]; @@ -2885,7 +2885,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i DIR *dir; struct dirent *de; struct stat st; - int ret; + int fd, ret;
/* try a shortcut for this directory */
@@ -2894,7 +2894,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i if (ret >= 0 && ret <= MAX_DIR_ENTRY_LEN) { unix_name[pos + ret] = 0; - if (!stat( unix_name, &st )) return STATUS_SUCCESS; + if (!fstatat( root_fd, unix_name, &st, 0 )) return STATUS_SUCCESS; } if (check_case) goto not_found; /* we want an exact match */
@@ -2908,14 +2908,14 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i is_name_8_dot_3 = is_name_8_dot_3 && length >= 8 && name[4] == '~'; #endif
- if (!is_name_8_dot_3 && !get_dir_case_sensitivity( AT_FDCWD, unix_name )) goto not_found; + if (!is_name_8_dot_3 && !get_dir_case_sensitivity( root_fd, unix_name )) goto not_found;
/* now look for it through the directory */
#ifdef VFAT_IOCTL_READDIR_BOTH if (is_name_8_dot_3) { - int fd = open( unix_name, O_RDONLY | O_DIRECTORY ); + int fd = openat( root_fd, unix_name, O_RDONLY | O_DIRECTORY ); if (fd != -1) { KERNEL_DIRENT kde[2]; @@ -2960,7 +2960,12 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i } #endif /* VFAT_IOCTL_READDIR_BOTH */
- if (!(dir = opendir( unix_name ))) return errno_to_status( errno ); + if ((fd = openat( root_fd, unix_name, O_RDONLY )) == -1) return errno_to_status( errno ); + if (!(dir = fdopendir( fd ))) + { + close( fd ); + return errno_to_status( errno ); + }
unix_name[pos - 1] = '/'; while ((de = readdir( dir ))) @@ -3512,8 +3517,8 @@ 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 NTSTATUS lookup_unix_name( int root_fd, 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; @@ -3555,7 +3560,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer char *p; unix_name[pos + 1 + ret] = 0; for (p = unix_name + pos ; *p; p++) if (*p == '\') *p = '/'; - if (!stat( unix_name, &st )) + if (!fstatat( root_fd, unix_name, &st, 0 )) { if (disposition == FILE_CREATE) return STATUS_OBJECT_NAME_COLLISION; return STATUS_SUCCESS; @@ -3589,7 +3594,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer unix_name = *buffer = new_name; }
- status = find_file_in_dir( unix_name, pos, name, end - name, is_unix ); + status = find_file_in_dir( root_fd, unix_name, pos, name, end - name, is_unix );
/* if this is the last element, not finding it is not necessarily fatal */ if (!name_len) @@ -3726,7 +3731,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( AT_FDCWD, name, name_len, &unix_name, unix_len, pos, disposition, is_unix ); if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE) { TRACE( "%s -> %s\n", debugstr_us(nameW), debugstr_a(unix_name) ); @@ -3753,7 +3758,7 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition ) { enum server_fd_type type; - int old_cwd, root_fd, needs_close; + int root_fd, needs_close; const WCHAR *name; char *unix_name; int name_len, unix_len; @@ -3780,15 +3785,7 @@ NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, U } else { - 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 ); - if (fchdir( old_cwd ) == -1) chdir( "/" ); - } - else status = errno_to_status( errno ); - mutex_unlock( &dir_mutex ); - if (old_cwd != -1) close( old_cwd ); + status = lookup_unix_name( root_fd, name, name_len, &unix_name, unix_len, 1, disposition, FALSE ); if (needs_close) close( root_fd ); } }