@@ -43,7 +43,7 @@ use super::cache::{DirCacheItem, INodeCacheItem};
4343use super :: path:: PathBuf ;
4444use super :: { cache, FileSystemError , Path } ;
4545
46- use super :: inode:: { DirEntry , INodeInterface , Metadata , PollFlags , PollTable } ;
46+ use super :: inode:: { self , INodeInterface , Metadata , PollFlags , PollTable } ;
4747use super :: FileSystem ;
4848
4949pub struct INode {
@@ -301,6 +301,7 @@ impl INode {
301301 entry. entry_size = block_size as _ ;
302302 entry. inode = inode. id as _ ;
303303 entry. file_type = file_type;
304+ // JSDJFKDSJFHJK CHECK THIS this is ub
304305 entry. set_name ( name) ;
305306 }
306307
@@ -314,7 +315,7 @@ impl INode {
314315 return Err ( FileSystemError :: NotDirectory ) ;
315316 }
316317
317- if DirEntryIter :: new ( self . sref ( ) ) . any ( |( e , _ ) | e == name) {
318+ if DirEntryIter :: new ( self . sref ( ) ) . any ( |entry| entry . name ( ) == name) {
318319 return Err ( FileSystemError :: EntryExists ) ;
319320 }
320321
@@ -349,7 +350,7 @@ impl INode {
349350 entry : & disk:: DirEntry ,
350351 ) -> Option < DirCacheItem > {
351352 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 ( ) ) )
353354 }
354355
355356 pub fn sref ( & self ) -> Arc < INode > {
@@ -410,19 +411,19 @@ impl INodeInterface for INode {
410411 }
411412
412413 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) )
415416 } else {
416417 Ok ( None )
417418 }
418419 }
419420
420421 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)
423424 . ok_or ( FileSystemError :: EntryNotFound ) ?;
424425
425- Ok ( self . make_dirent ( parent, & name, & entry) . unwrap ( ) )
426+ Ok ( self . make_dirent ( parent, entry . name ( ) , entry) . unwrap ( ) )
426427 }
427428
428429 fn read_at ( & self , offset : usize , usr_buffer : & mut [ u8 ] ) -> super :: Result < usize > {
@@ -456,7 +457,7 @@ impl INodeInterface for INode {
456457 fn rename ( & self , old : DirCacheItem , dest : & str ) -> super :: Result < ( ) > {
457458 assert ! ( self . metadata( ) ?. is_directory( ) ) ;
458459
459- if DirEntryIter :: new ( self . sref ( ) ) . any ( |( name , _ ) | name == dest) {
460+ if DirEntryIter :: new ( self . sref ( ) ) . any ( |entry| entry . name ( ) == dest) {
460461 return Err ( FileSystemError :: EntryExists ) ;
461462 }
462463
@@ -504,7 +505,7 @@ impl INodeInterface for INode {
504505 }
505506
506507 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 ( ) ) )
508509 }
509510
510511 fn mkdir ( & self , name : & str ) -> super :: Result < INodeCacheItem > {
@@ -645,46 +646,66 @@ impl INodeInterface for INode {
645646 }
646647}
647648
648- pub struct DirEntryIter {
649+ pub struct DirEntryIter < ' a > {
649650 inode : Arc < INode > ,
650651 offset : usize ,
652+
653+ current_block : Box < [ MaybeUninit < u8 > ] > ,
654+ block_size : usize ,
655+ _phantom : core:: marker:: PhantomData < & ' a disk:: DirEntry > ,
651656}
652657
653- impl DirEntryIter {
658+ impl < ' a > DirEntryIter < ' a > {
654659 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+ }
656671 }
657672}
658673
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 ;
661676
662677 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.
663681 let file_size = self . inode . inode . read ( ) . size ( ) ;
664682
665683 if self . offset + core:: mem:: size_of :: < disk:: DirEntry > ( ) > file_size {
666684 return None ;
667685 }
668686
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 ( ) ;
672692 }
673693
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+ } ;
681702
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+ }
685706
686707 self . offset += entry. entry_size as usize ;
687- Some ( ( name . to_string ( ) , entry) )
708+ Some ( entry)
688709 }
689710}
690711
@@ -747,6 +768,6 @@ impl FileSystem for Ext2 {
747768 . find_inode ( Ext2 :: ROOT_INODE_ID , None )
748769 . expect ( "ext2: invalid filesystem (root inode not found)" ) ;
749770
750- DirEntry :: new_root ( inode, String :: from ( "/" ) )
771+ inode :: DirEntry :: new_root ( inode, String :: from ( "/" ) )
751772 }
752773}
0 commit comments