Skip to content

Commit 09e36ad

Browse files
Rollup merge of rust-lang#129934 - ChrisDenton:remove-dir-all3, r=Amanieu
Win: Open dir for sync access in remove_dir_all A small follow up to rust-lang#129800. We should explicitly open directories for synchronous access. We ultimately use `GetFileInformationByHandleEx` to read directories which should paper over any issues caused by using async directory reads (or else return an error) but it's better to do the right thing in the first place. Note though that `delete` does not read or write any data so it's not necessary there.
2 parents 5480d57 + be2b964 commit 09e36ad

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

std/src/sys/pal/windows/fs/remove_dir_all.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,12 @@ unsafe fn nt_open_file(
7171
}
7272

7373
/// Open the file `path` in the directory `parent`, requesting the given `access` rights.
74+
/// `options` will be OR'd with `FILE_OPEN_REPARSE_POINT`.
7475
fn open_link_no_reparse(
7576
parent: &File,
7677
path: &[u16],
7778
access: u32,
79+
options: u32,
7880
) -> Result<Option<File>, WinError> {
7981
// This is implemented using the lower level `NtOpenFile` function as
8082
// unfortunately opening a file relative to a parent is not supported by
@@ -96,7 +98,7 @@ fn open_link_no_reparse(
9698
..c::OBJECT_ATTRIBUTES::default()
9799
};
98100
let share = c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE;
99-
let options = c::FILE_OPEN_REPARSE_POINT;
101+
let options = c::FILE_OPEN_REPARSE_POINT | options;
100102
let result = nt_open_file(access, &object, share, options);
101103

102104
// Retry without OBJ_DONT_REPARSE if it's not supported.
@@ -128,13 +130,20 @@ fn open_link_no_reparse(
128130
}
129131

130132
fn open_dir(parent: &File, name: &[u16]) -> Result<Option<File>, WinError> {
131-
open_link_no_reparse(parent, name, c::SYNCHRONIZE | c::FILE_LIST_DIRECTORY)
133+
// Open the directory for synchronous directory listing.
134+
open_link_no_reparse(
135+
parent,
136+
name,
137+
c::SYNCHRONIZE | c::FILE_LIST_DIRECTORY,
138+
// "_IO_NONALERT" means that a synchronous call won't be interrupted.
139+
c::FILE_SYNCHRONOUS_IO_NONALERT,
140+
)
132141
}
133142

134143
fn delete(parent: &File, name: &[u16]) -> Result<(), WinError> {
135144
// Note that the `delete` function consumes the opened file to ensure it's
136145
// dropped immediately. See module comments for why this is important.
137-
match open_link_no_reparse(parent, name, c::SYNCHRONIZE | c::DELETE) {
146+
match open_link_no_reparse(parent, name, c::DELETE, 0) {
138147
Ok(Some(f)) => f.delete(),
139148
Ok(None) => Ok(()),
140149
Err(e) => Err(e),

0 commit comments

Comments
 (0)