#!/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)