Rollup merge of #110918 - ChrisDenton:on-error-resume-next, r=cuviper

`remove_dir_all`: try deleting the directory even if `FILE_LIST_DIRECTORY` access is denied

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.

Fixes https://github.com/rust-lang/cargo/issues/12042
This commit is contained in:
Matthias Krüger 2023-04-28 07:34:04 +02:00 committed by GitHub
commit 6476b79df7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1132,27 +1132,30 @@ fn copy_handle(f: &File) -> mem::ManuallyDrop<File> {
&dir,
&name,
c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY,
)?;
dirlist.push(child_dir);
} else {
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();
);
// 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);
continue;
}
}
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 !more_data {