mirror of
https://github.com/platomav/BIOSUtilities.git
synced 2025-05-12 22:26:13 -04:00
Revamped path-related operations
Fixed dependencies detecton Fixed frozen state support
This commit is contained in:
parent
44546a67c5
commit
a2eca0aac6
14 changed files with 144 additions and 98 deletions
|
@ -1,10 +1,14 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from common.path_ops import get_script_dir
|
||||
from common.path_ops import project_root, safe_path
|
||||
from common.system import get_os_ver
|
||||
from common.system import printer
|
||||
|
||||
|
@ -12,29 +16,27 @@ from common.system import printer
|
|||
def get_7z_path(static=False):
|
||||
exec_name = '7z.exe' if get_os_ver()[1] else ('7zzs' if static else '7zz')
|
||||
|
||||
exec_path = os.path.join(get_script_dir(), '..', 'external', exec_name)
|
||||
|
||||
return exec_path
|
||||
return safe_path(project_root(), ['external',exec_name])
|
||||
|
||||
# Check if file is 7z supported
|
||||
def is_7z_supported(in_path, static=False):
|
||||
def is_7z_supported(in_path, padding=0, static=False):
|
||||
try:
|
||||
subprocess.run([get_7z_path(static), 't', in_path, '-bso0', '-bse0', '-bsp0'], check=True)
|
||||
|
||||
except:
|
||||
printer('Error: 7-Zip could not check support for file %s!' % in_path, padding)
|
||||
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
# Archive decompression via 7-Zip
|
||||
def a7z_decompress(in_path, out_path, in_name, padding, static=False):
|
||||
def a7z_decompress(in_path, out_path, in_name, padding=0, static=False):
|
||||
if not in_name: in_name = 'archive'
|
||||
|
||||
try:
|
||||
subprocess.run([get_7z_path(static), 'x', '-aou', '-bso0', '-bse0', '-bsp0', '-o' + out_path, in_path], check=True)
|
||||
|
||||
if not os.path.isdir(out_path): raise Exception('EXTRACT_DIR_MISSING')
|
||||
|
||||
except:
|
||||
printer('Error: 7-Zip could not extract %s file %s!' % (in_name, in_path), padding)
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
# Get Checksum 16-bit
|
||||
def get_chk_16(data, value=0, order='little'):
|
||||
for idx in range(0, len(data), 2):
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from common.path_ops import get_script_dir
|
||||
from common.path_ops import project_root, safe_path
|
||||
from common.system import get_os_ver
|
||||
from common.system import printer
|
||||
|
||||
|
@ -25,22 +29,19 @@ def is_efi_compressed(data, strict=True):
|
|||
return check_diff and check_size
|
||||
|
||||
# Get TianoCompress path
|
||||
def tianocompress_path():
|
||||
def get_tiano_path():
|
||||
exec_name = 'TianoCompress' + ('.exe' if get_os_ver()[1] else '')
|
||||
|
||||
exec_path = os.path.join(get_script_dir(), '..', 'external', exec_name)
|
||||
|
||||
return exec_path
|
||||
return safe_path(project_root(), ['external',exec_name])
|
||||
|
||||
# EFI/Tiano Decompression via TianoCompress
|
||||
def efi_decompress(in_path, out_path, padding, comp_type='--uefi'):
|
||||
def efi_decompress(in_path, out_path, padding=0, comp_type='--uefi'):
|
||||
try:
|
||||
subprocess.run([tianocompress_path(), '-d', in_path, '-o', out_path, '-q', comp_type], check=True, stdout=subprocess.DEVNULL)
|
||||
subprocess.run([get_tiano_path(), '-d', in_path, '-o', out_path, '-q', comp_type], check=True, stdout=subprocess.DEVNULL)
|
||||
|
||||
with open(in_path, 'rb') as file: _,size_orig = get_compress_sizes(file.read())
|
||||
|
||||
if os.path.getsize(out_path) != size_orig: raise Exception('EFI_DECOMPRESS_ERROR')
|
||||
|
||||
except:
|
||||
printer('Error: TianoCompress could not extract file %s!' % in_path, padding)
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
# https://github.com/allowitsme/big-tool by Dmitry Frolov
|
||||
def get_bgs_tool():
|
||||
try:
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
# https://leancrew.com/all-this/2020/06/ordinals-in-python/ by Dr. Drang
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
# https://leancrew.com/all-this/2020/06/ordinals-in-python/ by Dr. Drang
|
||||
def get_ordinal(number):
|
||||
s = ('th', 'st', 'nd', 'rd') + ('th',) * 10
|
||||
|
||||
|
|
|
@ -1,68 +1,89 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
from pathlib import Path, PurePath
|
||||
|
||||
from common.text_ops import to_string
|
||||
|
||||
# Fix illegal/reserved Windows characters
|
||||
def get_safe_name(in_name):
|
||||
def safe_name(in_name):
|
||||
name_repr = repr(in_name).strip("'")
|
||||
|
||||
return re.sub(r'[\\/:"*?<>|]+', '_', name_repr)
|
||||
|
||||
# Check and attempt to fix illegal/unsafe OS path traversals
|
||||
def get_safe_path(base_path, user_paths):
|
||||
def safe_path(base_path, user_paths):
|
||||
# Convert base path to absolute path
|
||||
base_path = get_real_path(base_path)
|
||||
base_path = real_path(base_path)
|
||||
|
||||
# Convert user path(s) to absolute path with OS separators
|
||||
# Merge user path(s) to string with OS separators
|
||||
user_path = to_string(user_paths, os.sep)
|
||||
|
||||
# Create target path from base + requested user path
|
||||
target_path = get_norm_path(base_path, user_path)
|
||||
target_path = norm_path(base_path, user_path)
|
||||
|
||||
# Check if target path is OS illegal/unsafe
|
||||
if is_safe_path(base_path, target_path):
|
||||
return target_path
|
||||
|
||||
# Re-create target path from base + leveled/safe illegal "path" (now file)
|
||||
nuked_path = get_norm_path(base_path, get_safe_name(user_path))
|
||||
nuked_path = norm_path(base_path, safe_name(user_path))
|
||||
|
||||
# Check if illegal path leveling worked
|
||||
if is_safe_path(base_path, nuked_path):
|
||||
return nuked_path
|
||||
|
||||
# Still illegal, create fallback base path + placeholder file
|
||||
failed_path = get_norm_path(base_path, 'illegal_path_traversal')
|
||||
|
||||
return failed_path
|
||||
# Still illegal, raise exception to halt execution
|
||||
raise Exception(f'ILLEGAL_PATH_TRAVERSAL: {user_path}')
|
||||
|
||||
# Check for illegal/unsafe OS path traversal
|
||||
def is_safe_path(base_path, target_path):
|
||||
base_path = get_real_path(base_path)
|
||||
base_path = real_path(base_path)
|
||||
|
||||
target_path = get_real_path(target_path)
|
||||
target_path = real_path(target_path)
|
||||
|
||||
common_path = os.path.commonpath((base_path, target_path))
|
||||
|
||||
return base_path == common_path
|
||||
|
||||
# Create normalized base path + OS separator + user path
|
||||
def get_norm_path(base_path, user_path):
|
||||
def norm_path(base_path, user_path):
|
||||
return os.path.normpath(base_path + os.sep + user_path)
|
||||
|
||||
# Get absolute path, resolving any symlinks
|
||||
def get_real_path(in_path):
|
||||
return str(Path(in_path).resolve())
|
||||
def real_path(in_path):
|
||||
return os.path.realpath(in_path)
|
||||
|
||||
# Get Windows/Posix OS compatible path
|
||||
def get_comp_path(in_path):
|
||||
return in_path.replace('\\', os.sep)
|
||||
# Get Windows/Posix OS agnostic path
|
||||
def agnostic_path(in_path):
|
||||
return PurePath(in_path.replace('\\', os.sep))
|
||||
|
||||
# Get absolute parent of path
|
||||
def path_parent(in_path):
|
||||
return Path(in_path).parent.absolute()
|
||||
|
||||
# Check if path is absolute
|
||||
def is_path_absolute(in_path):
|
||||
return Path(in_path).is_absolute()
|
||||
|
||||
# Create folder(s), controlling parents, existence and prior deletion
|
||||
def make_dirs(in_path, parents=True, exist_ok=False, delete=False):
|
||||
if delete: del_dirs(in_path)
|
||||
|
||||
Path.mkdir(Path(in_path), parents=parents, exist_ok=exist_ok)
|
||||
|
||||
# Delete folder(s), if present
|
||||
def del_dirs(in_path):
|
||||
if Path(in_path).is_dir():
|
||||
shutil.rmtree(in_path)
|
||||
|
||||
# Walk path to get all files
|
||||
def get_path_files(in_path):
|
||||
|
@ -74,20 +95,18 @@ def get_path_files(in_path):
|
|||
|
||||
return path_files
|
||||
|
||||
# Get parent of path
|
||||
def get_path_parent(in_path):
|
||||
return Path(in_path).parent.absolute()
|
||||
|
||||
# Get absolute file path of argparse object
|
||||
def get_argparse_path(argparse_path):
|
||||
script_dir = get_path_parent(get_script_dir())
|
||||
|
||||
if not argparse_path:
|
||||
absolute_path = script_dir # Use input file directory if no user path is specified
|
||||
# Use runtime directory if no user path is specified
|
||||
absolute_path = runtime_root()
|
||||
else:
|
||||
# Check if user specified path is absolute, otherwise convert it to input file relative
|
||||
if Path(argparse_path).is_absolute(): absolute_path = argparse_path
|
||||
else: absolute_path = os.path.join(script_dir, argparse_path)
|
||||
# Check if user specified path is absolute
|
||||
if is_path_absolute(argparse_path):
|
||||
absolute_path = argparse_path
|
||||
# Otherwise, make it runtime directory relative
|
||||
else:
|
||||
absolute_path = safe_path(runtime_root(), argparse_path)
|
||||
|
||||
return absolute_path
|
||||
|
||||
|
@ -104,22 +123,31 @@ def process_input_files(argparse_args, sys_argv=None):
|
|||
else:
|
||||
input_files = [file.name for file in argparse_args.files]
|
||||
|
||||
output_path = get_argparse_path(argparse_args.output_dir or argparse_args.input_dir)
|
||||
# Set output path via argparse Output Path or argparse Input Path or first input file Path
|
||||
output_path = argparse_args.output_dir or argparse_args.input_dir or path_parent(input_files[0])
|
||||
else:
|
||||
# Script w/o parameters
|
||||
input_path_user = input('\nEnter input directory path: ')
|
||||
input_path_full = get_argparse_path(input_path_user) if input_path_user else ''
|
||||
input_files = get_path_files(input_path_full)
|
||||
|
||||
output_path = get_argparse_path(input('\nEnter output directory path: '))
|
||||
output_path = input('\nEnter output directory path: ')
|
||||
|
||||
return input_files, output_path
|
||||
output_path_final = get_argparse_path(output_path)
|
||||
|
||||
return input_files, output_path_final
|
||||
|
||||
# https://stackoverflow.com/a/22881871 by jfs
|
||||
def get_script_dir():
|
||||
# Get project's root directory
|
||||
def project_root():
|
||||
root = Path(__file__).parent.parent
|
||||
|
||||
return real_path(root)
|
||||
|
||||
# Get runtime's root directory
|
||||
def runtime_root():
|
||||
if getattr(sys, 'frozen', False):
|
||||
path = sys.executable
|
||||
root = Path(sys.executable).parent
|
||||
else:
|
||||
path = inspect.getabsfile(get_script_dir)
|
||||
|
||||
return os.path.dirname(get_real_path(path))
|
||||
root = project_root()
|
||||
|
||||
return real_path(root)
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
PAT_AMI_PFAT = re.compile(b'_AMIPFAT.AMI_BIOS_GUARD_FLASH_CONFIGURATIONS', re.DOTALL)
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
# https://github.com/skochinsky/me-tools/blob/master/me_unpack.py by Igor Skochinsky
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
import ctypes
|
||||
|
||||
|
@ -11,6 +13,7 @@ uint16_t = ctypes.c_ushort
|
|||
uint32_t = ctypes.c_uint
|
||||
uint64_t = ctypes.c_uint64
|
||||
|
||||
# https://github.com/skochinsky/me-tools/blob/master/me_unpack.py by Igor Skochinsky
|
||||
def get_struct(buffer, start_offset, class_name, param_list=None):
|
||||
if param_list is None: param_list = []
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
import sys
|
||||
import ctypes
|
||||
import argparse
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
# Generate padding (spaces or tabs)
|
||||
def padder(padd_count, tab=False):
|
||||
return ('\t' if tab else ' ') * padd_count
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue