@@ -12,7 +12,7 @@ use crate::{
1212} ;
1313use byteorder:: { ByteOrder , LittleEndian } ;
1414use core:: convert:: TryFrom ;
15- use heapless:: String ;
15+ use heapless:: { String , Vec } ;
1616
1717/// An MS-DOS 11 character volume label.
1818///
@@ -615,8 +615,9 @@ impl FatVolume {
615615 _ => Some ( dir_info. cluster ) ,
616616 } ;
617617
618- let mut lfn_buffer = [ [ ' ' ; 13 ] ; 8 ] ;
619- let mut lfn_pointer = 0 ;
618+ let mut lfn_stack = Vec :: < String < 32 > , 8 > :: new ( ) ;
619+ let mut current_checksum: Option < u8 > = None ;
620+ let mut current_sequence: Option < u8 > = None ;
620621
621622 while let Some ( cluster) = current_cluster {
622623 let start_block_idx = self . cluster_to_block ( cluster) ;
@@ -630,26 +631,50 @@ impl FatVolume {
630631 return Ok ( ( ) ) ;
631632 } else if dir_entry. is_valid ( ) {
632633 if dir_entry. is_lfn ( ) {
633- if let Some ( ( _, _, data) ) = dir_entry. lfn_contents ( ) {
634- lfn_buffer[ lfn_pointer] = data. clone ( ) ;
635- lfn_pointer += 1 ;
634+ if let Some ( ( is_start, sequence, data, checksum) ) =
635+ dir_entry. lfn_contents ( )
636+ {
637+ // Case for malformed LFN entries, if they ale placed before
638+ // actual entries
639+ let checksum_ok = match current_checksum {
640+ Some ( c) => c == checksum,
641+ None => true ,
642+ } ;
643+ let sequence_ok = match current_sequence {
644+ Some ( s) => sequence == s - 1 && sequence < 8 ,
645+ None => true ,
646+ } ;
647+ if is_start || !checksum_ok || !sequence_ok {
648+ lfn_stack. clear ( ) ;
649+ current_checksum = None ;
650+ current_sequence = None ;
651+ } else {
652+ current_checksum = Some ( checksum) ;
653+ current_sequence = Some ( sequence) ;
654+ }
655+
656+ let mut name_chunk: String < 32 > = String :: new ( ) ;
657+ for i in 0 ..13 {
658+ if data[ i] == '\0' {
659+ break ;
660+ }
661+ name_chunk. push ( data[ i] ) . unwrap ( ) ;
662+ }
663+ lfn_stack. push ( name_chunk) . unwrap ( ) ;
636664 }
637665 } else {
638- if lfn_pointer > 0 {
666+ if !lfn_stack . is_empty ( ) {
639667 let mut filename: String < 255 > = String :: new ( ) ;
640- while lfn_pointer > 0 {
641- lfn_pointer -= 1 ;
642- for i in 0 ..13 {
643- // This will only happen on last chunk after last
644- // character, so simple break is enough
645- if lfn_buffer[ lfn_pointer] [ i] == '\0' {
646- break ;
647- } else {
648- filename. push ( lfn_buffer[ lfn_pointer] [ i] ) ;
649- }
650- }
668+ lfn_stack. reverse ( ) ;
669+ for name_chunk in lfn_stack. iter ( ) {
670+ filename. push_str ( name_chunk) . unwrap ( ) ;
651671 }
652672 }
673+
674+ lfn_stack. clear ( ) ;
675+ current_checksum = None ;
676+ current_sequence = None ;
677+ // TODO calculate checksum and compare with shorf file name
653678 // Safe, since Block::LEN always fits on a u32
654679 let start = ( i * OnDiskDirEntry :: LEN ) as u32 ;
655680 let entry = dir_entry. get_entry ( FatType :: Fat32 , block_idx, start) ;
0 commit comments