remove_dir_all: delete directory with fewer perms

If opening a directory with `FILE_LIST_DIRECTORY` access fails then we should try opening without requesting that access. We may still be able to delete it if it's empty or a link.
This commit is contained in:
Chris Denton
2023-04-28 02:19:00 +01:00
parent 1a6ae3d692
commit ddff7f0e50

View File

@@ -1132,9 +1132,14 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io
&dir, &dir,
&name, &name,
c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY, c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY,
)?; );
// On success, add the handle to the queue.
// If opening the directory fails we treat it the same as a file
if let Ok(child_dir) = child_dir {
dirlist.push(child_dir); dirlist.push(child_dir);
} else { continue;
}
}
for i in 1..=MAX_RETRIES { for i in 1..=MAX_RETRIES {
let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE); let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE);
match result { match result {
@@ -1145,15 +1150,13 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io
Err(e) Err(e)
if i < MAX_RETRIES if i < MAX_RETRIES
&& (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _) && (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _)
|| e.raw_os_error() || e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _)) => {}
== Some(c::ERROR_SHARING_VIOLATION as _)) => {}
// Otherwise return the error. // Otherwise return the error.
Err(e) => return Err(e), Err(e) => return Err(e),
} }
thread::yield_now(); thread::yield_now();
} }
} }
}
// If there were no more files then delete the directory. // If there were no more files then delete the directory.
if !more_data { if !more_data {
if let Some(dir) = dirlist.pop() { if let Some(dir) = dirlist.pop() {