Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-fonts
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
Aleksandr Isakov
wine-fonts
Commits
1080b7ce
Commit
1080b7ce
authored
Apr 11, 2019
by
Erich E. Hoover
Committed by
Vitaly Lipatov
Jul 30, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Add support for file symlinks.
Signed-off-by:
Erich E. Hoover
<
erich.e.hoover@gmail.com
>
parent
4fa44192
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
49 additions
and
5 deletions
+49
-5
file.c
dlls/ntdll/tests/file.c
+29
-0
file.c
dlls/ntdll/unix/file.c
+20
-5
No files found.
dlls/ntdll/tests/file.c
View file @
1080b7ce
...
...
@@ -5562,6 +5562,35 @@ static void test_reparse_points(void)
/* Delete the junction point directory and create a blank slate for symlink tests */
bret
=
RemoveDirectoryW
(
reparse_path
);
ok
(
bret
,
"Failed to delete junction point!
\n
"
);
/* Create the file symlink */
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
handle
=
CreateFileW
(
reparse_path
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
0
,
CREATE_NEW
,
FILE_FLAG_BACKUP_SEMANTICS
|
FILE_FLAG_OPEN_REPARSE_POINT
,
0
);
ok
(
handle
!=
INVALID_HANDLE_VALUE
,
"Failed to create symlink file.
\n
"
);
dwret
=
NtQueryInformationFile
(
handle
,
&
iosb
,
&
old_attrib
,
sizeof
(
old_attrib
),
FileBasicInformation
);
ok
(
dwret
==
STATUS_SUCCESS
,
"Failed to get symlink file's attributes (0x%x).
\n
"
,
dwret
);
buffer_len
=
build_reparse_buffer
(
nameW
.
Buffer
,
IO_REPARSE_TAG_SYMLINK
,
0
,
&
buffer
);
bret
=
DeviceIoControl
(
handle
,
FSCTL_SET_REPARSE_POINT
,
(
LPVOID
)
buffer
,
buffer_len
,
NULL
,
0
,
&
dwret
,
0
);
ok
(
bret
,
"Failed to create symlink! (0x%x)
\n
"
,
GetLastError
());
CloseHandle
(
handle
);
/* Check deleting a file symlink as if it were a directory */
bret
=
RemoveDirectoryW
(
reparse_path
);
todo_wine
ok
(
!
bret
,
"Succeeded in deleting file symlink as a directory!
\n
"
);
err
=
GetLastError
();
todo_wine
ok
(
err
==
ERROR_DIRECTORY
,
"Expected last error 0x%x for RemoveDirectory on file symlink (actually 0x%x)!
\n
"
,
ERROR_DIRECTORY
,
err
);
dwret
=
GetFileAttributesW
(
reparse_path
);
todo_wine
ok
(
dwret
!=
(
DWORD
)
~
0
,
"Symlink doesn't exist (attributes: 0x%x)!
\n
"
,
dwret
);
ok
(
dwret
&
FILE_ATTRIBUTE_REPARSE_POINT
,
"File is not a symlink! (attributes: 0x%x)
\n
"
,
dwret
);
/* Delete the symlink as a file */
bret
=
DeleteFileW
(
reparse_path
);
todo_wine
ok
(
bret
,
"Failed to delete symlink as a file!
\n
"
);
/* Create a blank slate for directory symlink tests */
bret
=
CreateDirectoryW
(
reparse_path
,
NULL
);
ok
(
bret
,
"Failed to create junction point directory.
\n
"
);
dwret
=
GetFileAttributesW
(
reparse_path
);
...
...
dlls/ntdll/unix/file.c
View file @
1080b7ce
...
...
@@ -5988,6 +5988,7 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
int
relative_offset
=
0
;
UNICODE_STRING
nt_dest
;
int
dest_len
,
offset
;
BOOL
is_dir
=
TRUE
;
NTSTATUS
status
;
struct
stat
st
;
WCHAR
*
dest
;
...
...
@@ -6121,7 +6122,6 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
/* Encode the type (file or directory) if NT symlink */
if
(
buffer
->
ReparseTag
==
IO_REPARSE_TAG_SYMLINK
)
{
BOOL
is_dir
;
if
(
fstat
(
dest_fd
,
&
st
)
==
-
1
)
{
status
=
errno_to_status
(
errno
);
...
...
@@ -6155,8 +6155,11 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
/* Atomically move the link into position */
if
(
!
renameat2
(
-
1
,
tmplink
,
-
1
,
unix_src
,
RENAME_EXCHANGE
))
{
/* success: link and folder have switched locations */
rmdir
(
tmplink
);
/* remove the folder (at link location) */
/* success: link and folder/file have switched locations */
if
(
is_dir
)
rmdir
(
tmplink
);
/* remove the folder (at link location) */
else
unlink
(
tmplink
);
/* remove the file (at link location) */
}
else
if
(
errno
==
ENOSYS
)
{
...
...
@@ -6375,6 +6378,7 @@ NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
char
tmpdir
[
PATH_MAX
],
tmpfile
[
PATH_MAX
],
*
d
;
BOOL
tempdir_created
=
FALSE
;
int
dest_fd
,
needs_close
;
BOOL
is_dir
=
TRUE
;
NTSTATUS
status
;
char
*
unix_name
;
struct
stat
st
;
...
...
@@ -6387,12 +6391,13 @@ NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
TRACE
(
"Deleting symlink %s
\n
"
,
unix_name
);
/* Produce the directory in a temporary location in the same folder */
/* Produce the
file/
directory in a temporary location in the same folder */
if
(
fstat
(
dest_fd
,
&
st
)
==
-
1
)
{
status
=
errno_to_status
(
errno
);
goto
cleanup
;
}
is_dir
=
S_ISDIR
(
st
.
st_mode
);
strcpy
(
tmpdir
,
unix_name
);
d
=
dirname
(
tmpdir
);
if
(
d
!=
tmpdir
)
strcpy
(
tmpdir
,
d
);
...
...
@@ -6405,11 +6410,21 @@ NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
tempdir_created
=
TRUE
;
strcpy
(
tmpfile
,
tmpdir
);
strcat
(
tmpfile
,
"/tmpfile"
);
if
(
mkdir
(
tmpfile
,
st
.
st_mode
))
if
(
is_dir
&&
mkdir
(
tmpfile
,
st
.
st_mode
))
{
status
=
errno_to_status
(
errno
);
goto
cleanup
;
}
else
if
(
!
is_dir
)
{
int
fd
=
open
(
tmpfile
,
O_CREAT
|
O_WRONLY
|
O_TRUNC
,
st
.
st_mode
);
if
(
fd
<
0
)
{
status
=
errno_to_status
(
errno
);
goto
cleanup
;
}
close
(
fd
);
}
/* attemp to retain the ownership (if possible) */
lchown
(
tmpfile
,
st
.
st_uid
,
st
.
st_gid
);
/* Atomically move the directory into position */
...
...
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