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,27 +1132,30 @@ 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,
)?; );
dirlist.push(child_dir); // On success, add the handle to the queue.
} else { // If opening the directory fails we treat it the same as a file
for i in 1..=MAX_RETRIES { if let Ok(child_dir) = child_dir {
let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE); dirlist.push(child_dir);
match result { continue;
Ok(f) => delete(&f)?,
// Already deleted, so skip.
Err(e) if e.kind() == io::ErrorKind::NotFound => break,
// Retry a few times if the file is locked or a delete is already in progress.
Err(e)
if i < MAX_RETRIES
&& (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _)
|| e.raw_os_error()
== Some(c::ERROR_SHARING_VIOLATION as _)) => {}
// Otherwise return the error.
Err(e) => return Err(e),
}
thread::yield_now();
} }
} }
for i in 1..=MAX_RETRIES {
let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE);
match result {
Ok(f) => delete(&f)?,
// Already deleted, so skip.
Err(e) if e.kind() == io::ErrorKind::NotFound => break,
// Retry a few times if the file is locked or a delete is already in progress.
Err(e)
if i < MAX_RETRIES
&& (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _)
|| e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _)) => {}
// Otherwise return the error.
Err(e) => return Err(e),
}
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 {