about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2024-09-18 14:32:25 -0700
committerGitHub <noreply@github.com>2024-09-18 14:32:25 -0700
commit591ec6c9cef734f9f687a69555a88beecc796eea (patch)
treeb10166adbadf39bd2189cadda21f4e573d91c4ef
parent2eb65a6667f2023d0c51eb0b717698365520088d (diff)
parent6b0fc97c7ab25b50c5b061cbe8ec4aaa5575e9f9 (diff)
downloadrust-591ec6c9cef734f9f687a69555a88beecc796eea.tar.gz
rust-591ec6c9cef734f9f687a69555a88beecc796eea.zip
Rollup merge of #129934 - ChrisDenton:remove-dir-all3, r=Amanieu
Win: Open dir for sync access in remove_dir_all

A small follow up to #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.
-rw-r--r--library/std/src/sys/pal/windows/fs/remove_dir_all.rs15
1 files changed, 12 insertions, 3 deletions
diff --git a/library/std/src/sys/pal/windows/fs/remove_dir_all.rs b/library/std/src/sys/pal/windows/fs/remove_dir_all.rs
index e7234ed8e5f..9416049da78 100644
--- a/library/std/src/sys/pal/windows/fs/remove_dir_all.rs
+++ b/library/std/src/sys/pal/windows/fs/remove_dir_all.rs
@@ -71,10 +71,12 @@ unsafe fn nt_open_file(
 }
 
 /// Open the file `path` in the directory `parent`, requesting the given `access` rights.
+/// `options` will be OR'd with `FILE_OPEN_REPARSE_POINT`.
 fn open_link_no_reparse(
     parent: &File,
     path: &[u16],
     access: u32,
+    options: u32,
 ) -> Result<Option<File>, WinError> {
     // This is implemented using the lower level `NtOpenFile` function as
     // unfortunately opening a file relative to a parent is not supported by
@@ -96,7 +98,7 @@ fn open_link_no_reparse(
             ..c::OBJECT_ATTRIBUTES::default()
         };
         let share = c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE;
-        let options = c::FILE_OPEN_REPARSE_POINT;
+        let options = c::FILE_OPEN_REPARSE_POINT | options;
         let result = nt_open_file(access, &object, share, options);
 
         // Retry without OBJ_DONT_REPARSE if it's not supported.
@@ -128,13 +130,20 @@ fn open_link_no_reparse(
 }
 
 fn open_dir(parent: &File, name: &[u16]) -> Result<Option<File>, WinError> {
-    open_link_no_reparse(parent, name, c::SYNCHRONIZE | c::FILE_LIST_DIRECTORY)
+    // Open the directory for synchronous directory listing.
+    open_link_no_reparse(
+        parent,
+        name,
+        c::SYNCHRONIZE | c::FILE_LIST_DIRECTORY,
+        // "_IO_NONALERT" means that a synchronous call won't be interrupted.
+        c::FILE_SYNCHRONOUS_IO_NONALERT,
+    )
 }
 
 fn delete(parent: &File, name: &[u16]) -> Result<(), WinError> {
     // Note that the `delete` function consumes the opened file to ensure it's
     // dropped immediately. See module comments for why this is important.
-    match open_link_no_reparse(parent, name, c::SYNCHRONIZE | c::DELETE) {
+    match open_link_no_reparse(parent, name, c::DELETE, 0) {
         Ok(Some(f)) => f.delete(),
         Ok(None) => Ok(()),
         Err(e) => Err(e),