Skip to content

Commit 735f60c

Browse files
committed
Integrate macos x86-64 remove_dir_all() impl. Step 2: readd
1 parent 41b4423 commit 735f60c

File tree

1 file changed

+60
-6
lines changed
  • library/std/src/sys/unix

1 file changed

+60
-6
lines changed

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

+60-6
Original file line numberDiff line numberDiff line change
@@ -1483,11 +1483,7 @@ mod remove_dir_impl {
14831483
}
14841484

14851485
// Modern implementation using openat(), unlinkat() and fdopendir()
1486-
#[cfg(not(any(
1487-
all(target_os = "macos", target_arch = "x86_64"),
1488-
target_os = "redox",
1489-
target_os = "espidf"
1490-
)))]
1486+
#[cfg(not(any(target_os = "redox", target_os = "espidf")))]
14911487
mod remove_dir_impl {
14921488
use super::{cstr, lstat, Dir, DirEntry, InnerReadDir, ReadDir};
14931489
use crate::ffi::CStr;
@@ -1497,7 +1493,49 @@ mod remove_dir_impl {
14971493
use crate::path::{Path, PathBuf};
14981494
use crate::sync::Arc;
14991495
use crate::sys::{cvt, cvt_r};
1496+
1497+
#[cfg(not(all(target_os = "macos", target_arch = "x86_64"),))]
15001498
use libc::{fdopendir, openat, unlinkat};
1499+
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
1500+
use macos_weak::{fdopendir, openat, unlinkat};
1501+
1502+
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
1503+
mod macos_weak {
1504+
use crate::sys::weak::weak;
1505+
use libc::{c_char, c_int, DIR};
1506+
1507+
fn get_openat_fn() -> Option<unsafe extern "C" fn(c_int, *const c_char, c_int) -> c_int> {
1508+
weak!(fn openat(c_int, *const c_char, c_int) -> c_int);
1509+
openat.get()
1510+
}
1511+
1512+
pub fn has_openat() -> bool {
1513+
get_openat_fn().is_some()
1514+
}
1515+
1516+
pub unsafe fn openat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int {
1517+
get_openat_fn().map(|openat| openat(dirfd, pathname, flags)).unwrap_or_else(|| {
1518+
crate::sys::unix::os::set_errno(libc::ENOSYS);
1519+
-1
1520+
})
1521+
}
1522+
1523+
pub unsafe fn fdopendir(fd: c_int) -> *mut DIR {
1524+
weak!(fn fdopendir(c_int) -> *mut DIR, "fdopendir$INODE64");
1525+
fdopendir.get().map(|fdopendir| fdopendir(fd)).unwrap_or_else(|| {
1526+
crate::sys::unix::os::set_errno(libc::ENOSYS);
1527+
crate::ptr::null_mut()
1528+
})
1529+
}
1530+
1531+
pub unsafe fn unlinkat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int {
1532+
weak!(fn unlinkat(c_int, *const c_char, c_int) -> c_int);
1533+
unlinkat.get().map(|unlinkat| unlinkat(dirfd, pathname, flags)).unwrap_or_else(|| {
1534+
crate::sys::unix::os::set_errno(libc::ENOSYS);
1535+
-1
1536+
})
1537+
}
1538+
}
15011539

15021540
pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> {
15031541
let fd = cvt_r(|| unsafe {
@@ -1609,7 +1647,7 @@ mod remove_dir_impl {
16091647
Ok(())
16101648
}
16111649

1612-
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
1650+
fn remove_dir_all_modern(p: &Path) -> io::Result<()> {
16131651
// We cannot just call remove_dir_all_recursive() here because that would not delete a passed
16141652
// symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse
16151653
// into symlinks.
@@ -1620,4 +1658,20 @@ mod remove_dir_impl {
16201658
remove_dir_all_recursive(None, p)
16211659
}
16221660
}
1661+
1662+
#[cfg(not(all(target_os = "macos", target_arch = "x86_64")))]
1663+
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
1664+
remove_dir_all_modern(p)
1665+
}
1666+
1667+
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
1668+
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
1669+
if macos_weak::has_openat() {
1670+
// openat() is available with macOS 10.10+, just like unlinkat() and fdopendir()
1671+
remove_dir_all_modern(p)
1672+
} else {
1673+
// fall back to classic implementation
1674+
crate::sys_common::fs::remove_dir_all(p)
1675+
}
1676+
}
16231677
}

0 commit comments

Comments
 (0)