@@ -43,7 +43,7 @@ use super::cache::{DirCacheItem, INodeCacheItem};
43
43
use super :: path:: PathBuf ;
44
44
use super :: { cache, FileSystemError , Path } ;
45
45
46
- use super :: inode:: { DirEntry , INodeInterface , Metadata , PollFlags , PollTable } ;
46
+ use super :: inode:: { self , INodeInterface , Metadata , PollFlags , PollTable } ;
47
47
use super :: FileSystem ;
48
48
49
49
pub struct INode {
@@ -301,6 +301,7 @@ impl INode {
301
301
entry. entry_size = block_size as _ ;
302
302
entry. inode = inode. id as _ ;
303
303
entry. file_type = file_type;
304
+ // JSDJFKDSJFHJK CHECK THIS this is ub
304
305
entry. set_name ( name) ;
305
306
}
306
307
@@ -314,7 +315,7 @@ impl INode {
314
315
return Err ( FileSystemError :: NotDirectory ) ;
315
316
}
316
317
317
- if DirEntryIter :: new ( self . sref ( ) ) . any ( |( e , _ ) | e == name) {
318
+ if DirEntryIter :: new ( self . sref ( ) ) . any ( |entry| entry . name ( ) == name) {
318
319
return Err ( FileSystemError :: EntryExists ) ;
319
320
}
320
321
@@ -349,7 +350,7 @@ impl INode {
349
350
entry : & disk:: DirEntry ,
350
351
) -> Option < DirCacheItem > {
351
352
let inode = self . fs . upgrade ( ) ?. find_inode ( entry. inode as usize , None ) ?;
352
- Some ( DirEntry :: new ( parent, inode, name. to_string ( ) ) )
353
+ Some ( inode :: DirEntry :: new ( parent, inode, name. to_string ( ) ) )
353
354
}
354
355
355
356
pub fn sref ( & self ) -> Arc < INode > {
@@ -410,19 +411,19 @@ impl INodeInterface for INode {
410
411
}
411
412
412
413
fn dirent ( & self , parent : DirCacheItem , index : usize ) -> super :: Result < Option < DirCacheItem > > {
413
- if let Some ( ( name , entry) ) = DirEntryIter :: new ( self . sref ( ) ) . nth ( index) {
414
- Ok ( self . make_dirent ( parent, & name, & entry) )
414
+ if let Some ( entry) = DirEntryIter :: new ( self . sref ( ) ) . nth ( index) {
415
+ Ok ( self . make_dirent ( parent, entry . name ( ) , entry) )
415
416
} else {
416
417
Ok ( None )
417
418
}
418
419
}
419
420
420
421
fn lookup ( & self , parent : DirCacheItem , name : & str ) -> super :: Result < DirCacheItem > {
421
- let ( name , entry) = DirEntryIter :: new ( self . sref ( ) )
422
- . find ( |( ename , _ ) | ename == name)
422
+ let entry = DirEntryIter :: new ( self . sref ( ) )
423
+ . find ( |entry| entry . name ( ) == name)
423
424
. ok_or ( FileSystemError :: EntryNotFound ) ?;
424
425
425
- Ok ( self . make_dirent ( parent, & name, & entry) . unwrap ( ) )
426
+ Ok ( self . make_dirent ( parent, entry . name ( ) , entry) . unwrap ( ) )
426
427
}
427
428
428
429
fn read_at ( & self , offset : usize , usr_buffer : & mut [ u8 ] ) -> super :: Result < usize > {
@@ -456,7 +457,7 @@ impl INodeInterface for INode {
456
457
fn rename ( & self , old : DirCacheItem , dest : & str ) -> super :: Result < ( ) > {
457
458
assert ! ( self . metadata( ) ?. is_directory( ) ) ;
458
459
459
- if DirEntryIter :: new ( self . sref ( ) ) . any ( |( name , _ ) | name == dest) {
460
+ if DirEntryIter :: new ( self . sref ( ) ) . any ( |entry| entry . name ( ) == dest) {
460
461
return Err ( FileSystemError :: EntryExists ) ;
461
462
}
462
463
@@ -504,7 +505,7 @@ impl INodeInterface for INode {
504
505
}
505
506
506
507
let inode = self . make_inode ( name, FileType :: File , None ) ?;
507
- Ok ( DirEntry :: new ( parent, inode, name. to_string ( ) ) )
508
+ Ok ( inode :: DirEntry :: new ( parent, inode, name. to_string ( ) ) )
508
509
}
509
510
510
511
fn mkdir ( & self , name : & str ) -> super :: Result < INodeCacheItem > {
@@ -645,46 +646,66 @@ impl INodeInterface for INode {
645
646
}
646
647
}
647
648
648
- pub struct DirEntryIter {
649
+ pub struct DirEntryIter < ' a > {
649
650
inode : Arc < INode > ,
650
651
offset : usize ,
652
+
653
+ current_block : Box < [ MaybeUninit < u8 > ] > ,
654
+ block_size : usize ,
655
+ _phantom : core:: marker:: PhantomData < & ' a disk:: DirEntry > ,
651
656
}
652
657
653
- impl DirEntryIter {
658
+ impl < ' a > DirEntryIter < ' a > {
654
659
pub fn new ( inode : Arc < INode > ) -> Self {
655
- Self { inode, offset : 0 }
660
+ let block_size = inode. fs . upgrade ( ) . unwrap ( ) . superblock . block_size ( ) ;
661
+ let buf = Box :: < [ u8 ] > :: new_uninit_slice ( block_size) ;
662
+
663
+ Self {
664
+ inode,
665
+ offset : 0 ,
666
+ current_block : buf,
667
+ block_size,
668
+
669
+ _phantom : core:: marker:: PhantomData ,
670
+ }
656
671
}
657
672
}
658
673
659
- impl Iterator for DirEntryIter {
660
- type Item = ( String , block :: DirtyRef < disk:: DirEntry > ) ;
674
+ impl < ' a > Iterator for DirEntryIter < ' a > {
675
+ type Item = & ' a mut disk:: DirEntry ;
661
676
662
677
fn next ( & mut self ) -> Option < Self :: Item > {
678
+ // Read 1 block at a time.
679
+ //
680
+ // XXX: A directory entry cannot span between multiple data blocks.
663
681
let file_size = self . inode . inode . read ( ) . size ( ) ;
664
682
665
683
if self . offset + core:: mem:: size_of :: < disk:: DirEntry > ( ) > file_size {
666
684
return None ;
667
685
}
668
686
669
- let entry = unsafe { self . inode . read_mut :: < disk:: DirEntry > ( self . offset ) } ;
670
- if entry. inode == 0 {
671
- return None ;
687
+ let block_offset = self . offset % self . block_size ;
688
+ if block_offset == 0 {
689
+ self . inode
690
+ . read ( self . offset , & mut self . current_block )
691
+ . unwrap ( ) ;
672
692
}
673
693
674
- let mut name = Box :: < [ u8 ] > :: new_uninit_slice ( entry. name_size as usize ) ;
675
- self . inode
676
- . read (
677
- self . offset + core:: mem:: size_of :: < disk:: DirEntry > ( ) ,
678
- MaybeUninit :: slice_as_bytes_mut ( & mut name) ,
679
- )
680
- . ok ( ) ?;
694
+ // SAFETY: We have initialized the current block above.
695
+ let entry = unsafe {
696
+ & mut * self
697
+ . current_block
698
+ . as_mut_ptr ( )
699
+ . add ( block_offset)
700
+ . cast :: < disk:: DirEntry > ( )
701
+ } ;
681
702
682
- // SAFETY: We have initialized the name above.
683
- let name = unsafe { name . assume_init ( ) } ;
684
- let name = unsafe { core :: str :: from_utf8_unchecked ( & name ) } ;
703
+ if !entry . is_used ( ) {
704
+ return None ;
705
+ }
685
706
686
707
self . offset += entry. entry_size as usize ;
687
- Some ( ( name . to_string ( ) , entry) )
708
+ Some ( entry)
688
709
}
689
710
}
690
711
@@ -747,6 +768,6 @@ impl FileSystem for Ext2 {
747
768
. find_inode ( Ext2 :: ROOT_INODE_ID , None )
748
769
. expect ( "ext2: invalid filesystem (root inode not found)" ) ;
749
770
750
- DirEntry :: new_root ( inode, String :: from ( "/" ) )
771
+ inode :: DirEntry :: new_root ( inode, String :: from ( "/" ) )
751
772
}
752
773
}
0 commit comments