Commit d97149b7 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Add support for converting file names to Unix when a root directory is specified.

parent a420a207
......@@ -2236,17 +2236,20 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
name_len--;
}
if (ret > 0 && !used_default) /* if we used the default char the name didn't convert properly */
if (ret >= 0 && !used_default) /* if we used the default char the name didn't convert properly */
{
char *p;
unix_name[pos + ret] = 0;
for (p = unix_name + pos ; *p; p++) if (*p == '\\') *p = '/';
if ((!redirect || !strstr( unix_name, "/windows/")) && !stat( unix_name, &st ))
if (!redirect || (!strstr( unix_name, "/windows/") && strncmp( unix_name, "windows/", 8 )))
{
/* creation fails with STATUS_ACCESS_DENIED for the root of the drive */
if (disposition == FILE_CREATE)
return name_len ? STATUS_OBJECT_NAME_COLLISION : STATUS_ACCESS_DENIED;
return STATUS_SUCCESS;
if (!stat( unix_name, &st ))
{
/* creation fails with STATUS_ACCESS_DENIED for the root of the drive */
if (disposition == FILE_CREATE)
return name_len ? STATUS_OBJECT_NAME_COLLISION : STATUS_ACCESS_DENIED;
return STATUS_SUCCESS;
}
}
}
......@@ -2326,6 +2329,80 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
/******************************************************************************
* nt_to_unix_file_name_attr
*/
NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *unix_name_ret,
UINT disposition )
{
static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 };
enum server_fd_type type;
int old_cwd, root_fd, needs_close;
const WCHAR *name, *p;
char *unix_name;
int name_len, unix_len;
NTSTATUS status;
BOOLEAN check_case = !(attr->Attributes & OBJ_CASE_INSENSITIVE);
if (!attr->RootDirectory) /* without root dir fall back to normal lookup */
return wine_nt_to_unix_file_name( attr->ObjectName, unix_name_ret, disposition, check_case );
name = attr->ObjectName->Buffer;
name_len = attr->ObjectName->Length / sizeof(WCHAR);
if (name_len && IS_SEPARATOR(name[0])) return STATUS_OBJECT_PATH_SYNTAX_BAD;
/* check for invalid characters */
for (p = name; p < name + name_len; p++)
if (*p < 32 || strchrW( invalid_charsW, *p )) return STATUS_OBJECT_NAME_INVALID;
unix_len = ntdll_wcstoumbs( 0, name, name_len, NULL, 0, NULL, NULL );
unix_len += MAX_DIR_ENTRY_LEN + 3;
if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len )))
return STATUS_NO_MEMORY;
unix_name[0] = '.';
if (!(status = server_get_unix_fd( attr->RootDirectory, FILE_READ_DATA, &root_fd,
&needs_close, &type, NULL )))
{
if (type != FD_TYPE_DIR)
{
if (needs_close) close( root_fd );
status = STATUS_BAD_DEVICE_TYPE;
}
else
{
RtlEnterCriticalSection( &dir_section );
if ((old_cwd = open( ".", O_RDONLY )) != -1 && fchdir( root_fd ) != -1)
{
status = lookup_unix_name( name, name_len, &unix_name, unix_len, 1,
disposition, check_case );
if (fchdir( old_cwd ) == -1) chdir( "/" );
}
else status = FILE_GetNtStatus();
RtlLeaveCriticalSection( &dir_section );
if (old_cwd != -1) close( old_cwd );
if (needs_close) close( root_fd );
}
}
else if (status == STATUS_OBJECT_TYPE_MISMATCH) status = STATUS_BAD_DEVICE_TYPE;
if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE)
{
TRACE( "%s -> %s\n", debugstr_us(attr->ObjectName), debugstr_a(unix_name) );
unix_name_ret->Buffer = unix_name;
unix_name_ret->Length = strlen(unix_name);
unix_name_ret->MaximumLength = unix_len;
}
else
{
TRACE( "%s not found in %s\n", debugstr_w(name), unix_name );
RtlFreeHeap( GetProcessHeap(), 0, unix_name );
}
return status;
}
/******************************************************************************
* wine_nt_to_unix_file_name (NTDLL.@) Not a Windows API
*
* Convert a file name from NT namespace to Unix namespace.
......
......@@ -115,9 +115,7 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
if (alloc_size) FIXME( "alloc_size not supported\n" );
if (attr->RootDirectory ||
(io->u.Status = wine_nt_to_unix_file_name( attr->ObjectName, &unix_name, disposition,
!(attr->Attributes & OBJ_CASE_INSENSITIVE) )) == STATUS_BAD_DEVICE_TYPE)
if ((io->u.Status = nt_to_unix_file_name_attr( attr, &unix_name, disposition )) == STATUS_BAD_DEVICE_TYPE)
{
SERVER_START_REQ( open_file_object )
{
......@@ -147,7 +145,7 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
struct security_descriptor *sd = NULL;
struct object_attributes objattr;
objattr.rootdir = 0;
objattr.rootdir = wine_server_obj_handle( attr->RootDirectory );
objattr.sd_len = 0;
objattr.name_len = 0;
if (attr)
......@@ -2117,8 +2115,7 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
ANSI_STRING unix_name;
NTSTATUS status;
if (!(status = wine_nt_to_unix_file_name( attr->ObjectName, &unix_name, FILE_OPEN,
!(attr->Attributes & OBJ_CASE_INSENSITIVE) )))
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
{
struct stat st;
......@@ -2160,8 +2157,7 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC
ANSI_STRING unix_name;
NTSTATUS status;
if (!(status = wine_nt_to_unix_file_name( attr->ObjectName, &unix_name, FILE_OPEN,
!(attr->Attributes & OBJ_CASE_INSENSITIVE) )))
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
{
struct stat st;
......
......@@ -147,6 +147,8 @@ extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name );
extern NTSTATUS DIR_unmount_device( HANDLE handle );
extern NTSTATUS DIR_get_unix_cwd( char **cwd );
extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] );
extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *unix_name_ret,
UINT disposition );
/* virtual memory */
extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment