@@ -1483,11 +1483,7 @@ mod remove_dir_impl {
1483
1483
}
1484
1484
1485
1485
// 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" ) ) ) ]
1491
1487
mod remove_dir_impl {
1492
1488
use super :: { cstr, lstat, Dir , DirEntry , InnerReadDir , ReadDir } ;
1493
1489
use crate :: ffi:: CStr ;
@@ -1497,7 +1493,49 @@ mod remove_dir_impl {
1497
1493
use crate :: path:: { Path , PathBuf } ;
1498
1494
use crate :: sync:: Arc ;
1499
1495
use crate :: sys:: { cvt, cvt_r} ;
1496
+
1497
+ #[ cfg( not( all( target_os = "macos" , target_arch = "x86_64" ) , ) ) ]
1500
1498
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
+ }
1501
1539
1502
1540
pub fn openat_nofollow_dironly ( parent_fd : Option < RawFd > , p : & CStr ) -> io:: Result < OwnedFd > {
1503
1541
let fd = cvt_r ( || unsafe {
@@ -1609,7 +1647,7 @@ mod remove_dir_impl {
1609
1647
Ok ( ( ) )
1610
1648
}
1611
1649
1612
- pub fn remove_dir_all ( p : & Path ) -> io:: Result < ( ) > {
1650
+ fn remove_dir_all_modern ( p : & Path ) -> io:: Result < ( ) > {
1613
1651
// We cannot just call remove_dir_all_recursive() here because that would not delete a passed
1614
1652
// symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse
1615
1653
// into symlinks.
@@ -1620,4 +1658,20 @@ mod remove_dir_impl {
1620
1658
remove_dir_all_recursive ( None , p)
1621
1659
}
1622
1660
}
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
+ }
1623
1677
}
0 commit comments