mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
8ef66536ed
Closes IDF-4975
92 lines
3.9 KiB
Python
92 lines
3.9 KiB
Python
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
import os
|
|
import sys
|
|
from typing import Tuple
|
|
|
|
from fatfs_utils.boot_sector import BootSector
|
|
from fatfs_utils.cluster import Cluster
|
|
from fatfs_utils.entry import Entry
|
|
from fatfs_utils.fat import FAT
|
|
from fatfs_utils.fatfs_state import BootSectorState
|
|
from fatfs_utils.utils import PAD_CHAR, FATDefaults, read_filesystem
|
|
|
|
|
|
def get_chained_full_content(cluster_id_: int,
|
|
fat_: FAT,
|
|
state_: BootSectorState,
|
|
binary_array_: bytearray) -> bytearray:
|
|
if fat_.is_cluster_last(cluster_id_):
|
|
data_address_ = Cluster.compute_cluster_data_address(state_, cluster_id_)
|
|
content_: bytearray = binary_array_[data_address_: data_address_ + state_.sector_size]
|
|
return content_
|
|
fat_value_: int = fat_.get_cluster_value(cluster_id_)
|
|
data_address_ = Cluster.compute_cluster_data_address(state_, cluster_id_)
|
|
content_ = binary_array_[data_address_: data_address_ + state_.sector_size]
|
|
|
|
while not fat_.is_cluster_last(cluster_id_):
|
|
cluster_id_ = fat_value_
|
|
fat_value_ = fat_.get_cluster_value(cluster_id_)
|
|
data_address_ = Cluster.compute_cluster_data_address(state_, cluster_id_)
|
|
content_ += binary_array_[data_address_: data_address_ + state_.sector_size]
|
|
return content_
|
|
|
|
|
|
def get_name_and_id(obj_: dict) -> Tuple[str, int]:
|
|
cluster_id_ = obj_['DIR_FstClusLO']
|
|
obj_ext_ = obj_['DIR_Name_ext'].rstrip(chr(PAD_CHAR))
|
|
ext_ = f'.{obj_ext_}' if len(obj_ext_) > 0 else ''
|
|
obj_name_ = obj_['DIR_Name'].rstrip(chr(PAD_CHAR)) + ext_
|
|
return obj_name_, cluster_id_
|
|
|
|
|
|
def traverse_folder_tree(directory_bytes_: bytes,
|
|
name: str,
|
|
state_: BootSectorState, fat_: FAT,
|
|
binary_array_: bytearray) -> None:
|
|
if name not in ('.', '..'):
|
|
os.makedirs(name)
|
|
for i in range(len(directory_bytes_) // FATDefaults.ENTRY_SIZE):
|
|
obj_address_ = FATDefaults.ENTRY_SIZE * i
|
|
obj_ = Entry.ENTRY_FORMAT_SHORT_NAME.parse(
|
|
directory_bytes_[obj_address_: obj_address_ + FATDefaults.ENTRY_SIZE])
|
|
if obj_['DIR_Attr'] == Entry.ATTR_ARCHIVE:
|
|
obj_name_, cluster_id_ = get_name_and_id(obj_)
|
|
content_ = get_chained_full_content(
|
|
cluster_id_=cluster_id_,
|
|
fat_=fat_,
|
|
state_=state_,
|
|
binary_array_=binary_array_
|
|
).rstrip(chr(0x00).encode())
|
|
with open(os.path.join(name, obj_name_), 'wb') as new_file:
|
|
new_file.write(content_)
|
|
elif obj_['DIR_Attr'] == Entry.ATTR_DIRECTORY:
|
|
obj_name_, cluster_id_ = get_name_and_id(obj_)
|
|
if obj_name_ in ('.', '..'):
|
|
continue
|
|
child_directory_bytes_ = get_chained_full_content(
|
|
cluster_id_=obj_['DIR_FstClusLO'],
|
|
fat_=fat_,
|
|
state_=state_,
|
|
binary_array_=binary_array_
|
|
)
|
|
traverse_folder_tree(directory_bytes_=child_directory_bytes_,
|
|
name=os.path.join(name, obj_name_),
|
|
state_=state_,
|
|
fat_=fat_,
|
|
binary_array_=binary_array_)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
fs = read_filesystem(sys.argv[1])
|
|
parser = BootSector()
|
|
parser.parse_boot_sector(fs)
|
|
fat = FAT(parser.boot_sector_state, init_=False)
|
|
|
|
boot_dir_start_ = parser.boot_sector_state.root_directory_start
|
|
boot_dir_sectors = parser.boot_sector_state.root_dir_sectors_cnt
|
|
full_ = fs[boot_dir_start_: boot_dir_start_ + boot_dir_sectors * parser.boot_sector_state.sector_size]
|
|
traverse_folder_tree(full_,
|
|
parser.boot_sector_state.volume_label.rstrip(chr(PAD_CHAR)),
|
|
parser.boot_sector_state, fat, fs)
|