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