fwupd/contrib/standalone-installer/assets/header.py

253 lines
8.0 KiB
Python

#!/usr/bin/python3
#
# Copyright (C) 2017 Dell, Inc.
#
# SPDX-License-Identifier: LGPL-2.1+
#
from base64 import b64decode
import io
import os
import subprocess
import sys
import shutil
import tempfile
import zipfile
TAG = b'#\x00'
def parse_args():
import argparse
parser = argparse.ArgumentParser(description="Self extracting firmware updater")
parser.add_argument("--directory", help="Directory to extract to")
parser.add_argument("--uninstall", action='store_true', help="Uninstall tools when done with installation")
parser.add_argument("--verbose", action='store_true', help="Run the tool in verbose mode")
parser.add_argument("--allow-reinstall", action='store_true', help="Allow re-installing existing firmware versions")
parser.add_argument("--allow-older", action='store_true', help="Allow downgrading firmware versions")
parser.add_argument("command", choices=["install", "extract"], help="Command to run")
args = parser.parse_args()
return args
def error (msg):
print(msg)
sys.exit(1)
def bytes_slicer(length, source):
start = 0
stop = length
while start < len(source):
yield source[start:stop]
start = stop
stop += length
def get_zip():
script = os.path.realpath (__file__)
bytes_out = io.BytesIO()
with open(script, 'rb') as source:
for line in source:
if not line.startswith(TAG):
continue
bytes_out.write(b64decode(line[len(TAG):-1]))
return bytes_out
def unzip (destination):
zipf = get_zip ()
source = zipfile.ZipFile (zipf, 'r')
for item in source.namelist():
# extract handles the sanitization
source.extract (item, destination)
def copy_cabs (source, target):
if not os.path.exists (target):
os.makedirs (target)
cabs = []
for root, dirs, files in os.walk (source):
for f in files:
if (f.endswith ('.cab')):
origf = os.path.join(root, f)
shutil.copy (origf, target)
cabs.append (os.path.join (target, f))
return cabs
def install_snap (directory, verbose, allow_reinstall, allow_older, uninstall):
app = 'fwupd'
common = '/root/snap/%s/common' % app
#check if snap is installed
with open(os.devnull, 'w') as devnull:
subprocess.run (['snap'], check=True, stdout=devnull, stderr=devnull)
#check existing installed
cmd = ['snap', 'list', app]
with open(os.devnull, 'w') as devnull:
if verbose:
print(cmd)
ret = subprocess.run (cmd, stdout=devnull, stderr=devnull)
if ret.returncode == 0:
cmd = ['snap', 'remove', app]
if verbose:
print(cmd)
subprocess.run (cmd, check=True)
# install the snap
cmd = ['snap', 'ack', os.path.join (directory, 'fwupd.assert')]
if verbose:
print(cmd)
subprocess.run (cmd, check=True)
cmd = ['snap', 'install', '--classic', os.path.join (directory, 'fwupd.snap')]
if verbose:
print(cmd)
subprocess.run (cmd, check=True)
# copy the CAB files
cabs = copy_cabs (directory, common)
# run the snap
for cab in cabs:
cmd = ["%s.fwupdmgr" % app, 'install', cab]
if allow_reinstall:
cmd += ["--allow-reinstall"]
if allow_older:
cmd += ["--allow-older"]
if verbose:
cmd += ["--verbose"]
print(cmd)
subprocess.run (cmd)
#remove copied cabs
for f in cabs:
os.remove(f)
#cleanup
if uninstall:
cmd = ['snap', 'remove', app]
if verbose:
print(cmd)
subprocess.run (cmd)
def install_flatpak (directory, verbose, allow_reinstall, allow_older, uninstall):
app = 'org.freedesktop.fwupd'
common = '%s/.var/app/%s' % (os.getenv ('HOME'), app)
with open(os.devnull, 'w') as devnull:
if not verbose:
output = devnull
else:
output = None
#look for dependencies
dep = 'org.gnome.Platform/x86_64/3.30'
repo = 'flathub'
repo_url = 'https://flathub.org/repo/flathub.flatpakrepo'
cmd = ['flatpak', 'info', dep]
if verbose:
print(cmd)
ret = subprocess.run (cmd, stdout=output, stderr=output)
#not installed
if ret.returncode != 0:
#look for remotes
cmd = ['flatpak', 'remote-info', repo, dep]
if verbose:
print(cmd)
ret = subprocess.run (cmd, stdout=output, stderr=output)
#not enabled, enable it
if ret.returncode != 0:
cmd = ['flatpak', 'remote-add', repo, repo_url]
if verbose:
print(cmd)
ret = subprocess.run (cmd, stderr=output)
# install dep
cmd = ['flatpak', 'install', repo, dep]
if verbose:
print(cmd)
ret = subprocess.run (cmd)
#check existing installed
cmd = ['flatpak', 'info', app]
if verbose:
print(cmd)
ret = subprocess.run (cmd, stdout=output, stderr=output)
if ret.returncode == 0:
cmd = ['flatpak', 'remove', app]
if verbose:
print(cmd)
subprocess.run (cmd, check=True)
#install the flatpak
cmd = ['flatpak', 'install', os.path.join (directory, 'fwupd.flatpak')]
if verbose:
print(cmd)
subprocess.run (cmd, check=True)
# copy the CAB files
cabs = copy_cabs (directory, common)
#run command
for cab in cabs:
cmd = ['flatpak', 'run', app, 'install', cab]
if allow_reinstall:
cmd += ["--allow-reinstall"]
if allow_older:
cmd += ["--allow-older"]
if verbose:
cmd += ["--verbose"]
print(cmd)
subprocess.run (cmd)
#remove copied cabs
for f in cabs:
os.remove(f)
#cleanup
if uninstall:
cmd = ['flatpak', 'remove', app]
if verbose:
print(cmd)
subprocess.run (cmd)
def run_installation (directory, verbose, allow_reinstall, allow_older, uninstall):
try_snap = False
try_flatpak = False
# determine what self extracting binary has
if os.path.exists (os.path.join (directory, 'fwupd.snap')) and \
os.path.exists (os.path.join (directory, 'fwupd.assert')):
try_snap = True
if os.path.exists (os.path.join (directory, 'fwupd.flatpak')):
try_flatpak = True
if try_snap:
try:
install_snap (directory, verbose, allow_reinstall, allow_older, uninstall)
return True
except Exception as _:
if verbose:
print ("Snap installation failed")
if not try_flatpak:
error ("Snap installation failed")
if try_flatpak:
install_flatpak (directory, verbose, allow_reinstall, allow_older, uninstall)
if __name__ == '__main__':
args = parse_args()
if 'extract' in args.command:
if args.allow_reinstall:
error ("allow-reinstall argument doesn't make sense with command %s" % args.command)
if args.allow_older:
error ("allow-older argument doesn't make sense with command %s" % args.command)
if args.uninstall:
error ("Uninstall argument doesn't make sense with command %s" % args.command)
if args.directory is None:
error ("No directory specified")
if not os.path.exists (args.directory):
print ("Creating %s" % args.directory)
os.makedirs (args.directory)
unzip (args.directory)
else:
if args.directory:
error ("Directory argument %s doesn't make sense with command %s" % (args.directory, args.command))
if os.getuid() != 0:
error ("This tool must be run as root")
with tempfile.TemporaryDirectory (prefix='fwupd') as target:
unzip (target)
run_installation (target, args.verbose, args.allow_reinstall, args.allow_older, args.uninstall)