@@ -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" ) ) ) ]
14831479mod 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