fwupd/contrib/standalone-installer/make.py
Mario Limonciello 2d12a24234 contrib: Add a standalone installer creation script
This is meant to produce standalone installer binaries that can operate
on machines without current tools or internet access.

It works by wrapping around the container technologies snap and flatpak
and putting all the pieces together.
2018-09-14 12:34:09 -05:00

119 lines
3.8 KiB
Python
Executable File

#!/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("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):
cmd = ['wget', 'https://people.freedesktop.org/~hughsient/temp/fwupd.flatpak', '-O', 'fwupd.flatpak']
if 'DEBUG' in os.environ:
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)
generate_installer (directory, args.target)