@@ -1482,124 +1482,6 @@ mod remove_dir_impl {
14821482 pub use crate :: sys_common:: fs:: remove_dir_all;
14831483}
14841484
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-
16031485// Modern implementation using openat(), unlinkat() and fdopendir()
16041486#[ cfg( not( any(
16051487 all( target_os = "macos" , target_arch = "x86_64" ) ,
0 commit comments