mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
fix(fatfs): fix a bug in SFN generation from LFN and rewrite to match C algorithm
Rewrite build_lfn_short_entry_name() and add _gen_numname_suffix() helper to match the gen_numname() algorithm in ff.c. This fixes: - chr(order) producing raw binary instead of ASCII digits - Collision for order >= 10 when str(order) makes the name exceed 8 chars - Hex suffix with dynamic stem shortening (matching C implementation) - CRC16-CCITT hash for seq > 5 to reduce collision probability Also fix LDIR_Name2_SIZE typo in long_filename_utils.py (should be LDIR_Name3_SIZE), which made the assertion guard too permissive. Add ShortFilenameGenerationTestCase with 9 unit tests covering single-digit, multi-digit, hash-based, and collision-free generation scenarios.
This commit is contained in:
@@ -53,7 +53,7 @@ def split_name_to_lfn_entry_blocks(name: str) -> List[bytes]:
|
||||
Notice that since every character is coded using 2 bytes be must add 0x00 to ASCII symbols ('G' -> 'G\x00', etc.),
|
||||
since character 'T' ends in the first block, we must add '\x00\x00' after 'T\x00'.
|
||||
"""
|
||||
max_entry_size: int = Entry.LDIR_Name1_SIZE + Entry.LDIR_Name2_SIZE + Entry.LDIR_Name2_SIZE
|
||||
max_entry_size: int = Entry.LDIR_Name1_SIZE + Entry.LDIR_Name2_SIZE + Entry.LDIR_Name3_SIZE
|
||||
assert len(name) <= max_entry_size
|
||||
blocks_: List[bytes] = [
|
||||
convert_to_utf16_and_pad(content=name[:Entry.LDIR_Name1_SIZE],
|
||||
@@ -68,10 +68,11 @@ def split_name_to_lfn_entry_blocks(name: str) -> List[bytes]:
|
||||
|
||||
def build_lfn_unique_entry_name_order(entities: list, lfn_entry_name: str) -> int:
|
||||
"""
|
||||
The short entry contains only the first 6 characters of the file name,
|
||||
and we have to distinguish it from other names within the directory starting with the same 6 characters.
|
||||
To make it unique, we add its order in relation to other names such that lfn_entry_name[:6] == other[:6].
|
||||
The order is specified by the character, starting with chr(1).
|
||||
The short entry contains only the first characters of the file name plus a '~' suffix
|
||||
with hexadecimal sequence number, matching the gen_numname() algorithm in ff.c.
|
||||
|
||||
For seq <= 5 the suffix is the decimal-looking hex digit (e.g. ~1 .. ~5).
|
||||
For seq > 5 a CRC hash is used instead (handled by build_lfn_short_entry_name).
|
||||
|
||||
E.g. the file in directory 'thisisverylongfilenama.txt' will be named 'THISIS~1TXT' in its short entry.
|
||||
If we add another file 'thisisverylongfilenamax.txt' its name in the short entry will be 'THISIS~2TXT'.
|
||||
|
||||
Reference in New Issue
Block a user