X-Git-Url: https://git.grml.org/?p=grml2usb.git;a=blobdiff_plain;f=grml2usb;h=7afeb4881b76f0f48184bc008385c7498dc0367f;hp=70d514299e07b884044965ac83821135a3162778;hb=3664e4ae1482b8951b741d459f8860ba3a4b38c1;hpb=8576eac780fdac5bd1c71eafb5d8520da39c8d05 diff --git a/grml2usb b/grml2usb index 70d5142..7afeb48 100755 --- a/grml2usb +++ b/grml2usb @@ -14,7 +14,6 @@ This script installs a Grml system (either a running system or ISO[s]) to a USB """ -import datetime import fileinput import glob import logging @@ -22,11 +21,9 @@ import os import os.path import re import shutil -import struct import subprocess import sys import tempfile -import time import uuid from inspect import isclass, isroutine from optparse import OptionParser @@ -53,9 +50,6 @@ except Exception: # global variables MOUNTED = set() # register mountpoints TMPFILES = set() # register tmpfiles -DATESTAMP = time.mktime( - datetime.datetime.now().timetuple() -) # unique identifier for syslinux.cfg GRML_FLAVOURS = set() # which flavours are being installed? GRML_DEFAULT = None UUID = None @@ -63,7 +57,6 @@ SYSLINUX_LIBS = [ "/usr/lib/syslinux/modules/bios/", # Debian "/usr/lib/syslinux/bios/", # Arch Linux ] -GPT_HEADER = b"\x55\xaa\x45\x46\x49\x20\x50\x41\x52\x54" # original GPT header GRUB_INSTALL = None RE_PARTITION = re.compile(r"([a-z/]*?)(\d+)$") @@ -71,7 +64,7 @@ RE_P_PARTITION = re.compile(r"(.*?\d+)p(\d+)$") RE_LOOP_DEVICE = re.compile(r"/dev/loop\d+$") -def syslinux_warning(option, opt, value, opt_parser): +def syslinux_warning(option, opt, opt_parser): """A helper function for printing a warning about deprecated option """ # pylint: disable-msg=W0613 @@ -83,7 +76,7 @@ def syslinux_warning(option, opt, value, opt_parser): # if grub option is set, unset syslinux option -def grub_option(option, opt, value, opt_parser): +def grub_option(option, opt, opt_parser): """A helper function adjusting other option values """ # pylint: disable-msg=W0613 @@ -273,29 +266,12 @@ class VerifyException(Exception): @Exception: message""" -# The following two functions help to operate on strings as -# array (list) of bytes (octets). In Python 3000, the bytes -# datatype will need to be used. This is intended for using -# with manipulation of files on the octet level, like shell -# arrays, e.g. in MBR creation. - - -def array2string(*a): - """Convert a list of integers [0;255] to a string.""" - return struct.pack("%sB" % len(a), *a) - - -def string2array(s): - """Convert a (bytes) string into a list of integers.""" - return struct.unpack("%sB" % len(s), s) - - def cleanup(): """Cleanup function to make sure there aren't any mounted devices left behind. """ - def del_failed(fn, path, exc): - logging.warn("Deletion of %s failed in temporary folder" % path) + def del_failed(_fn, path, _exc): + logging.warning("Deletion of %s failed in temporary folder", path) logging.info("Cleaning up before exiting...") proc = subprocess.Popen(["sync"]) @@ -465,8 +441,7 @@ def search_file( retval.append(os.path.abspath(os.path.join(current_dir, filename))) if not lst_return: break - # pylint: disable-msg=W0612 - for current_dir, directories, files in os.walk(path): + for current_dir, _directories, _files in os.walk(path): if match_file(current_dir): retval.append(os.path.abspath(os.path.join(current_dir, filename))) if not lst_return: @@ -503,6 +478,12 @@ def get_partition_for_path(path): def check_boot_flag(device): + if os.path.isdir(device): + logging.debug( + "Device %s is a directory, skipping check for boot flag." % device + ) + return + boot_dev, x = get_device_from_partition(device) logging.info("Checking for boot flag") @@ -545,29 +526,8 @@ def mkfs_fat16(device): raise CriticalException("error executing mkfs.vfat") -def generate_isolinux_splash(grml_flavour): - """Generate bootsplash for isolinux/syslinux - - @grml_flavour: name of grml flavour the configuration should be generated for""" - - grml_name = grml_flavour - - return """\ -17 /boot/syslinux/logo.16 - -Some information and boot options available via keys F2 - F10. http://grml.org/ -%(grml_name)s -""" % { - "grml_name": grml_name - } - - -def generate_main_syslinux_config(*arg): - """Generate main configuration for use in syslinux.cfg - - @*arg: just for backward compatibility""" - # pylint: disable-msg=W0613 - # remove warning about unused arg +def generate_main_syslinux_config(): + """Generate main configuration for use in syslinux.cfg""" return """\ label - @@ -748,16 +708,14 @@ def install_mbr(mbrtemplate, device, partition, ismirbsdmbr=True): "mbrtemplate" file, set the "partition" (0..3) active, and install the result back to "device". - @mbrtemplate: default MBR file + @mbrtemplate: default MBR file (must be a valid MBR file of at least 440 + (or 439 if ismirbsdmbr) bytes) @device: name of a file assumed to be a hard disc (or USB stick) image, or something like "/dev/sdb" @partition: must be a number between 0 and 3, inclusive - @mbrtemplate: must be a valid MBR file of at least 440 (or 439 if - ismirbsdmbr) bytes. - @ismirbsdmbr: if true then ignore the active flag, set the mirbsdmbr specific flag to 0/1/2/3 and set the MBR's default value accordingly. If false then leave the mirbsdmbr specific flag set to FFh, set all @@ -776,7 +734,7 @@ def install_mbr(mbrtemplate, device, partition, ismirbsdmbr=True): raise CriticalException("%s can not be read." % mbrtemplate) if partition is not None and ((partition < 0) or (partition > 3)): - logging.warn("Cannot activate partition %d", partition) + logging.warning("Cannot activate partition %d", partition) partition = None if ismirbsdmbr: @@ -875,21 +833,15 @@ def install_mbr(mbrtemplate, device, partition, ismirbsdmbr=True): proc = subprocess.Popen(["sync"]) proc.wait() - set_rw(device) - - -def is_writeable(device): - """Check if the device is writeable for the current user - - @device: partition where bootloader should be installed to""" - - if not device: - return False - - if not os.path.exists(device): - return False + logging.debug("Probing device via 'blockdev --rereadpt %s'", device) + proc = subprocess.Popen(["blockdev", "--rereadpt", device]) + proc.wait() + if proc.returncode != 0: + raise Exception( + "Couldn't execute blockdev on '%s' (install util-linux?)", device + ) - return os.access(device, os.W_OK) and os.access(device, os.R_OK) + set_rw(device) def mount(source, target, mount_options): @@ -906,7 +858,7 @@ def mount(source, target, mount_options): if x.startswith(source): raise CriticalException( ( - "Error executing mount: %s already mounted - " + "Error executing mount: {0} already mounted - " "please unmount before invoking grml2usb" ).format(source) ) @@ -1126,54 +1078,6 @@ def copy_system_files(grml_flavour, iso_mount, target): exec_rsync(source, dest) -def update_grml_versions(iso_mount, target): - """Update the grml version file on a cd - Returns true if version was updated successfully, - False if grml-version does not exist yet on the mountpoint - - @iso_mount: string of the iso mount point - @target: path of the target mount point - """ - grml_target = target + "/grml/" - target_grml_version_file = search_file("grml-version", grml_target) - if target_grml_version_file: - iso_grml_version_file = search_file("grml-version", iso_mount) - if not iso_grml_version_file: - logging.warn( - "Warning: %s could not be found - can not install it", - iso_grml_version_file, - ) - return False - try: - # read the flavours from the iso image - iso_versions = {} - iso_file = open(iso_grml_version_file, "r") - for line in iso_file: - iso_versions[get_flavour(line)] = line.strip() - - # update the existing flavours on the target - for line in fileinput.input([target_grml_version_file], inplace=1): - flavour = get_flavour(line) - if flavour in list(iso_versions.keys()): - print(iso_versions.pop(flavour)) - else: - print(line.strip()) - fileinput.close() - - target_file = open(target_grml_version_file, "a") - # add the new flavours from the current iso - for flavour in iso_versions: - target_file.write("%s\n" % iso_versions[flavour]) - except IOError: - logging.warn("Warning: Could not write file") - finally: - iso_file.close() - target_file.close() - return True - else: - return False - - def copy_grml_files(grml_flavour, iso_mount, target): """copy some minor grml files to a given target @@ -1191,7 +1095,9 @@ def copy_grml_files(grml_flavour, iso_mount, target): exec_rsync(filename, grml_target) break else: - logging.warn("Warning: could not find flavour directory for %s ", grml_flavour) + logging.warning( + "Warning: could not find flavour directory for %s ", grml_flavour + ) def copy_addons(iso_mount, target): @@ -1302,6 +1208,9 @@ def copy_bootloader_files(iso_mount, target, grml_flavour): exec_rsync(efi_img, target + "/boot/efi.img") handle_secure_boot(target, efi_img) + execute(mkdir, target + "/conf/") + glob_and_copy(iso_mount + "/conf/bootfile_*", target + "/conf/") + for ffile in ["f%d" % number for number in range(1, 11)]: search_and_copy(ffile, iso_mount, syslinux_target + ffile) @@ -1481,7 +1390,6 @@ def handle_grub_config(grml_flavour, device, target): logging.debug("Updating grub configuration") grub_target = target + "/boot/grub/" - secureboot_target = target + "/EFI/ubuntu/" bootid_re = re.compile(r"bootid=[\w_-]+") live_media_path_re = re.compile(r"live-media-path=[\w_/-]+") @@ -1496,9 +1404,7 @@ def handle_grub_config(grml_flavour, device, target): remove_regexes.append(re.compile(regex)) shortname = get_shortname(grml_flavour) - for filename in glob.glob(grub_target + "*.cfg") + glob.glob( - secureboot_target + "*.cfg" - ): + for filename in glob.glob(grub_target + "*.cfg"): for line in fileinput.input(filename, inplace=1): line = line.rstrip("\r\n") if option_re.search(line): @@ -1748,18 +1654,18 @@ def handle_secure_boot(target, efi_img): logging.critical("Fatal: %s", error) sys.exit(1) - ubuntu_cfg = search_file("grub.cfg", efi_mountpoint + "/EFI/ubuntu") - logging.debug("ubuntu_cfg = %s" % ubuntu_cfg) - if not ubuntu_cfg: + grub_cfg = search_file("grub.cfg", efi_mountpoint + "/boot/grub/") + logging.debug("grub_cfg = %s" % grub_cfg) + if not grub_cfg: logging.info( - "No /EFI/ubuntu/grub.cfg found inside EFI image, looks like Secure Boot support is missing." + "No /boot/grub/grub.cfg found inside EFI image, looks like Secure Boot support is missing." ) else: - mkdir(target + "/efi/ubuntu") + mkdir(target + "/boot/grub/x86_64-efi/") logging.debug( - "exec_rsync(%s, %s + '/efi/ubuntu/grub.cfg')" % (ubuntu_cfg, target) + "exec_rsync(%s, %s + '/boot/grub/x86_64-efi/grub.cfg')" % (grub_cfg, target) ) - exec_rsync(ubuntu_cfg, target + "/efi/ubuntu/grub.cfg") + exec_rsync(grub_cfg, target + "/boot/grub/x86_64-efi/grub.cfg") logging.debug( "exec_rsync(%s + '/EFI/BOOT/grubx64.efi', %s + '/efi/boot/grubx64.efi')'" @@ -1917,7 +1823,7 @@ def handle_mbr(device): mbr_device, partition_number = get_device_from_partition(device) if partition_number is None: - logging.warn("Could not detect partition number, not activating partition") + logging.warning("Could not detect partition number, not activating partition") # if we get e.g. /dev/loop1 as device we don't want to put the MBR # into /dev/loop of course, therefore use /dev/loop1 as mbr_device @@ -1941,7 +1847,7 @@ def handle_mbr(device): break if not mbrcode: - str_locations = " or ".join(['"%s"' % l for l in mbr_locations]) + str_locations = " or ".join(['"%s"' % x for x in mbr_locations]) logging.error("Cannot find syslinux MBR, install it at %s)", str_locations) raise CriticalException( "syslinux MBR can not be found at %s." % str_locations @@ -2152,7 +2058,7 @@ def main(): if not os.path.isdir(device): if device[-1:].isdigit(): if int(device[-1:]) > 4 or device[-2:].isdigit(): - logging.warn( + logging.warning( "Warning: installing on partition number >4, booting *might* fail depending on your system." )