diff options
| author | bors <bors@rust-lang.org> | 2024-08-23 08:31:26 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-08-23 08:31:26 +0000 |
| commit | c8b14ba7b6777dfbfb64a02d7bbe867a54dddf2a (patch) | |
| tree | 7e4bbc1407c3d14d35dc1e424a61654cc1f648a8 /library/std/src/sys/pal/unix/fs.rs | |
| parent | b5723af3457b9cd3795eeb97e9af2d34964854f2 (diff) | |
| parent | 6c2ee6fe77b4db7b1b523a8a514d67d68855eeb1 (diff) | |
| download | rust-c8b14ba7b6777dfbfb64a02d7bbe867a54dddf2a.tar.gz rust-c8b14ba7b6777dfbfb64a02d7bbe867a54dddf2a.zip | |
Auto merge of #129443 - matthiaskrgr:rollup-tbgdj0p, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #127623 (fix: fs::remove_dir_all: treat internal ENOENT as success) - #128876 (Ship MinGW-w64 runtime DLLs along with `rust-lld.exe` for `-pc-windows-gnu` targets) - #129055 (Migrate `x86_64-fortanix-unknown-sgx-lvi` `run-make` test to rmake) - #129386 (Use a LocalDefId in ResolvedArg.) - #129400 (Update `compiler_builtins` to `0.1.120`) - #129414 (Fix extern crates not being hidden with `doc(hidden)`) - #129417 (Don't trigger refinement lint if predicates reference errors) - #129433 (Fix a missing import in a doc in run-make-support) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'library/std/src/sys/pal/unix/fs.rs')
| -rw-r--r-- | library/std/src/sys/pal/unix/fs.rs | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index be13e1ae9b3..fc9d7e98883 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -2002,6 +2002,7 @@ mod remove_dir_impl { use crate::path::{Path, PathBuf}; use crate::sys::common::small_c_string::run_path_with_cstr; use crate::sys::{cvt, cvt_r}; + use crate::sys_common::ignore_notfound; pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> { let fd = cvt_r(|| unsafe { @@ -2055,6 +2056,16 @@ mod remove_dir_impl { } } + fn is_enoent(result: &io::Result<()>) -> bool { + if let Err(err) = result + && matches!(err.raw_os_error(), Some(libc::ENOENT)) + { + true + } else { + false + } + } + fn remove_dir_all_recursive(parent_fd: Option<RawFd>, path: &CStr) -> io::Result<()> { // try opening as directory let fd = match openat_nofollow_dironly(parent_fd, &path) { @@ -2078,27 +2089,35 @@ mod remove_dir_impl { for child in dir { let child = child?; let child_name = child.name_cstr(); - match is_dir(&child) { - Some(true) => { - remove_dir_all_recursive(Some(fd), child_name)?; - } - Some(false) => { - cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?; - } - None => { - // POSIX specifies that calling unlink()/unlinkat(..., 0) on a directory can succeed - // if the process has the appropriate privileges. This however can causing orphaned - // directories requiring an fsck e.g. on Solaris and Illumos. So we try recursing - // into it first instead of trying to unlink() it. - remove_dir_all_recursive(Some(fd), child_name)?; + // we need an inner try block, because if one of these + // directories has already been deleted, then we need to + // continue the loop, not return ok. + let result: io::Result<()> = try { + match is_dir(&child) { + Some(true) => { + remove_dir_all_recursive(Some(fd), child_name)?; + } + Some(false) => { + cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?; + } + None => { + // POSIX specifies that calling unlink()/unlinkat(..., 0) on a directory can succeed + // if the process has the appropriate privileges. This however can causing orphaned + // directories requiring an fsck e.g. on Solaris and Illumos. So we try recursing + // into it first instead of trying to unlink() it. + remove_dir_all_recursive(Some(fd), child_name)?; + } } + }; + if result.is_err() && !is_enoent(&result) { + return result; } } // unlink the directory after removing its contents - cvt(unsafe { + ignore_notfound(cvt(unsafe { unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), path.as_ptr(), libc::AT_REMOVEDIR) - })?; + }))?; Ok(()) } |
