fix(fatfs): fix formatting in relevant python files to satisfy pre-commit check

This commit is contained in:
Adam Múdry
2026-04-13 15:59:49 +02:00
parent abea28451f
commit 033405abb6
4 changed files with 536 additions and 474 deletions
+156 -118
View File
@@ -1,26 +1,38 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
import os import os
from datetime import datetime from datetime import datetime
from typing import List, Optional, Tuple, Union
from .entry import Entry from .entry import Entry
from .exceptions import FatalError, WriteDirectoryException from .exceptions import FatalError
from .fat import FAT, Cluster from .exceptions import WriteDirectoryException
from .fat import FAT
from .fat import Cluster
from .fatfs_state import FATFSState from .fatfs_state import FATFSState
from .long_filename_utils import (build_lfn_full_name, build_lfn_unique_entry_name_order, from .long_filename_utils import build_lfn_full_name
get_required_lfn_entries_count, split_name_to_lfn_entries, from .long_filename_utils import build_lfn_unique_entry_name_order
split_name_to_lfn_entry_blocks) from .long_filename_utils import get_required_lfn_entries_count
from .utils import (DATETIME, INVALID_SFN_CHARS_PATTERN, MAX_EXT_SIZE, MAX_NAME_SIZE, FATDefaults, from .long_filename_utils import split_name_to_lfn_entries
build_lfn_short_entry_name, build_name, lfn_checksum, required_clusters_count, from .long_filename_utils import split_name_to_lfn_entry_blocks
split_content_into_sectors, split_to_name_and_extension) from .utils import DATETIME
from .utils import INVALID_SFN_CHARS_PATTERN
from .utils import MAX_EXT_SIZE
from .utils import MAX_NAME_SIZE
from .utils import FATDefaults
from .utils import build_lfn_short_entry_name
from .utils import build_name
from .utils import lfn_checksum
from .utils import required_clusters_count
from .utils import split_content_into_sectors
from .utils import split_to_name_and_extension
class File: class File:
""" """
The class File provides API to write into the files. It represents file in the FS. The class File provides API to write into the files. It represents file in the FS.
""" """
ATTR_ARCHIVE: int = 0x20 ATTR_ARCHIVE: int = 0x20
ENTITY_TYPE: int = ATTR_ARCHIVE ENTITY_TYPE: int = ATTR_ARCHIVE
@@ -30,7 +42,7 @@ class File:
self.fatfs_state: FATFSState = fatfs_state self.fatfs_state: FATFSState = fatfs_state
self.fat: FAT = fat self.fat: FAT = fat
self.size: int = 0 self.size: int = 0
self._first_cluster: Optional[Cluster] = None self._first_cluster: Cluster | None = None
self._entry: Entry = entry self._entry: Entry = entry
@property @property
@@ -38,7 +50,7 @@ class File:
return self._entry return self._entry
@property @property
def first_cluster(self) -> Optional[Cluster]: def first_cluster(self) -> Cluster | None:
return self._first_cluster return self._first_cluster
@first_cluster.setter @first_cluster.setter
@@ -59,7 +71,7 @@ class File:
raise FatalError('No free space left!') raise FatalError('No free space left!')
address: int = current_cluster.cluster_data_address address: int = current_cluster.cluster_data_address
self.fatfs_state.binary_image[address: address + len(content_part)] = content_as_list self.fatfs_state.binary_image[address : address + len(content_part)] = content_as_list
current_cluster = current_cluster.next_cluster current_cluster = current_cluster.next_cluster
@@ -68,6 +80,7 @@ class Directory:
The Directory class provides API to add files and directories into the directory The Directory class provides API to add files and directories into the directory
and to find the file according to path and write it. and to find the file according to path and write it.
""" """
ATTR_DIRECTORY: int = 0x10 ATTR_DIRECTORY: int = 0x10
ATTR_ARCHIVE: int = 0x20 ATTR_ARCHIVE: int = 0x20
ENTITY_TYPE: int = ATTR_DIRECTORY ENTITY_TYPE: int = ATTR_DIRECTORY
@@ -75,16 +88,17 @@ class Directory:
CURRENT_DIRECTORY = '.' CURRENT_DIRECTORY = '.'
PARENT_DIRECTORY = '..' PARENT_DIRECTORY = '..'
def __init__(self, def __init__(
name, self,
fat, name: str,
fatfs_state, fat: FAT,
entry=None, fatfs_state: FATFSState,
cluster=None, entry: Entry | None = None,
size=None, cluster: Cluster | None = None,
extension='', size: int | None = None,
parent=None): extension: str = '',
# type: (str, FAT, FATFSState, Optional[Entry], Cluster, Optional[int], str, Directory) -> None parent: 'Directory | None' = None,
) -> None:
self.name: str = name self.name: str = name
self.fatfs_state: FATFSState = fatfs_state self.fatfs_state: FATFSState = fatfs_state
self.extension: str = extension self.extension: str = extension
@@ -97,8 +111,8 @@ class Directory:
self._first_cluster: Cluster = cluster self._first_cluster: Cluster = cluster
# entries will be initialized after the cluster allocation # entries will be initialized after the cluster allocation
self.entries: List[Entry] = [] self.entries: list[Entry] = []
self.entities: List[Union[File, Directory]] = [] # type: ignore self.entities: list[File | Directory] = [] # type: ignore
self._entry = entry # currently not in use (will use later for e.g. modification time, etc.) self._entry = entry # currently not in use (will use later for e.g. modification time, etc.)
@property @property
@@ -122,11 +136,11 @@ class Directory:
entries_count_: int = self.size // FATDefaults.ENTRY_SIZE entries_count_: int = self.size // FATDefaults.ENTRY_SIZE
return entries_count_ return entries_count_
def create_entries(self, cluster: Cluster) -> List[Entry]: def create_entries(self, cluster: Cluster) -> list[Entry]:
return [Entry(entry_id=i, return [
parent_dir_entries_address=cluster.cluster_data_address, Entry(entry_id=i, parent_dir_entries_address=cluster.cluster_data_address, fatfs_state=self.fatfs_state)
fatfs_state=self.fatfs_state) for i in range(self.entries_count)
for i in range(self.entries_count)] ]
def init_directory(self) -> None: def init_directory(self) -> None:
self.entries = self.create_entries(self._first_cluster) self.entries = self.create_entries(self._first_cluster)
@@ -137,10 +151,12 @@ class Directory:
# if the directory is not root we initialize the reference to itself and to the parent directory # if the directory is not root we initialize the reference to itself and to the parent directory
for dir_id, name_ in ((self, self.CURRENT_DIRECTORY), (self.parent, self.PARENT_DIRECTORY)): for dir_id, name_ in ((self, self.CURRENT_DIRECTORY), (self.parent, self.PARENT_DIRECTORY)):
new_dir_: Entry = self.find_free_entry() or self.chain_directory() new_dir_: Entry = self.find_free_entry() or self.chain_directory()
new_dir_.allocate_entry(first_cluster_id=dir_id.first_cluster.id, new_dir_.allocate_entry(
entity_name=name_, first_cluster_id=dir_id.first_cluster.id,
entity_extension='', entity_name=name_,
entity_type=dir_id.ENTITY_TYPE) entity_extension='',
entity_type=dir_id.ENTITY_TYPE,
)
def lookup_entity(self, object_name: str, extension: str): # type: ignore def lookup_entity(self, object_name: str, extension: str): # type: ignore
for entity in self.entities: for entity in self.entities:
@@ -149,7 +165,7 @@ class Directory:
return None return None
@staticmethod @staticmethod
def _is_end_of_path(path_as_list: List[str]) -> bool: def _is_end_of_path(path_as_list: list[str]) -> bool:
""" """
:param path_as_list: path split into the list :param path_as_list: path split into the list
@@ -168,7 +184,7 @@ class Directory:
return next_obj return next_obj
return self.recursive_search(path_as_list[1:], next_obj) return self.recursive_search(path_as_list[1:], next_obj)
def find_free_entry(self) -> Optional[Entry]: def find_free_entry(self) -> Entry | None:
for entry in self.entries: for entry in self.entries:
if entry.is_empty: if entry.is_empty:
return entry return entry
@@ -197,18 +213,21 @@ class Directory:
return free_entry return free_entry
@staticmethod @staticmethod
def allocate_long_name_object(free_entry, def allocate_long_name_object(
name, free_entry: Entry,
extension, name: str,
target_dir, extension: str,
free_cluster_id, target_dir: 'Directory',
entity_type, free_cluster_id: int,
date, entity_type: int,
time): date: DATETIME,
# type: (Entry, str, str, Directory, int, int, DATETIME, DATETIME) -> Entry time: DATETIME,
) -> Entry:
lfn_full_name: str = build_lfn_full_name(name, extension) lfn_full_name: str = build_lfn_full_name(name, extension)
lfn_unique_entry_order: int = build_lfn_unique_entry_name_order(target_dir.entities, name) lfn_unique_entry_order: int = build_lfn_unique_entry_name_order(target_dir.entities, name)
lfn_short_entry_name: str = build_lfn_short_entry_name(name, extension, lfn_unique_entry_order, lfn=lfn_full_name) lfn_short_entry_name: str = build_lfn_short_entry_name(
name, extension, lfn_unique_entry_order, lfn=lfn_full_name
)
checksum: int = lfn_checksum(lfn_short_entry_name) checksum: int = lfn_checksum(lfn_short_entry_name)
entries_count: int = get_required_lfn_entries_count(lfn_full_name) entries_count: int = get_required_lfn_entries_count(lfn_full_name)
@@ -216,24 +235,28 @@ class Directory:
split_names_reversed = list(reversed(list(enumerate(split_name_to_lfn_entries(lfn_full_name, entries_count))))) split_names_reversed = list(reversed(list(enumerate(split_name_to_lfn_entries(lfn_full_name, entries_count)))))
for i, name_split_to_entry in split_names_reversed: for i, name_split_to_entry in split_names_reversed:
order: int = i + 1 order: int = i + 1
blocks_: List[bytes] = split_name_to_lfn_entry_blocks(name_split_to_entry) blocks_: list[bytes] = split_name_to_lfn_entry_blocks(name_split_to_entry)
lfn_names: List[bytes] = list(map(lambda x: x.lower(), blocks_)) lfn_names: list[bytes] = list(map(lambda x: x.lower(), blocks_))
free_entry.allocate_entry(first_cluster_id=free_cluster_id, free_entry.allocate_entry(
entity_name=name, first_cluster_id=free_cluster_id,
entity_extension=extension, entity_name=name,
entity_type=entity_type, entity_extension=extension,
lfn_order=order, entity_type=entity_type,
lfn_names=lfn_names, lfn_order=order,
lfn_checksum_=checksum, lfn_names=lfn_names,
lfn_is_last=order == entries_count) lfn_checksum_=checksum,
lfn_is_last=order == entries_count,
)
free_entry = target_dir.find_free_entry() or target_dir.chain_directory() free_entry = target_dir.find_free_entry() or target_dir.chain_directory()
free_entry.allocate_entry(first_cluster_id=free_cluster_id, free_entry.allocate_entry(
entity_name=lfn_short_entry_name[:MAX_NAME_SIZE], first_cluster_id=free_cluster_id,
entity_extension=lfn_short_entry_name[MAX_NAME_SIZE:], entity_name=lfn_short_entry_name[:MAX_NAME_SIZE],
entity_type=entity_type, entity_extension=lfn_short_entry_name[MAX_NAME_SIZE:],
lfn_order=Entry.SHORT_ENTRY_LN, entity_type=entity_type,
date=date, lfn_order=Entry.SHORT_ENTRY_LN,
time=time) date=date,
time=time,
)
return free_entry return free_entry
@staticmethod @staticmethod
@@ -243,21 +266,22 @@ class Directory:
ret: bool = len(name) <= MAX_NAME_SIZE and len(extension) <= MAX_EXT_SIZE ret: bool = len(name) <= MAX_NAME_SIZE and len(extension) <= MAX_EXT_SIZE
return ret return ret
def allocate_object(self, def allocate_object(
name, self,
entity_type, name: str,
object_timestamp_, entity_type: int,
path_from_root=None, object_timestamp_: datetime,
extension='', path_from_root: list[str] | None = None,
is_empty=False): extension: str = '',
# type: (str, int, datetime, Optional[List[str]], str, bool) -> Tuple[Cluster, Entry, Directory] is_empty: bool = False,
) -> tuple[Cluster, Entry, 'Directory']:
""" """
Method finds the target directory in the path Method finds the target directory in the path
and allocates cluster (both the record in FAT and cluster in the data region) and allocates cluster (both the record in FAT and cluster in the data region)
and entry in the specified directory and entry in the specified directory
""" """
free_cluster: Optional[Cluster] = None free_cluster: Cluster | None = None
free_cluster_id = 0x00 free_cluster_id = 0x00
if not is_empty: if not is_empty:
free_cluster = self.fat.find_free_cluster() free_cluster = self.fat.find_free_cluster()
@@ -270,61 +294,74 @@ class Directory:
fatfs_time_ = (object_timestamp_.hour, object_timestamp_.minute, object_timestamp_.second) fatfs_time_ = (object_timestamp_.hour, object_timestamp_.minute, object_timestamp_.second)
if not self.fatfs_state.long_names_enabled or self._is_valid_sfn(name, extension): if not self.fatfs_state.long_names_enabled or self._is_valid_sfn(name, extension):
free_entry.allocate_entry(first_cluster_id=free_cluster_id, free_entry.allocate_entry(
entity_name=name, first_cluster_id=free_cluster_id,
entity_extension=extension, entity_name=name,
date=fatfs_date_, entity_extension=extension,
time=fatfs_time_, date=fatfs_date_,
fits_short=True, time=fatfs_time_,
entity_type=entity_type) fits_short=True,
entity_type=entity_type,
)
return free_cluster, free_entry, target_dir return free_cluster, free_entry, target_dir
return free_cluster, self.allocate_long_name_object(free_entry=free_entry, return (
name=name, free_cluster,
extension=extension, self.allocate_long_name_object(
target_dir=target_dir, free_entry=free_entry,
free_cluster_id=free_cluster_id, name=name,
entity_type=entity_type, extension=extension,
date=fatfs_date_, target_dir=target_dir,
time=fatfs_time_), target_dir free_cluster_id=free_cluster_id,
entity_type=entity_type,
date=fatfs_date_,
time=fatfs_time_,
),
target_dir,
)
def new_file(self, def new_file(
name: str, self,
extension: str, name: str,
path_from_root: Optional[List[str]], extension: str,
object_timestamp_: datetime, path_from_root: list[str] | None,
is_empty: bool) -> None: object_timestamp_: datetime,
free_cluster, free_entry, target_dir = self.allocate_object(name=name, is_empty: bool,
extension=extension, ) -> None:
entity_type=Directory.ATTR_ARCHIVE, free_cluster, free_entry, target_dir = self.allocate_object(
path_from_root=path_from_root, name=name,
object_timestamp_=object_timestamp_, extension=extension,
is_empty=is_empty) entity_type=Directory.ATTR_ARCHIVE,
path_from_root=path_from_root,
object_timestamp_=object_timestamp_,
is_empty=is_empty,
)
file: File = File(name=name, file: File = File(name=name, fat=self.fat, extension=extension, fatfs_state=self.fatfs_state, entry=free_entry)
fat=self.fat,
extension=extension,
fatfs_state=self.fatfs_state,
entry=free_entry)
file.first_cluster = free_cluster file.first_cluster = free_cluster
target_dir.entities.append(file) target_dir.entities.append(file)
def new_directory(self, name, parent, path_from_root, object_timestamp_): def new_directory(
# type: (str, Directory, Optional[List[str]], datetime) -> None self,
free_cluster, free_entry, target_dir = self.allocate_object(name=name, name: str,
entity_type=Directory.ATTR_DIRECTORY, parent: 'Directory',
path_from_root=path_from_root, path_from_root: list[str] | None,
object_timestamp_=object_timestamp_) object_timestamp_: datetime,
) -> None:
free_cluster, free_entry, target_dir = self.allocate_object(
name=name,
entity_type=Directory.ATTR_DIRECTORY,
path_from_root=path_from_root,
object_timestamp_=object_timestamp_,
)
directory: Directory = Directory(name=name, directory: Directory = Directory(
fat=self.fat, name=name, fat=self.fat, parent=parent, fatfs_state=self.fatfs_state, entry=free_entry
parent=parent, )
fatfs_state=self.fatfs_state,
entry=free_entry)
directory.first_cluster = free_cluster directory.first_cluster = free_cluster
directory.init_directory() directory.init_directory()
target_dir.entities.append(directory) target_dir.entities.append(directory)
def write_to_file(self, path: List[str], content: bytes) -> None: def write_to_file(self, path: list[str], content: bytes) -> None:
""" """
Writes to file existing in the directory structure. Writes to file existing in the directory structure.
@@ -335,8 +372,9 @@ class Directory:
""" """
entity_to_write: Entry = self.recursive_search(path, self) entity_to_write: Entry = self.recursive_search(path, self)
if isinstance(entity_to_write, File): if isinstance(entity_to_write, File):
clusters_cnt: int = required_clusters_count(cluster_size=self.fatfs_state.boot_sector_state.sector_size, clusters_cnt: int = required_clusters_count(
content=content) cluster_size=self.fatfs_state.boot_sector_state.sector_size, content=content
)
self.fat.allocate_chain(entity_to_write.first_cluster, clusters_cnt) self.fat.allocate_chain(entity_to_write.first_cluster, clusters_cnt)
entity_to_write.write(content) entity_to_write.write(content)
else: else:
@@ -1,10 +1,10 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
from typing import List
from .entry import Entry from .entry import Entry
from .exceptions import NoFreeClusterException from .exceptions import NoFreeClusterException
from .utils import build_name, convert_to_utf16_and_pad from .utils import build_name
from .utils import convert_to_utf16_and_pad
# File name with long filenames support can be as long as memory allows. It is split into entries # File name with long filenames support can be as long as memory allows. It is split into entries
# holding 13 characters of the filename, thus the number of required entries is ceil(len(long_name) / 13). # holding 13 characters of the filename, thus the number of required entries is ceil(len(long_name) / 13).
@@ -27,7 +27,7 @@ def get_required_lfn_entries_count(lfn_full_name: str) -> int:
return entries_count return entries_count
def split_name_to_lfn_entries(name: str, entries: int) -> List[str]: def split_name_to_lfn_entries(name: str, entries: int) -> list[str]:
""" """
If the filename is longer than 8 (name) + 3 (extension) characters, If the filename is longer than 8 (name) + 3 (extension) characters,
generator uses long name structure and splits the name into suitable amount of blocks. generator uses long name structure and splits the name into suitable amount of blocks.
@@ -35,10 +35,10 @@ def split_name_to_lfn_entries(name: str, entries: int) -> List[str]:
E.g. 'thisisverylongfilenama.txt' would be split to ['THISISVERYLON', 'GFILENAMA.TXT'], E.g. 'thisisverylongfilenama.txt' would be split to ['THISISVERYLON', 'GFILENAMA.TXT'],
in case of 'thisisverylongfilenamax.txt' - ['THISISVERYLON', 'GFILENAMAX.TX', 'T'] in case of 'thisisverylongfilenamax.txt' - ['THISISVERYLON', 'GFILENAMAX.TX', 'T']
""" """
return [name[i * Entry.CHARS_PER_ENTRY:(i + 1) * Entry.CHARS_PER_ENTRY] for i in range(entries)] return [name[i * Entry.CHARS_PER_ENTRY : (i + 1) * Entry.CHARS_PER_ENTRY] for i in range(entries)]
def split_name_to_lfn_entry_blocks(name: str) -> List[bytes]: def split_name_to_lfn_entry_blocks(name: str) -> list[bytes]:
""" """
Filename is divided into three blocks in every long file name entry. Sizes of the blocks are defined Filename is divided into three blocks in every long file name entry. Sizes of the blocks are defined
by LDIR_Name1_SIZE, LDIR_Name2_SIZE and LDIR_Name3_SIZE, thus every block contains LDIR_Name{X}_SIZE * 2 bytes. by LDIR_Name1_SIZE, LDIR_Name2_SIZE and LDIR_Name3_SIZE, thus every block contains LDIR_Name{X}_SIZE * 2 bytes.
@@ -55,13 +55,15 @@ def split_name_to_lfn_entry_blocks(name: str) -> List[bytes]:
""" """
max_entry_size: int = Entry.LDIR_Name1_SIZE + Entry.LDIR_Name2_SIZE + Entry.LDIR_Name3_SIZE max_entry_size: int = Entry.LDIR_Name1_SIZE + Entry.LDIR_Name2_SIZE + Entry.LDIR_Name3_SIZE
assert len(name) <= max_entry_size assert len(name) <= max_entry_size
blocks_: List[bytes] = [ blocks_: list[bytes] = [
convert_to_utf16_and_pad(content=name[:Entry.LDIR_Name1_SIZE], convert_to_utf16_and_pad(content=name[: Entry.LDIR_Name1_SIZE], expected_size=Entry.LDIR_Name1_SIZE),
expected_size=Entry.LDIR_Name1_SIZE), convert_to_utf16_and_pad(
convert_to_utf16_and_pad(content=name[Entry.LDIR_Name1_SIZE:Entry.LDIR_Name1_SIZE + Entry.LDIR_Name2_SIZE], content=name[Entry.LDIR_Name1_SIZE : Entry.LDIR_Name1_SIZE + Entry.LDIR_Name2_SIZE],
expected_size=Entry.LDIR_Name2_SIZE), expected_size=Entry.LDIR_Name2_SIZE,
convert_to_utf16_and_pad(content=name[Entry.LDIR_Name1_SIZE + Entry.LDIR_Name2_SIZE:], ),
expected_size=Entry.LDIR_Name3_SIZE) convert_to_utf16_and_pad(
content=name[Entry.LDIR_Name1_SIZE + Entry.LDIR_Name2_SIZE :], expected_size=Entry.LDIR_Name3_SIZE
),
] ]
return blocks_ return blocks_
+80 -78
View File
@@ -6,9 +6,6 @@ import os
import re import re
import uuid import uuid
from datetime import datetime from datetime import datetime
from typing import List
from typing import Optional
from typing import Tuple
from construct import BitsInteger from construct import BitsInteger
from construct import BitStruct from construct import BitStruct
@@ -32,7 +29,7 @@ BYTES_PER_DIRECTORY_ENTRY: int = 32
UINT32_MAX: int = (1 << 32) - 1 UINT32_MAX: int = (1 << 32) - 1
MAX_NAME_SIZE: int = 8 MAX_NAME_SIZE: int = 8
MAX_EXT_SIZE: int = 3 MAX_EXT_SIZE: int = 3
DATETIME = Tuple[int, int, int] DATETIME = tuple[int, int, int]
FATFS_INCEPTION_YEAR: int = 1980 FATFS_INCEPTION_YEAR: int = 1980
FATFS_INCEPTION: datetime = datetime(FATFS_INCEPTION_YEAR, 1, 1, 0, 0, 0, 0) FATFS_INCEPTION: datetime = datetime(FATFS_INCEPTION_YEAR, 1, 1, 0, 0, 0, 0)
@@ -53,13 +50,13 @@ SHORT_NAMES_ENCODING: str = 'utf-8'
# compatible with WL_SECTOR_SIZE # compatible with WL_SECTOR_SIZE
# choices for WL are WL_SECTOR_SIZE_512 and WL_SECTOR_SIZE_4096 # choices for WL are WL_SECTOR_SIZE_512 and WL_SECTOR_SIZE_4096
ALLOWED_WL_SECTOR_SIZES: List[int] = [512, 4096] ALLOWED_WL_SECTOR_SIZES: list[int] = [512, 4096]
ALLOWED_SECTOR_SIZES: List[int] = [512, 1024, 2048, 4096] ALLOWED_SECTOR_SIZES: list[int] = [512, 1024, 2048, 4096]
ALLOWED_SECTORS_PER_CLUSTER: List[int] = [1, 2, 4, 8, 16, 32, 64, 128] ALLOWED_SECTORS_PER_CLUSTER: list[int] = [1, 2, 4, 8, 16, 32, 64, 128]
def crc32(input_values: List[int], crc: int) -> int: def crc32(input_values: list[int], crc: int) -> int:
""" """
Name Polynomial Reversed? Init-value XOR-out Name Polynomial Reversed? Init-value XOR-out
crc32 0x104C11DB7 True 4294967295 (UINT32_MAX) 0xFFFFFFFF crc32 0x104C11DB7 True 4294967295 (UINT32_MAX) 0xFFFFFFFF
@@ -71,7 +68,9 @@ def number_of_clusters(number_of_sectors: int, sectors_per_cluster: int) -> int:
return number_of_sectors // sectors_per_cluster return number_of_sectors // sectors_per_cluster
def get_non_data_sectors_cnt(reserved_sectors_cnt: int, sectors_per_fat_cnt: int, fat_tables_cnt: int, root_dir_sectors_cnt: int) -> int: def get_non_data_sectors_cnt(
reserved_sectors_cnt: int, sectors_per_fat_cnt: int, fat_tables_cnt: int, root_dir_sectors_cnt: int
) -> int:
return reserved_sectors_cnt + sectors_per_fat_cnt * fat_tables_cnt + root_dir_sectors_cnt return reserved_sectors_cnt + sectors_per_fat_cnt * fat_tables_cnt + root_dir_sectors_cnt
@@ -90,7 +89,8 @@ def get_fat_sectors_count(clusters_count: int, sector_size: int) -> int:
# number of byte halves # number of byte halves
cluster_s: int = fatfs_type_ // 4 cluster_s: int = fatfs_type_ // 4
fat_size_bytes: int = ( fat_size_bytes: int = (
clusters_count * 2 + cluster_s) if fatfs_type_ == FAT16 else (clusters_count * 3 + 1) // 2 + cluster_s (clusters_count * 2 + cluster_s) if fatfs_type_ == FAT16 else (clusters_count * 3 + 1) // 2 + cluster_s
)
return (fat_size_bytes + sector_size - 1) // sector_size return (fat_size_bytes + sector_size - 1) // sector_size
@@ -103,7 +103,7 @@ def generate_4bytes_random() -> int:
return uuid.uuid4().int & 0xFFFFFFFF return uuid.uuid4().int & 0xFFFFFFFF
def pad_string(content: str, size: Optional[int] = None, pad: int = PAD_CHAR) -> str: def pad_string(content: str, size: int | None = None, pad: int = PAD_CHAR) -> str:
# cut string if longer and fill with pad character if shorter than size # cut string if longer and fill with pad character if shorter than size
return content.ljust(size or len(content), chr(pad))[:size] return content.ljust(size or len(content), chr(pad))[:size]
@@ -161,20 +161,18 @@ def lfn_checksum(short_entry_name: str) -> int:
for i in range(MAX_NAME_SIZE + MAX_EXT_SIZE): for i in range(MAX_NAME_SIZE + MAX_EXT_SIZE):
# operation is a right rotation on 8 bits (Python equivalent for unsigned char in C) # operation is a right rotation on 8 bits (Python equivalent for unsigned char in C)
checksum_result = (0x80 if checksum_result & 1 else 0x00) + (checksum_result >> 1) + ord(short_entry_name[i]) checksum_result = (0x80 if checksum_result & 1 else 0x00) + (checksum_result >> 1) + ord(short_entry_name[i])
checksum_result &= 0xff checksum_result &= 0xFF
return checksum_result return checksum_result
def convert_to_utf16_and_pad(content: str, def convert_to_utf16_and_pad(content: str, expected_size: int, pad: bytes = FULL_BYTE) -> bytes:
expected_size: int,
pad: bytes = FULL_BYTE) -> bytes:
# we need to get rid of the Byte order mark 0xfeff or 0xfffe, fatfs does not use it # we need to get rid of the Byte order mark 0xfeff or 0xfffe, fatfs does not use it
bom_utf16: bytes = b'\xfe\xff' bom_utf16: bytes = b'\xfe\xff'
encoded_content_utf16: bytes = content.encode(LONG_NAMES_ENCODING)[len(bom_utf16):] encoded_content_utf16: bytes = content.encode(LONG_NAMES_ENCODING)[len(bom_utf16) :]
return encoded_content_utf16.ljust(2 * expected_size, pad) return encoded_content_utf16.ljust(2 * expected_size, pad)
def split_to_name_and_extension(full_name: str) -> Tuple[str, str]: def split_to_name_and_extension(full_name: str) -> tuple[str, str]:
name, extension = os.path.splitext(full_name) name, extension = os.path.splitext(full_name)
return name, extension.replace('.', '') return name, extension.replace('.', '')
@@ -183,9 +181,9 @@ def is_valid_fatfs_name(string: str) -> bool:
return string == string.upper() return string == string.upper()
def split_by_half_byte_12_bit_little_endian(value: int) -> Tuple[int, int, int]: def split_by_half_byte_12_bit_little_endian(value: int) -> tuple[int, int, int]:
value_as_bytes: bytes = Int16ul.build(value) value_as_bytes: bytes = Int16ul.build(value)
return value_as_bytes[0] & 0x0f, value_as_bytes[0] >> 4, value_as_bytes[1] & 0x0f return value_as_bytes[0] & 0x0F, value_as_bytes[0] >> 4, value_as_bytes[1] & 0x0F
def merge_by_half_byte_12_bit_little_endian(v1: int, v2: int, v3: int) -> int: def merge_by_half_byte_12_bit_little_endian(v1: int, v2: int, v3: int) -> int:
@@ -196,65 +194,73 @@ def build_byte(first_half: int, second_half: int) -> int:
return (first_half << 4) | second_half return (first_half << 4) | second_half
def split_content_into_sectors(content: bytes, sector_size: int) -> List[bytes]: def split_content_into_sectors(content: bytes, sector_size: int) -> list[bytes]:
result = [] result = []
clusters_cnt: int = required_clusters_count(cluster_size=sector_size, content=content) clusters_cnt: int = required_clusters_count(cluster_size=sector_size, content=content)
for i in range(clusters_cnt): for i in range(clusters_cnt):
result.append(content[sector_size * i:(i + 1) * sector_size]) result.append(content[sector_size * i : (i + 1) * sector_size])
return result return result
def get_args_for_partition_generator(desc: str, wl: bool) -> argparse.Namespace: def get_args_for_partition_generator(desc: str, wl: bool) -> argparse.Namespace:
parser: argparse.ArgumentParser = argparse.ArgumentParser(description=desc) parser: argparse.ArgumentParser = argparse.ArgumentParser(description=desc)
parser.add_argument('input_directory', parser.add_argument('input_directory', help='Path to the directory that will be encoded into fatfs image')
help='Path to the directory that will be encoded into fatfs image') parser.add_argument('--output_file', default='fatfs_image.img', help='Filename of the generated fatfs image')
parser.add_argument('--output_file', parser.add_argument(
default='fatfs_image.img', '--partition_size',
help='Filename of the generated fatfs image') default=FATDefaults.SIZE,
parser.add_argument('--partition_size', help='Size of the partition in bytes.'
default=FATDefaults.SIZE, + ('' if wl else ' Use `--partition_size detect` for detecting the minimal partition size.'),
help='Size of the partition in bytes.' + )
('' if wl else ' Use `--partition_size detect` for detecting the minimal partition size.') parser.add_argument(
) '--sector_size',
parser.add_argument('--sector_size', default=FATDefaults.SECTOR_SIZE,
default=FATDefaults.SECTOR_SIZE, type=int,
type=int, choices=ALLOWED_WL_SECTOR_SIZES if wl else ALLOWED_SECTOR_SIZES,
choices=ALLOWED_WL_SECTOR_SIZES if wl else ALLOWED_SECTOR_SIZES, help='Size of the partition in bytes',
help='Size of the partition in bytes') )
parser.add_argument('--sectors_per_cluster', parser.add_argument(
default=1, '--sectors_per_cluster',
type=int, default=1,
choices=ALLOWED_SECTORS_PER_CLUSTER, type=int,
help='Number of sectors per cluster') choices=ALLOWED_SECTORS_PER_CLUSTER,
parser.add_argument('--root_entry_count', help='Number of sectors per cluster',
default=FATDefaults.ROOT_ENTRIES_COUNT, )
help='Number of entries in the root directory') parser.add_argument(
parser.add_argument('--long_name_support', '--root_entry_count', default=FATDefaults.ROOT_ENTRIES_COUNT, help='Number of entries in the root directory'
action='store_true', )
help='Set flag to enable long names support.') parser.add_argument('--long_name_support', action='store_true', help='Set flag to enable long names support.')
parser.add_argument('--use_default_datetime', parser.add_argument(
action='store_true', '--use_default_datetime',
help='For test purposes. If the flag is set the files are created with ' action='store_true',
'the default timestamp that is the 1st of January 1980') help='For test purposes. If the flag is set the files are created with '
parser.add_argument('--fat_type', 'the default timestamp that is the 1st of January 1980',
default=0, )
type=int, parser.add_argument(
choices=[FAT12, FAT16, 0], '--fat_type',
help=""" default=0,
type=int,
choices=[FAT12, FAT16, 0],
help="""
Type of the FAT file-system. Select '12' for FAT12, '16' for FAT16. Type of the FAT file-system. Select '12' for FAT12, '16' for FAT16.
Leave unset or select 0 for automatic file-system type detection. Leave unset or select 0 for automatic file-system type detection.
""") """,
parser.add_argument('--fat_count', )
default=FATDefaults.FAT_TABLES_COUNT, parser.add_argument(
type=int, '--fat_count',
choices=[1, 2], default=FATDefaults.FAT_TABLES_COUNT,
help='Number of file allocation tables (FATs) in the filesystem.') type=int,
parser.add_argument('--wl_mode', choices=[1, 2],
default=None, help='Number of file allocation tables (FATs) in the filesystem.',
type=str, )
choices=['safe', 'perf'], parser.add_argument(
help='Wear levelling mode to use. Safe or performance. Only for sector size of 512') '--wl_mode',
default=None,
type=str,
choices=['safe', 'perf'],
help='Wear levelling mode to use. Safe or performance. Only for sector size of 512',
)
args = parser.parse_args() args = parser.parse_args()
if args.fat_type == 0: if args.fat_type == 0:
@@ -275,10 +281,7 @@ def read_filesystem(path: str) -> bytearray:
return bytearray(fs_file.read()) return bytearray(fs_file.read())
DATE_ENTRY = BitStruct( DATE_ENTRY = BitStruct('year' / BitsInteger(7), 'month' / BitsInteger(4), 'day' / BitsInteger(5))
'year' / BitsInteger(7),
'month' / BitsInteger(4),
'day' / BitsInteger(5))
TIME_ENTRY = BitStruct( TIME_ENTRY = BitStruct(
'hour' / BitsInteger(5), 'hour' / BitsInteger(5),
@@ -318,9 +321,8 @@ def build_time_entry(hour: int, minute: int, sec: int) -> int:
assert hour in range(FATFS_MAX_HOURS) assert hour in range(FATFS_MAX_HOURS)
assert minute in range(FATFS_MAX_MINUTES) assert minute in range(FATFS_MAX_MINUTES)
assert sec in range(FATFS_MAX_SECONDS) assert sec in range(FATFS_MAX_SECONDS)
return int.from_bytes(TIME_ENTRY.build( return int.from_bytes(
dict(hour=hour, minute=minute, second=sec // FATFS_SECONDS_GRANULARITY)), TIME_ENTRY.build(dict(hour=hour, minute=minute, second=sec // FATFS_SECONDS_GRANULARITY)), byteorder='big'
byteorder='big'
) )
@@ -333,14 +335,14 @@ class FATDefaults:
SECTOR_SIZE: int = 0x1000 SECTOR_SIZE: int = 0x1000
HIDDEN_SECTORS: int = 0 HIDDEN_SECTORS: int = 0
ENTRY_SIZE: int = 32 ENTRY_SIZE: int = 32
NUM_HEADS: int = 0xff NUM_HEADS: int = 0xFF
OEM_NAME: str = 'MSDOS5.0' OEM_NAME: str = 'MSDOS5.0'
SEC_PER_TRACK: int = 0x3f SEC_PER_TRACK: int = 0x3F
VOLUME_LABEL: str = 'Espressif' VOLUME_LABEL: str = 'Espressif'
FILE_SYS_TYPE: str = 'FAT' FILE_SYS_TYPE: str = 'FAT'
ROOT_ENTRIES_COUNT: int = 512 # number of entries in the root directory, recommended 512 ROOT_ENTRIES_COUNT: int = 512 # number of entries in the root directory, recommended 512
MEDIA_TYPE: int = 0xf8 MEDIA_TYPE: int = 0xF8
SIGNATURE_WORD: bytes = b'\x55\xAA' SIGNATURE_WORD: bytes = b'\x55\xaa'
# wear levelling defaults # wear levelling defaults
VERSION: int = 2 VERSION: int = 2
+285 -265
View File
@@ -6,9 +6,13 @@ import os
import shutil import shutil
import sys import sys
import unittest import unittest
from subprocess import STDOUT, check_output from subprocess import STDOUT
from subprocess import check_output
from test_utils import CFG, fill_sector, generate_test_dir_1, generate_test_dir_2 from test_utils import CFG
from test_utils import fill_sector
from test_utils import generate_test_dir_1
from test_utils import generate_test_dir_2
sys.path.append(os.path.join(os.path.dirname(__file__), '..')) sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import fatfsgen # noqa E402 # pylint: disable=C0413 import fatfsgen # noqa E402 # pylint: disable=C0413
@@ -46,7 +50,7 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000:0x300c], b'TESTFILE \x20') # check entry name and type self.assertEqual(file_system[0x3000:0x300C], b'TESTFILE \x20') # check entry name and type
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
def test_empty_file_sn_fat12_one_fat(self) -> None: def test_empty_file_sn_fat12_one_fat(self) -> None:
@@ -56,7 +60,7 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000:0x200c], b'TESTFILE \x20') # check entry name and type self.assertEqual(file_system[0x2000:0x200C], b'TESTFILE \x20') # check entry name and type
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
def test_directory_sn_fat12(self) -> None: def test_directory_sn_fat12(self) -> None:
@@ -65,10 +69,10 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000:0x300c], b'TESTFOLD \x10') # check entry name and type self.assertEqual(file_system[0x3000:0x300C], b'TESTFOLD \x10') # check entry name and type
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
self.assertEqual(file_system[0x7000:0x700c], b'. \x10') # reference to itself self.assertEqual(file_system[0x7000:0x700C], b'. \x10') # reference to itself
self.assertEqual(file_system[0x7020:0x702c], b'.. \x10') # reference to parent self.assertEqual(file_system[0x7020:0x702C], b'.. \x10') # reference to parent
def test_directory_sn_fat12_one_fat(self) -> None: def test_directory_sn_fat12_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs = fatfsgen.FATFS(fat_tables_cnt=1)
@@ -76,17 +80,17 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000:0x200c], b'TESTFOLD \x10') # check entry name and type self.assertEqual(file_system[0x2000:0x200C], b'TESTFOLD \x10') # check entry name and type
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
self.assertEqual(file_system[0x6000:0x600c], b'. \x10') # reference to itself self.assertEqual(file_system[0x6000:0x600C], b'. \x10') # reference to itself
self.assertEqual(file_system[0x6020:0x602c], b'.. \x10') # reference to parent self.assertEqual(file_system[0x6020:0x602C], b'.. \x10') # reference to parent
def test_empty_file_with_extension_sn_fat12(self) -> None: def test_empty_file_with_extension_sn_fat12(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs = fatfsgen.FATFS(fat_tables_cnt=2)
fatfs.create_file('TESTF', extension='TXT') fatfs.create_file('TESTF', extension='TXT')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000:0x300c], b'TESTF TXT\x20') # check entry name and type self.assertEqual(file_system[0x3000:0x300C], b'TESTF TXT\x20') # check entry name and type
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
def test_empty_file_with_extension_sn_fat12_one_fat(self) -> None: def test_empty_file_with_extension_sn_fat12_one_fat(self) -> None:
@@ -94,7 +98,7 @@ class FatFSGen(unittest.TestCase):
fatfs.create_file('TESTF', extension='TXT') fatfs.create_file('TESTF', extension='TXT')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000:0x200c], b'TESTF TXT\x20') # check entry name and type self.assertEqual(file_system[0x2000:0x200C], b'TESTF TXT\x20') # check entry name and type
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
def test_write_to_file_with_extension_sn_fat12(self) -> None: def test_write_to_file_with_extension_sn_fat12(self) -> None:
@@ -104,10 +108,10 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000:0x300c], b'WRITEF TXT\x20') # check entry name and type self.assertEqual(file_system[0x3000:0x300C], b'WRITEF TXT\x20') # check entry name and type
self.assertEqual(file_system[0x301a:0x3020], b'\x02\x00\x0b\x00\x00\x00') # check size and cluster ref self.assertEqual(file_system[0x301A:0x3020], b'\x02\x00\x0b\x00\x00\x00') # check size and cluster ref
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
self.assertEqual(file_system[0x7000:0x700f], b'testcontent\x00\x00\x00\x00') # check file content self.assertEqual(file_system[0x7000:0x700F], b'testcontent\x00\x00\x00\x00') # check file content
def test_write_to_file_with_extension_sn_fat12_one_fat(self) -> None: def test_write_to_file_with_extension_sn_fat12_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs = fatfsgen.FATFS(fat_tables_cnt=1)
@@ -116,10 +120,10 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000:0x200c], b'WRITEF TXT\x20') # check entry name and type self.assertEqual(file_system[0x2000:0x200C], b'WRITEF TXT\x20') # check entry name and type
self.assertEqual(file_system[0x201a:0x2020], b'\x02\x00\x0b\x00\x00\x00') # check size and cluster ref self.assertEqual(file_system[0x201A:0x2020], b'\x02\x00\x0b\x00\x00\x00') # check size and cluster ref
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
self.assertEqual(file_system[0x6000:0x600f], b'testcontent\x00\x00\x00\x00') # check file content self.assertEqual(file_system[0x6000:0x600F], b'testcontent\x00\x00\x00\x00') # check file content
def test_write_to_file_in_folder_sn_fat12(self) -> None: def test_write_to_file_in_folder_sn_fat12(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs = fatfsgen.FATFS(fat_tables_cnt=2)
@@ -129,13 +133,13 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000:0x300c], b'TESTFOLD \x10') self.assertEqual(file_system[0x3000:0x300C], b'TESTFOLD \x10')
self.assertEqual( self.assertEqual(
file_system[0x1000:0x1010], file_system[0x1000:0x1010], b'\xf8\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'\xf8\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') )
self.assertEqual(file_system[0x7040:0x7050], b'WRITEF TXT\x20\x00\x00\x00\x00') self.assertEqual(file_system[0x7040:0x7050], b'WRITEF TXT\x20\x00\x00\x00\x00')
self.assertEqual(file_system[0x705a:0x7060], b'\x03\x00\x0b\x00\x00\x00') self.assertEqual(file_system[0x705A:0x7060], b'\x03\x00\x0b\x00\x00\x00')
self.assertEqual(file_system[0x8000:0x800b], b'testcontent') # check file content self.assertEqual(file_system[0x8000:0x800B], b'testcontent') # check file content
def test_write_to_file_in_folder_sn_fat12_one_fat(self) -> None: def test_write_to_file_in_folder_sn_fat12_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs = fatfsgen.FATFS(fat_tables_cnt=1)
@@ -145,13 +149,13 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000:0x200c], b'TESTFOLD \x10') self.assertEqual(file_system[0x2000:0x200C], b'TESTFOLD \x10')
self.assertEqual( self.assertEqual(
file_system[0x1000:0x1010], file_system[0x1000:0x1010], b'\xf8\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'\xf8\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') )
self.assertEqual(file_system[0x6040:0x6050], b'WRITEF TXT\x20\x00\x00\x00\x00') self.assertEqual(file_system[0x6040:0x6050], b'WRITEF TXT\x20\x00\x00\x00\x00')
self.assertEqual(file_system[0x605a:0x6060], b'\x03\x00\x0b\x00\x00\x00') self.assertEqual(file_system[0x605A:0x6060], b'\x03\x00\x0b\x00\x00\x00')
self.assertEqual(file_system[0x7000:0x700b], b'testcontent') # check file content self.assertEqual(file_system[0x7000:0x700B], b'testcontent') # check file content
def test_cluster_setting_values(self) -> None: def test_cluster_setting_values(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs = fatfsgen.FATFS(fat_tables_cnt=2)
@@ -166,8 +170,8 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual( self.assertEqual(
file_system[0x1000:0x1010], file_system[0x1000:0x1010], b'\xf8\xff\xff\xe8\x43\x00\x05\xf0\xff\xff\x0f\x00\x00\x00\x00\x00'
b'\xf8\xff\xff\xe8\x43\x00\x05\xf0\xff\xff\x0f\x00\x00\x00\x00\x00') )
def test_full_sector_file(self) -> None: def test_full_sector_file(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs = fatfsgen.FATFS(fat_tables_cnt=2)
@@ -175,8 +179,8 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\xff\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x1000:0x100E], b'\xf8\xff\xff\xff\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7000: 0x8000], CFG['sector_size'] * b'a') self.assertEqual(file_system[0x7000:0x8000], CFG['sector_size'] * b'a')
def test_full_sector_file_one_fat(self) -> None: def test_full_sector_file_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs = fatfsgen.FATFS(fat_tables_cnt=1)
@@ -184,8 +188,8 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\xff\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x1000:0x100E], b'\xf8\xff\xff\xff\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6000: 0x7000], CFG['sector_size'] * b'a') self.assertEqual(file_system[0x6000:0x7000], CFG['sector_size'] * b'a')
def test_file_chaining(self) -> None: def test_file_chaining(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs = fatfsgen.FATFS(fat_tables_cnt=2)
@@ -193,8 +197,8 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\x03\xf0\xff\x00\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x1000:0x100E], b'\xf8\xff\xff\x03\xf0\xff\x00\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x8000: 0x9000], b'a' + (CFG['sector_size'] - 1) * b'\x00') self.assertEqual(file_system[0x8000:0x9000], b'a' + (CFG['sector_size'] - 1) * b'\x00')
def test_file_chaining_one_fat(self) -> None: def test_file_chaining_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs = fatfsgen.FATFS(fat_tables_cnt=1)
@@ -202,8 +206,8 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\x03\xf0\xff\x00\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x1000:0x100E], b'\xf8\xff\xff\x03\xf0\xff\x00\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7000: 0x8000], b'a' + (CFG['sector_size'] - 1) * b'\x00') self.assertEqual(file_system[0x7000:0x8000], b'a' + (CFG['sector_size'] - 1) * b'\x00')
def test_full_sector_folder(self) -> None: def test_full_sector_folder(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs = fatfsgen.FATFS(fat_tables_cnt=2)
@@ -214,8 +218,7 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later') fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x1000: 0x10d0], self.assertEqual(file_system[0x1000:0x10D0], b'\xf8\xff\xff\x82\xf0\xff' + 192 * b'\xff' + 10 * b'\x00')
b'\xf8\xff\xff\x82\xf0\xff' + 192 * b'\xff' + 10 * b'\x00')
self.assertEqual(file_system[0x86000:0x86005], b'later') self.assertEqual(file_system[0x86000:0x86005], b'later')
self.assertEqual(file_system[0x87000:0x87010], b'A126 \x00\x00\x00\x00') self.assertEqual(file_system[0x87000:0x87010], b'A126 \x00\x00\x00\x00')
self.assertEqual(file_system[0x87020:0x87030], b'A127 \x00\x00\x00\x00') self.assertEqual(file_system[0x87020:0x87030], b'A127 \x00\x00\x00\x00')
@@ -229,8 +232,7 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later') fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x1000: 0x10d0], self.assertEqual(file_system[0x1000:0x10D0], b'\xf8\xff\xff\x82\xf0\xff' + 192 * b'\xff' + 10 * b'\x00')
b'\xf8\xff\xff\x82\xf0\xff' + 192 * b'\xff' + 10 * b'\x00')
self.assertEqual(file_system[0x85000:0x85005], b'later') self.assertEqual(file_system[0x85000:0x85005], b'later')
self.assertEqual(file_system[0x86000:0x86010], b'A126 \x00\x00\x00\x00') self.assertEqual(file_system[0x86000:0x86010], b'A126 \x00\x00\x00\x00')
self.assertEqual(file_system[0x86020:0x86030], b'A127 \x00\x00\x00\x00') self.assertEqual(file_system[0x86020:0x86030], b'A127 \x00\x00\x00\x00')
@@ -239,14 +241,19 @@ class FatFSGen(unittest.TestCase):
fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs = fatfsgen.FATFS(fat_tables_cnt=2)
fatfs.create_directory('TESTFOLD') fatfs.create_directory('TESTFOLD')
fatfs.create_directory('TESTFOLL', path_from_root=['TESTFOLD']) fatfs.create_directory('TESTFOLL', path_from_root=['TESTFOLD'])
self.assertRaises(WriteDirectoryException, fatfs.write_content, path_from_root=['TESTFOLD', 'TESTFOLL'], self.assertRaises(
content=b'testcontent') WriteDirectoryException,
fatfs.write_content,
path_from_root=['TESTFOLD', 'TESTFOLL'],
content=b'testcontent',
)
def test_write_non_existing_file_in_folder_sn_fat12(self) -> None: def test_write_non_existing_file_in_folder_sn_fat12(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs = fatfsgen.FATFS(fat_tables_cnt=2)
fatfs.create_directory('TESTFOLD') fatfs.create_directory('TESTFOLD')
self.assertRaises(FileNotFoundError, fatfs.write_content, path_from_root=['TESTFOLD', 'AHOJ'], self.assertRaises(
content=b'testcontent') FileNotFoundError, fatfs.write_content, path_from_root=['TESTFOLD', 'AHOJ'], content=b'testcontent'
)
@staticmethod @staticmethod
def create_too_many_files() -> None: def create_too_many_files() -> None:
@@ -313,7 +320,7 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0xa000:0xa010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0xA000:0xA010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
def test_deep_structure_one_fat(self) -> None: def test_deep_structure_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs = fatfsgen.FATFS(fat_tables_cnt=1)
@@ -344,7 +351,7 @@ class FatFSGen(unittest.TestCase):
self.assertEqual(file_system[0x8040:0x8050], b'TESTFOLD \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x8040:0x8050], b'TESTFOLD \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x9040:0x9050], b'WRITEF TXT \x00\x00\x00\x00') self.assertEqual(file_system[0x9040:0x9050], b'WRITEF TXT \x00\x00\x00\x00')
self.assertEqual(file_system[0xa000:0xa010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0xA000:0xA010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
def test_same_name_deep_structure_one_fat(self) -> None: def test_same_name_deep_structure_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs = fatfsgen.FATFS(fat_tables_cnt=1)
@@ -374,8 +381,8 @@ class FatFSGen(unittest.TestCase):
self.assertEqual(file_system[0x7070:0x7080], b'!\x00!\x00\x00\x00\x00\x00!\x00\x05\x00\x0b\x00\x00\x00') self.assertEqual(file_system[0x7070:0x7080], b'!\x00!\x00\x00\x00\x00\x00!\x00\x05\x00\x0b\x00\x00\x00')
self.assertEqual(file_system[0x8040:0x8050], b'LASTFILE \x00\x00\x00\x00') self.assertEqual(file_system[0x8040:0x8050], b'LASTFILE \x00\x00\x00\x00')
self.assertEqual(file_system[0x9000:0x9010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x9000:0x9010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0xa000:0xa010], b'thisistest\n\x00\x00\x00\x00\x00') self.assertEqual(file_system[0xA000:0xA010], b'thisistest\n\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0xb000:0xb010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0xB000:0xB010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
def test_e2e_deep_folder_into_image_one_fat(self) -> None: def test_e2e_deep_folder_into_image_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs = fatfsgen.FATFS(fat_tables_cnt=1)
@@ -387,7 +394,7 @@ class FatFSGen(unittest.TestCase):
self.assertEqual(file_system[0x7040:0x7050], b'LASTFILE \x00\x00\x00\x00') self.assertEqual(file_system[0x7040:0x7050], b'LASTFILE \x00\x00\x00\x00')
self.assertEqual(file_system[0x8000:0x8010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x8000:0x8010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x9000:0x9010], b'thisistest\n\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x9000:0x9010], b'thisistest\n\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0xa000:0xa010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0xA000:0xA010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
def test_e2e_deep_folder_into_image_ext(self) -> None: def test_e2e_deep_folder_into_image_ext(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs = fatfsgen.FATFS(fat_tables_cnt=2)
@@ -400,9 +407,9 @@ class FatFSGen(unittest.TestCase):
self.assertEqual(file_system[0x8000:0x8010], b'. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x8000:0x8010], b'. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x8040:0x8050], b'LASTFILETXT \x00\x00\x00\x00') self.assertEqual(file_system[0x8040:0x8050], b'LASTFILETXT \x00\x00\x00\x00')
self.assertEqual(file_system[0x9000:0x9010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x9000:0x9010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0xa000:0xa010], b'thisistest\n\x00\x00\x00\x00\x00') self.assertEqual(file_system[0xA000:0xA010], b'thisistest\n\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0xb000:0xb010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0xB000:0xB010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0xc000:0xc009], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff') self.assertEqual(file_system[0xC000:0xC009], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff')
def test_e2e_deep_folder_into_image_ext_one_fat(self) -> None: def test_e2e_deep_folder_into_image_ext_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs = fatfsgen.FATFS(fat_tables_cnt=1)
@@ -416,8 +423,8 @@ class FatFSGen(unittest.TestCase):
self.assertEqual(file_system[0x7040:0x7050], b'LASTFILETXT \x00\x00\x00\x00') self.assertEqual(file_system[0x7040:0x7050], b'LASTFILETXT \x00\x00\x00\x00')
self.assertEqual(file_system[0x8000:0x8010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x8000:0x8010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x9000:0x9010], b'thisistest\n\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x9000:0x9010], b'thisistest\n\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0xa000:0xa010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0xA000:0xA010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0xb000:0xb009], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff') self.assertEqual(file_system[0xB000:0xB009], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff')
def test_empty_fat16(self) -> None: def test_empty_fat16(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2, size=17 * 1024 * 1024) fatfs = fatfsgen.FATFS(fat_tables_cnt=2, size=17 * 1024 * 1024)
@@ -438,8 +445,8 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\xff\x03\x00\xff\xff\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x1000:0x100E], b'\xf8\xff\xff\xff\x03\x00\xff\xff\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0xc000: 0xd000], b'a' + (CFG['sector_size'] - 1) * b'\x00') self.assertEqual(file_system[0xC000:0xD000], b'a' + (CFG['sector_size'] - 1) * b'\x00')
def test_chaining_fat16_one_fat(self) -> None: def test_chaining_fat16_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1, size=17 * 1024 * 1024) fatfs = fatfsgen.FATFS(fat_tables_cnt=1, size=17 * 1024 * 1024)
@@ -447,8 +454,8 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\xff\x03\x00\xff\xff\x00\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x1000:0x100E], b'\xf8\xff\xff\xff\x03\x00\xff\xff\x00\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x9000: 0xa000], b'a' + (CFG['sector_size'] - 1) * b'\x00') self.assertEqual(file_system[0x9000:0xA000], b'a' + (CFG['sector_size'] - 1) * b'\x00')
def test_full_sector_folder_fat16(self) -> None: def test_full_sector_folder_fat16(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2, size=17 * 1024 * 1024) fatfs = fatfsgen.FATFS(fat_tables_cnt=2, size=17 * 1024 * 1024)
@@ -459,11 +466,10 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later') fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x1000: 0x1110], self.assertEqual(file_system[0x1000:0x1110], b'\xf8\xff\xff\xff\x82\x00' + 258 * b'\xff' + 8 * b'\x00')
b'\xf8\xff\xff\xff\x82\x00' + 258 * b'\xff' + 8 * b'\x00') self.assertEqual(file_system[0x8A000:0x8A005], b'later')
self.assertEqual(file_system[0x8a000:0x8a005], b'later') self.assertEqual(file_system[0x8B000:0x8B010], b'A126 \x00\x00\x00\x00')
self.assertEqual(file_system[0x8b000:0x8b010], b'A126 \x00\x00\x00\x00') self.assertEqual(file_system[0x8B020:0x8B030], b'A127 \x00\x00\x00\x00')
self.assertEqual(file_system[0x8b020:0x8b030], b'A127 \x00\x00\x00\x00')
def test_full_sector_folder_fat16_one_fat(self) -> None: def test_full_sector_folder_fat16_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1, size=17 * 1024 * 1024) fatfs = fatfsgen.FATFS(fat_tables_cnt=1, size=17 * 1024 * 1024)
@@ -474,8 +480,7 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later') fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x1000: 0x1110], self.assertEqual(file_system[0x1000:0x1110], b'\xf8\xff\xff\xff\x82\x00' + 258 * b'\xff' + 8 * b'\x00')
b'\xf8\xff\xff\xff\x82\x00' + 258 * b'\xff' + 8 * b'\x00')
self.assertEqual(file_system[0x87000:0x87005], b'later') self.assertEqual(file_system[0x87000:0x87005], b'later')
self.assertEqual(file_system[0x88000:0x88010], b'A126 \x00\x00\x00\x00') self.assertEqual(file_system[0x88000:0x88010], b'A126 \x00\x00\x00\x00')
self.assertEqual(file_system[0x88020:0x88030], b'A127 \x00\x00\x00\x00') self.assertEqual(file_system[0x88020:0x88030], b'A127 \x00\x00\x00\x00')
@@ -485,14 +490,14 @@ class FatFSGen(unittest.TestCase):
fatfs.create_file('HELLO', extension='TXT') fatfs.create_file('HELLO', extension='TXT')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000: 0x3019], b'HELLO TXT \x18\x00\x00\x00!\x00!\x00\x00\x00\x00\x00!') self.assertEqual(file_system[0x3000:0x3019], b'HELLO TXT \x18\x00\x00\x00!\x00!\x00\x00\x00\x00\x00!')
def test_empty_lfn_short_name_one_fat(self) -> None: def test_empty_lfn_short_name_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True)
fatfs.create_file('HELLO', extension='TXT') fatfs.create_file('HELLO', extension='TXT')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000: 0x2019], b'HELLO TXT \x18\x00\x00\x00!\x00!\x00\x00\x00\x00\x00!') self.assertEqual(file_system[0x2000:0x2019], b'HELLO TXT \x18\x00\x00\x00!\x00!\x00\x00\x00\x00\x00!')
def test_lfn_short_name(self) -> None: def test_lfn_short_name(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True)
@@ -500,9 +505,9 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['HELLO.TXT'], content=b'this is a test') fatfs.write_content(path_from_root=['HELLO.TXT'], content=b'this is a test')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000: 0x3010], b'HELLO TXT \x18\x00\x00\x00') self.assertEqual(file_system[0x3000:0x3010], b'HELLO TXT \x18\x00\x00\x00')
self.assertEqual(file_system[0x3010: 0x3020], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00') self.assertEqual(file_system[0x3010:0x3020], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00')
self.assertEqual(file_system[0x7000: 0x7010], b'this is a test\x00\x00') self.assertEqual(file_system[0x7000:0x7010], b'this is a test\x00\x00')
def test_lfn_short_name_one_fat(self) -> None: def test_lfn_short_name_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True)
@@ -510,33 +515,33 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['HELLO.TXT'], content=b'this is a test') fatfs.write_content(path_from_root=['HELLO.TXT'], content=b'this is a test')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000: 0x2010], b'HELLO TXT \x18\x00\x00\x00') self.assertEqual(file_system[0x2000:0x2010], b'HELLO TXT \x18\x00\x00\x00')
self.assertEqual(file_system[0x2010: 0x2020], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00') self.assertEqual(file_system[0x2010:0x2020], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00')
self.assertEqual(file_system[0x6000: 0x6010], b'this is a test\x00\x00') self.assertEqual(file_system[0x6000:0x6010], b'this is a test\x00\x00')
def test_lfn_empty_name(self) -> None: def test_lfn_empty_name(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True)
fatfs.create_file('HELLOHELLOHELLO', extension='TXT') fatfs.create_file('HELLOHELLOHELLO', extension='TXT')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000: 0x3010], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xb3t\x00') self.assertEqual(file_system[0x3000:0x3010], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xb3t\x00')
self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x3012:0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x3020: 0x3030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00') self.assertEqual(file_system[0x3020:0x3030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00')
self.assertEqual(file_system[0x3030: 0x3040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') self.assertEqual(file_system[0x3030:0x3040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00')
self.assertEqual(file_system[0x3040: 0x3050], b'HELLOH~1TXT \x00\x00\x00\x00') self.assertEqual(file_system[0x3040:0x3050], b'HELLOH~1TXT \x00\x00\x00\x00')
self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x3050:0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
def test_lfn_empty_name_one_fat(self) -> None: def test_lfn_empty_name_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True)
fatfs.create_file('HELLOHELLOHELLO', extension='TXT') fatfs.create_file('HELLOHELLOHELLO', extension='TXT')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000: 0x2010], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xb3t\x00') self.assertEqual(file_system[0x2000:0x2010], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xb3t\x00')
self.assertEqual(file_system[0x2012: 0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x2012:0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x2020: 0x2030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00') self.assertEqual(file_system[0x2020:0x2030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00')
self.assertEqual(file_system[0x2030: 0x2040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') self.assertEqual(file_system[0x2030:0x2040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00')
self.assertEqual(file_system[0x2040: 0x2050], b'HELLOH~1TXT \x00\x00\x00\x00') self.assertEqual(file_system[0x2040:0x2050], b'HELLOH~1TXT \x00\x00\x00\x00')
self.assertEqual(file_system[0x2050: 0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x2050:0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
def test_lfn_plain_name(self) -> None: def test_lfn_plain_name(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True)
@@ -544,13 +549,13 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['HELLOHELLOHELLO.TXT'], content=b'this is a test') fatfs.write_content(path_from_root=['HELLOHELLOHELLO.TXT'], content=b'this is a test')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000: 0x3010], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xb3t\x00') self.assertEqual(file_system[0x3000:0x3010], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xb3t\x00')
self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x3012:0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x3020: 0x3030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00') self.assertEqual(file_system[0x3020:0x3030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00')
self.assertEqual(file_system[0x3030: 0x3040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') self.assertEqual(file_system[0x3030:0x3040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00')
self.assertEqual(file_system[0x3040: 0x3050], b'HELLOH~1TXT \x00\x00\x00\x00') self.assertEqual(file_system[0x3040:0x3050], b'HELLOH~1TXT \x00\x00\x00\x00')
self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00') self.assertEqual(file_system[0x3050:0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00')
self.assertEqual(file_system[0x7000: 0x7010], b'this is a test\x00\x00') self.assertEqual(file_system[0x7000:0x7010], b'this is a test\x00\x00')
def test_lfn_plain_name_one_fat(self) -> None: def test_lfn_plain_name_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True)
@@ -558,13 +563,13 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['HELLOHELLOHELLO.TXT'], content=b'this is a test') fatfs.write_content(path_from_root=['HELLOHELLOHELLO.TXT'], content=b'this is a test')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000: 0x2010], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xb3t\x00') self.assertEqual(file_system[0x2000:0x2010], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xb3t\x00')
self.assertEqual(file_system[0x2012: 0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x2012:0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x2020: 0x2030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00') self.assertEqual(file_system[0x2020:0x2030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00')
self.assertEqual(file_system[0x2030: 0x2040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') self.assertEqual(file_system[0x2030:0x2040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00')
self.assertEqual(file_system[0x2040: 0x2050], b'HELLOH~1TXT \x00\x00\x00\x00') self.assertEqual(file_system[0x2040:0x2050], b'HELLOH~1TXT \x00\x00\x00\x00')
self.assertEqual(file_system[0x2050: 0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00') self.assertEqual(file_system[0x2050:0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00')
self.assertEqual(file_system[0x6000: 0x6010], b'this is a test\x00\x00') self.assertEqual(file_system[0x6000:0x6010], b'this is a test\x00\x00')
def test_lfn_plain_name_no_ext(self) -> None: def test_lfn_plain_name_no_ext(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True)
@@ -572,13 +577,13 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['HELLOHELLOHELLO'], content=b'this is a test') fatfs.write_content(path_from_root=['HELLOHELLOHELLO'], content=b'this is a test')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000: 0x3010], b'Bl\x00o\x00\x00\x00\xff\xff\xff\xff\x0f\x00V\xff\xff') self.assertEqual(file_system[0x3000:0x3010], b'Bl\x00o\x00\x00\x00\xff\xff\xff\xff\x0f\x00V\xff\xff')
self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x3012:0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x3020: 0x3030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00Vh\x00') self.assertEqual(file_system[0x3020:0x3030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00Vh\x00')
self.assertEqual(file_system[0x3030: 0x3040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') self.assertEqual(file_system[0x3030:0x3040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00')
self.assertEqual(file_system[0x3040: 0x3050], b'HELLOH~1 \x00\x00\x00\x00') self.assertEqual(file_system[0x3040:0x3050], b'HELLOH~1 \x00\x00\x00\x00')
self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00') self.assertEqual(file_system[0x3050:0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00')
self.assertEqual(file_system[0x7000: 0x7010], b'this is a test\x00\x00') self.assertEqual(file_system[0x7000:0x7010], b'this is a test\x00\x00')
def test_lfn_plain_name_no_ext_one_fat(self) -> None: def test_lfn_plain_name_no_ext_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True)
@@ -586,13 +591,13 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['HELLOHELLOHELLO'], content=b'this is a test') fatfs.write_content(path_from_root=['HELLOHELLOHELLO'], content=b'this is a test')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000: 0x2010], b'Bl\x00o\x00\x00\x00\xff\xff\xff\xff\x0f\x00V\xff\xff') self.assertEqual(file_system[0x2000:0x2010], b'Bl\x00o\x00\x00\x00\xff\xff\xff\xff\x0f\x00V\xff\xff')
self.assertEqual(file_system[0x2012: 0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x2012:0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x2020: 0x2030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00Vh\x00') self.assertEqual(file_system[0x2020:0x2030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00Vh\x00')
self.assertEqual(file_system[0x2030: 0x2040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') self.assertEqual(file_system[0x2030:0x2040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00')
self.assertEqual(file_system[0x2040: 0x2050], b'HELLOH~1 \x00\x00\x00\x00') self.assertEqual(file_system[0x2040:0x2050], b'HELLOH~1 \x00\x00\x00\x00')
self.assertEqual(file_system[0x2050: 0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00') self.assertEqual(file_system[0x2050:0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00')
self.assertEqual(file_system[0x6000: 0x6010], b'this is a test\x00\x00') self.assertEqual(file_system[0x6000:0x6010], b'this is a test\x00\x00')
def test_lfn_short_entry_exception(self) -> None: def test_lfn_short_entry_exception(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True)
@@ -604,19 +609,19 @@ class FatFSGen(unittest.TestCase):
fatfs.create_file('HELLO', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) fatfs.create_file('HELLO', extension='TXT', path_from_root=['VERYLONGTESTFOLD'])
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000: 0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff') self.assertEqual(file_system[0x3000:0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff')
self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x3012:0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x3020: 0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00') self.assertEqual(file_system[0x3020:0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00')
self.assertEqual(file_system[0x3030: 0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') self.assertEqual(file_system[0x3030:0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00')
self.assertEqual(file_system[0x3040: 0x3050], b'VERYLO~1 \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x3040:0x3050], b'VERYLO~1 \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x3050:0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7000: 0x7010], b'. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x7000:0x7010], b'. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x7012: 0x7020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x7012:0x7020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7020: 0x7030], b'.. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x7020:0x7030], b'.. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x7030: 0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x7030:0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7040: 0x7050], b'HELLO TXT \x18\x00\x00\x00') self.assertEqual(file_system[0x7040:0x7050], b'HELLO TXT \x18\x00\x00\x00')
self.assertEqual(file_system[0x7050: 0x7060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x7050:0x7060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x00\x00\x00\x00')
def test_lfn_nested_empty_one_fat(self) -> None: def test_lfn_nested_empty_one_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True)
@@ -624,19 +629,19 @@ class FatFSGen(unittest.TestCase):
fatfs.create_file('HELLO', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) fatfs.create_file('HELLO', extension='TXT', path_from_root=['VERYLONGTESTFOLD'])
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000: 0x2010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff') self.assertEqual(file_system[0x2000:0x2010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff')
self.assertEqual(file_system[0x2012: 0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x2012:0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x2020: 0x2030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00') self.assertEqual(file_system[0x2020:0x2030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00')
self.assertEqual(file_system[0x2030: 0x2040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') self.assertEqual(file_system[0x2030:0x2040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00')
self.assertEqual(file_system[0x2040: 0x2050], b'VERYLO~1 \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x2040:0x2050], b'VERYLO~1 \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x2050: 0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x2050:0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6000: 0x6010], b'. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x6000:0x6010], b'. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x6012: 0x6020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x6012:0x6020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6020: 0x6030], b'.. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x6020:0x6030], b'.. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x6030: 0x6040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x6030:0x6040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6040: 0x6050], b'HELLO TXT \x18\x00\x00\x00') self.assertEqual(file_system[0x6040:0x6050], b'HELLO TXT \x18\x00\x00\x00')
self.assertEqual(file_system[0x6050: 0x6060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x6050:0x6060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x00\x00\x00\x00')
def test_lfn_nested_long_empty(self) -> None: def test_lfn_nested_long_empty(self) -> None:
fatfs: fatfsgen.fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) fatfs: fatfsgen.fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True)
@@ -645,20 +650,21 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000: 0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\x10\xff\xff') self.assertEqual(file_system[0x3000:0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\x10\xff\xff')
self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x3012:0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x3020: 0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\x10o\x00') self.assertEqual(file_system[0x3020:0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\x10o\x00')
self.assertEqual(file_system[0x3030: 0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') self.assertEqual(file_system[0x3030:0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00')
self.assertEqual(file_system[0x3040: 0x3050], b'verylo~1 \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x3040:0x3050], b'verylo~1 \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x3050:0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7000: 0x7010], b'. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x7000:0x7010], b'. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x7012: 0x7020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x7012:0x7020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7020: 0x7030], b'.. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x7020:0x7030], b'.. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x7030: 0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x7030:0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7040: 0x7050], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xd5t\x00') self.assertEqual(file_system[0x7040:0x7050], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xd5t\x00')
self.assertEqual(file_system[0x7050: 0x7060], self.assertEqual(
b'\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') file_system[0x7050:0x7060], b'\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff'
)
def test_lfn_nested_long_empty_one_fat(self) -> None: def test_lfn_nested_long_empty_one_fat(self) -> None:
fatfs: fatfsgen.FATFS = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs: fatfsgen.FATFS = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True)
@@ -667,20 +673,21 @@ class FatFSGen(unittest.TestCase):
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000: 0x2010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\x10\xff\xff') self.assertEqual(file_system[0x2000:0x2010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\x10\xff\xff')
self.assertEqual(file_system[0x2012: 0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x2012:0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x2020: 0x2030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\x10o\x00') self.assertEqual(file_system[0x2020:0x2030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\x10o\x00')
self.assertEqual(file_system[0x2030: 0x2040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') self.assertEqual(file_system[0x2030:0x2040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00')
self.assertEqual(file_system[0x2040: 0x2050], b'verylo~1 \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x2040:0x2050], b'verylo~1 \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x2050: 0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x2050:0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6000: 0x6010], b'. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x6000:0x6010], b'. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x6012: 0x6020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x6012:0x6020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6020: 0x6030], b'.. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x6020:0x6030], b'.. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x6030: 0x6040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x6030:0x6040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6040: 0x6050], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xd5t\x00') self.assertEqual(file_system[0x6040:0x6050], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xd5t\x00')
self.assertEqual(file_system[0x6050: 0x6060], self.assertEqual(
b'\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') file_system[0x6050:0x6060], b'\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff'
)
def test_lfn_nested_text(self) -> None: def test_lfn_nested_text(self) -> None:
fatfs: fatfsgen.fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) fatfs: fatfsgen.fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True)
@@ -689,21 +696,21 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLO.TXT'], content=b'this is a test') fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLO.TXT'], content=b'this is a test')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000: 0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff') self.assertEqual(file_system[0x3000:0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff')
self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x3012:0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x3020: 0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00') self.assertEqual(file_system[0x3020:0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00')
self.assertEqual(file_system[0x3030: 0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') self.assertEqual(file_system[0x3030:0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00')
self.assertEqual(file_system[0x3040: 0x3050], b'VERYLO~1 \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x3040:0x3050], b'VERYLO~1 \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x3050:0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7000: 0x7010], b'. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x7000:0x7010], b'. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x7012: 0x7020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x7012:0x7020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7020: 0x7030], b'.. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x7020:0x7030], b'.. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x7030: 0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x7030:0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7040: 0x7050], b'HELLO TXT \x18\x00\x00\x00') self.assertEqual(file_system[0x7040:0x7050], b'HELLO TXT \x18\x00\x00\x00')
self.assertEqual(file_system[0x7050: 0x7060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x0e\x00\x00\x00') self.assertEqual(file_system[0x7050:0x7060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x0e\x00\x00\x00')
self.assertEqual(file_system[0x8000: 0x8010], b'this is a test\x00\x00') self.assertEqual(file_system[0x8000:0x8010], b'this is a test\x00\x00')
def test_lfn_nested_text_one_fat(self) -> None: def test_lfn_nested_text_one_fat(self) -> None:
fatfs: fatfsgen.FATFS = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs: fatfsgen.FATFS = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True)
@@ -712,35 +719,37 @@ class FatFSGen(unittest.TestCase):
fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLO.TXT'], content=b'this is a test') fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLO.TXT'], content=b'this is a test')
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000: 0x2010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff') self.assertEqual(file_system[0x2000:0x2010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff')
self.assertEqual(file_system[0x2012: 0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x2012:0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x2020: 0x2030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00') self.assertEqual(file_system[0x2020:0x2030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00')
self.assertEqual(file_system[0x2030: 0x2040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') self.assertEqual(file_system[0x2030:0x2040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00')
self.assertEqual(file_system[0x2040: 0x2050], b'VERYLO~1 \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x2040:0x2050], b'VERYLO~1 \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x2050: 0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x2050:0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6000: 0x6010], b'. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x6000:0x6010], b'. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x6012: 0x6020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x6012:0x6020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6020: 0x6030], b'.. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x6020:0x6030], b'.. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x6030: 0x6040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x6030:0x6040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6040: 0x6050], b'HELLO TXT \x18\x00\x00\x00') self.assertEqual(file_system[0x6040:0x6050], b'HELLO TXT \x18\x00\x00\x00')
self.assertEqual(file_system[0x6050: 0x6060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x0e\x00\x00\x00') self.assertEqual(file_system[0x6050:0x6060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x0e\x00\x00\x00')
self.assertEqual(file_system[0x7000: 0x7010], b'this is a test\x00\x00') self.assertEqual(file_system[0x7000:0x7010], b'this is a test\x00\x00')
def test_boundary_clusters12(self) -> None: def test_boundary_clusters12(self) -> None:
output: bytes = check_output(['python', '../fatfsgen.py', '--partition_size', '16732160', 'test_dir'], output: bytes = check_output(
stderr=STDOUT) ['python', '../fatfsgen.py', '--partition_size', '16732160', 'test_dir'], stderr=STDOUT
)
self.assertEqual( self.assertEqual(
output, output, b'WARNING: It is not recommended to create FATFS with bounding count of clusters: 4085 or 65525\n'
b'WARNING: It is not recommended to create FATFS with bounding count of clusters: 4085 or 65525\n') )
def test_boundary_clusters16(self) -> None: def test_boundary_clusters16(self) -> None:
output: bytes = check_output(['python', '../fatfsgen.py', '--partition_size', '268390400', 'test_dir'], output: bytes = check_output(
stderr=STDOUT) ['python', '../fatfsgen.py', '--partition_size', '268390400', 'test_dir'], stderr=STDOUT
)
self.assertEqual( self.assertEqual(
output, output, b'WARNING: It is not recommended to create FATFS with bounding count of clusters: 4085 or 65525\n'
b'WARNING: It is not recommended to create FATFS with bounding count of clusters: 4085 or 65525\n') )
def test_boundary_clusters_fat32(self) -> None: def test_boundary_clusters_fat32(self) -> None:
self.assertRaises(NotImplementedError, fatfsgen.FATFS, size=268419193) self.assertRaises(NotImplementedError, fatfsgen.FATFS, size=268419193)
@@ -753,76 +762,80 @@ class FatFSGen(unittest.TestCase):
fatfs.create_directory('VERYLONGTESTFOLD') fatfs.create_directory('VERYLONGTESTFOLD')
fatfs.create_file('HELLOHELLOHELLOOOOOOO', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) fatfs.create_file('HELLOHELLOHELLOOOOOOO', extension='TXT', path_from_root=['VERYLONGTESTFOLD'])
fatfs.create_file('HELLOHELLOHELLOOOOOOB', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) fatfs.create_file('HELLOHELLOHELLOOOOOOB', extension='TXT', path_from_root=['VERYLONGTESTFOLD'])
fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLOHELLOHELLOOOOOOO.TXT'], fatfs.write_content(
content=b'this is a test A') path_from_root=['VERYLONGTESTFOLD', 'HELLOHELLOHELLOOOOOOO.TXT'], content=b'this is a test A'
fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLOHELLOHELLOOOOOOB.TXT'], )
content=b'this is a test B') fatfs.write_content(
path_from_root=['VERYLONGTESTFOLD', 'HELLOHELLOHELLOOOOOOB.TXT'], content=b'this is a test B'
)
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x3000: 0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff') self.assertEqual(file_system[0x3000:0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff')
self.assertEqual(file_system[0x3011: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x3011:0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x3020: 0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00') self.assertEqual(file_system[0x3020:0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00')
self.assertEqual(file_system[0x3030: 0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') self.assertEqual(file_system[0x3030:0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00')
self.assertEqual(file_system[0x3040: 0x3050], b'VERYLO~1 \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x3040:0x3050], b'VERYLO~1 \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x3050:0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7000: 0x7010], b'. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x7000:0x7010], b'. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x7011: 0x7020], b'\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x7011:0x7020], b'\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7020: 0x7030], b'.. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x7020:0x7030], b'.. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x7030: 0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x7030:0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x7040: 0x7050], b'Bl\x00o\x00o\x00o\x00o\x00\x0f\x00\xb3o\x00') self.assertEqual(file_system[0x7040:0x7050], b'Bl\x00o\x00o\x00o\x00o\x00\x0f\x00\xb3o\x00')
self.assertEqual(file_system[0x7050: 0x7060], b'o\x00o\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00') self.assertEqual(file_system[0x7050:0x7060], b'o\x00o\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00')
self.assertEqual(file_system[0x7050: 0x7060], b'o\x00o\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00') self.assertEqual(file_system[0x7050:0x7060], b'o\x00o\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00')
self.assertEqual(file_system[0x7060: 0x7070], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00') self.assertEqual(file_system[0x7060:0x7070], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00')
self.assertEqual(file_system[0x7070: 0x7080], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') self.assertEqual(file_system[0x7070:0x7080], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00')
self.assertEqual(file_system[0x7080: 0x7090], b'HELLOH~1TXT \x00\x00\x00\x00') self.assertEqual(file_system[0x7080:0x7090], b'HELLOH~1TXT \x00\x00\x00\x00')
self.assertEqual(file_system[0x7090: 0x70a0], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x10\x00\x00\x00') self.assertEqual(file_system[0x7090:0x70A0], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x10\x00\x00\x00')
self.assertEqual(file_system[0x70a0: 0x70b0], b'Bl\x00o\x00o\x00o\x00o\x00\x0f\x00\x93o\x00') self.assertEqual(file_system[0x70A0:0x70B0], b'Bl\x00o\x00o\x00o\x00o\x00\x0f\x00\x93o\x00')
self.assertEqual(file_system[0x70b0: 0x70c0], b'o\x00b\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00') self.assertEqual(file_system[0x70B0:0x70C0], b'o\x00b\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00')
self.assertEqual(file_system[0x70c0: 0x70d0], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\x93h\x00') self.assertEqual(file_system[0x70C0:0x70D0], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\x93h\x00')
self.assertEqual(file_system[0x70d0: 0x70e0], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') self.assertEqual(file_system[0x70D0:0x70E0], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00')
self.assertEqual(file_system[0x70e0: 0x70f0], b'HELLOH~2TXT \x00\x00\x00\x00') self.assertEqual(file_system[0x70E0:0x70F0], b'HELLOH~2TXT \x00\x00\x00\x00')
def test_lfn_increasing_one_fat(self) -> None: def test_lfn_increasing_one_fat(self) -> None:
fatfs: fatfsgen.FATFS = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs: fatfsgen.FATFS = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True)
fatfs.create_directory('VERYLONGTESTFOLD') fatfs.create_directory('VERYLONGTESTFOLD')
fatfs.create_file('HELLOHELLOHELLOOOOOOO', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) fatfs.create_file('HELLOHELLOHELLOOOOOOO', extension='TXT', path_from_root=['VERYLONGTESTFOLD'])
fatfs.create_file('HELLOHELLOHELLOOOOOOB', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) fatfs.create_file('HELLOHELLOHELLOOOOOOB', extension='TXT', path_from_root=['VERYLONGTESTFOLD'])
fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLOHELLOHELLOOOOOOO.TXT'], fatfs.write_content(
content=b'this is a test A') path_from_root=['VERYLONGTESTFOLD', 'HELLOHELLOHELLOOOOOOO.TXT'], content=b'this is a test A'
fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLOHELLOHELLOOOOOOB.TXT'], )
content=b'this is a test B') fatfs.write_content(
path_from_root=['VERYLONGTESTFOLD', 'HELLOHELLOHELLOOOOOOB.TXT'], content=b'this is a test B'
)
fatfs.write_filesystem(CFG['output_file']) fatfs.write_filesystem(CFG['output_file'])
file_system = read_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file'])
self.assertEqual(file_system[0x2000: 0x2010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff') self.assertEqual(file_system[0x2000:0x2010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa6\xff\xff')
self.assertEqual(file_system[0x2011: 0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') self.assertEqual(file_system[0x2011:0x2020], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff')
self.assertEqual(file_system[0x2020: 0x2030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00') self.assertEqual(file_system[0x2020:0x2030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa6o\x00')
self.assertEqual(file_system[0x2030: 0x2040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') self.assertEqual(file_system[0x2030:0x2040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00')
self.assertEqual(file_system[0x2040: 0x2050], b'VERYLO~1 \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x2040:0x2050], b'VERYLO~1 \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x2050: 0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x2050:0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6000: 0x6010], b'. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x6000:0x6010], b'. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x6011: 0x6020], b'\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x6011:0x6020], b'\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6020: 0x6030], b'.. \x10\x00\x00\x00\x00') self.assertEqual(file_system[0x6020:0x6030], b'.. \x10\x00\x00\x00\x00')
self.assertEqual(file_system[0x6030: 0x6040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') self.assertEqual(file_system[0x6030:0x6040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00')
self.assertEqual(file_system[0x6040: 0x6050], b'Bl\x00o\x00o\x00o\x00o\x00\x0f\x00\xb3o\x00') self.assertEqual(file_system[0x6040:0x6050], b'Bl\x00o\x00o\x00o\x00o\x00\x0f\x00\xb3o\x00')
self.assertEqual(file_system[0x6050: 0x6060], b'o\x00o\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00') self.assertEqual(file_system[0x6050:0x6060], b'o\x00o\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00')
self.assertEqual(file_system[0x6050: 0x6060], b'o\x00o\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00') self.assertEqual(file_system[0x6050:0x6060], b'o\x00o\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00')
self.assertEqual(file_system[0x6060: 0x6070], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00') self.assertEqual(file_system[0x6060:0x6070], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xb3h\x00')
self.assertEqual(file_system[0x6070: 0x6080], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') self.assertEqual(file_system[0x6070:0x6080], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00')
self.assertEqual(file_system[0x6080: 0x6090], b'HELLOH~1TXT \x00\x00\x00\x00') self.assertEqual(file_system[0x6080:0x6090], b'HELLOH~1TXT \x00\x00\x00\x00')
self.assertEqual(file_system[0x6090: 0x60a0], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x10\x00\x00\x00') self.assertEqual(file_system[0x6090:0x60A0], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x10\x00\x00\x00')
self.assertEqual(file_system[0x60a0: 0x60b0], b'Bl\x00o\x00o\x00o\x00o\x00\x0f\x00\x93o\x00') self.assertEqual(file_system[0x60A0:0x60B0], b'Bl\x00o\x00o\x00o\x00o\x00\x0f\x00\x93o\x00')
self.assertEqual(file_system[0x60b0: 0x60c0], b'o\x00b\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00') self.assertEqual(file_system[0x60B0:0x60C0], b'o\x00b\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00')
self.assertEqual(file_system[0x60c0: 0x60d0], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\x93h\x00') self.assertEqual(file_system[0x60C0:0x60D0], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\x93h\x00')
self.assertEqual(file_system[0x60d0: 0x60e0], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') self.assertEqual(file_system[0x60D0:0x60E0], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00')
self.assertEqual(file_system[0x60e0: 0x60f0], b'HELLOH~2TXT \x00\x00\x00\x00') self.assertEqual(file_system[0x60E0:0x60F0], b'HELLOH~2TXT \x00\x00\x00\x00')
def test_bs_not_initialized(self) -> None: def test_bs_not_initialized(self) -> None:
self.assertEqual(str(BootSector()), 'Boot sector is not initialized!') self.assertEqual(str(BootSector()), 'Boot sector is not initialized!')
@@ -834,13 +847,15 @@ class FatFSGen(unittest.TestCase):
bs = BootSector(fatfs.state.boot_sector_state) bs = BootSector(fatfs.state.boot_sector_state)
bs.generate_boot_sector() bs.generate_boot_sector()
bs.parse_boot_sector(bs.binary_image) bs.parse_boot_sector(bs.binary_image)
x = 'FATFS properties:,clusters: 251,data_region_start: 28672,data_sectors: ' \ x = (
'249,entries_root_count: 512,fat_table_start_address: 4096,fat_tables_cnt: 2,' \ 'FATFS properties:,clusters: 251,data_region_start: 28672,data_sectors: '
'fatfs_type: 12,file_sys_type: FAT ,hidden_sectors: 0,media_type: 248,' \ '249,entries_root_count: 512,fat_table_start_address: 4096,fat_tables_cnt: 2,'
'non_data_sectors: 7,num_heads: 255,oem_name: MSDOS5.0,reserved_sectors_cnt: 1,' \ 'fatfs_type: 12,file_sys_type: FAT ,hidden_sectors: 0,media_type: 248,'
'root_dir_sectors_cnt: 4,root_directory_start: 12288,sec_per_track: 63,sector_size: 4096,' \ 'non_data_sectors: 7,num_heads: 255,oem_name: MSDOS5.0,reserved_sectors_cnt: 1,'
'sectors_count: 256,sectors_per_cluster: 1,sectors_per_fat_cnt: 1,size: 1048576,' \ 'root_dir_sectors_cnt: 4,root_directory_start: 12288,sec_per_track: 63,sector_size: 4096,'
'sectors_count: 256,sectors_per_cluster: 1,sectors_per_fat_cnt: 1,size: 1048576,'
'volume_label: Espressif ,volume_uuid: 1144419653,' 'volume_label: Espressif ,volume_uuid: 1144419653,'
)
self.assertEqual(x.split(',')[:-2], str(bs).split('\n')[:-2]) # except for volume id self.assertEqual(x.split(',')[:-2], str(bs).split('\n')[:-2]) # except for volume id
def test_bs_str_one_fat(self) -> None: def test_bs_str_one_fat(self) -> None:
@@ -848,13 +863,15 @@ class FatFSGen(unittest.TestCase):
bs = BootSector(fatfs.state.boot_sector_state) bs = BootSector(fatfs.state.boot_sector_state)
bs.generate_boot_sector() bs.generate_boot_sector()
bs.parse_boot_sector(bs.binary_image) bs.parse_boot_sector(bs.binary_image)
x = 'FATFS properties:,clusters: 252,data_region_start: 24576,data_sectors: ' \ x = (
'250,entries_root_count: 512,fat_table_start_address: 4096,fat_tables_cnt: 1,' \ 'FATFS properties:,clusters: 252,data_region_start: 24576,data_sectors: '
'fatfs_type: 12,file_sys_type: FAT ,hidden_sectors: 0,media_type: 248,' \ '250,entries_root_count: 512,fat_table_start_address: 4096,fat_tables_cnt: 1,'
'non_data_sectors: 6,num_heads: 255,oem_name: MSDOS5.0,reserved_sectors_cnt: 1,' \ 'fatfs_type: 12,file_sys_type: FAT ,hidden_sectors: 0,media_type: 248,'
'root_dir_sectors_cnt: 4,root_directory_start: 8192,sec_per_track: 63,sector_size: 4096,' \ 'non_data_sectors: 6,num_heads: 255,oem_name: MSDOS5.0,reserved_sectors_cnt: 1,'
'sectors_count: 256,sectors_per_cluster: 1,sectors_per_fat_cnt: 1,size: 1048576,' \ 'root_dir_sectors_cnt: 4,root_directory_start: 8192,sec_per_track: 63,sector_size: 4096,'
'sectors_count: 256,sectors_per_cluster: 1,sectors_per_fat_cnt: 1,size: 1048576,'
'volume_label: Espressif ,volume_uuid: 1144419653,' 'volume_label: Espressif ,volume_uuid: 1144419653,'
)
self.assertEqual(x.split(',')[:-2], str(bs).split('\n')[:-2]) # except for volume id self.assertEqual(x.split(',')[:-2], str(bs).split('\n')[:-2]) # except for volume id
def test_parsing_error(self) -> None: def test_parsing_error(self) -> None:
@@ -864,8 +881,11 @@ class FatFSGen(unittest.TestCase):
self.assertEqual( self.assertEqual(
Entry.get_cluster_id( Entry.get_cluster_id(
Entry.ENTRY_FORMAT_SHORT_NAME.parse( Entry.ENTRY_FORMAT_SHORT_NAME.parse(
bytearray(b'AHOJ \x18\x00\xb0[&U&U\x00\x00\xb0[&U\x02\x00\x08\x00\x00\x00'))), bytearray(b'AHOJ \x18\x00\xb0[&U&U\x00\x00\xb0[&U\x02\x00\x08\x00\x00\x00')
2) )
),
2,
)
def test_get_cluster_value_from_fat(self) -> None: def test_get_cluster_value_from_fat(self) -> None:
fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs = fatfsgen.FATFS(fat_tables_cnt=2)