diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-04-28 07:34:04 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-28 07:34:04 +0200 |
| commit | 6476b79df7769afc531dc74308f3e27e11ab95d2 (patch) | |
| tree | 06e38dde6d568cfbd36bd46ae43ae7785352c59c | |
| parent | 901bab70d34748379331f1c1f069f57029f46b5e (diff) | |
| parent | ddff7f0e50c1184c5cfa1a54c7bd2b6848ed85d6 (diff) | |
| download | rust-6476b79df7769afc531dc74308f3e27e11ab95d2.tar.gz rust-6476b79df7769afc531dc74308f3e27e11ab95d2.zip | |
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
| -rw-r--r-- | library/std/src/sys/windows/fs.rs | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 956db577d53..8ed62cdddcd 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -1132,26 +1132,29 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io &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. |
