@@ -435,105 +435,130 @@ impl FatVolume {
435435 & self ,
436436 block_device : & D ,
437437 dir : & DirectoryInfo ,
438- mut func : F ,
438+ func : F ,
439439 ) -> Result < ( ) , Error < D :: Error > >
440440 where
441441 F : FnMut ( & DirEntry ) ,
442442 D : BlockDevice ,
443443 {
444444 match & self . fat_specific_info {
445445 FatSpecificInfo :: Fat16 ( fat16_info) => {
446- // Root directories on FAT16 have a fixed size, because they use
447- // a specially reserved space on disk (see
448- // `first_root_dir_block`). Other directories can have any size
449- // as they are made of regular clusters.
450- let mut current_cluster = Some ( dir. cluster ) ;
451- let mut first_dir_block_num = match dir. cluster {
452- ClusterId :: ROOT_DIR => self . lba_start + fat16_info. first_root_dir_block ,
453- _ => self . cluster_to_block ( dir. cluster ) ,
454- } ;
455- let dir_size = match dir. cluster {
456- ClusterId :: ROOT_DIR => {
457- let len_bytes =
458- u32:: from ( fat16_info. root_entries_count ) * OnDiskDirEntry :: LEN_U32 ;
459- BlockCount :: from_bytes ( len_bytes)
460- }
461- _ => BlockCount ( u32:: from ( self . blocks_per_cluster ) ) ,
462- } ;
446+ self . iterate_fat16 ( dir, fat16_info, block_device, func)
447+ }
448+ FatSpecificInfo :: Fat32 ( fat32_info) => {
449+ self . iterate_fat32 ( dir, fat32_info, block_device, func)
450+ }
451+ }
452+ }
463453
464- let mut block_cache = BlockCache :: empty ( ) ;
465- while let Some ( cluster) = current_cluster {
466- for block_idx in first_dir_block_num. range ( dir_size) {
467- let block = block_cache. read ( block_device, block_idx, "read_dir" ) ?;
468- for entry in 0 ..Block :: LEN / OnDiskDirEntry :: LEN {
469- let start = entry * OnDiskDirEntry :: LEN ;
470- let end = ( entry + 1 ) * OnDiskDirEntry :: LEN ;
471- let dir_entry = OnDiskDirEntry :: new ( & block[ start..end] ) ;
472- if dir_entry. is_end ( ) {
473- // Can quit early
474- return Ok ( ( ) ) ;
475- } else if dir_entry. is_valid ( ) && !dir_entry. is_lfn ( ) {
476- // Safe, since Block::LEN always fits on a u32
477- let start = u32:: try_from ( start) . unwrap ( ) ;
478- let entry = dir_entry. get_entry ( FatType :: Fat16 , block_idx, start) ;
479- func ( & entry) ;
480- }
481- }
482- }
483- if cluster != ClusterId :: ROOT_DIR {
484- current_cluster =
485- match self . next_cluster ( block_device, cluster, & mut block_cache) {
486- Ok ( n) => {
487- first_dir_block_num = self . cluster_to_block ( n) ;
488- Some ( n)
489- }
490- _ => None ,
491- } ;
492- } else {
493- current_cluster = None ;
454+ fn iterate_fat16 < D , F > (
455+ & self ,
456+ dir : & DirectoryInfo ,
457+ fat16_info : & Fat16Info ,
458+ block_device : & D ,
459+ mut func : F ,
460+ ) -> Result < ( ) , Error < D :: Error > >
461+ where
462+ F : FnMut ( & DirEntry ) ,
463+ D : BlockDevice ,
464+ {
465+ // Root directories on FAT16 have a fixed size, because they use
466+ // a specially reserved space on disk (see
467+ // `first_root_dir_block`). Other directories can have any size
468+ // as they are made of regular clusters.
469+ let mut current_cluster = Some ( dir. cluster ) ;
470+ let mut first_dir_block_num = match dir. cluster {
471+ ClusterId :: ROOT_DIR => self . lba_start + fat16_info. first_root_dir_block ,
472+ _ => self . cluster_to_block ( dir. cluster ) ,
473+ } ;
474+ let dir_size = match dir. cluster {
475+ ClusterId :: ROOT_DIR => {
476+ let len_bytes = u32:: from ( fat16_info. root_entries_count ) * OnDiskDirEntry :: LEN_U32 ;
477+ BlockCount :: from_bytes ( len_bytes)
478+ }
479+ _ => BlockCount ( u32:: from ( self . blocks_per_cluster ) ) ,
480+ } ;
481+
482+ let mut block_cache = BlockCache :: empty ( ) ;
483+ while let Some ( cluster) = current_cluster {
484+ for block_idx in first_dir_block_num. range ( dir_size) {
485+ let block = block_cache. read ( block_device, block_idx, "read_dir" ) ?;
486+ for entry in 0 ..Block :: LEN / OnDiskDirEntry :: LEN {
487+ let start = entry * OnDiskDirEntry :: LEN ;
488+ let end = ( entry + 1 ) * OnDiskDirEntry :: LEN ;
489+ let dir_entry = OnDiskDirEntry :: new ( & block[ start..end] ) ;
490+ if dir_entry. is_end ( ) {
491+ // Can quit early
492+ return Ok ( ( ) ) ;
493+ } else if dir_entry. is_valid ( ) && !dir_entry. is_lfn ( ) {
494+ // Safe, since Block::LEN always fits on a u32
495+ let start = u32:: try_from ( start) . unwrap ( ) ;
496+ let entry = dir_entry. get_entry ( FatType :: Fat16 , block_idx, start) ;
497+ func ( & entry) ;
494498 }
495499 }
496- Ok ( ( ) )
497500 }
498- FatSpecificInfo :: Fat32 ( fat32_info) => {
499- // All directories on FAT32 have a cluster chain but the root
500- // dir starts in a specified cluster.
501- let mut current_cluster = match dir. cluster {
502- ClusterId :: ROOT_DIR => Some ( fat32_info. first_root_dir_cluster ) ,
503- _ => Some ( dir. cluster ) ,
501+ if cluster != ClusterId :: ROOT_DIR {
502+ current_cluster = match self . next_cluster ( block_device, cluster, & mut block_cache) {
503+ Ok ( n) => {
504+ first_dir_block_num = self . cluster_to_block ( n) ;
505+ Some ( n)
506+ }
507+ _ => None ,
504508 } ;
505- let mut blocks = [ Block :: new ( ) ] ;
506- let mut block_cache = BlockCache :: empty ( ) ;
507- while let Some ( cluster) = current_cluster {
508- let block_idx = self . cluster_to_block ( cluster) ;
509- for block in block_idx. range ( BlockCount ( u32:: from ( self . blocks_per_cluster ) ) ) {
510- block_device
511- . read ( & mut blocks, block, "read_dir" )
512- . map_err ( Error :: DeviceError ) ?;
513- for entry in 0 ..Block :: LEN / OnDiskDirEntry :: LEN {
514- let start = entry * OnDiskDirEntry :: LEN ;
515- let end = ( entry + 1 ) * OnDiskDirEntry :: LEN ;
516- let dir_entry = OnDiskDirEntry :: new ( & blocks[ 0 ] [ start..end] ) ;
517- if dir_entry. is_end ( ) {
518- // Can quit early
519- return Ok ( ( ) ) ;
520- } else if dir_entry. is_valid ( ) && !dir_entry. is_lfn ( ) {
521- // Safe, since Block::LEN always fits on a u32
522- let start = u32:: try_from ( start) . unwrap ( ) ;
523- let entry = dir_entry. get_entry ( FatType :: Fat32 , block, start) ;
524- func ( & entry) ;
525- }
526- }
509+ } else {
510+ current_cluster = None ;
511+ }
512+ }
513+ Ok ( ( ) )
514+ }
515+
516+ fn iterate_fat32 < D , F > (
517+ & self ,
518+ dir : & DirectoryInfo ,
519+ fat32_info : & Fat32Info ,
520+ block_device : & D ,
521+ mut func : F ,
522+ ) -> Result < ( ) , Error < D :: Error > >
523+ where
524+ F : FnMut ( & DirEntry ) ,
525+ D : BlockDevice ,
526+ {
527+ // All directories on FAT32 have a cluster chain but the root
528+ // dir starts in a specified cluster.
529+ let mut current_cluster = match dir. cluster {
530+ ClusterId :: ROOT_DIR => Some ( fat32_info. first_root_dir_cluster ) ,
531+ _ => Some ( dir. cluster ) ,
532+ } ;
533+ let mut blocks = [ Block :: new ( ) ] ;
534+ let mut block_cache = BlockCache :: empty ( ) ;
535+ while let Some ( cluster) = current_cluster {
536+ let block_idx = self . cluster_to_block ( cluster) ;
537+ for block in block_idx. range ( BlockCount ( u32:: from ( self . blocks_per_cluster ) ) ) {
538+ block_device
539+ . read ( & mut blocks, block, "read_dir" )
540+ . map_err ( Error :: DeviceError ) ?;
541+ for entry in 0 ..Block :: LEN / OnDiskDirEntry :: LEN {
542+ let start = entry * OnDiskDirEntry :: LEN ;
543+ let end = ( entry + 1 ) * OnDiskDirEntry :: LEN ;
544+ let dir_entry = OnDiskDirEntry :: new ( & blocks[ 0 ] [ start..end] ) ;
545+ if dir_entry. is_end ( ) {
546+ // Can quit early
547+ return Ok ( ( ) ) ;
548+ } else if dir_entry. is_valid ( ) && !dir_entry. is_lfn ( ) {
549+ // Safe, since Block::LEN always fits on a u32
550+ let start = u32:: try_from ( start) . unwrap ( ) ;
551+ let entry = dir_entry. get_entry ( FatType :: Fat32 , block, start) ;
552+ func ( & entry) ;
527553 }
528- current_cluster =
529- match self . next_cluster ( block_device, cluster, & mut block_cache) {
530- Ok ( n) => Some ( n) ,
531- _ => None ,
532- } ;
533554 }
534- Ok ( ( ) )
535555 }
556+ current_cluster = match self . next_cluster ( block_device, cluster, & mut block_cache) {
557+ Ok ( n) => Some ( n) ,
558+ _ => None ,
559+ } ;
536560 }
561+ Ok ( ( ) )
537562 }
538563
539564 /// Get an entry from the given directory
0 commit comments