Revamped path-related operations

Fixed dependencies detecton

Fixed frozen state support
This commit is contained in:
platomav 2022-04-17 20:48:43 +03:00
parent 44546a67c5
commit a2eca0aac6
14 changed files with 144 additions and 98 deletions

View file

@ -7,14 +7,13 @@ Dell PFS Update Extractor
Copyright (C) 2018-2022 Plato Mavropoulos
"""
title = 'Dell PFS Update Extractor v6.0_a5'
title = 'Dell PFS Update Extractor v6.0_a6'
import os
import io
import sys
import lzma
import zlib
import shutil
import ctypes
import contextlib
@ -22,7 +21,7 @@ import contextlib
sys.dont_write_bytecode = True
from common.checksums import get_chk_8_xor
from common.path_ops import get_safe_name
from common.path_ops import safe_name, make_dirs
from common.patterns import PAT_DELL_HDR, PAT_DELL_FTR, PAT_DELL_PKG
from common.struct_ops import get_struct, char, uint8_t, uint16_t, uint32_t, uint64_t
from common.system import script_init, argparse_init, printer
@ -243,13 +242,10 @@ def pfs_section_parse(zlib_data, zlib_start, output_path, pfs_name, pfs_index, p
printer('Extracting Dell PFS %d >%s > %s' % (pfs_index, pfs_name, section_name), padding)
# Set PFS ZLIB Section extraction sub-directory path
section_path = os.path.join(output_path, get_safe_name(section_name))
section_path = os.path.join(output_path, safe_name(section_name))
# Delete existing extraction sub-directory (not in recursions)
if os.path.isdir(section_path) and not is_rec: shutil.rmtree(section_path)
# Create extraction sub-directory
if not os.path.isdir(section_path): os.makedirs(section_path)
# Create extraction sub-directory and delete old (if present, not in recursions)
make_dirs(section_path, delete=(not is_rec), parents=True, exist_ok=True)
# Store the compressed zlib stream start offset
compressed_start = zlib_start + 0xB
@ -406,7 +402,7 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, i
name_start = info_start + PFS_INFO_LEN + PFS_NAME_LEN # PFS Entry's FileName start offset
name_size = entry_info_mod.CharacterCount * 2 # PFS Entry's FileName buffer total size
name_data = filename_info[name_start:name_start + name_size] # PFS Entry's FileName buffer
entry_name = get_safe_name(name_data.decode('utf-16').strip()) # PFS Entry's FileName value
entry_name = safe_name(name_data.decode('utf-16').strip()) # PFS Entry's FileName value
# Show PFS FileName Structure info
if is_structure:
@ -443,7 +439,7 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, i
# As Nested PFS Entry Name, we'll use the actual PFS File Name
# Replace common Windows reserved/illegal filename characters
entry_name = get_safe_name(entry_info.FileName.decode('utf-8').strip('.exe'))
entry_name = safe_name(entry_info.FileName.decode('utf-8').strip('.exe'))
# As Nested PFS Entry Version, we'll use the actual PFS File Version
entry_version = entry_info.FileVersion.decode('utf-8')
@ -537,7 +533,7 @@ def pfs_extract(buffer, pfs_index, pfs_name, pfs_count, output_path, pfs_padd, i
sub_pfs_name = ' %s v%s' % (info_all[pfs_count - 2][1], info_all[pfs_count - 2][2]) if info_all else ' UNKNOWN'
# Set the sub-PFS output path (create sub-folders for each sub-PFS and its ZLIB sections)
sub_pfs_path = os.path.join(output_path, str(pfs_count) + get_safe_name(sub_pfs_name))
sub_pfs_path = os.path.join(output_path, str(pfs_count) + safe_name(sub_pfs_name))
# Recursively call the PFS ZLIB Section Parser function for the sub-PFS Volume (pfs_index = pfs_count)
pfs_section_parse(entry_data, offset, sub_pfs_path, sub_pfs_name, pfs_count, pfs_count, True, pfs_padd + 4, is_structure, is_advanced)
@ -844,7 +840,7 @@ def chk_pfs_ftr(footer_buffer, data_buffer, data_size, text, padding, is_structu
def pfs_file_write(bin_buff, bin_name, bin_type, full_name, out_path, padding, is_structure=True, is_advanced=True):
# Store Data/Metadata Signature (advanced users only)
if bin_name.startswith('sign'):
final_name = '%s.%s.sig' % (get_safe_name(full_name), bin_name.split('_')[1])
final_name = '%s.%s.sig' % (safe_name(full_name), bin_name.split('_')[1])
final_path = os.path.join(out_path, final_name)
with open(final_path, 'wb') as pfs_out: pfs_out.write(bin_buff) # Write final Data/Metadata Signature
@ -857,7 +853,7 @@ def pfs_file_write(bin_buff, bin_name, bin_type, full_name, out_path, padding, i
# Some Data may be Text or XML files with useful information for non-advanced users
is_text,final_data,file_ext,write_mode = bin_is_text(bin_buff, bin_type, bin_name == 'meta', padding, is_structure, is_advanced)
final_name = '%s%s' % (get_safe_name(full_name), bin_ext[:-4] + file_ext if is_text else bin_ext)
final_name = '%s%s' % (safe_name(full_name), bin_ext[:-4] + file_ext if is_text else bin_ext)
final_path = os.path.join(out_path, final_name)
with open(final_path, write_mode) as pfs_out: pfs_out.write(final_data) # Write final Data/Metadata Payload