#!/usr/bin/python3 # # Copyright (C) 2017 Dell, Inc. # # SPDX-License-Identifier: LGPL-2.1+ # from base64 import b64encode import io import os import subprocess import shutil import sys import tempfile import zipfile from assets.header import TAG def error (msg): print(msg) sys.exit(1) def parse_args(): import argparse parser = argparse.ArgumentParser(description="Generate a standalone firmware updater") parser.add_argument("--disable-snap-download", action='store_true', help="Don't download support for snap") parser.add_argument("--disable-flatpak-download", action='store_true', help="Don't download support for flatpak") parser.add_argument("--snap-channel", help="Channel to download snap from (optional)") parser.add_argument("--minimum", help="Use already installed fwupd version if at least this version") parser.add_argument("cab", help="CAB file or directory containing CAB files to automatically install") parser.add_argument('target', help='target file to create') args = parser.parse_args() return args def bytes_slicer(length, source): start = 0 stop = length while start < len(source): yield source[start:stop] start = stop stop += length def generate_installer (directory, target): asset_base = os.path.join (os.path.dirname(os.path.realpath(__file__)), "assets") #header shutil.copy (os.path.join (asset_base, "header.py"), target) #zip file buffer = io.BytesIO() archive = zipfile.ZipFile(buffer, "a") for root, dirs, files in os.walk (directory): for f in files: source = os.path.join(root, f) archive_fname = source.split (directory) [1] archive.write(source, archive_fname) if 'DEBUG' in os.environ: print (archive.namelist()) archive.close() with open (target, 'ab') as bytes_out: encoded = b64encode(buffer.getvalue()) for section in bytes_slicer(64, encoded): bytes_out.write(TAG) bytes_out.write(section) bytes_out.write(b'\n') def download_snap (directory, channel): cmd = ['snap', 'download', 'fwupd'] if channel is not None: cmd += ['--channel', channel] if 'DEBUG' in os.environ: print(cmd) subprocess.run (cmd, cwd=directory, check=True) for f in os.listdir (directory): # the signatures associated with the snap if f.endswith(".assert"): shutil.move (os.path.join(directory, f), os.path.join(directory, 'fwupd.assert')) # the snap binary itself elif f.endswith(".snap"): shutil.move (os.path.join(directory, f), os.path.join(directory, 'fwupd.snap')) def download_cab_file (directory, uri): cmd = ['wget', uri] if 'DEBUG' in os.environ: print(cmd) subprocess.run (cmd, cwd=directory, check=True) def download_flatpak (directory): dep = 'org.freedesktop.fwupd' flatpak_dir = os.path.join(os.getenv('HOME'),'.local', 'share', 'flatpak') verbose = 'DEBUG' in os.environ #check if we have installed locally already or not if not os.path.exists (os.path.join (flatpak_dir, 'app', dep)): # install into local user's repo cmd = ['flatpak', 'install', '--user', 'https://www.flathub.org/repo/appstream/org.freedesktop.fwupd.flatpakref', '--no-deps', '-y'] if verbose: print(cmd) subprocess.run (cmd, cwd=directory, check=True) # generate a bundle repo = os.path.join(flatpak_dir, 'repo') cmd = ['flatpak', 'build-bundle', repo, 'fwupd.flatpak', dep, 'stable'] if verbose: print(cmd) subprocess.run (cmd, cwd=directory, check=True) if __name__ == '__main__': args = parse_args() if not args.cab.startswith("http"): local = args.cab with tempfile.TemporaryDirectory (prefix='fwupd') as directory: if local: if not os.path.exists (local): error ("%s doesn't exist" % local) if not os.path.isdir(local): shutil.copy (local, directory) else: for root, dirs, files in os.walk(local): for f in files: shutil.copy (os.path.join(root, f), directory) else: download_cab_file (directory, args.cab) if not args.disable_snap_download: download_snap (directory, args.snap_channel) if not args.disable_flatpak_download: download_flatpak (directory) if args.minimum: with open(os.path.join(directory, "minimum"), "w") as wfd: wfd.write(args.minimum) generate_installer (directory, args.target)