Merge branch 'bugfix/fatfsgen-omit-cluster-for-empty-files' into 'master'

fatfsgen.py: omit cluster allocation when the file is empty

Closes IDF-6037

See merge request espressif/esp-idf!20441
This commit is contained in:
Martin Vychodil
2022-09-30 14:42:52 +08:00
3 changed files with 39 additions and 24 deletions

View File

@@ -201,11 +201,11 @@ class Directory:
name, name,
extension, extension,
target_dir, target_dir,
free_cluster, free_cluster_id,
entity_type, entity_type,
date, date,
time): time):
# type: (Entry, str, str, Directory, Cluster, int, DATETIME, DATETIME) -> Tuple[Cluster, Entry, Directory] # type: (Entry, str, str, Directory, int, int, DATETIME, 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_short_entry_name: str = build_lfn_short_entry_name(name, extension, lfn_unique_entry_order)
@@ -218,7 +218,7 @@ class Directory:
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(first_cluster_id=free_cluster_id,
entity_name=name, entity_name=name,
entity_extension=extension, entity_extension=extension,
entity_type=entity_type, entity_type=entity_type,
@@ -227,14 +227,14 @@ class Directory:
lfn_checksum_=checksum, lfn_checksum_=checksum,
lfn_is_last=order == entries_count) 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(first_cluster_id=free_cluster_id,
entity_name=lfn_short_entry_name[:MAX_NAME_SIZE], entity_name=lfn_short_entry_name[:MAX_NAME_SIZE],
entity_extension=lfn_short_entry_name[MAX_NAME_SIZE:], entity_extension=lfn_short_entry_name[MAX_NAME_SIZE:],
entity_type=entity_type, entity_type=entity_type,
lfn_order=Entry.SHORT_ENTRY_LN, lfn_order=Entry.SHORT_ENTRY_LN,
date=date, date=date,
time=time) time=time)
return free_cluster, free_entry, target_dir return free_entry
@staticmethod @staticmethod
def _is_valid_sfn(name: str, extension: str) -> bool: def _is_valid_sfn(name: str, extension: str) -> bool:
@@ -248,14 +248,21 @@ class Directory:
entity_type, entity_type,
object_timestamp_, object_timestamp_,
path_from_root=None, path_from_root=None,
extension=''): extension='',
# type: (str, int, datetime, Optional[List[str]], str) -> Tuple[Cluster, Entry, Directory] is_empty=False):
# type: (str, int, datetime, Optional[List[str]], str, bool) -> 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: Cluster = self.fat.find_free_cluster()
free_cluster: Optional[Cluster] = None
free_cluster_id = 0x00
if not is_empty:
free_cluster = self.fat.find_free_cluster()
free_cluster_id = free_cluster.id
target_dir: Directory = self if not path_from_root else self.recursive_search(path_from_root, self) target_dir: Directory = self if not path_from_root else self.recursive_search(path_from_root, self)
free_entry: Entry = target_dir.find_free_entry() or target_dir.chain_directory() free_entry: Entry = target_dir.find_free_entry() or target_dir.chain_directory()
@@ -263,7 +270,7 @@ 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(first_cluster_id=free_cluster_id,
entity_name=name, entity_name=name,
entity_extension=extension, entity_extension=extension,
date=fatfs_date_, date=fatfs_date_,
@@ -271,25 +278,27 @@ class Directory:
fits_short=True, fits_short=True,
entity_type=entity_type) entity_type=entity_type)
return free_cluster, free_entry, target_dir return free_cluster, free_entry, target_dir
return self.allocate_long_name_object(free_entry=free_entry, return free_cluster, self.allocate_long_name_object(free_entry=free_entry,
name=name, name=name,
extension=extension, extension=extension,
target_dir=target_dir, target_dir=target_dir,
free_cluster=free_cluster, free_cluster_id=free_cluster_id,
entity_type=entity_type, entity_type=entity_type,
date=fatfs_date_, date=fatfs_date_,
time=fatfs_time_) time=fatfs_time_), target_dir
def new_file(self, def new_file(self,
name: str, name: str,
extension: str, extension: str,
path_from_root: Optional[List[str]], path_from_root: Optional[List[str]],
object_timestamp_: datetime) -> None: object_timestamp_: datetime,
is_empty: bool) -> None:
free_cluster, free_entry, target_dir = self.allocate_object(name=name, free_cluster, free_entry, target_dir = self.allocate_object(name=name,
extension=extension, extension=extension,
entity_type=Directory.ATTR_ARCHIVE, entity_type=Directory.ATTR_ARCHIVE,
path_from_root=path_from_root, path_from_root=path_from_root,
object_timestamp_=object_timestamp_) object_timestamp_=object_timestamp_,
is_empty=is_empty)
file: File = File(name=name, file: File = File(name=name,
fat=self.fat, fat=self.fat,

View File

@@ -78,7 +78,8 @@ class FATFS:
def create_file(self, name: str, def create_file(self, name: str,
extension: str = '', extension: str = '',
path_from_root: Optional[List[str]] = None, path_from_root: Optional[List[str]] = None,
object_timestamp_: datetime = FATFS_INCEPTION) -> None: object_timestamp_: datetime = FATFS_INCEPTION,
is_empty: bool = False) -> None:
""" """
Root directory recursively finds the parent directory of the new file, allocates cluster, Root directory recursively finds the parent directory of the new file, allocates cluster,
entry and appends a new file into the parent directory. entry and appends a new file into the parent directory.
@@ -89,11 +90,13 @@ class FATFS:
:param extension: The extension of the file. :param extension: The extension of the file.
:param path_from_root: List of strings containing names of the ancestor directories in the given order. :param path_from_root: List of strings containing names of the ancestor directories in the given order.
:param object_timestamp_: is not None, this will be propagated to the file's entry :param object_timestamp_: is not None, this will be propagated to the file's entry
:param is_empty: True if there is no need to allocate any cluster, otherwise False
""" """
self.root_directory.new_file(name=name, self.root_directory.new_file(name=name,
extension=extension, extension=extension,
path_from_root=path_from_root, path_from_root=path_from_root,
object_timestamp_=object_timestamp_) object_timestamp_=object_timestamp_,
is_empty=is_empty)
def create_directory(self, name: str, def create_directory(self, name: str,
path_from_root: Optional[List[str]] = None, path_from_root: Optional[List[str]] = None,
@@ -159,7 +162,8 @@ class FATFS:
self.create_file(name=file_name, self.create_file(name=file_name,
extension=extension, extension=extension,
path_from_root=split_path[1:-1] or None, path_from_root=split_path[1:-1] or None,
object_timestamp_=object_timestamp) object_timestamp_=object_timestamp,
is_empty=len(content) == 0)
self.write_content(split_path[1:], content) self.write_content(split_path[1:], content)
elif os.path.isdir(real_path): elif os.path.isdir(real_path):
if not is_dir: if not is_dir:

View File

@@ -69,6 +69,8 @@ def traverse_folder_tree(directory_bytes_: bytes,
entry_position_=i, entry_position_=i,
lfn_checksum_=lfn_checksum(obj_['DIR_Name'] + obj_['DIR_Name_ext'])) lfn_checksum_=lfn_checksum(obj_['DIR_Name'] + obj_['DIR_Name_ext']))
if obj_['DIR_Attr'] == Entry.ATTR_ARCHIVE: if obj_['DIR_Attr'] == Entry.ATTR_ARCHIVE:
content_ = b''
if obj_['DIR_FileSize'] > 0:
content_ = fat_.get_chained_content(cluster_id_=Entry.get_cluster_id(obj_), content_ = fat_.get_chained_content(cluster_id_=Entry.get_cluster_id(obj_),
size=obj_['DIR_FileSize']) size=obj_['DIR_FileSize'])
with open(os.path.join(name, obj_name_), 'wb') as new_file: with open(os.path.join(name, obj_name_), 'wb') as new_file: