Skip to content

Commit ddff7f0

Browse files
committed
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.
1 parent 1a6ae3d commit ddff7f0

File tree

1 file changed

+22
-19
lines changed
  • library/std/src/sys/windows

1 file changed

+22
-19
lines changed

library/std/src/sys/windows/fs.rs

+22-19
Original file line numberDiff line numberDiff line change
@@ -1132,26 +1132,29 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io
11321132
&dir,
11331133
&name,
11341134
c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY,
1135-
)?;
1136-
dirlist.push(child_dir);
1137-
} else {
1138-
for i in 1..=MAX_RETRIES {
1139-
let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE);
1140-
match result {
1141-
Ok(f) => delete(&f)?,
1142-
// Already deleted, so skip.
1143-
Err(e) if e.kind() == io::ErrorKind::NotFound => break,
1144-
// Retry a few times if the file is locked or a delete is already in progress.
1145-
Err(e)
1146-
if i < MAX_RETRIES
1147-
&& (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _)
1148-
|| e.raw_os_error()
1149-
== Some(c::ERROR_SHARING_VIOLATION as _)) => {}
1150-
// Otherwise return the error.
1151-
Err(e) => return Err(e),
1152-
}
1153-
thread::yield_now();
1135+
);
1136+
// On success, add the handle to the queue.
1137+
// If opening the directory fails we treat it the same as a file
1138+
if let Ok(child_dir) = child_dir {
1139+
dirlist.push(child_dir);
1140+
continue;
1141+
}
1142+
}
1143+
for i in 1..=MAX_RETRIES {
1144+
let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE);
1145+
match result {
1146+
Ok(f) => delete(&f)?,
1147+
// Already deleted, so skip.
1148+
Err(e) if e.kind() == io::ErrorKind::NotFound => break,
1149+
// Retry a few times if the file is locked or a delete is already in progress.
1150+
Err(e)
1151+
if i < MAX_RETRIES
1152+
&& (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _)
1153+
|| e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _)) => {}
1154+
// Otherwise return the error.
1155+
Err(e) => return Err(e),
11541156
}
1157+
thread::yield_now();
11551158
}
11561159
}
11571160
// If there were no more files then delete the directory.

0 commit comments

Comments
 (0)