@@ -1482,124 +1482,6 @@ mod remove_dir_impl {
1482
1482
pub use crate :: sys_common:: fs:: remove_dir_all;
1483
1483
}
1484
1484
1485
- // Dynamically choose implementation Macos x86-64: modern for 10.10+, fallback for older versions
1486
- #[ cfg( all( target_os = "macos" , target_arch = "x86_64" ) ) ]
1487
- mod remove_dir_impl {
1488
- use super :: { cstr, lstat, Dir , InnerReadDir , ReadDir } ;
1489
- use crate :: ffi:: CStr ;
1490
- use crate :: io;
1491
- use crate :: os:: unix:: io:: { AsRawFd , FromRawFd , IntoRawFd } ;
1492
- use crate :: os:: unix:: prelude:: { OwnedFd , RawFd } ;
1493
- use crate :: path:: { Path , PathBuf } ;
1494
- use crate :: sync:: Arc ;
1495
- use crate :: sys:: weak:: weak;
1496
- use crate :: sys:: { cvt, cvt_r} ;
1497
- use libc:: { c_char, c_int, DIR } ;
1498
-
1499
- pub fn openat_nofollow_dironly ( parent_fd : Option < RawFd > , p : & CStr ) -> io:: Result < OwnedFd > {
1500
- weak ! ( fn openat( c_int, * const c_char, c_int) -> c_int) ;
1501
- let fd = cvt_r ( || unsafe {
1502
- openat. get ( ) . unwrap ( ) (
1503
- parent_fd. unwrap_or ( libc:: AT_FDCWD ) ,
1504
- p. as_ptr ( ) ,
1505
- libc:: O_CLOEXEC | libc:: O_RDONLY | libc:: O_NOFOLLOW | libc:: O_DIRECTORY ,
1506
- )
1507
- } ) ?;
1508
- Ok ( unsafe { OwnedFd :: from_raw_fd ( fd) } )
1509
- }
1510
-
1511
- fn fdreaddir ( dir_fd : OwnedFd ) -> io:: Result < ( ReadDir , RawFd ) > {
1512
- weak ! ( fn fdopendir( c_int) -> * mut DIR , "fdopendir$INODE64" ) ;
1513
- let ptr = unsafe { fdopendir. get ( ) . unwrap ( ) ( dir_fd. as_raw_fd ( ) ) } ;
1514
- if ptr. is_null ( ) {
1515
- return Err ( io:: Error :: last_os_error ( ) ) ;
1516
- }
1517
- let dirp = Dir ( ptr) ;
1518
- // file descriptor is automatically closed by libc::closedir() now, so give up ownership
1519
- let new_parent_fd = dir_fd. into_raw_fd ( ) ;
1520
- // a valid root is not needed because we do not call any functions involving the full path
1521
- // of the DirEntrys.
1522
- let dummy_root = PathBuf :: new ( ) ;
1523
- Ok ( (
1524
- ReadDir {
1525
- inner : Arc :: new ( InnerReadDir { dirp, root : dummy_root } ) ,
1526
- end_of_stream : false ,
1527
- } ,
1528
- new_parent_fd,
1529
- ) )
1530
- }
1531
-
1532
- fn remove_dir_all_recursive ( parent_fd : Option < RawFd > , p : & Path ) -> io:: Result < ( ) > {
1533
- weak ! ( fn unlinkat( c_int, * const c_char, c_int) -> c_int) ;
1534
-
1535
- let pcstr = cstr ( p) ?;
1536
-
1537
- // entry is expected to be a directory, open as such
1538
- let fd = openat_nofollow_dironly ( parent_fd, & pcstr) ?;
1539
-
1540
- // open the directory passing ownership of the fd
1541
- let ( dir, fd) = fdreaddir ( fd) ?;
1542
- for child in dir {
1543
- let child = child?;
1544
- match child. entry . d_type {
1545
- libc:: DT_DIR => {
1546
- remove_dir_all_recursive ( Some ( fd) , Path :: new ( & child. file_name ( ) ) ) ?;
1547
- }
1548
- libc:: DT_UNKNOWN => {
1549
- match cvt ( unsafe { unlinkat. get ( ) . unwrap ( ) ( fd, child. name_cstr ( ) . as_ptr ( ) , 0 ) } )
1550
- {
1551
- // type unknown - try to unlink
1552
- Err ( err) if err. raw_os_error ( ) == Some ( libc:: EPERM ) => {
1553
- // if the file is a directory unlink fails with EPERM
1554
- remove_dir_all_recursive ( Some ( fd) , Path :: new ( & child. file_name ( ) ) ) ?;
1555
- }
1556
- result => {
1557
- result?;
1558
- }
1559
- }
1560
- }
1561
- _ => {
1562
- // not a directory -> unlink
1563
- cvt ( unsafe { unlinkat. get ( ) . unwrap ( ) ( fd, child. name_cstr ( ) . as_ptr ( ) , 0 ) } ) ?;
1564
- }
1565
- }
1566
- }
1567
-
1568
- // unlink the directory after removing its contents
1569
- cvt ( unsafe {
1570
- unlinkat. get ( ) . unwrap ( ) (
1571
- parent_fd. unwrap_or ( libc:: AT_FDCWD ) ,
1572
- pcstr. as_ptr ( ) ,
1573
- libc:: AT_REMOVEDIR ,
1574
- )
1575
- } ) ?;
1576
- Ok ( ( ) )
1577
- }
1578
-
1579
- fn remove_dir_all_modern ( p : & Path ) -> io:: Result < ( ) > {
1580
- // We cannot just call remove_dir_all_recursive() here because that would not delete a passed
1581
- // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse
1582
- // into symlinks.
1583
- let attr = lstat ( p) ?;
1584
- if attr. file_type ( ) . is_symlink ( ) {
1585
- crate :: fs:: remove_file ( p)
1586
- } else {
1587
- remove_dir_all_recursive ( None , p)
1588
- }
1589
- }
1590
-
1591
- pub fn remove_dir_all ( p : & Path ) -> io:: Result < ( ) > {
1592
- weak ! ( fn openat( c_int, * const c_char, c_int) -> c_int) ;
1593
- if openat. get ( ) . is_some ( ) {
1594
- // openat() is available with macOS 10.10+, just like unlinkat() and fdopendir()
1595
- remove_dir_all_modern ( p)
1596
- } else {
1597
- // fall back to classic implementation
1598
- crate :: sys_common:: fs:: remove_dir_all ( p)
1599
- }
1600
- }
1601
- }
1602
-
1603
1485
// Modern implementation using openat(), unlinkat() and fdopendir()
1604
1486
#[ cfg( not( any(
1605
1487
all( target_os = "macos" , target_arch = "x86_64" ) ,
0 commit comments