@@ -440,86 +440,38 @@ where
440
440
}
441
441
}
442
442
443
- /// Open a file with the given full path . A file can only be opened once.
444
- pub fn open_file_in_dir (
443
+ /// Open a file from DirEntry. This is obtained by calling iterate_dir . A file can only be opened once.
444
+ pub fn open_dir_entry (
445
445
& mut self ,
446
446
volume : & mut Volume ,
447
- dir : & Directory ,
448
- name : & str ,
447
+ dir_entry : DirEntry ,
449
448
mode : Mode ,
450
449
) -> Result < File , Error < D :: Error > > {
451
- // Find a free directory entry
452
- let mut open_files_row = None ;
453
- for ( i , d ) in self . open_files . iter ( ) . enumerate ( ) {
454
- if d . 1 == Cluster :: INVALID {
455
- open_files_row = Some ( i ) ;
450
+ let open_files_row = self . get_open_files_row ( ) ? ;
451
+ // Check it's not already open
452
+ for dir_table_row in self . open_files . iter ( ) {
453
+ if * dir_table_row == ( volume . idx , dir_entry . cluster ) {
454
+ return Err ( Error :: DirAlreadyOpen ) ;
456
455
}
457
456
}
458
- let open_files_row = open_files_row. ok_or ( Error :: TooManyOpenDirs ) ?;
459
- let dir_entry = match & volume. volume_type {
460
- VolumeType :: Fat ( fat) => fat. find_directory_entry ( self , dir, name) ,
461
- } ;
462
-
463
- let dir_entry = match dir_entry {
464
- Ok ( entry) => Some ( entry) ,
465
- Err ( _)
466
- if ( mode == Mode :: ReadWriteCreate )
467
- | ( mode == Mode :: ReadWriteCreateOrTruncate )
468
- | ( mode == Mode :: ReadWriteCreateOrAppend ) =>
469
- {
470
- None
471
- }
472
- _ => return Err ( Error :: FileNotFound ) ,
473
- } ;
474
-
475
- if let Some ( entry) = & dir_entry {
476
- // Check it's not already open
477
- for dir_table_row in self . open_files . iter ( ) {
478
- if * dir_table_row == ( volume. idx , entry. cluster ) {
479
- return Err ( Error :: DirAlreadyOpen ) ;
480
- }
481
- }
482
- if entry. attributes . is_directory ( ) {
483
- return Err ( Error :: OpenedDirAsFile ) ;
484
- }
485
- if entry. attributes . is_read_only ( ) && mode != Mode :: ReadOnly {
486
- return Err ( Error :: ReadOnly ) ;
487
- }
488
- } ;
489
-
490
- let mut mode = mode;
491
- if mode == Mode :: ReadWriteCreateOrAppend {
492
- if dir_entry. is_some ( ) {
493
- mode = Mode :: ReadWriteAppend ;
494
- } else {
495
- mode = Mode :: ReadWriteCreate ;
496
- }
497
- } else if mode == Mode :: ReadWriteCreateOrTruncate {
498
- if dir_entry. is_some ( ) {
499
- mode = Mode :: ReadWriteTruncate ;
500
- } else {
501
- mode = Mode :: ReadWriteCreate ;
502
- }
457
+ if dir_entry. attributes . is_directory ( ) {
458
+ return Err ( Error :: OpenedDirAsFile ) ;
459
+ }
460
+ if dir_entry. attributes . is_read_only ( ) && mode != Mode :: ReadOnly {
461
+ return Err ( Error :: ReadOnly ) ;
503
462
}
504
463
464
+ let mode = solve_mode_variant ( mode, true ) ;
505
465
let file = match mode {
506
- Mode :: ReadOnly => {
507
- // Safe to unwrap, since we actually have an entry if we got here
508
- let dir_entry = dir_entry. unwrap ( ) ;
509
-
510
- File {
511
- starting_cluster : dir_entry. cluster ,
512
- current_cluster : ( 0 , dir_entry. cluster ) ,
513
- current_offset : 0 ,
514
- length : dir_entry. size ,
515
- mode,
516
- entry : dir_entry,
517
- }
518
- }
466
+ Mode :: ReadOnly => File {
467
+ starting_cluster : dir_entry. cluster ,
468
+ current_cluster : ( 0 , dir_entry. cluster ) ,
469
+ current_offset : 0 ,
470
+ length : dir_entry. size ,
471
+ mode,
472
+ entry : dir_entry,
473
+ } ,
519
474
Mode :: ReadWriteAppend => {
520
- // Safe to unwrap, since we actually have an entry if we got here
521
- let dir_entry = dir_entry. unwrap ( ) ;
522
-
523
475
let mut file = File {
524
476
starting_cluster : dir_entry. cluster ,
525
477
current_cluster : ( 0 , dir_entry. cluster ) ,
@@ -533,9 +485,6 @@ where
533
485
file
534
486
}
535
487
Mode :: ReadWriteTruncate => {
536
- // Safe to unwrap, since we actually have an entry if we got here
537
- let dir_entry = dir_entry. unwrap ( ) ;
538
-
539
488
let mut file = File {
540
489
starting_cluster : dir_entry. cluster ,
541
490
current_cluster : ( 0 , dir_entry. cluster ) ,
@@ -560,6 +509,41 @@ where
560
509
561
510
file
562
511
}
512
+ _ => return Err ( Error :: Unsupported ) ,
513
+ } ;
514
+ // Remember this open file
515
+ self . open_files [ open_files_row] = ( volume. idx , file. starting_cluster ) ;
516
+ Ok ( file)
517
+ }
518
+
519
+ /// Open a file with the given full path. A file can only be opened once.
520
+ pub fn open_file_in_dir (
521
+ & mut self ,
522
+ volume : & mut Volume ,
523
+ dir : & Directory ,
524
+ name : & str ,
525
+ mode : Mode ,
526
+ ) -> Result < File , Error < D :: Error > > {
527
+ let dir_entry = match & volume. volume_type {
528
+ VolumeType :: Fat ( fat) => fat. find_directory_entry ( self , dir, name) ,
529
+ } ;
530
+
531
+ let open_files_row = self . get_open_files_row ( ) ?;
532
+ let dir_entry = match dir_entry {
533
+ Ok ( entry) => Some ( entry) ,
534
+ Err ( _)
535
+ if ( mode == Mode :: ReadWriteCreate )
536
+ | ( mode == Mode :: ReadWriteCreateOrTruncate )
537
+ | ( mode == Mode :: ReadWriteCreateOrAppend ) =>
538
+ {
539
+ None
540
+ }
541
+ _ => return Err ( Error :: FileNotFound ) ,
542
+ } ;
543
+
544
+ let mode = solve_mode_variant ( mode, dir_entry. is_some ( ) ) ;
545
+
546
+ match mode {
563
547
Mode :: ReadWriteCreate => {
564
548
if dir_entry. is_some ( ) {
565
549
return Err ( Error :: FileAlreadyExists ) ;
@@ -573,20 +557,36 @@ where
573
557
}
574
558
} ;
575
559
576
- File {
560
+ let file = File {
577
561
starting_cluster : entry. cluster ,
578
562
current_cluster : ( 0 , entry. cluster ) ,
579
563
current_offset : 0 ,
580
564
length : entry. size ,
581
565
mode,
582
566
entry,
583
- }
567
+ } ;
568
+ // Remember this open file
569
+ self . open_files [ open_files_row] = ( volume. idx , file. starting_cluster ) ;
570
+ Ok ( file)
584
571
}
585
- _ => return Err ( Error :: Unsupported ) ,
586
- } ;
587
- // Remember this open file
588
- self . open_files [ open_files_row] = ( volume. idx , file. starting_cluster ) ;
589
- Ok ( file)
572
+ _ => {
573
+ // Safe to unwrap, since we actually have an entry if we got here
574
+ let dir_entry = dir_entry. unwrap ( ) ;
575
+ self . open_dir_entry ( volume, dir_entry, mode)
576
+ }
577
+ }
578
+ }
579
+
580
+ /// Get the next entry in open_files list
581
+ fn get_open_files_row ( & self ) -> Result < usize , Error < D :: Error > > {
582
+ // Find a free directory entry
583
+ let mut open_files_row = None ;
584
+ for ( i, d) in self . open_files . iter ( ) . enumerate ( ) {
585
+ if d. 1 == Cluster :: INVALID {
586
+ open_files_row = Some ( i) ;
587
+ }
588
+ }
589
+ open_files_row. ok_or ( Error :: TooManyOpenDirs )
590
590
}
591
591
592
592
/// Read from an open file.
@@ -800,7 +800,25 @@ where
800
800
//
801
801
// ****************************************************************************
802
802
803
- // None
803
+ /// Transform mode variants (ReadWriteCreate_Or_Append) to simple modes ReadWriteAppend or
804
+ /// ReadWriteCreate
805
+ fn solve_mode_variant ( mode : Mode , dir_entry_is_some : bool ) -> Mode {
806
+ let mut mode = mode;
807
+ if mode == Mode :: ReadWriteCreateOrAppend {
808
+ if dir_entry_is_some {
809
+ mode = Mode :: ReadWriteAppend ;
810
+ } else {
811
+ mode = Mode :: ReadWriteCreate ;
812
+ }
813
+ } else if mode == Mode :: ReadWriteCreateOrTruncate {
814
+ if dir_entry_is_some {
815
+ mode = Mode :: ReadWriteTruncate ;
816
+ } else {
817
+ mode = Mode :: ReadWriteCreate ;
818
+ }
819
+ }
820
+ mode
821
+ }
804
822
805
823
// ****************************************************************************
806
824
//
0 commit comments