@@ -1482,7 +1482,7 @@ mod remove_dir_impl {
1482
1482
use crate :: io;
1483
1483
use crate :: mem;
1484
1484
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 } ;
1486
1486
use crate :: path:: { Path , PathBuf } ;
1487
1487
use crate :: sync:: Arc ;
1488
1488
use crate :: sys:: { cvt, cvt_r} ;
@@ -1537,18 +1537,21 @@ mod remove_dir_impl {
1537
1537
1538
1538
const MAX_OPEN_FDS : usize = 32 ;
1539
1539
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 > {
1541
1544
let fd = cvt_r ( || unsafe {
1542
1545
openat (
1543
- parent_fd. unwrap_or ( libc:: AT_FDCWD ) ,
1546
+ parent_fd. map ( |fd| fd . as_raw_fd ( ) ) . unwrap_or ( libc:: AT_FDCWD ) ,
1544
1547
p. as_ptr ( ) ,
1545
1548
libc:: O_CLOEXEC | libc:: O_RDONLY | libc:: O_NOFOLLOW | libc:: O_DIRECTORY ,
1546
1549
)
1547
1550
} ) ?;
1548
1551
Ok ( unsafe { OwnedFd :: from_raw_fd ( fd) } )
1549
1552
}
1550
1553
1551
- fn fdreaddir ( dir_fd : OwnedFd ) -> io:: Result < ( ReadDir , RawFd ) > {
1554
+ fn fdreaddir ( dir_fd : OwnedFd ) -> io:: Result < CachedReadDir > {
1552
1555
let ptr = unsafe { fdopendir ( dir_fd. as_raw_fd ( ) ) } ;
1553
1556
if ptr. is_null ( ) {
1554
1557
return Err ( io:: Error :: last_os_error ( ) ) ;
@@ -1559,8 +1562,8 @@ mod remove_dir_impl {
1559
1562
// a valid root is not needed because we do not call any functions involving the full path
1560
1563
// of the DirEntrys.
1561
1564
let dummy_root = PathBuf :: new ( ) ;
1562
- Ok ( (
1563
- ReadDir {
1565
+ Ok ( CachedReadDir {
1566
+ readdir : ReadDir {
1564
1567
inner : Arc :: new ( InnerReadDir { dirp, root : dummy_root } ) ,
1565
1568
#[ cfg( not( any(
1566
1569
target_os = "android" ,
@@ -1572,8 +1575,8 @@ mod remove_dir_impl {
1572
1575
) ) ) ]
1573
1576
end_of_stream : false ,
1574
1577
} ,
1575
- new_parent_fd,
1576
- ) )
1578
+ raw_fd : new_parent_fd,
1579
+ } )
1577
1580
}
1578
1581
1579
1582
#[ cfg( any(
@@ -1600,15 +1603,15 @@ mod remove_dir_impl {
1600
1603
}
1601
1604
}
1602
1605
1603
- fn unlink_direntry ( ent : & DirEntry , parent_fd : RawFd ) -> io:: Result < bool > {
1606
+ fn unlink_direntry ( ent : & DirEntry , parent_fd : BorrowedFd < ' _ > ) -> io:: Result < bool > {
1604
1607
match is_dir ( & ent) {
1605
1608
Some ( true ) => Ok ( false ) ,
1606
1609
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 ) } ) ?;
1608
1611
Ok ( true )
1609
1612
}
1610
1613
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 ) } ) {
1612
1615
// type unknown - try to unlink
1613
1616
Err ( err)
1614
1617
if err. raw_os_error ( ) == Some ( libc:: EISDIR )
@@ -1629,6 +1632,12 @@ mod remove_dir_impl {
1629
1632
raw_fd : RawFd ,
1630
1633
}
1631
1634
1635
+ impl CachedReadDir {
1636
+ fn as_fd ( & self ) -> BorrowedFd < ' _ > {
1637
+ unsafe { BorrowedFd :: borrow_raw_fd ( self . raw_fd ) }
1638
+ }
1639
+ }
1640
+
1632
1641
struct DirComponent {
1633
1642
name : CString ,
1634
1643
ino : u64 ,
@@ -1640,30 +1649,27 @@ mod remove_dir_impl {
1640
1649
// use fstat() to get the inode of the directory
1641
1650
let mut stat = unsafe { mem:: zeroed ( ) } ;
1642
1651
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) )
1648
1654
}
1649
1655
1650
1656
fn readdir_open_child (
1651
1657
readdir : & CachedReadDir ,
1652
1658
child : & DirEntry ,
1653
1659
) -> 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) ?;
1656
1662
Ok ( (
1657
1663
DirComponent { name : child. name_cstr ( ) . into ( ) , ino : child. entry . d_ino } ,
1658
- CachedReadDir { readdir , raw_fd } ,
1664
+ cached_readdir ,
1659
1665
) )
1660
1666
}
1661
1667
1662
1668
fn readdir_reopen_parent (
1663
1669
dir : & CachedReadDir ,
1664
1670
expected_parent_dir : & DirComponent ,
1665
1671
) -> 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 {
1667
1673
CStr :: from_bytes_with_nul_unchecked ( b"..\0 " )
1668
1674
} ) ?;
1669
1675
let mut stat = unsafe { mem:: zeroed ( ) } ;
@@ -1676,8 +1682,7 @@ mod remove_dir_impl {
1676
1682
"parent directory inode does not match" ,
1677
1683
) ) ;
1678
1684
}
1679
- let ( readdir, raw_fd) = fdreaddir ( parent_dir_fd) ?;
1680
- Ok ( CachedReadDir { readdir, raw_fd } )
1685
+ fdreaddir ( parent_dir_fd)
1681
1686
}
1682
1687
1683
1688
fn remove_dir_all_loop ( root : & Path ) -> io:: Result < ( ) > {
@@ -1691,7 +1696,7 @@ mod remove_dir_impl {
1691
1696
loop {
1692
1697
while let Some ( child) = current_readdir. readdir . next ( ) {
1693
1698
let child = child?;
1694
- if !unlink_direntry ( & child, current_readdir. raw_fd ) ? {
1699
+ if !unlink_direntry ( & child, current_readdir. as_fd ( ) ) ? {
1695
1700
// Descend into this child directory
1696
1701
1697
1702
let ( child_dir_compoment, child_readdir) =
0 commit comments