@@ -435,105 +435,130 @@ impl FatVolume {
435
435
& self ,
436
436
block_device : & D ,
437
437
dir : & DirectoryInfo ,
438
- mut func : F ,
438
+ func : F ,
439
439
) -> Result < ( ) , Error < D :: Error > >
440
440
where
441
441
F : FnMut ( & DirEntry ) ,
442
442
D : BlockDevice ,
443
443
{
444
444
match & self . fat_specific_info {
445
445
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
+ }
463
453
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) ;
494
498
}
495
499
}
496
- Ok ( ( ) )
497
500
}
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 ,
504
508
} ;
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) ;
527
553
}
528
- current_cluster =
529
- match self . next_cluster ( block_device, cluster, & mut block_cache) {
530
- Ok ( n) => Some ( n) ,
531
- _ => None ,
532
- } ;
533
554
}
534
- Ok ( ( ) )
535
555
}
556
+ current_cluster = match self . next_cluster ( block_device, cluster, & mut block_cache) {
557
+ Ok ( n) => Some ( n) ,
558
+ _ => None ,
559
+ } ;
536
560
}
561
+ Ok ( ( ) )
537
562
}
538
563
539
564
/// Get an entry from the given directory
0 commit comments