Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
7e9ccbe6
Commit
7e9ccbe6
authored
Jun 16, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Move the Unix to NT file name conversion support to the Unix library.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
f6bfb4ce
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
153 additions
and
166 deletions
+153
-166
path.c
dlls/ntdll/path.c
+19
-164
file.c
dlls/ntdll/unix/file.c
+130
-1
loader.c
dlls/ntdll/unix/loader.c
+1
-0
unix_private.h
dlls/ntdll/unix/unix_private.h
+1
-0
unixlib.h
dlls/ntdll/unixlib.h
+2
-1
No files found.
dlls/ntdll/path.c
View file @
7e9ccbe6
...
...
@@ -49,97 +49,6 @@ static const WCHAR UncPfxW[] = {'U','N','C','\\',0};
#define IS_SEPARATOR(ch) ((ch) == '\\' || (ch) == '/')
/***********************************************************************
* remove_last_componentA
*
* Remove the last component of the path. Helper for find_drive_rootA.
*/
static
inline
unsigned
int
remove_last_componentA
(
const
char
*
path
,
unsigned
int
len
)
{
int
level
=
0
;
while
(
level
<
1
)
{
/* find start of the last path component */
unsigned
int
prev
=
len
;
if
(
prev
<=
1
)
break
;
/* reached root */
while
(
prev
>
1
&&
path
[
prev
-
1
]
!=
'/'
)
prev
--
;
/* does removing it take us up a level? */
if
(
len
-
prev
!=
1
||
path
[
prev
]
!=
'.'
)
/* not '.' */
{
if
(
len
-
prev
==
2
&&
path
[
prev
]
==
'.'
&&
path
[
prev
+
1
]
==
'.'
)
/* is it '..'? */
level
--
;
else
level
++
;
}
/* strip off trailing slashes */
while
(
prev
>
1
&&
path
[
prev
-
1
]
==
'/'
)
prev
--
;
len
=
prev
;
}
return
len
;
}
/***********************************************************************
* find_drive_rootA
*
* Find a drive for which the root matches the beginning of the given path.
* This can be used to translate a Unix path into a drive + DOS path.
* Return value is the drive, or -1 on error. On success, ppath is modified
* to point to the beginning of the DOS path.
*/
static
NTSTATUS
find_drive_rootA
(
LPCSTR
*
ppath
,
unsigned
int
len
,
int
*
drive_ret
)
{
/* Starting with the full path, check if the device and inode match any of
* the wine 'drives'. If not then remove the last path component and try
* again. If the last component was a '..' then skip a normal component
* since it's a directory that's ascended back out of.
*/
int
drive
;
char
*
buffer
;
const
char
*
path
=
*
ppath
;
struct
stat
st
;
struct
drive_info
info
[
MAX_DOS_DRIVES
];
/* get device and inode of all drives */
if
(
!
DIR_get_drives_info
(
info
))
return
STATUS_OBJECT_PATH_NOT_FOUND
;
/* strip off trailing slashes */
while
(
len
>
1
&&
path
[
len
-
1
]
==
'/'
)
len
--
;
/* make a copy of the path */
if
(
!
(
buffer
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
len
+
1
)))
return
STATUS_NO_MEMORY
;
memcpy
(
buffer
,
path
,
len
);
buffer
[
len
]
=
0
;
for
(;;)
{
if
(
!
stat
(
buffer
,
&
st
)
&&
S_ISDIR
(
st
.
st_mode
))
{
/* Find the drive */
for
(
drive
=
0
;
drive
<
MAX_DOS_DRIVES
;
drive
++
)
{
if
((
info
[
drive
].
dev
==
st
.
st_dev
)
&&
(
info
[
drive
].
ino
==
st
.
st_ino
))
{
if
(
len
==
1
)
len
=
0
;
/* preserve root slash in returned path */
TRACE
(
"%s -> drive %c:, root=%s, name=%s
\n
"
,
debugstr_a
(
path
),
'A'
+
drive
,
debugstr_a
(
buffer
),
debugstr_a
(
path
+
len
));
*
ppath
+=
len
;
*
drive_ret
=
drive
;
RtlFreeHeap
(
GetProcessHeap
(),
0
,
buffer
);
return
STATUS_SUCCESS
;
}
}
}
if
(
len
<=
1
)
break
;
/* reached root */
len
=
remove_last_componentA
(
buffer
,
len
);
buffer
[
len
]
=
0
;
}
RtlFreeHeap
(
GetProcessHeap
(),
0
,
buffer
);
return
STATUS_OBJECT_PATH_NOT_FOUND
;
}
/***********************************************************************
* remove_last_componentW
*
* Remove the last component of the path. Helper for find_drive_rootW.
...
...
@@ -1069,86 +978,32 @@ NTSTATUS WINAPI RtlSetCurrentDirectory_U(const UNICODE_STRING* dir)
*/
NTSTATUS
CDECL
wine_unix_to_nt_file_name
(
const
ANSI_STRING
*
name
,
UNICODE_STRING
*
nt
)
{
static
const
WCHAR
prefixW
[]
=
{
'\\'
,
'?'
,
'?'
,
'\\'
,
'A'
,
':'
,
'\\'
};
static
const
WCHAR
unix_prefixW
[]
=
{
'\\'
,
'?'
,
'?'
,
'\\'
,
'u'
,
'n'
,
'i'
,
'x'
};
unsigned
int
lenW
,
lenA
=
name
->
Length
;
const
char
*
path
=
name
->
Buffer
;
char
*
cwd
;
WCHAR
*
p
;
NTSTATUS
status
;
int
drive
;
if
(
!
lenA
||
path
[
0
]
!=
'/'
)
{
char
*
newcwd
,
*
end
;
size_t
size
;
if
((
status
=
DIR_get_unix_cwd
(
&
cwd
))
!=
STATUS_SUCCESS
)
return
status
;
if
(
!
lenA
)
return
STATUS_INVALID_PARAMETER
;
size
=
strlen
(
cwd
)
+
lenA
+
1
;
if
(
!
(
newcwd
=
RtlReAllocateHeap
(
GetProcessHeap
(),
0
,
cwd
,
size
)))
{
status
=
STATUS_NO_MEMORY
;
goto
done
;
}
cwd
=
newcwd
;
end
=
cwd
+
strlen
(
cwd
);
if
(
end
>
cwd
&&
end
[
-
1
]
!=
'/'
)
*
end
++
=
'/'
;
memcpy
(
end
,
path
,
lenA
);
lenA
+=
end
-
cwd
;
path
=
cwd
;
status
=
find_drive_rootA
(
&
path
,
lenA
,
&
drive
);
lenA
-=
(
path
-
cwd
);
}
else
if
(
path
[
0
]
!=
'/'
)
/* relative path name */
{
cwd
=
NULL
;
status
=
find_drive_rootA
(
&
path
,
lenA
,
&
drive
);
lenA
-=
(
path
-
name
->
Buffer
);
}
WCHAR
*
tmp
;
if
(
status
!=
STATUS_SUCCESS
)
{
if
(
status
==
STATUS_OBJECT_PATH_NOT_FOUND
)
path
++
;
lenA
--
;
if
(
!
(
tmp
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
(
lenA
+
1
)
*
sizeof
(
WCHAR
)
)))
return
STATUS_NO_MEMORY
;
lenW
=
ntdll_umbstowcs
(
path
,
lenA
,
tmp
,
lenA
);
tmp
[
lenW
]
=
0
;
lenW
=
RtlGetFullPathName_U
(
tmp
,
0
,
NULL
,
NULL
);
if
(
!
lenW
||
!
(
nt
->
Buffer
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
lenW
)))
{
nt
->
Buffer
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
(
lenA
+
1
)
*
sizeof
(
WCHAR
)
+
sizeof
(
unix_prefixW
)
);
if
(
nt
->
Buffer
==
NULL
)
{
status
=
STATUS_NO_MEMORY
;
goto
done
;
}
memcpy
(
nt
->
Buffer
,
unix_prefixW
,
sizeof
(
unix_prefixW
)
);
lenW
=
ARRAY_SIZE
(
unix_prefixW
);
lenW
+=
ntdll_umbstowcs
(
path
,
lenA
,
nt
->
Buffer
+
lenW
,
lenA
);
nt
->
Buffer
[
lenW
]
=
0
;
nt
->
Length
=
lenW
*
sizeof
(
WCHAR
);
nt
->
MaximumLength
=
nt
->
Length
+
sizeof
(
WCHAR
);
for
(
p
=
nt
->
Buffer
+
ARRAY_SIZE
(
unix_prefixW
);
*
p
;
p
++
)
if
(
*
p
==
'/'
)
*
p
=
'\\'
;
status
=
STATUS_SUCCESS
;
RtlFreeHeap
(
GetProcessHeap
(),
0
,
tmp
);
return
STATUS_NO_MEMORY
;
}
goto
done
;
}
while
(
lenA
&&
path
[
0
]
==
'/'
)
{
lenA
--
;
path
++
;
}
if
(
!
(
nt
->
Buffer
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
(
lenA
+
1
)
*
sizeof
(
WCHAR
)
+
sizeof
(
prefixW
)
)))
{
status
=
STATUS_NO_MEMORY
;
goto
done
;
lenW
=
RtlGetFullPathName_U
(
tmp
,
lenW
,
nt
->
Buffer
,
NULL
);
nt
->
Length
=
lenW
;
nt
->
MaximumLength
=
lenW
+
sizeof
(
WCHAR
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
tmp
);
return
STATUS_SUCCESS
;
}
memcpy
(
nt
->
Buffer
,
prefixW
,
sizeof
(
prefixW
)
);
nt
->
Buffer
[
4
]
+=
drive
;
lenW
=
ARRAY_SIZE
(
prefixW
);
lenW
+=
ntdll_umbstowcs
(
path
,
lenA
,
nt
->
Buffer
+
lenW
,
lenA
);
nt
->
Buffer
[
lenW
]
=
0
;
nt
->
Length
=
lenW
*
sizeof
(
WCHAR
);
nt
->
MaximumLength
=
nt
->
Length
+
sizeof
(
WCHAR
);
for
(
p
=
nt
->
Buffer
+
ARRAY_SIZE
(
prefixW
);
*
p
;
p
++
)
if
(
*
p
==
'/'
)
*
p
=
'\\'
;
done:
RtlFreeHeap
(
GetProcessHeap
(),
0
,
cwd
);
return
status
;
return
unix_funcs
->
unix_to_nt_file_name
(
name
,
nt
);
}
dlls/ntdll/unix/file.c
View file @
7e9ccbe6
...
...
@@ -1803,7 +1803,7 @@ static NTSTATUS fill_name_info( const ANSI_STRING *unix_name, FILE_NAME_INFORMAT
UNICODE_STRING
nt_name
;
NTSTATUS
status
;
if
(
!
(
status
=
wine_
unix_to_nt_file_name
(
unix_name
,
&
nt_name
)))
if
(
!
(
status
=
unix_to_nt_file_name
(
unix_name
,
&
nt_name
)))
{
const
WCHAR
*
ptr
=
nt_name
.
Buffer
;
const
WCHAR
*
end
=
ptr
+
(
nt_name
.
Length
/
sizeof
(
WCHAR
));
...
...
@@ -2894,6 +2894,97 @@ static inline int get_dos_prefix_len( const UNICODE_STRING *name )
}
/***********************************************************************
* remove_last_componentA
*
* Remove the last component of the path. Helper for find_drive_rootA.
*/
static
inline
unsigned
int
remove_last_componentA
(
const
char
*
path
,
unsigned
int
len
)
{
int
level
=
0
;
while
(
level
<
1
)
{
/* find start of the last path component */
unsigned
int
prev
=
len
;
if
(
prev
<=
1
)
break
;
/* reached root */
while
(
prev
>
1
&&
path
[
prev
-
1
]
!=
'/'
)
prev
--
;
/* does removing it take us up a level? */
if
(
len
-
prev
!=
1
||
path
[
prev
]
!=
'.'
)
/* not '.' */
{
if
(
len
-
prev
==
2
&&
path
[
prev
]
==
'.'
&&
path
[
prev
+
1
]
==
'.'
)
/* is it '..'? */
level
--
;
else
level
++
;
}
/* strip off trailing slashes */
while
(
prev
>
1
&&
path
[
prev
-
1
]
==
'/'
)
prev
--
;
len
=
prev
;
}
return
len
;
}
/***********************************************************************
* find_drive_rootA
*
* Find a drive for which the root matches the beginning of the given path.
* This can be used to translate a Unix path into a drive + DOS path.
* Return value is the drive, or -1 on error. On success, ppath is modified
* to point to the beginning of the DOS path.
*/
static
NTSTATUS
find_drive_rootA
(
LPCSTR
*
ppath
,
unsigned
int
len
,
int
*
drive_ret
)
{
/* Starting with the full path, check if the device and inode match any of
* the wine 'drives'. If not then remove the last path component and try
* again. If the last component was a '..' then skip a normal component
* since it's a directory that's ascended back out of.
*/
int
drive
;
char
*
buffer
;
const
char
*
path
=
*
ppath
;
struct
stat
st
;
struct
file_identity
info
[
MAX_DOS_DRIVES
];
/* get device and inode of all drives */
if
(
!
get_drives_info
(
info
))
return
STATUS_OBJECT_PATH_NOT_FOUND
;
/* strip off trailing slashes */
while
(
len
>
1
&&
path
[
len
-
1
]
==
'/'
)
len
--
;
/* make a copy of the path */
if
(
!
(
buffer
=
malloc
(
len
+
1
)))
return
STATUS_NO_MEMORY
;
memcpy
(
buffer
,
path
,
len
);
buffer
[
len
]
=
0
;
for
(;;)
{
if
(
!
stat
(
buffer
,
&
st
)
&&
S_ISDIR
(
st
.
st_mode
))
{
/* Find the drive */
for
(
drive
=
0
;
drive
<
MAX_DOS_DRIVES
;
drive
++
)
{
if
((
info
[
drive
].
dev
==
st
.
st_dev
)
&&
(
info
[
drive
].
ino
==
st
.
st_ino
))
{
if
(
len
==
1
)
len
=
0
;
/* preserve root slash in returned path */
TRACE
(
"%s -> drive %c:, root=%s, name=%s
\n
"
,
debugstr_a
(
path
),
'A'
+
drive
,
debugstr_a
(
buffer
),
debugstr_a
(
path
+
len
));
*
ppath
+=
len
;
*
drive_ret
=
drive
;
free
(
buffer
);
return
STATUS_SUCCESS
;
}
}
}
if
(
len
<=
1
)
break
;
/* reached root */
len
=
remove_last_componentA
(
buffer
,
len
);
buffer
[
len
]
=
0
;
}
free
(
buffer
);
return
STATUS_OBJECT_PATH_NOT_FOUND
;
}
/******************************************************************************
* find_file_id
*
...
...
@@ -3331,6 +3422,44 @@ NTSTATUS CDECL nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *u
}
/******************************************************************
* unix_to_nt_file_name
*/
NTSTATUS
CDECL
unix_to_nt_file_name
(
const
ANSI_STRING
*
name
,
UNICODE_STRING
*
nt
)
{
static
const
WCHAR
unix_prefixW
[]
=
{
'\\'
,
'?'
,
'?'
,
'\\'
,
'u'
,
'n'
,
'i'
,
'x'
,
0
};
WCHAR
dos_prefixW
[]
=
{
'\\'
,
'?'
,
'?'
,
'\\'
,
'A'
,
':'
,
'\\'
,
0
};
const
WCHAR
*
prefix
=
unix_prefixW
;
unsigned
int
lenW
,
lenA
=
name
->
Length
;
const
char
*
path
=
name
->
Buffer
;
NTSTATUS
status
;
WCHAR
*
p
;
int
drive
;
status
=
find_drive_rootA
(
&
path
,
lenA
,
&
drive
);
lenA
-=
(
path
-
name
->
Buffer
);
if
(
status
==
STATUS_SUCCESS
)
{
while
(
lenA
&&
path
[
0
]
==
'/'
)
{
lenA
--
;
path
++
;
}
dos_prefixW
[
4
]
+=
drive
;
prefix
=
dos_prefixW
;
}
else
if
(
status
!=
STATUS_OBJECT_PATH_NOT_FOUND
)
return
status
;
lenW
=
wcslen
(
prefix
);
if
(
!
(
nt
->
Buffer
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
(
lenA
+
lenW
+
1
)
*
sizeof
(
WCHAR
)
)))
return
STATUS_NO_MEMORY
;
memcpy
(
nt
->
Buffer
,
prefix
,
lenW
*
sizeof
(
WCHAR
)
);
lenW
+=
ntdll_umbstowcs
(
path
,
lenA
,
nt
->
Buffer
+
lenW
,
lenA
);
nt
->
Buffer
[
lenW
]
=
0
;
nt
->
Length
=
lenW
*
sizeof
(
WCHAR
);
nt
->
MaximumLength
=
nt
->
Length
+
sizeof
(
WCHAR
);
for
(
p
=
nt
->
Buffer
;
*
p
;
p
++
)
if
(
*
p
==
'/'
)
*
p
=
'\\'
;
return
STATUS_SUCCESS
;
}
/***********************************************************************
* unmount_device
*
...
...
dlls/ntdll/unix/loader.c
View file @
7e9ccbe6
...
...
@@ -961,6 +961,7 @@ static struct unix_funcs unix_funcs =
server_release_fd
,
server_init_process_done
,
nt_to_unix_file_name
,
unix_to_nt_file_name
,
set_show_dot_files
,
__wine_dbg_get_channel_flags
,
__wine_dbg_strdup
,
...
...
dlls/ntdll/unix/unix_private.h
View file @
7e9ccbe6
...
...
@@ -114,6 +114,7 @@ extern NTSTATUS CDECL exec_process( const UNICODE_STRING *cmdline, const pe_imag
extern
NTSTATUS
CDECL
nt_to_unix_file_name
(
const
UNICODE_STRING
*
nameW
,
ANSI_STRING
*
unix_name_ret
,
UINT
disposition
,
BOOLEAN
check_case
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
CDECL
unix_to_nt_file_name
(
const
ANSI_STRING
*
name
,
UNICODE_STRING
*
nt
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
set_show_dot_files
(
BOOL
enable
)
DECLSPEC_HIDDEN
;
extern
const
char
*
data_dir
DECLSPEC_HIDDEN
;
...
...
dlls/ntdll/unixlib.h
View file @
7e9ccbe6
...
...
@@ -28,7 +28,7 @@ struct ldt_copy;
struct
msghdr
;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 5
0
#define NTDLL_UNIXLIB_VERSION 5
1
struct
unix_funcs
{
...
...
@@ -302,6 +302,7 @@ struct unix_funcs
/* file functions */
NTSTATUS
(
CDECL
*
nt_to_unix_file_name
)(
const
UNICODE_STRING
*
nameW
,
ANSI_STRING
*
unix_name_ret
,
UINT
disposition
,
BOOLEAN
check_case
);
NTSTATUS
(
CDECL
*
unix_to_nt_file_name
)(
const
ANSI_STRING
*
name
,
UNICODE_STRING
*
nt
);
void
(
CDECL
*
set_show_dot_files
)(
BOOL
enable
);
/* debugging functions */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment