"""
-import datetime
import fileinput
import glob
import logging
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
# 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
"/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+)$")
RE_LOOP_DEVICE = re.compile(r"/dev/loop\d+$")
-def syslinux_warning(option, opt, value, opt_parser):
- """A helper function for printing a warning about deprecated option
- """
+def syslinux_warning(option, opt, _value, opt_parser):
+ """A helper function for printing a warning about deprecated option"""
# pylint: disable-msg=W0613
sys.stderr.write(
"Note: the --syslinux option is deprecated as syslinux "
# if grub option is set, unset syslinux option
-def grub_option(option, opt, value, opt_parser):
- """A helper function adjusting other option values
- """
+def grub_option(option, opt, _value, opt_parser):
+ """A helper function adjusting other option values"""
# pylint: disable-msg=W0613
setattr(opt_parser.values, option.dest, True)
setattr(opt_parser.values, "syslinux", False)
@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.
- """
+ """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"])
def get_defaults_file(iso_mount, flavour, name):
- """get the default file for syslinux
- """
+ """get the default file for syslinux"""
bootloader_dirs = ["/boot/isolinux/", "/boot/syslinux/"]
for directory in bootloader_dirs:
for name in name, "%s_%s" % (get_flavour_filename(flavour), name):
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:
logging.info("Formating partition with fat16 filesystem")
logging.debug("mkfs.vfat -F 16 %s", device)
- proc = subprocess.Popen(["mkfs.vfat", "-F", "16", device])
+ proc = subprocess.Popen(["mkfs.vfat", "-n", "GRML", "-F", "16", device])
proc.wait()
if proc.returncode != 0:
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 """\
-\ f17\f\18/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 -
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:
set_rw(device)
logging.debug(
- "executing: dd if='%s' of='%s' bs=512 count=1 conv=notrunc", tmpf.name, device
+ "executing: dd if='%s' of='%s' bs=512 count=1 conv=notrunc,fsync",
+ tmpf.name,
+ device,
)
proc = subprocess.Popen(
[
"of=%s" % device,
"bs=512",
"count=1",
- "conv=notrunc",
+ "conv=notrunc,fsync",
],
stderr=open(os.devnull, "r+"),
)
raise Exception("error executing dd (third run)")
del tmpf
- # make sure we sync filesystems before returning
- logging.debug("executing: sync")
- proc = subprocess.Popen(["sync"])
- proc.wait()
-
logging.debug("Probing device via 'blockdev --rereadpt %s'", device)
proc = subprocess.Popen(["blockdev", "--rereadpt", device])
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
-
- return os.access(device, os.W_OK) and os.access(device, os.R_OK)
-
-
def mount(source, target, mount_options):
"""Mount specified source on given target
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)
)
unregister_mountpoint(target)
+def extract_device_name(device):
+ """Extract the device name of a given path
+
+ @device: device name, like /dev/sda1 or /dev/sda
+ """
+ return re.match(r"/dev/(.*?)\d*$", device).group(1)
+
+
def check_for_usbdevice(device):
"""Check whether the specified device is a removable USB device
@device: device name, like /dev/sda1 or /dev/sda
"""
- usbdevice = re.match(r"/dev/(.*?)\d*$", device).group(1)
+ usbdevice = extract_device_name(device)
# newer systems:
usbdev = os.path.realpath("/sys/class/block/" + usbdevice + "/removable")
if not os.path.isfile(usbdev):
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
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):
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)
def get_flavour(flavour_str):
- """Returns the flavour of a grml version string
- """
+ """Returns the flavour of a grml version string"""
return re.match(r"[\w-]*", flavour_str).group()
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_/-]+")
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):
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')'"
def remove_mountpoint(mountpoint):
- """remove a registered mountpoint
- """
+ """remove a registered mountpoint"""
try:
unmount(mountpoint, "")
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
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
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."
)