@@ -1482,7 +1482,7 @@ mod remove_dir_impl {
14821482 use crate :: io;
14831483 use crate :: mem;
14841484 use crate :: os:: unix:: io:: { AsRawFd , FromRawFd , IntoRawFd } ;
1485- use crate :: os:: unix:: prelude:: { OwnedFd , RawFd } ;
1485+ use crate :: os:: unix:: prelude:: { BorrowedFd , OwnedFd , RawFd } ;
14861486 use crate :: path:: { Path , PathBuf } ;
14871487 use crate :: sync:: Arc ;
14881488 use crate :: sys:: { cvt, cvt_r} ;
@@ -1537,18 +1537,21 @@ mod remove_dir_impl {
15371537
15381538 const MAX_OPEN_FDS : usize = 32 ;
15391539
1540- pub fn openat_nofollow_dironly ( parent_fd : Option < RawFd > , p : & CStr ) -> io:: Result < OwnedFd > {
1540+ pub fn openat_nofollow_dironly (
1541+ parent_fd : Option < BorrowedFd < ' _ > > ,
1542+ p : & CStr ,
1543+ ) -> io:: Result < OwnedFd > {
15411544 let fd = cvt_r ( || unsafe {
15421545 openat (
1543- parent_fd. unwrap_or ( libc:: AT_FDCWD ) ,
1546+ parent_fd. map ( |fd| fd . as_raw_fd ( ) ) . unwrap_or ( libc:: AT_FDCWD ) ,
15441547 p. as_ptr ( ) ,
15451548 libc:: O_CLOEXEC | libc:: O_RDONLY | libc:: O_NOFOLLOW | libc:: O_DIRECTORY ,
15461549 )
15471550 } ) ?;
15481551 Ok ( unsafe { OwnedFd :: from_raw_fd ( fd) } )
15491552 }
15501553
1551- fn fdreaddir ( dir_fd : OwnedFd ) -> io:: Result < ( ReadDir , RawFd ) > {
1554+ fn fdreaddir ( dir_fd : OwnedFd ) -> io:: Result < CachedReadDir > {
15521555 let ptr = unsafe { fdopendir ( dir_fd. as_raw_fd ( ) ) } ;
15531556 if ptr. is_null ( ) {
15541557 return Err ( io:: Error :: last_os_error ( ) ) ;
@@ -1559,8 +1562,8 @@ mod remove_dir_impl {
15591562 // a valid root is not needed because we do not call any functions involving the full path
15601563 // of the DirEntrys.
15611564 let dummy_root = PathBuf :: new ( ) ;
1562- Ok ( (
1563- ReadDir {
1565+ Ok ( CachedReadDir {
1566+ readdir : ReadDir {
15641567 inner : Arc :: new ( InnerReadDir { dirp, root : dummy_root } ) ,
15651568 #[ cfg( not( any(
15661569 target_os = "android" ,
@@ -1572,8 +1575,8 @@ mod remove_dir_impl {
15721575 ) ) ) ]
15731576 end_of_stream : false ,
15741577 } ,
1575- new_parent_fd,
1576- ) )
1578+ raw_fd : new_parent_fd,
1579+ } )
15771580 }
15781581
15791582 #[ cfg( any(
@@ -1600,15 +1603,15 @@ mod remove_dir_impl {
16001603 }
16011604 }
16021605
1603- fn unlink_direntry ( ent : & DirEntry , parent_fd : RawFd ) -> io:: Result < bool > {
1606+ fn unlink_direntry ( ent : & DirEntry , parent_fd : BorrowedFd < ' _ > ) -> io:: Result < bool > {
16041607 match is_dir ( & ent) {
16051608 Some ( true ) => Ok ( false ) ,
16061609 Some ( false ) => {
1607- cvt ( unsafe { unlinkat ( parent_fd, ent. name_cstr ( ) . as_ptr ( ) , 0 ) } ) ?;
1610+ cvt ( unsafe { unlinkat ( parent_fd. as_raw_fd ( ) , ent. name_cstr ( ) . as_ptr ( ) , 0 ) } ) ?;
16081611 Ok ( true )
16091612 }
16101613 None => {
1611- match cvt ( unsafe { unlinkat ( parent_fd, ent. name_cstr ( ) . as_ptr ( ) , 0 ) } ) {
1614+ match cvt ( unsafe { unlinkat ( parent_fd. as_raw_fd ( ) , ent. name_cstr ( ) . as_ptr ( ) , 0 ) } ) {
16121615 // type unknown - try to unlink
16131616 Err ( err)
16141617 if err. raw_os_error ( ) == Some ( libc:: EISDIR )
@@ -1629,6 +1632,12 @@ mod remove_dir_impl {
16291632 raw_fd : RawFd ,
16301633 }
16311634
1635+ impl CachedReadDir {
1636+ fn as_fd ( & self ) -> BorrowedFd < ' _ > {
1637+ unsafe { BorrowedFd :: borrow_raw_fd ( self . raw_fd ) }
1638+ }
1639+ }
1640+
16321641 struct DirComponent {
16331642 name : CString ,
16341643 ino : u64 ,
@@ -1640,30 +1649,27 @@ mod remove_dir_impl {
16401649 // use fstat() to get the inode of the directory
16411650 let mut stat = unsafe { mem:: zeroed ( ) } ;
16421651 cvt ( unsafe { fstat64 ( dir_fd. as_raw_fd ( ) , & mut stat) } ) ?;
1643- let ( readdir, raw_fd) = fdreaddir ( dir_fd) ?;
1644- Ok ( (
1645- DirComponent { name : CString :: new ( "" ) ?, ino : stat. st_ino } ,
1646- CachedReadDir { readdir, raw_fd } ,
1647- ) )
1652+ let cached_readdir = fdreaddir ( dir_fd) ?;
1653+ Ok ( ( DirComponent { name : CString :: new ( "" ) ?, ino : stat. st_ino } , cached_readdir) )
16481654 }
16491655
16501656 fn readdir_open_child (
16511657 readdir : & CachedReadDir ,
16521658 child : & DirEntry ,
16531659 ) -> io:: Result < ( DirComponent , CachedReadDir ) > {
1654- let dir_fd = openat_nofollow_dironly ( Some ( readdir. raw_fd ) , child. name_cstr ( ) ) ?;
1655- let ( readdir , raw_fd ) = fdreaddir ( dir_fd) ?;
1660+ let dir_fd = openat_nofollow_dironly ( Some ( readdir. as_fd ( ) ) , child. name_cstr ( ) ) ?;
1661+ let cached_readdir = fdreaddir ( dir_fd) ?;
16561662 Ok ( (
16571663 DirComponent { name : child. name_cstr ( ) . into ( ) , ino : child. entry . d_ino } ,
1658- CachedReadDir { readdir , raw_fd } ,
1664+ cached_readdir ,
16591665 ) )
16601666 }
16611667
16621668 fn readdir_reopen_parent (
16631669 dir : & CachedReadDir ,
16641670 expected_parent_dir : & DirComponent ,
16651671 ) -> io:: Result < CachedReadDir > {
1666- let parent_dir_fd = openat_nofollow_dironly ( Some ( dir. raw_fd ) , unsafe {
1672+ let parent_dir_fd = openat_nofollow_dironly ( Some ( dir. as_fd ( ) ) , unsafe {
16671673 CStr :: from_bytes_with_nul_unchecked ( b"..\0 " )
16681674 } ) ?;
16691675 let mut stat = unsafe { mem:: zeroed ( ) } ;
@@ -1676,8 +1682,7 @@ mod remove_dir_impl {
16761682 "parent directory inode does not match" ,
16771683 ) ) ;
16781684 }
1679- let ( readdir, raw_fd) = fdreaddir ( parent_dir_fd) ?;
1680- Ok ( CachedReadDir { readdir, raw_fd } )
1685+ fdreaddir ( parent_dir_fd)
16811686 }
16821687
16831688 fn remove_dir_all_loop ( root : & Path ) -> io:: Result < ( ) > {
@@ -1691,7 +1696,7 @@ mod remove_dir_impl {
16911696 loop {
16921697 while let Some ( child) = current_readdir. readdir . next ( ) {
16931698 let child = child?;
1694- if !unlink_direntry ( & child, current_readdir. raw_fd ) ? {
1699+ if !unlink_direntry ( & child, current_readdir. as_fd ( ) ) ? {
16951700 // Descend into this child directory
16961701
16971702 let ( child_dir_compoment, child_readdir) =
0 commit comments