Skip to content

Commit d2cfba1

Browse files
committed
Readd Macos x86-64 remove_dir_all() special case using dynamic symbols.
1 parent 7cf62c7 commit d2cfba1

File tree

1 file changed

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

1 file changed

+49
-6
lines changed

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

+49-6
Original file line numberDiff line numberDiff line change
@@ -1475,11 +1475,7 @@ mod remove_dir_impl {
14751475
}
14761476

14771477
// Modern implementation using openat(), unlinkat() and fdopendir()
1478-
#[cfg(not(any(
1479-
all(target_os = "macos", target_arch = "x86_64"),
1480-
target_os = "redox",
1481-
target_os = "espidf"
1482-
)))]
1478+
#[cfg(not(any(target_os = "redox", target_os = "espidf")))]
14831479
mod remove_dir_impl {
14841480
use super::{cstr, lstat, Dir, DirEntry, InnerReadDir, ReadDir};
14851481
use crate::ffi::CStr;
@@ -1489,8 +1485,39 @@ mod remove_dir_impl {
14891485
use crate::path::{Path, PathBuf};
14901486
use crate::sync::Arc;
14911487
use crate::sys::{cvt, cvt_r};
1488+
1489+
#[cfg(not(all(target_os = "macos", target_arch = "x86_64"),))]
14921490
use libc::{fdopendir, openat, unlinkat};
14931491

1492+
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
1493+
mod macos_weak {
1494+
use crate::sys::weak::weak;
1495+
use libc::{c_char, c_int, DIR};
1496+
1497+
pub unsafe fn openat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int {
1498+
weak!(fn openat(c_int, *const c_char, c_int) -> c_int);
1499+
openat.get().unwrap()(dirfd, pathname, flags)
1500+
}
1501+
1502+
pub unsafe fn fdopendir(fd: c_int) -> *mut DIR {
1503+
weak!(fn fdopendir(c_int) -> *mut DIR, "fdopendir$INODE64");
1504+
fdopendir.get().unwrap()(fd)
1505+
}
1506+
1507+
pub unsafe fn unlinkat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int {
1508+
weak!(fn unlinkat(c_int, *const c_char, c_int) -> c_int);
1509+
unlinkat.get().unwrap()(dirfd, pathname, flags)
1510+
}
1511+
1512+
pub fn has_openat() -> bool {
1513+
weak!(fn openat(c_int, *const c_char, c_int) -> c_int);
1514+
openat.get().is_some()
1515+
}
1516+
}
1517+
1518+
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
1519+
use macos_weak::{fdopendir, openat, unlinkat};
1520+
14941521
pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> {
14951522
let fd = cvt_r(|| unsafe {
14961523
openat(
@@ -1629,7 +1656,7 @@ mod remove_dir_impl {
16291656
}
16301657
}
16311658

1632-
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
1659+
fn remove_dir_all_modern(p: &Path) -> io::Result<()> {
16331660
// We cannot just call remove_dir_all_loop() here because that would not delete a passed
16341661
// symlink. No need to worry about races, because remove_dir_all_loop() does not descend
16351662
// into symlinks.
@@ -1640,4 +1667,20 @@ mod remove_dir_impl {
16401667
remove_dir_all_loop(p)
16411668
}
16421669
}
1670+
1671+
#[cfg(not(all(target_os = "macos", target_arch = "x86_64")))]
1672+
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
1673+
remove_dir_all_modern(p)
1674+
}
1675+
1676+
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
1677+
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
1678+
if macos_weak::has_openat() {
1679+
// openat() is available with macOS 10.10+, just like unlinkat() and fdopendir()
1680+
remove_dir_all_modern(p)
1681+
} else {
1682+
// fall back to classic implementation
1683+
crate::sys_common::fs::remove_dir_all(p)
1684+
}
1685+
}
16431686
}

0 commit comments

Comments
 (0)