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
8d5a2a99
Commit
8d5a2a99
authored
Jan 16, 2014
by
Erich E. Hoover
Committed by
Vitaly Lipatov
Jul 30, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
server: Add support for deleting junction points with RemoveDirectory.
Signed-off-by:
Erich E. Hoover
<
erich.e.hoover@gmail.com
>
parent
13be6a07
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
61 additions
and
10 deletions
+61
-10
file.c
dlls/ntdll/tests/file.c
+33
-1
fd.c
server/fd.c
+28
-9
No files found.
dlls/ntdll/tests/file.c
View file @
8d5a2a99
...
...
@@ -5371,7 +5371,7 @@ static void test_reparse_points(void)
REPARSE_GUID_DATA_BUFFER
guid_buffer
;
static
const
WCHAR
dotW
[]
=
{
'.'
,
0
};
REPARSE_DATA_BUFFER
*
buffer
=
NULL
;
DWORD
dwret
,
dwLen
,
dwFlags
;
DWORD
dwret
,
dwLen
,
dwFlags
,
err
;
IO_STATUS_BLOCK
iosb
;
UNICODE_STRING
nameW
;
HANDLE
handle
;
...
...
@@ -5465,6 +5465,38 @@ static void test_reparse_points(void)
"Junction point folder's access time does not match.
\n
"
);
CloseHandle
(
handle
);
/* Check deleting a junction point as if it were a directory */
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
handle
=
CreateFileW
(
reparse_path
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
0
,
OPEN_EXISTING
,
FILE_FLAG_BACKUP_SEMANTICS
|
FILE_FLAG_OPEN_REPARSE_POINT
,
0
);
buffer_len
=
build_reparse_buffer
(
nameW
.
Buffer
,
&
buffer
);
bret
=
DeviceIoControl
(
handle
,
FSCTL_SET_REPARSE_POINT
,
(
LPVOID
)
buffer
,
buffer_len
,
NULL
,
0
,
&
dwret
,
0
);
ok
(
bret
,
"Failed to create junction point! (0x%x)
\n
"
,
GetLastError
());
CloseHandle
(
handle
);
bret
=
RemoveDirectoryW
(
reparse_path
);
ok
(
bret
,
"Failed to delete junction point as directory!
\n
"
);
dwret
=
GetFileAttributesW
(
reparse_path
);
ok
(
dwret
==
(
DWORD
)
~
0
,
"Junction point still exists (attributes: 0x%x)!
\n
"
,
dwret
);
/* Check deleting a junction point as if it were a file */
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
bret
=
CreateDirectoryW
(
reparse_path
,
NULL
);
ok
(
bret
,
"Failed to create junction point target directory.
\n
"
);
handle
=
CreateFileW
(
reparse_path
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
0
,
OPEN_EXISTING
,
FILE_FLAG_BACKUP_SEMANTICS
|
FILE_FLAG_OPEN_REPARSE_POINT
,
0
);
buffer_len
=
build_reparse_buffer
(
nameW
.
Buffer
,
&
buffer
);
bret
=
DeviceIoControl
(
handle
,
FSCTL_SET_REPARSE_POINT
,
(
LPVOID
)
buffer
,
buffer_len
,
NULL
,
0
,
&
dwret
,
0
);
ok
(
bret
,
"Failed to create junction point! (0x%x)
\n
"
,
GetLastError
());
CloseHandle
(
handle
);
bret
=
DeleteFileW
(
reparse_path
);
ok
(
!
bret
,
"Succeeded in deleting junction point as file!
\n
"
);
err
=
GetLastError
();
ok
(
err
==
ERROR_ACCESS_DENIED
,
"Expected last error 0x%x for DeleteFile on junction point (actually 0x%x)!
\n
"
,
ERROR_ACCESS_DENIED
,
err
);
dwret
=
GetFileAttributesW
(
reparse_path
);
ok
(
dwret
!=
(
DWORD
)
~
0
,
"Junction point doesn't exist (attributes: 0x%x)!
\n
"
,
dwret
);
ok
(
dwret
&
FILE_ATTRIBUTE_REPARSE_POINT
,
"File is not a junction point! (attributes: 0x%x)
\n
"
,
dwret
);
cleanup:
/* Cleanup */
pRtlFreeUnicodeString
(
&
nameW
);
...
...
server/fd.c
View file @
8d5a2a99
...
...
@@ -163,7 +163,8 @@ struct closed_fd
struct
list
entry
;
/* entry in inode closed list */
int
unix_fd
;
/* the unix file descriptor */
int
unlink
;
/* whether to unlink on close: -1 - implicit FILE_DELETE_ON_CLOSE, 1 - explicit disposition */
char
*
unix_name
;
/* name to unlink on close, points to parent fd unix_name */
char
*
unlink_name
;
/* name to unlink on close, points to parent fd unix_name */
char
*
unix_name
;
/* name to real file path, points to parent fd unix_name */
};
struct
fd
...
...
@@ -178,6 +179,7 @@ struct fd
unsigned
int
access
;
/* file access (FILE_READ_DATA etc.) */
unsigned
int
options
;
/* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */
unsigned
int
sharing
;
/* file sharing mode */
char
*
unlink_name
;
/* file name to unlink on close */
char
*
unix_name
;
/* unix file name */
WCHAR
*
nt_name
;
/* NT file name */
data_size_t
nt_namelen
;
/* length of NT file name */
...
...
@@ -1125,6 +1127,7 @@ static void inode_close_pending( struct inode *inode, int keep_unlinks )
if
(
!
keep_unlinks
||
!
fd
->
unlink
)
/* get rid of it unless there's an unlink pending on that file */
{
list_remove
(
ptr
);
free
(
fd
->
unlink_name
);
free
(
fd
->
unix_name
);
free
(
fd
);
}
...
...
@@ -1159,12 +1162,13 @@ static void inode_destroy( struct object *obj )
{
/* make sure it is still the same file */
struct
stat
st
;
if
(
!
stat
(
fd
->
unix
_name
,
&
st
)
&&
st
.
st_dev
==
inode
->
device
->
dev
&&
st
.
st_ino
==
inode
->
ino
)
if
(
!
lstat
(
fd
->
unlink
_name
,
&
st
)
&&
st
.
st_dev
==
inode
->
device
->
dev
&&
st
.
st_ino
==
inode
->
ino
)
{
if
(
S_ISDIR
(
st
.
st_mode
))
rmdir
(
fd
->
un
ix
_name
);
else
unlink
(
fd
->
un
ix
_name
);
if
(
S_ISDIR
(
st
.
st_mode
))
rmdir
(
fd
->
un
link
_name
);
else
unlink
(
fd
->
un
link
_name
);
}
}
free
(
fd
->
unlink_name
);
free
(
fd
->
unix_name
);
free
(
fd
);
}
...
...
@@ -1585,6 +1589,7 @@ static void fd_destroy( struct object *obj )
else
/* no inode, close it right away */
{
if
(
fd
->
unix_fd
!=
-
1
)
close
(
fd
->
unix_fd
);
free
(
fd
->
unlink_name
);
free
(
fd
->
unix_name
);
}
}
...
...
@@ -1694,6 +1699,7 @@ static struct fd *alloc_fd_object(void)
fd
->
options
=
0
;
fd
->
sharing
=
0
;
fd
->
unix_fd
=
-
1
;
fd
->
unlink_name
=
NULL
;
fd
->
unix_name
=
NULL
;
fd
->
nt_name
=
NULL
;
fd
->
nt_namelen
=
0
;
...
...
@@ -1731,6 +1737,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
fd
->
access
=
0
;
fd
->
options
=
options
;
fd
->
sharing
=
0
;
fd
->
unlink_name
=
NULL
;
fd
->
unix_name
=
NULL
;
fd
->
nt_name
=
NULL
;
fd
->
nt_namelen
=
0
;
...
...
@@ -1772,6 +1779,12 @@ struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sha
fd
->
nt_namelen
=
orig
->
nt_namelen
;
}
if
(
orig
->
unlink_name
)
{
if
(
!
(
fd
->
unlink_name
=
mem_alloc
(
strlen
(
orig
->
unlink_name
)
+
1
)))
goto
failed
;
strcpy
(
fd
->
unlink_name
,
orig
->
unlink_name
);
}
if
(
orig
->
inode
)
{
struct
closed_fd
*
closed
=
mem_alloc
(
sizeof
(
*
closed
)
);
...
...
@@ -1784,6 +1797,7 @@ struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sha
}
closed
->
unix_fd
=
fd
->
unix_fd
;
closed
->
unlink
=
0
;
closed
->
unlink_name
=
fd
->
unlink_name
;
closed
->
unix_name
=
fd
->
unix_name
;
fd
->
closed
=
closed
;
fd
->
inode
=
(
struct
inode
*
)
grab_object
(
orig
->
inode
);
...
...
@@ -1972,18 +1986,19 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
fd
->
unix_name
=
NULL
;
if
((
path
=
dup_fd_name
(
root
,
name
)))
{
fd
->
unlink_name
=
path
;
fd
->
unix_name
=
realpath
(
path
,
NULL
);
free
(
path
);
}
closed_fd
->
unix_fd
=
fd
->
unix_fd
;
closed_fd
->
unlink
=
0
;
closed_fd
->
unlink_name
=
fd
->
unlink_name
;
closed_fd
->
unix_name
=
fd
->
unix_name
;
fstat
(
fd
->
unix_fd
,
&
st
);
lstat
(
fd
->
unlink_name
,
&
st
);
*
mode
=
st
.
st_mode
;
/* only bother with an inode for normal files and directories */
if
(
S_ISREG
(
st
.
st_mode
)
||
S_ISDIR
(
st
.
st_mode
))
if
(
S_ISREG
(
st
.
st_mode
)
||
S_ISDIR
(
st
.
st_mode
)
||
S_ISLNK
(
st
.
st_mode
)
)
{
unsigned
int
err
;
struct
inode
*
inode
=
get_inode
(
st
.
st_dev
,
st
.
st_ino
,
fd
->
unix_fd
);
...
...
@@ -2001,6 +2016,9 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
list_add_head
(
&
inode
->
open
,
&
fd
->
inode_entry
);
closed_fd
=
NULL
;
fstat
(
fd
->
unix_fd
,
&
st
);
*
mode
=
st
.
st_mode
;
/* check directory options */
if
((
options
&
FILE_DIRECTORY_FILE
)
&&
!
S_ISDIR
(
st
.
st_mode
))
{
...
...
@@ -2648,10 +2666,11 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da
free
(
fd
->
nt_name
);
fd
->
nt_name
=
dup_nt_name
(
root
,
nt_name
,
&
fd
->
nt_namelen
);
free
(
fd
->
unlink_name
);
free
(
fd
->
unix_name
);
fd
->
closed
->
unlink_name
=
fd
->
unlink_name
=
name
;
fd
->
closed
->
unix_name
=
fd
->
unix_name
=
realpath
(
name
,
NULL
);
free
(
name
);
if
(
!
fd
->
unix_name
)
if
(
!
fd
->
unlink_name
||
!
fd
->
unix_name
)
set_error
(
STATUS_NO_MEMORY
);
return
;
...
...
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