diff options
| author | Chris Denton <chris@chrisdenton.dev> | 2023-04-28 02:19:00 +0100 |
|---|---|---|
| committer | Chris Denton <chris@chrisdenton.dev> | 2023-04-28 02:30:45 +0100 |
| commit | ddff7f0e50c1184c5cfa1a54c7bd2b6848ed85d6 (patch) | |
| tree | db3e2c3656b64b4d4b6d6d1fdd6eddcba00e2b84 | |
| parent | 1a6ae3d692cfb52b21d0f45ba50b659486e53d6c (diff) | |
| download | rust-ddff7f0e50c1184c5cfa1a54c7bd2b6848ed85d6.tar.gz rust-ddff7f0e50c1184c5cfa1a54c7bd2b6848ed85d6.zip | |
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.
| -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. |
