#!/usr/bin/env python3
"""This module is used for creation of autoloaders."""
import glob # filename matching
import os # path work
from bbarchivist import exceptions # exception handling
from bbarchivist import jsonutils # json
from bbarchivist import pseudocap # implement cap
from bbarchivist import utilities # directory handler
__author__ = "Thurask"
__license__ = "WTFPL v2"
__copyright__ = "2015-2018 Thurask"
[docs]def read_files(localdir, core=False):
"""
Read list of signed files, return name assignments.
:param localdir: Directory to use.
:type localdir: str
:param core: If we're using a core OS image. Default is false.
:type core: bool
"""
oslist = read_os_files(localdir, core)
# [8960, 8x30, 8974, ti]
radlist = read_radio_files(localdir)
# [ti, z10, z10_vzw, q10, z30, z3, 8974]
pairdict = {}
mapping = {0:3, 1:0, 2:0, 3:0, 4:0, 5:1, 6:2}
for idx, rad in enumerate(radlist):
pairdict[rad] = oslist[mapping[idx]]
filtdict = {k: v for k, v in pairdict.items() if k} # pop None
return filtdict
[docs]def find_signed_file(match, localdir, title, silent=False):
"""
Use pattern matching to find a signed file in a directory.
:param match: Match pattern to use.
:type match: str
:param localdir: Directory to use.
:type localdir: str
:param title: File type, in case it isn't found.
:type title: str
:param silent: Don't print that a file wasn't found. Default is False.
:type silent: bool
"""
try:
signedfile = glob.glob(os.path.join(localdir, match))[0]
except IndexError:
signedfile = None
if not silent:
print("No {0} found".format(title))
return signedfile
[docs]def generate_os_fixes(core=False):
"""
Generate name regexes for OS signed files.
:param core: If we're using a core OS image. Default is false.
:type core: bool
"""
if core:
fix8960 = "*qc8960.*_sfi.BB*.signed"
fixomap_new = "*winchester.*_sfi.BB*.signed"
fixomap_old = "*os.factory_sfi.BB*.signed"
fix8930 = "*qc8x30.BB*.signed"
fix8974_new = "*qc8974.BB*.signed"
fix8974_old = "*qc8974.*_sfi.BB*.signed"
else:
fix8960 = "*qc8960.*_sfi.desktop.BB*.signed"
fixomap_new = "*winchester.*_sfi.desktop.BB*.signed"
fixomap_old = "*os.factory_sfi.desktop.BB*.signed"
fix8930 = "*qc8x30.desktop.BB*.signed"
fix8974_new = "*qc8974.desktop.BB*.signed"
fix8974_old = "*qc8974.*_sfi.desktop.BB*.signed"
return fix8960, fixomap_new, fixomap_old, fix8930, fix8974_new, fix8974_old
[docs]def read_os_files(localdir, core=False):
"""
Read list of OS signed files, return name assignments.
:param localdir: Directory to use.
:type localdir: str
:param core: If we're using a core OS image. Default is false.
:type core: bool
"""
fix8960, fixomap_new, fixomap_old, fix8930, fix8974_new, fix8974_old = generate_os_fixes(core)
# 8960
os_8960 = find_signed_file(fix8960, localdir, "8960 OS")
# 8x30 (10.3.1 MR+)
os_8x30 = find_signed_file(fix8930, localdir, "8x30 OS", True)
if os_8x30 is None:
os_8x30 = find_signed_file(fix8960, localdir, "8x30 OS")
# 8974
os_8974 = find_signed_file(fix8974_new, localdir, "8974 OS", True)
if os_8974 is None:
os_8974 = find_signed_file(fix8974_old, localdir, "8974 OS")
# OMAP
os_ti = find_signed_file(fixomap_new, localdir, "OMAP OS", True)
if os_ti is None:
os_ti = find_signed_file(fixomap_old, localdir, "OMAP OS")
return [os_8960, os_8x30, os_8974, os_ti]
[docs]def read_radio_files(localdir):
"""
Read list of radio signed files, return name assignments.
:param localdir: Directory to use.
:type localdir: str
"""
# STL100-1
radio_ti = find_signed_file("*radio.m5730*.signed", localdir, "OMAP radio")
# STL100-X
radio_z10 = find_signed_file("*radio.qc8960.BB*.signed", localdir, "8960 radio")
# STL100-4
radio_z10_vzw = find_signed_file("*radio.qc8960*omadm*.signed", localdir, "VZW 8960 radio")
# Q10/Q5
radio_q10 = find_signed_file("*radio.qc8960*wtr.*signed", localdir, "Q10/Q5 radio")
# Z30/Classic
radio_z30 = find_signed_file("*radio.qc8960*wtr5*.signed", localdir, "Z30/Classic radio")
# Z3
radio_z3 = find_signed_file("*radio.qc8930*wtr5*.signed", localdir, "Z3 radio")
# Passport
radio_8974 = find_signed_file("*radio.qc8974*wtr2*.signed", localdir, "Passport radio")
return [radio_ti, radio_z10, radio_z10_vzw, radio_q10, radio_z30, radio_z3, radio_8974]
[docs]def zeropad(splitver, idx, padlen):
"""
Zero-pad an element of an OS/radio version to a certain length.
:param splitver: OS/radio version, but split into quarters.
:type splitver: list(str)
:param idx: Index of splitver which must be checked.
:type idx: int
:param padlen: Length to pad to.
:type padlen: int
"""
if len(splitver[idx]) < padlen:
splitver[idx] = splitver[idx].rjust(padlen, "0")
return splitver
[docs]def versionpad(splitver):
"""
Properly pad an OS/radio version.
:param splitver: OS/radio version, but split into quarters.
:type splitver: list(str)
"""
splitver = zeropad(splitver, 2, 2)
splitver = zeropad(splitver, 3, 4)
return splitver
[docs]def generate_loaders(osversion, radioversion, radios=True, localdir=None, altradio=False, core=False):
"""
Create and label autoloaders for :mod:`bbarchivist.scripts.archivist`.
:param osversion: OS version, 10.x.y.zzzz.
:type osversion: str
:param radioversion: Radio version, 10.x.y.zzzz.
:type radioversion: str
:param radios: Whether to make radios or not. True by default.
:type radios: bool
:param localdir: Working path. Default is local dir.
:type localdir: str
:param altradio: If we're using an alternate radio. Default is false.
:type altradio: bool
:param core: If we're using a core OS image. Default is false.
:type core: bool
"""
# default parsing
localdir = utilities.dirhandler(localdir, os.getcwd())
print("GETTING FILENAMES...")
filedict = read_files(localdir, core)
osversion, radioversion = pretty_formatter(osversion, radioversion)
suffix = format_suffix(altradio, radioversion, core)
# Generate loaders
print("CREATING LOADERS...")
filtrad = [rad for rad in filedict.keys() if rad] # pop None
generate_individual_loaders(filtrad, osversion, radioversion, suffix, filedict, radios, localdir)
[docs]def generate_individual_loaders(filtrad, osversion, radioversion, suffix, filedict, radios, localdir):
"""
Generate individual loaders when generating several at once.
:param filtrad: List of radio files, if they exist.
:type filtrad: list(str)
:param osversion: OS version, 10.x.y.zzzz.
:type osversion: str
:param radioversion: Radio version, 10.x.y.zzzz.
:type radioversion: str
:param suffix: Alternate radio, or blank.
:type suffix: str
:param filedict: Dictionary of radio:OS pairs.
:type filedict: dict(str: str)
:param radios: Whether to make radios or not. True by default.
:type radios: bool
:param localdir: Working path. Default is local dir.
:type localdir: str
"""
for radval in filtrad:
device = generate_device(radval)
osname = generate_filename(device, osversion, suffix)
osfile = filedict[radval]
if osfile is not None:
wrap_pseudocap(osname, localdir, osfile, radval)
if radios:
radname = generate_filename(device, radioversion, "")
wrap_pseudocap(radname, localdir, radval)
[docs]def wrap_pseudocap(filename, folder, first, second=None):
"""
A filtered, excepting wrapper for pseudocap.
:param filename: The title of the new loader.
:type filename: str
:param folder: The folder to create the loader in.
:type folder: str
:param first: The first signed file, required.
:type first: str
:param second: The second signed file, optional.
:type second: str
"""
if first is None:
print("No OS!")
raise SystemError
try:
pseudocap.make_autoloader(filename, [first, second], folder=folder)
except (OSError, IndexError, SystemError) as exc:
msg = "Could not create {0}".format(filename)
exceptions.handle_exception(exc, msg, None)
[docs]def generate_skeletons():
"""
Read JSON to get a dict of all filename components.
"""
namelist = {0: None, 1: None, 2: None, 3: None, 4: None, 5: None, 6: None}
data = jsonutils.load_json('integermap')
for key in data:
if key['id'] in namelist:
namelist[key['id']] = (key['parts'])
namelist[key['id']].append(".exe")
return namelist
[docs]def generate_device(radio):
"""
Read JSON to get the device integer ID from device radio.
:param radio: The radio filename to look up.
:type radio: str
"""
data = jsonutils.load_json('integermap')
for key in data:
if key['radtype'] in radio:
idx = int(key['id'])
break
return idx
[docs]def generate_filename(device, version, suffix=None):
"""
Use skeleton dict to create loader filenames.
:param device: Device to use.
:type device: int
:param version: OS or radio version.
:type version: str
:param suffix: Alternate radio, or blank.
:type suffix: str
"""
thed = generate_skeletons()
if device < 0:
return None
dev = thed[device]
if suffix is None:
suffix = ""
return "{0}{1}{2}{3}{4}".format(dev[0], version, suffix, dev[1], dev[2])
[docs]def generate_lazy_loader(osversion, device, localdir=None, altradio=None, core=False):
"""
Create and label autoloaders for :mod:`bbarchivist.scripts.lazyloader`.
:func:`generate_loaders`, but for making one OS/radio loader.
:param osversion: OS version, 10.x.y.zzzz.
:type osversion: str
:param device: Selected device, from
:type device: int
:param localdir: Working path. Default is local dir.
:type localdir: str
:param altradio: The alternate radio in use, if there is one.
:type altradio: str
:param core: If we're using a core OS image. Default is false.
:type core: bool
"""
# default parsing
localdir = utilities.dirhandler(localdir, os.getcwd())
print("CREATING LOADER...")
suffix = format_suffix(bool(altradio), altradio, core)
osfile = None
absoglob = "{0}{1}".format(localdir, os.sep)
try:
osfile = str(glob.glob("{0}*_sfi*.signed".format(absoglob))[0])
except IndexError:
print("No OS found")
else:
generate_lazy_set(osversion, device, osfile, suffix, absoglob, localdir)
[docs]def generate_lazy_set(osversion, device, osfile, suffix, absoglob, localdir=None):
"""
Get radio file and then generate autoloader.
:param osversion: OS version, 10.x.y.zzzz.
:type osversion: str
:param device: Selected device, from
:type device: int
:param osfile: OS signed filename.
:type osfile: str
:param suffix: Loader name suffix.
:type suffix: str
:param absoglob: Local path + path separator.
:type absoglob: str
:param localdir: Working path. Default is local dir.
:type localdir: str
"""
radiofile = None
try:
sset = set(glob.glob("{0}*.signed".format(absoglob)))
rset = sset - set(glob.glob("{0}*_sfi*.signed".format(absoglob)))
radiofile = str(list(rset)[0])
except IndexError:
print("No radio found")
else:
loadername = generate_lazy_filename(osversion, suffix, device)
wrap_pseudocap(loadername, localdir, osfile, radiofile)
[docs]def generate_lazy_filename(osversion, suffix, device):
"""
Read JSON to formulate a single filename.
:param osversion: OS version.
:type osversion: str
:param suffix: Alternate radio, or just blank.
:type suffix: str
:param device: Device to use.
:type device: int
"""
data = jsonutils.load_json('integermap')
for key in data:
if key['id'] == device:
fname = key['parts']
break
return "{0}{1}{2}{3}.exe".format(fname[0], osversion, suffix, fname[1])