You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
multibootusb/scripts/update_cfg_file.py

1311 lines
63 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Name: update_cfg_file.py
# Purpose: Module to manipulate distro specific and main config files.
# Authors: Sundar
# Licence: This file is a part of multibootusb package. You can redistribute it or modify
# under the terms of GNU General Public License, v.2 or above
import os
import re
import shutil
from functools import partial
from .usb import *
from .gen import *
from .iso import *
from . import config
from . import grub
from . import menus
from .param_rewrite import add_tokens, remove_tokens, replace_token, \
add_or_replace_kv, replace_kv, remove_keys, \
always, contains_token, contains_all_tokens, contains_any_token, \
contains_key, contains_all_keys, contains_any_key, starter_is_either, _not
def dont_require_tweaking(fname, content, match_start, match_end):
# Avoid fixing a path on a comment line
beginning_of_line = content.rfind('\n', 0, match_start)
if beginning_of_line<0:
beginning_of_line = 0
if content[beginning_of_line:match_start].lstrip()[:1]=='#':
return True
if fname.startswith(('cdrom/', 'dev/')):
return True
if (4 <= match_start and # Don't write an arg of 'init=' param.
content[match_start-4:match_start+1] == 'init='):
return True
def fix_abspath_r(pattern, string, install_dir, iso_name, kept_paths):
"""Return a list of tuples consisting of 'string' with replaced path and a bool representing if /boot/ was prepended in the expression."""
m = pattern.search(string)
if not m:
return [(string, False)]
start, end = m.span()
prologue, specified_path = m.group(1), m.group(2)
if dont_require_tweaking(specified_path, string, start, end):
return [(string[:start] + prologue + '/' + specified_path,
'/%s is kept as is.' % specified_path)] \
+ fix_abspath_r(pattern, string[end:], install_dir, iso_name,
kept_paths)
# See if a path that has 'boot/' prepended is a better choice.
# E.g. Debian debian-live-9.4.0-amd64-cinnamon has a loopback.cfg
# which contains "source /grub/grub.cfg".
specified_path_exists = os.path.exists(
os.path.join(install_dir, specified_path))
if specified_path_exists:
# Confidently accept what is specified.
selected_path, fixed = specified_path, False
elif os.path.exists(os.path.join(install_dir, 'boot', specified_path)):
selected_path, fixed = ('boot/' + specified_path,
"Prepended '/boot/' to %s" % specified_path)
# A path specified by 'preseed/file=' or 'file=' is utilized
# after OS boots up. Doing this for grub is moot.
#elif specified_path.startswith('cdrom/') and \
# os.path.exists(os.path.join(install_dir, # len('cdrom/') => 6
# specified_path[6:])):
# # See /boot/grub/loopback.cfg in
# # ubuntu-14.04.5-desktop-amd64.iso for an example of this case.
# selected_path, fixed = specified_path[6:], "Removed '/cdrom/'"
elif specified_path.endswith('.efi') and \
os.path.exists(os.path.join(install_dir, specified_path[:-4])):
# Avira-RS provides boot/grub/loopback.cfg which points
# to non-existent /boot/grub/vmlinuz.efi.
selected_path, fixed = (specified_path[:-4],
"Removed '.efi' from %s" % specified_path)
else:
# Reluctantly accept what is specified.
if specified_path not in kept_paths:
kept_paths.append(specified_path)
selected_path, fixed = specified_path, False
out = string[:start] + prologue + '/multibootusb/' + iso_name + '/' \
+ selected_path.replace('\\', '/')
return [(out, fixed)] \
+ fix_abspath_r(pattern, string[end:], install_dir, iso_name,
kept_paths)
def fix_abspath(string, install_dir, iso_name, config_fname):
"""Rewrite what appear to be a path within 'string'. If a file does not exist with specified path, one with '/boot' prepended is tried."""
path_expression = re.compile(r'([ \t=,])/(.*?)((?=[,|\s*])|$)')
kept_paths = []
chunks = fix_abspath_r(
path_expression, string, install_dir, iso_name, kept_paths)
if len(kept_paths)==1:
log("In '%s', '/%s' is kept as is though it does not exist."
% (config_fname, kept_paths[0]))
elif 2<=len(kept_paths):
log("In '%s', "
"following paths are used as they are though they don't exist."
% config_fname)
for kept_path in kept_paths:
log(' /' + kept_path)
tweaked_chunks = [c for c in chunks if c[1]]
if len(tweaked_chunks) == 0:
# Fallback to the legacy implementation so that
# this tweak brings as little breakage as possible.
replace_text = r'\1/multibootusb/' + iso_name + '/'
return re.sub(r'([ \t =,])/', replace_text, string)
else:
log("Applied %s on '%s' as shown below:" %
(len(tweaked_chunks)==1 and 'a rewrite exception' or
('%d rewrite exceptions' % len(tweaked_chunks)), config_fname))
count_dict = {}
for path, op_desc in tweaked_chunks:
count_dict.setdefault(op_desc, []).append((path,op_desc))
for op_desc, sub_chunks in count_dict.items():
log(" %s [%d]" % (op_desc, len(sub_chunks)))
return ''.join([c[0] for c in chunks])
def update_distro_cfg_files(iso_link, usb_disk, distro, persistence=0):
"""
Main function to modify/update distro specific strings on distro config files.
:return:
"""
try:
usb_details = details(config.usb_disk)
except PartitionNotMounted as e:
log(str(e))
return
usb_mount = usb_details['mount_point']
usb_uuid = usb_details['uuid']
usb_label = usb_details['label']
usb_fs_type = usb_details['file_system']
# iso_cfg_ext_dir = os.path.join(multibootusb_host_dir(), "iso_cfg_ext_dir")
config.status_text = "Updating config files..."
_iso_name = iso_basename(iso_link)
install_dir = os.path.join(usb_mount, "multibootusb", _iso_name)
install_dir_for_grub = '/multibootusb/%s' % _iso_name
log('Updating distro specific config files...')
tweaker_params = ConfigTweakerParam(
iso_link, install_dir_for_grub,
persistence, usb_uuid, usb_mount, usb_disk, usb_fs_type)
tweaker_class_dict = {
'ubuntu' : UbuntuConfigTweaker,
'debian' : DebianConfigTweaker,
'debian-install' : DebianConfigTweaker,
'gentoo' : GentooConfigTweaker,
'centos' : FedoraConfigTweaker,
'centos-install' : FedoraConfigTweaker,
'fedora' : FedoraConfigTweaker,
'antix' : AntixConfigTweaker,
'salix-live' : SalixConfigTweaker,
'wifislax' : WifislaxConfigTweaker,
}
tweaker_class = tweaker_class_dict.get(distro)
for dirpath, dirnames, filenames in os.walk(install_dir):
for f in filenames:
if f.endswith(".cfg") or f.endswith('.CFG') or f.endswith('.lst') or f.endswith('.conf'):
cfg_file = os.path.join(dirpath, f)
try:
string = open(cfg_file, errors='ignore').read()
except IOError:
log("Unable to read %s" % cfg_file)
else:
if not distro == "generic":
string = fix_abspath(string, install_dir, _iso_name,
os.path.join(dirpath, f))
string = re.sub(r'linuxefi', 'linux', string)
string = re.sub(r'initrdefi', 'initrd', string)
if tweaker_class:
tweaker = tweaker_class(distro, tweaker_params)
string = tweaker.tweak(string)
elif distro == 'grml':
string = re.sub(r'live-media-path=', 'ignore_bootid live-media-path=', string)
elif distro == "ubuntu-server":
string = re.sub(r'file',
'cdrom-detect/try-usb=true floppy.allowed_drive_mask=0 ignore_uuid ignore_bootid root=UUID=' +
usb_uuid + ' file', string)
elif distro == 'kaspersky':
if not os.path.exists(os.path.join(usb_mount, 'multibootusb', iso_basename(iso_link), 'kaspersky.cfg')):
shutil.copyfile(resource_path(os.path.join('data', 'multibootusb', 'syslinux.cfg')),
os.path.join(usb_mount, 'multibootusb', iso_basename(iso_link), 'kaspersky.cfg'))
config_string = kaspersky_config('kaspersky')
config_string = config_string.replace('$INSTALL_DIR', '/multibootusb/' + iso_basename(iso_link))
config_string = re.sub(r'root=live:UUID=', 'root=live:UUID=' + usb_uuid, config_string)
with open(os.path.join(usb_mount, 'multibootusb', iso_basename(iso_link), 'kaspersky.cfg'), "a") as f:
f.write(config_string)
elif distro == "parted-magic":
if re.search(r'append', string, re.I):
string = re.sub(r'append', 'append directory=/multibootusb/' + iso_basename(iso_link), string,
flags=re.I)
string = re.sub(r'initrd=', 'directory=/multibootusb/' + iso_basename(iso_link) + '/ initrd=',
string)
string = re.sub(r'linux_64=\"', 'linux_64=\"/multibootusb/' + iso_basename(iso_link), string,
flags=re.I)
string = re.sub(r'linux_32=\"', 'linux_32=\"/multibootusb/' + iso_basename(iso_link), string,
flags=re.I)
string = re.sub(r'initrd_img=\"', 'initrd_img=\"/multibootusb/' + iso_basename(iso_link), string,
flags=re.I)
string = re.sub(r'initrd_img32=\"', 'initrd_img32=\"/multibootusb/' + iso_basename(iso_link), string,
flags=re.I)
string = re.sub(r'default_settings=\"', 'default_settings=\"directory=/multibootusb/' + iso_basename(iso_link) + ' ', string,
flags=re.I)
string = re.sub(r'live_settings=\"', 'live_settings=\"directory=/multibootusb/' + iso_basename(iso_link) + ' ', string,
flags=re.I)
elif distro == "ubcd":
string = re.sub(r'iso_filename=\S*', 'directory=/multibootusb/' + iso_basename(iso_link),
string, flags=re.I)
elif distro == 'f4ubcd':
if not 'multibootusb' in string:
string = re.sub(r'/HBCD', '/multibootusb/' + iso_basename(iso_link) + '/HBCD', string)
if not 'multibootusb' in string:
string = re.sub(r'/F4UBCD', '/multibootusb/' + iso_basename(iso_link) + '/F4UBCD', string)
elif distro == "ipcop":
string = re.sub(r'ipcopboot=cdrom\S*', 'ipcopboot=usb', string)
elif distro == "puppy":
if 'pmedia=cd' in string:
string = re.sub(r'pmedia=cd\S*',
'pmedia=usbflash psubok=TRUE psubdir=/multibootusb/' + iso_basename(iso_link) + '/',
string)
elif 'rootfstype' in string:
string = re.sub(r'rootfstype',
'pmedia=usbflash psubok=TRUE psubdir=/multibootusb/' + iso_basename(iso_link) + '/ rootfstype',
string)
elif distro == "slax":
string = re.sub(r'initrd=',
r'from=/multibootusb/' + iso_basename(iso_link) + '/slax changes=/multibootusb/' + iso_basename(iso_link) + '/slax fromusb initrd=', string)
elif distro == "finnix":
string = re.sub(r'initrd=',
r'finnixdir=/multibootusb/' + iso_basename(iso_link) + '/finnix initrd=', string)
elif distro == "knoppix":
string = re.sub(r'initrd=', 'knoppix_dir=/multibootusb/' + iso_basename(iso_link) + '/KNOPPIX initrd=', string)
elif distro == "systemrescuecd":
rows = []
subdir = '/multibootusb/' + iso_basename(iso_link)
for line in string.splitlines(True):
addline = True
if re.match(r'append.*--.*', line, flags=re.I):
line = re.sub(r'(append)(.*)--(.*)', r'\1\2subdir=' + subdir + r' --\3 subdir=' + subdir,
line, flags=re.I)
elif re.match(r'append', line, flags=re.I):
line = re.sub(r'(append)', r'\1 subdir=' + subdir, line, flags=re.I)
elif re.match(r'label rescue(32|64)_1', line, flags=re.I):
rows.append(line)
rows.append('append subdir=%s\n' % (subdir,))
addline = False
if addline:
rows.append(line)
string = ''.join(rows)
elif distro in ["arch", "chakra"]:
string = re.sub(r'isolabel=\S*',
'isodevice=/dev/disk/by-uuid/' + usb_uuid, string, flags=re.I)
string = re.sub(r'isobasedir=',
'isobasedir=/multibootusb/' + iso_basename(iso_link) + '/', string, flags=re.I)
string = commentout_gfxboot(string)
string = string.replace('%INSTALL_DIR%', 'arch')
if 'manjaro' in string:
if not os.path.exists(os.path.join(usb_mount, '.miso')):
with open(os.path.join(usb_mount, '.miso'), "w") as f:
f.write('')
elif distro == "kaos":
string = re.sub(r'kdeosisolabel=\S*',
'kdeosisodevice=/dev/disk/by-uuid/' + usb_uuid, string, flags=re.I)
string = re.sub(r'append',
'append kdeosisobasedir=/multibootusb/' + iso_basename(iso_link) + '/kdeos/', string, flags=re.I)
string = commentout_gfxboot(string)
elif distro in ["suse", "opensuse"]:
if re.search(r'opensuse_12', string, re.I):
string = re.sub(r'append',
'append loader=syslinux isofrom_system=/dev/disk/by-uuid/' + usb_uuid + ":/" +
iso_name(iso_link), string, flags=re.I)
else:
string = re.sub(r'append',
'append loader=syslinux isofrom_device=/dev/disk/by-uuid/' + usb_uuid +
' isofrom_system=/multibootusb/' + iso_basename(iso_link) + '/' + iso_name(iso_link),
string, flags=re.I)
elif distro == 'opensuse-install':
string = re.sub(r'splash=silent', 'splash=silent install=hd:/dev/disk/by-uuid/'
+ config.usb_uuid + '/multibootusb/' + iso_basename(iso_link), string)
elif distro == "pclinuxos":
string = re.sub(r'livecd=',
'fromusb livecd=' + '/multibootusb/' + iso_basename(iso_link) + '/',
string)
string = re.sub(r'prompt', '#prompt', string)
string = commentout_gfxboot(string)
string = re.sub(r'timeout', '#timeout', string)
elif distro == "wifislax":
string = re.sub(r'vmlinuz',
'vmlinuz from=multibootusb/' + iso_basename(iso_link) + ' noauto', string)
string = re.sub(r'vmlinuz2',
'vmlinuz2 from=multibootusb/' + iso_basename(iso_link) + ' noauto', string)
elif distro == "porteus":
string = re.sub(r'APPEND',
'APPEND from=/multibootusb/' + iso_basename(iso_link) + ' noauto', string)
string = re.sub(r'vmlinuz2',
'vmlinuz2 from=multibootusb/' + iso_basename(iso_link) + ' noauto', string)
elif distro == "hbcd":
if not 'multibootusb' in string:
string = re.sub(r'/HBCD', '/multibootusb/' + iso_basename(iso_link) + '/HBCD', string)
elif distro == "zenwalk":
string = re.sub(r'initrd=',
'from=/multibootusb/' + iso_basename(iso_link) + '/' + iso_name(iso_link) + ' initrd=',
string)
elif distro == "mageialive":
string = re.sub(r'LABEL=\S*', 'UUID=' + usb_uuid + ' mgalive.basedir=/multibootusb/' + iso_basename(iso_link),
string)
elif distro == "solydx":
string = re.sub(r'live-media-path=', 'live-media-path=/multibootusb/' + iso_basename(iso_link),
string)
elif distro == 'alt-linux':
string = re.sub(r':cdrom', ':disk', string)
elif distro == 'fsecure':
string = re.sub(r'APPEND ramdisk_size', 'APPEND noprompt ' + 'knoppix_dir=/multibootusb/' + iso_basename(iso_link)
+ '/KNOPPIX ramdisk_size', string)
elif distro == 'alpine':
string = re.sub(r'modules', 'alpine_dev=usbdisk:vfat modules', string)
elif config.distro == 'trinity-rescue':
# USB disk must have volume label to work properly
string = re.sub(r'initrd=', 'vollabel=' + config.usb_label + ' initrd=', string)
string = re.sub(r'root=\S*', 'root=/dev/ram0', string, flags=re.I)
config_file = open(cfg_file, "w")
config_file.write(string)
config_file.close()
update_mbusb_cfg_file(iso_link, usb_uuid, usb_mount, distro)
grub.mbusb_update_grub_cfg()
# copy isolinux.cfg file to syslinux.cfg for grub to boot.
def copy_to_syslinux_cfg_callback(dir_, fname):
if not fname.lower().endswith('isolinux.cfg'):
return
isolinux_cfg_path = os.path.join(dir_, fname)
syslinux_cfg_fname = fname.lower().replace('isolinux.cfg','syslinux.cfg')
syslinux_cfg_path = os.path.join(dir_, syslinux_cfg_fname)
if os.path.exists(syslinux_cfg_path):
return # don't overwrite.
try:
shutil.copyfile(isolinux_cfg_path, syslinux_cfg_path)
except Exception as e:
log('Copying %s %s to %s failed...' % (
fname, dir_, syslinux_cfg_fname))
log(e)
def fix_desktop_image_in_thema_callback(install_dir_for_grub,
dir_, fname):
if not fname.lower().endswith('.txt'):
return
theme_file = os.path.join(dir_, fname)
updated = False
with open(theme_file, 'r', encoding='utf-8') as f:
pattern = re.compile(r'^desktop-image\s*:\s*(.*)$')
try:
src_lines = f.readlines()
except UnicodeDecodeError:
log("Unexpected encoding in %s" % theme_file)
return
lines = []
for line in src_lines:
line = line.rstrip()
m = pattern.match(line)
if m and m.group(1).startswith(('/', '"/')):
log("Updating '%s' in %s" % (line,theme_file))
updated = True
partial_path = m.group(1).strip('"').lstrip('/')
line = 'desktop-image: "%s/%s"' % \
(install_dir_for_grub, partial_path)
lines.append(line)
if updated:
with open(theme_file, 'w') as f:
f.write('\n'.join(lines))
visitor_callbacks = [
# Ensure that isolinux.cfg file is copied as syslinux.cfg
# to boot correctly.
copy_to_syslinux_cfg_callback,
# Rewrite 'desktop-image: ...' line in a theme definition file
# so that a background image is displaymed during boot item selection.
# This tweak was first introduced for kali-linux-light-2018-1.
partial(fix_desktop_image_in_thema_callback, install_dir_for_grub),
]
# Now visit the tree.
for dirpath, dirnames, filenames in os.walk(install_dir):
for f in filenames:
for callback in visitor_callbacks:
callback(dirpath, f)
# Assertain if the entry is made..
sys_cfg_file = os.path.join(config.usb_mount, "multibootusb", "syslinux.cfg")
if gen.check_text_in_file(sys_cfg_file, iso_basename(config.image_path)):
log('Updated entry in syslinux.cfg...')
else:
log('Unable to update entry in syslinux.cfg...')
# Check if bootx64.efi is replaced by distro
efi_grub_img = os.path.join(config.usb_mount, 'EFI', 'BOOT', 'bootx64.efi')
if not os.path.exists(efi_grub_img):
gen.log('EFI image does not exist. Copying now...')
shutil.copy2(resource_path(os.path.join("data", "EFI", "BOOT", "bootx64.efi")),
os.path.join(config.usb_mount, 'EFI', 'BOOT'))
elif gen.grub_efi_exist(efi_grub_img) is False:
if distro == "Windows":
gen.log('EFI image overwritten by Windows install. Moving it now...')
dst = os.path.join(config.usb_mount, 'EFI', 'BOOT_WINDOWS')
os.makedirs(dst)
shutil.move(efi_grub_img, dst)
else:
gen.log('EFI image overwritten by distro install. Replacing it now...')
shutil.copy2(resource_path(os.path.join("data", "EFI", "BOOT", "bootx64.efi")),
os.path.join(config.usb_mount, 'EFI', 'BOOT'))
else:
gen.log('multibootusb EFI image already exist. Not copying...')
# Bug in the isolinux package
def commentout_gfxboot(input_text):
return re.sub(r'(ui\s+.*?gfxboot\.c32.*)$', r'# \1', input_text,
flags=re.I | re.MULTILINE)
def update_mbusb_cfg_file(iso_link, usb_uuid, usb_mount, distro):
"""
Update main multibootusb syslinux.cfg file after distro is installed.
:return:
"""
log('Updating multibootusb config file...')
name_from_iso = iso_basename(iso_link)
name_of_iso = iso_name(iso_link)
_isolinux_bin_exists = isolinux_bin_exist(config.image_path)
_isolinux_bin_dir = isolinux_bin_dir(iso_link)
sys_cfg_file = os.path.join(usb_mount, "multibootusb", "syslinux.cfg")
install_dir = os.path.join(usb_mount, "multibootusb", name_from_iso)
label = name_from_iso + ('' if _isolinux_bin_exists else ' via GRUB')
if os.path.exists(sys_cfg_file):
if distro == "hbcd":
if os.path.exists(os.path.join(usb_mount, "multibootusb", "menu.lst")):
_config_file = os.path.join(usb_mount, "multibootusb", "menu.lst")
config_file = open(_config_file, "w")
string = re.sub(r'/HBCD', '/multibootusb/' + name_from_iso + '/HBCD', _config_file)
config_file.write(string)
config_file.close()
with open(sys_cfg_file, "a") as f:
f.write("#start " + iso_basename(config.image_path) + "\n")
f.write("LABEL " + label + "\n")
f.write("MENU LABEL " + label + "\n")
f.write("BOOT " + '/multibootusb/' + name_from_iso + '/' + _isolinux_bin_dir.replace("\\", "/") + '/' + distro + '.bs' + "\n")
f.write("#end " + iso_basename(config.image_path) + "\n")
elif distro == "Windows":
if os.path.exists(sys_cfg_file):
config_file = open(sys_cfg_file, "a")
config_file.write("#start " + name_from_iso + "\n")
config_file.write("LABEL " + label + "\n")
config_file.write("MENU LABEL " + label + "\n")
config_file.write("KERNEL chain.c32 hd0 1 ntldr=/bootmgr" + "\n")
config_file.write("#end " + name_from_iso + "\n")
config_file.close()
elif distro == 'f4ubcd':
if os.path.exists(sys_cfg_file):
config_file = open(sys_cfg_file, "a")
config_file.write("#start " + name_from_iso + "\n")
config_file.write("LABEL " + label + "\n")
config_file.write("MENU LABEL " + label + "\n")
config_file.write("KERNEL grub.exe" + "\n")
config_file.write('APPEND --config-file=/multibootusb/' + iso_basename(config.image_path) + '/menu.lst' + "\n")
config_file.write("#end " + name_from_iso + "\n")
config_file.close()
elif distro == 'kaspersky':
if os.path.exists(sys_cfg_file):
config_file = open(sys_cfg_file, "a")
config_file.write("#start " + name_from_iso + "\n")
config_file.write("LABEL " + label + "\n")
config_file.write("MENU LABEL " + label + "\n")
config_file.write("CONFIG " + '/multibootusb/' + iso_basename(config.image_path) + '/kaspersky.cfg' + "\n")
config_file.write("#end " + name_from_iso + "\n")
config_file.close()
elif distro == 'grub4dos':
update_menu_lst()
elif distro == 'grub4dos_iso':
update_grub4dos_iso_menu()
else:
config_file = open(sys_cfg_file, "a")
config_file.write("#start " + name_from_iso + "\n")
config_file.write("LABEL " + label + "\n")
config_file.write("MENU LABEL " + label + "\n")
if distro == "salix-live":
if os.path.exists(
os.path.join(install_dir, 'boot', 'grub2-linux.img')):
config_file.write(
"LINUX " + '/multibootusb/' + name_from_iso +
'/boot/grub2-linux.img' + "\n")
else:
config_file.write("BOOT " + '/multibootusb/' + name_from_iso + '/' + _isolinux_bin_dir.replace("\\", "/") + '/' + distro + '.bs' + "\n")
elif distro == "pclinuxos":
config_file.write("kernel " + '/multibootusb/' + name_from_iso
+ '/isolinux/vmlinuz' + "\n")
config_file.write("append livecd=livecd root=/dev/rd/3 acpi=on vga=788 keyb=us vmalloc=256M nokmsboot "
"fromusb root=UUID=" + usb_uuid + " bootfromiso=/multibootusb/" +
name_from_iso + "/" + name_of_iso + " initrd=/multibootusb/"
+ name_from_iso + '/isolinux/initrd.gz' + "\n")
elif distro == "memtest":
config_file.write("kernel " + '/multibootusb/' + name_from_iso + '/BOOT/MEMTEST.IMG\n')
elif distro == "sgrubd2" or config.distro == 'raw_iso':
config_file.write("LINUX memdisk\n")
config_file.write("INITRD " + "/multibootusb/" + name_from_iso + '/' + name_of_iso + '\n')
config_file.write("APPEND iso\n")
elif distro == 'ReactOS':
config_file.write("COM32 mboot.c32" + '\n')
config_file.write("APPEND /loader/setupldr.sys" + '\n')
elif distro == 'pc-unlocker':
config_file.write("kernel ../ldntldr" + '\n')
config_file.write("append initrd=../ntldr" + '\n')
elif distro == 'pc-tool':
config_file.write(menus.pc_tool_config(syslinux=True, grub=False))
elif distro == 'grub2only':
config_file.write(menus.grub2only())
elif distro == 'memdisk_iso':
config_file.write(menus.memdisk_iso_cfg(syslinux=True, grub=False))
elif distro == 'memdisk_img':
config_file.write(menus.memdisk_img_cfg(syslinux=True, grub=False))
else:
if _isolinux_bin_exists is True:
if distro == "generic":
distro_syslinux_install_dir = _isolinux_bin_dir
if _isolinux_bin_dir != "/":
distro_sys_install_bs = os.path.join(usb_mount, _isolinux_bin_dir) + '/' + distro + '.bs'
else:
distro_sys_install_bs = '/' + distro + '.bs'
else:
distro_syslinux_install_dir = install_dir
distro_syslinux_install_dir = distro_syslinux_install_dir.replace(usb_mount, '')
distro_sys_install_bs = distro_syslinux_install_dir + '/' + _isolinux_bin_dir + '/' + distro + '.bs'
distro_sys_install_bs = "/" + distro_sys_install_bs.replace("\\", "/") # Windows path issue.
if config.syslinux_version == '3':
config_file.write("CONFIG /multibootusb/" + name_from_iso + '/' + _isolinux_bin_dir.replace("\\", "/") + '/isolinux.cfg\n')
config_file.write("APPEND /multibootusb/" + name_from_iso + '/' + _isolinux_bin_dir.replace("\\", "/") + '\n')
config_file.write("# Delete or comment above two lines using # and remove # from below line if "
"you get not a COM module error.\n")
config_file.write("#BOOT " + distro_sys_install_bs.replace("//", "/") + "\n")
else:
config_file.write("BOOT " + distro_sys_install_bs.replace("//", "/") + "\n")
else:
# isolinux_bin does not exist.
config_file.write('Linux /multibootusb/grub/lnxboot.img\n')
config_file.write('INITRD /multibootusb/grub/core.img\n')
config_file.write('TEXT HELP\n')
config_file.write('Booting via syslinux is not supported. '
'Please boot via GRUB\n')
config_file.write('ENDTEXT\n')
config_file.write("#end " + name_from_iso + "\n")
config_file.close()
# Update extlinux.cfg file by copying updated syslinux.cfg
shutil.copy(os.path.join(usb_mount, 'multibootusb', 'syslinux.cfg'),
os.path.join(usb_mount, 'multibootusb', 'extlinux.cfg'))
def kaspersky_config(distro):
if distro == 'kaspersky':
return """
menu label Kaspersky Rescue Disk
kernel $INSTALL_DIR/boot/rescue
append root=live:UUID= live_dir=$INSTALL_DIR/rescue/LiveOS/ subdir=$INSTALL_DIR/rescue/LiveOS/ looptype=squashfs rootfstype=auto vga=791 init=/linuxrc loop=$INSTALL_DIR/rescue/LiveOS/squashfs.img initrd=$INSTALL_DIR/boot/rescue.igz lang=en udev liveimg splash quiet doscsi nomodeset
label text
menu label Kaspersky Rescue Disk - Text Mode
kernel $INSTALL_DIR/boot/rescue
append root=live:UUID= live_dir=$INSTALL_DIR/rescue/LiveOS/ subdir=$INSTALL_DIR/rescue/LiveOS/ rootfstype=auto vga=791 init=/linuxrc loop=/multiboot/rescue/LiveOS/squashfs.img initrd=$INSTALL_DIR/boot/rescue.igz SLUG_lang=en udev liveimg quiet nox shell noresume doscsi nomodeset
label hwinfo
menu label Kaspersky Hardware Info
kernel $INSTALL_DIR/boot/rescue
append root=live:UUID= live_dir=$INSTALL_DIR/rescue/LiveOS/ subdir=$INSTALL_DIR/rescue/LiveOS/ rootfstype=auto vga=791 init=/linuxrc loop=$INSTALL_DIR/rescue/LiveOS/squashfs.img initrd=$INSTALL_DIR/boot/rescue.igz SLUG_lang=en udev liveimg quiet softlevel=boot nox hwinfo noresume doscsi nomodeset """
def update_menu_lst():
sys_cfg_file = os.path.join(config.usb_mount, "multibootusb", "syslinux.cfg")
# install_dir = os.path.join(config.usb_mount, "multibootusb", iso_basename(config.image_path))
menu_lst = iso_menu_lst_path(config.image_path).replace("\\", "/")
with open(sys_cfg_file, "a") as f:
f.write("#start " + iso_basename(config.image_path) + "\n")
f.write("LABEL " + iso_basename(config.image_path) + "\n")
f.write("MENU LABEL " + iso_basename(config.image_path) + "\n")
f.write("KERNEL grub.exe" + "\n")
f.write('APPEND --config-file=/' + menu_lst + "\n")
f.write("#end " + iso_basename(config.image_path) + "\n")
def update_grub4dos_iso_menu():
sys_cfg_file = os.path.join(config.usb_mount, "multibootusb",
"syslinux.cfg")
install_dir = os.path.join(config.usb_mount, "multibootusb",
iso_basename(config.image_path))
menu_lst_file = os.path.join(install_dir, 'menu.lst')
with open(menu_lst_file, "w") as f:
f.write("title Boot " + iso_name(config.image_path) + "\n")
f.write("find --set-root --ignore-floppies --ignore-cd /multibootusb/" + iso_basename(config.image_path) + '/'
+ iso_name(config.image_path) + "\n")
f.write("map --heads=0 --sectors-per-track=0 /multibootusb/" + iso_basename(config.image_path)
+ '/' + iso_name(config.image_path) + ' (hd32)' + "\n")
f.write("map --hook" + "\n")
f.write("chainloader (hd32)")
with open(sys_cfg_file, "a") as f:
f.write("#start " + iso_basename(config.image_path) + "\n")
f.write("LABEL " + iso_basename(config.image_path) + "\n")
f.write("MENU LABEL " + iso_basename(config.image_path) + "\n")
f.write("KERNEL grub.exe" + "\n")
f.write('APPEND --config-file=/multibootusb/' + iso_basename(config.image_path) + '/menu.lst' + "\n")
f.write("#end " + iso_basename(config.image_path) + "\n")
class ConfigTweakerParam:
# 'iso_link' is also known as 'image_path'
def __init__(self, iso_link, distro_path, persistence_size,
usb_uuid, usb_mount, usb_disk, usb_fs_type):
self.iso_fname = os.path.split(iso_link)[1]
self.distro_name = os.path.splitext(self.iso_fname)[0]
assert distro_path[0] == '/'
self.distro_path = distro_path # drive relative
self.persistence_size = persistence_size
self.usb_uuid = usb_uuid
self.usb_mount = usb_mount
self.usb_disk = usb_disk
self.usb_fs_type = usb_fs_type
class ConfigTweaker:
BOOT_PARAMS_STARTER = 'kernel|append|linux'
def __init__(self, distro_type, setup_params):
self.disto_type = distro_type
self.setup_params = setup_params
def tweak_first_match(self, content, kernel_param_line_pattern,
apply_persistence_to_all_lines,
param_operations,
param_operations_for_persistence):
"""Perofrm specified parameter modification to the first maching
line and return the concatination of the string leading up to the
match and the tweaked paramer line. If no match is found,
unmodified 'content' is returned.
"""
m = kernel_param_line_pattern.search(content)
if m is None:
return content
start, end = m.span()
upto_match, rest_of_content = content[:start], content[end:]
starter_part, starter_token, params_part = [
m.group(i) for i in [1,2,3]]
params = params_part.split(' ')
if apply_persistence_to_all_lines or \
self.has_persistency_param(params):
ops_to_apply = param_operations + \
param_operations_for_persistence
else:
ops_to_apply = param_operations
for op_or_op_list, precondition in ops_to_apply:
if not precondition(starter_token, params):
continue
try:
iter(op_or_op_list)
op_list = op_or_op_list
except TypeError:
op_list = [op_or_op_list]
for op in op_list:
params = op(params)
# I see something special about this param. Place it at the end.
three_dashes = '---'
if three_dashes in params:
params.remove(three_dashes)
params.append(three_dashes)
return upto_match + starter_part + ' '.join(params) + \
self.tweak_first_match(
rest_of_content, kernel_param_line_pattern,
apply_persistence_to_all_lines,
param_operations, param_operations_for_persistence)
def legacy_tweak(self, content):
return None
def tweak(self, content):
tweaked = self.legacy_tweak(content)
if tweaked:
return tweaked
apply_persistence_to_all_lines = \
0 < self.setup_params.persistence_size and \
not self.config_is_persistence_aware(content)
matching_re = r'^(\s*(%s)\s*)(.*)$' % self.BOOT_PARAMS_STARTER
kernel_parameter_line_pattern = re.compile(
matching_re,
flags = re.I | re.MULTILINE)
out = self.tweak_first_match(
content,
kernel_parameter_line_pattern,
apply_persistence_to_all_lines,
self.param_operations(),
self.param_operations_for_persistence())
return self.post_process(out)
def on_liveboot_params(self, starter, params):
return self.LIVE_BOOT_DETECT_PARAM in params
def post_process(self, entire_string):
return entire_string
def add_op_if_file_exists(self, op_list, op_creator_func, key,
candidate_relative_path_list, predicate):
for candidate in candidate_relative_path_list:
relpath = os.path.join(self.setup_params.distro_path[1:],
candidate)
if os.path.exists(os.path.join(
self.setup_params.usb_mount, relpath)):
normalized_relpath = '/' + relpath.replace('\\','/')
op_list.append((op_creator_func(key, normalized_relpath),
predicate))
break
def fullpath(self, subpath):
p = self.setup_params
return os.path.join(p.usb_mount, p.distro_path[1:],
subpath).replace('/', os.sep)
def file_is_installed(self, subpath):
return os.path.exists(self.fullpath(subpath))
def file_content(self, subpath):
fp = self.fullpath(subpath)
if not os.path.exists(fp):
return None
with open(fp, errors='ignore') as f:
return f.read()
def extract_distroinfo_from_file(self, subpath, regex, distro_group,
version_group):
content = self.file_content(subpath)
if not content:
return None
m = re.compile(regex, re.I).search(content)
if not m:
return None
return (m.group(distro_group),
[int(x) for x in m.group(version_group).split('.')])
def extract_distroinfo_from_fname(self, which_dir, regex, distro_group,
version_group):
p = re.compile(regex, re.I)
for fname in os.listdir(self.fullpath(which_dir)):
m = p.match(fname)
if m:
return (m.group(distro_group),
[int(x) for x in m.group(version_group).split('.')])
return None
class PersistenceConfigTweaker(ConfigTweaker):
def __init__(self, pac_re, *args, **kw):
self.persistence_awareness_checking_re = pac_re
super(PersistenceConfigTweaker, self).__init__(*args, **kw)
def config_is_persistence_aware(self, content):
""" Used to restrict update of boot parameters to persistent-aware
menu entries if the distribution provides any.
"""
return self.persistence_awareness_checking_re.search(content) \
is not None
class ConfigTweakerWithDebianStylePersistenceParam(PersistenceConfigTweaker):
def __init__(self, *args, **kw):
persistence_awareness_checking_re = re.compile(
r'^\s*(%s).*?\s%s(\s.*|)$' % \
(self.BOOT_PARAMS_STARTER, self.PERSISTENCY_TOKEN),
flags=re.I|re.MULTILINE)
super(ConfigTweakerWithDebianStylePersistenceParam,
self).__init__(persistence_awareness_checking_re, *args, **kw)
def has_persistency_param(self, params):
return self.PERSISTENCY_TOKEN in params
def param_operations_for_persistence(self):
return [
([add_tokens(self.PERSISTENCY_TOKEN),
add_or_replace_kv('%s-path=' % self.PERSISTENCY_TOKEN,
self.setup_params.distro_path)],
self.on_liveboot_params)]
class UbuntuConfigTweaker(ConfigTweakerWithDebianStylePersistenceParam):
LIVE_BOOT_DETECT_PARAM = 'boot=casper'
PERSISTENCY_TOKEN = 'persistent'
def param_operations(self):
return [
([add_tokens('ignore_bootid'),
add_or_replace_kv('live-media-path=',
'%s/casper' % self.setup_params.distro_path),
add_or_replace_kv('cdrom-detect/try-usb=', 'true'),
# Recently, correct param seems to be 'floppy=0,allowed_driver_mask
add_or_replace_kv('floppy.allowed_drive_mask=', '0'),
add_tokens('ignore_uuid'),
add_or_replace_kv('root=UUID=', self.setup_params.usb_uuid),
],
self.on_liveboot_params),
(replace_kv('live-media=',
'/dev/disk/by-uuid/%s' % self.setup_params.usb_uuid),
always),
]
def post_process(self, entire_string):
return entire_string.replace(r'ui gfxboot', '#ui gfxboot')
class DebianConfigTweaker(ConfigTweakerWithDebianStylePersistenceParam):
LIVE_BOOT_DETECT_PARAM = 'boot=live'
PERSISTENCY_TOKEN = 'persistence'
def param_operations(self):
return [
(add_tokens('ignore_bootid'), self.on_liveboot_params),
(add_or_replace_kv('live-media-path=',
'%s/live' % self.setup_params.distro_path),
self.on_liveboot_params),
]
class NoPersistenceTweaker(ConfigTweaker):
def config_is_persistence_aware(self, content):
return False
def param_operations_for_persistence(self):
return []
def has_persistency_param(self, params):
return False
class GentooConfigTweaker(NoPersistenceTweaker):
def param_operations(self):
uuid_spec = 'UUID=%s' % self.setup_params.usb_uuid
ops = [
([add_or_replace_kv('real_root=', uuid_spec),
add_tokens('slowusb'),
add_or_replace_kv('subdir=', self.setup_params.distro_path),
remove_keys('cdroot_hash='),
# Without this, pentoo-amd64-hardened-2018.0_RC5.8_pre20180305/
# stucks at "copying read-write image contents to tmpfs"
add_tokens('overlayfs'),
# Said distro fails to mount root device if this param is given
remove_tokens('aufs'),
],
starter_is_either('append', 'linux')),
]
fs_type = self.setup_params.usb_fs_type
if fs_type == 'vfat':
ops.append( (add_or_replace_kv('cdroot_type=', fs_type),
always) )
self.add_op_if_file_exists(
ops, add_or_replace_kv,
'loop=', ['liberte/boot/root-x86.sfs', 'image.squashfs'],
starter_is_either('append', 'linux'))
return ops
class FedoraConfigTweaker(PersistenceConfigTweaker):
def __init__(self, *args, **kw):
persistence_awareness_checking_re = re.compile(
r'^\s*(%s).*?\s(rd.live.overlay|overlay)=.+?' %
self.BOOT_PARAMS_STARTER, flags=re.I|re.MULTILINE)
super(FedoraConfigTweaker, self).__init__(
persistence_awareness_checking_re, *args, **kw)
def has_persistency_param(self, params):
return any(p.startswith(('overlay=', 'rd.live.overlay='))
for p in params)
def param_operations(self):
uuid_spec = 'UUID=%s' % self.setup_params.usb_uuid
escaped_distro_path = self.setup_params.distro_path \
.replace(' ', '\\0x20')
live_path = escaped_distro_path + '/LiveOS'
ops = [(replace_kv('inst.stage2=', 'hd:%s:%s' %
(uuid_spec, escaped_distro_path)), always),
(add_or_replace_kv('inst.repo=',
'http://mirror.centos.org'
'/centos/7/os/x86_64/'),
contains_key('inst.stage2=')),
(replace_kv('root=', 'live:' + uuid_spec), always),
(add_or_replace_kv('rd.live.dir=', live_path),
contains_any_token('rd.live.image', 'Solus')),
(add_or_replace_kv('live_dir=', live_path),
contains_token('liveimage')), ]
if self.file_is_installed('.treeinfo'):
# Add or replace value of 'inst.repo=' with reference
# to the copied iso.
ops.append(
(add_or_replace_kv(
'inst.repo=',
'hd:UUID=%s:%s' % (
self.setup_params.usb_uuid,
self.setup_params.distro_path + '/' +
self.setup_params.iso_fname)),
starter_is_either('append', 'linux')))
return ops
def param_operations_for_persistence(self):
uuid_spec = 'UUID=%s' % self.setup_params.usb_uuid
return [
(remove_tokens('ro'), always),
(add_or_replace_kv('overlay=', uuid_spec),
contains_token('liveimage')),
([add_tokens('rw'),
add_or_replace_kv('rd.live.overlay=', uuid_spec)],
contains_token('rd.live.image'))
]
class AntixConfigTweaker(NoPersistenceTweaker):
def param_operations(self):
dinfo = self.extract_distroinfo_from_file(
'version', r'(antiX|MX)-(\d+\.\d+)', 1, 2)
if not dinfo:
dinfo = self.extract_distroinfo_from_file(
'boot/isolinux/isolinux.cfg', r'(antiX|MX)-(\d+\.\d+)', 1, 2)
if not dinfo:
dinfo = self.extract_distroinfo_from_fname(
'', r'(MX)-(\d+\.\d+).*', 1, 2)
if dinfo and 17<=dinfo[1][0]:
ops = [
add_or_replace_kv('buuid=', self.setup_params.usb_uuid),
add_or_replace_kv('bdir=',
self.setup_params.distro_path + '/antiX')]
else:
ops = add_or_replace_kv('image_dir=',
self.setup_params.distro_path)
return [(ops, starter_is_either('append', 'APPEND', 'linux'))]
def post_process(self, s):
s = re.sub(r'^(\s*UI\s+(.*?gfxboot(\.c32|)))\s+(.*?)\s+(.*)$',
r'# \1 \4.renamed-to-avoid-lockup \5', s,
flags=re.I + re.MULTILINE)
return s
class SalixConfigTweaker(NoPersistenceTweaker):
def legacy_tweak(self, content):
if content.find('iso_path') < 0:
return None
p = self.setup_params
for replacee, replacer in [
('iso_path', "%s/%s" % (p.distro_path, p.iso_fname)),
('initrd=', 'fromiso=%s/%s initrd=' % (
p.distro_path, p.iso_fname)),
]:
content = content.replace(replacee, replacer)
return content
# salixlive-xfce-14.2.1 assumes that the installation media is
# labeled "LIVE" and the file tree is exploded at the root.
# (See /init for details.) Supporing it in harmony with installation
# of other distros is very hard to impossible. Do nothing here.
def param_operations(self):
return []
class WifislaxConfigTweaker(NoPersistenceTweaker):
def param_operations(self):
ops = [
(add_or_replace_kv('livemedia=','%s:%s/%s' % (
self.setup_params.usb_uuid, self.setup_params.distro_path,
self.setup_params.iso_fname)),
starter_is_either('append', 'linux'))]
return ops
def post_process(self, entire_string):
return entire_string.replace('($root)', self.setup_params.distro_path)
def test_tweak_objects():
def os_path_exists(f):
if f.endswith('liberte/boot/root-x86.sfs'):
return False
if f.endswith('image.squashfs'):
return True
return False
saved = os.path.exists
os.path.exists = os_path_exists
try:
_test_tweak_objects()
finally:
os.path.exists = saved
def _test_tweak_objects():
usb_mount = 'L:'
usb_disk = 'L:'
setup_params_no_persistence = ConfigTweakerParam(
'{iso-name}', '/multibootusb/{iso-name}', 0,
'{usb-uuid}', usb_mount, usb_disk)
debian_tweaker = DebianConfigTweaker('debian', setup_params_no_persistence)
ubuntu_tweaker = UbuntuConfigTweaker('ubuntu', setup_params_no_persistence)
centos_tweaker = FedoraConfigTweaker('centos', setup_params_no_persistence)
salix_tweaker = SalixConfigTweaker('centos', setup_params_no_persistence)
# Test awareness on 'persistent'
content = """
append boot=live foo baz=1 double-spaced ignore_bootid persistent more stuff""".lstrip()
print ("Testing awareness on 'persistent' of ubuntu tweaker.")
assert ubuntu_tweaker.config_is_persistence_aware(content)
print ("Testing awareness on 'persistent' of debian tweaker.")
assert not debian_tweaker.config_is_persistence_aware(content)
content = """
append boot=live foo baz=1 double-spaced ignore_bootid persistence more stuff""".lstrip()
print ("Testing awareness on 'persistence' of ubuntu tweaker.")
assert not ubuntu_tweaker.config_is_persistence_aware(content)
print ("Testing awareness on 'persistence' of debian tweaker.")
assert debian_tweaker.config_is_persistence_aware(content)
print ("Testing awareness on 'overlay=' of centos tweaker.")
content = """
append boot=live foo baz=1 overlay=UUID:2234-1224 double-spaced ignore_bootid persistence more stuff""".lstrip()
assert centos_tweaker.config_is_persistence_aware(content)
print ("Testing awareness on 'rd.live.overlay=' of centos tweaker.")
content = """
append boot=live foo baz=1 rd.live.overlay=UUID:2234-1224 double-spaced ignore_bootid persistence more stuff""".lstrip()
assert centos_tweaker.config_is_persistence_aware(content)
print ("Testing indefference on persistence keys of centos tweaker.")
content = """
append boot=live foo baz=1 double-spaced ignore_bootid persistence more stuff""".lstrip()
assert not centos_tweaker.config_is_persistence_aware(content)
print ("Testing awareness on 'overlay=' of centos tweaker.")
content = """
append boot=live foo baz=1 double-spaced ignore_bootid persistence more stuff""".lstrip()
assert not centos_tweaker.config_is_persistence_aware(content)
print ("Testing if 'persistence' token is left at the original place.")
content = "\tlinux\tfoo persistence boot=live in the middle"
assert debian_tweaker.tweak(content) == "\tlinux\tfoo persistence boot=live in the middle ignore_bootid live-media-path=/multibootusb/{iso-name}/live persistence-path=/multibootusb/{iso-name}"""
print ("Testing if 'boot=live' at the very end is recognized.")
content = "menu\n\tlinux\tfoo persistence in the middle boot=live"
assert debian_tweaker.tweak(content) == "menu\n\tlinux\tfoo persistence in the middle boot=live ignore_bootid live-media-path=/multibootusb/{iso-name}/live persistence-path=/multibootusb/{iso-name}"""
print ("Testing if 'boot=live' at a line end is recognized.")
content = """append zoo
\tappend\tfoo persistence in the middle boot=live
append foo"""
assert debian_tweaker.tweak(content) == """append zoo
\tappend\tfoo persistence in the middle boot=live ignore_bootid live-media-path=/multibootusb/{iso-name}/live persistence-path=/multibootusb/{iso-name}
append foo"""
print ("Testing if replacement of 'live-media=' happens on non-boot lines.")
content = "\t\tlinux live-media=/tobe/replaced"
assert ubuntu_tweaker.tweak(content)==\
"\t\tlinux live-media=/dev/disk/by-uuid/{usb-uuid}"
print ("Testing if \\tappend is recognized as a starter.")
content = """\tappend foo boot=live ignore_bootid persistence in the middle live-media-path=/foo/bar"""
assert debian_tweaker.tweak(content) == """\tappend foo boot=live ignore_bootid persistence in the middle live-media-path=/multibootusb/{iso-name}/live persistence-path=/multibootusb/{iso-name}"""
print ("Testing if debian tweaker does not get tickled by 'persistent'.")
content = """\tappend boot=live foo ignore_bootid persistent in the middle live-media-path=/foo/bar"""
assert debian_tweaker.tweak(content) == """\tappend boot=live foo ignore_bootid persistent in the middle live-media-path=/multibootusb/{iso-name}/live"""
print ("Testing replacement of 'live-media-path' value.")
content = " append boot=live foo live-media-path=/foo/bar more"
assert debian_tweaker.tweak(content) == """ append boot=live foo live-media-path=/multibootusb/{iso-name}/live more ignore_bootid"""
print ("Testing rewriting of 'file=' param by debian_tweaker.")
content = " kernel file=/cdrom/preseed/ubuntu.seed boot=live"
setup_params_persistent = ConfigTweakerParam(
'debian', '/multibootusb/{iso-name}', 128*1024*1024, '{usb-uuid}',
usb_mount, usb_disk)
debian_persistence_tweaker = DebianConfigTweaker(
'debian', setup_params_persistent)
ubuntu_persistence_tweaker = UbuntuConfigTweaker(
'ubuntu', setup_params_persistent)
centos_persistence_tweaker = FedoraConfigTweaker(
'centos', setup_params_persistent)
print ("Testing if debian tweaker appends persistence parameters.")
content = """label foo
kernel foo bar
append boot=live foo live-media-path=/foo/bar more
"""
assert debian_persistence_tweaker.tweak(content) == """label foo
kernel foo bar
append boot=live foo live-media-path=/multibootusb/{iso-name}/live more ignore_bootid persistence persistence-path=/multibootusb/{iso-name}
"""
print ("Testing if ubuntu tweaker selectively appends persistence params.")
content = """label foo
kernel foo bar
append boot=casper foo live-media-path=/foo/bar more
"""
assert ubuntu_persistence_tweaker.tweak(content) == """label foo
kernel foo bar
append boot=casper foo live-media-path=/multibootusb/{iso-name}/casper more ignore_bootid cdrom-detect/try-usb=true floppy.allowed_drive_mask=0 ignore_uuid root=UUID={usb-uuid} persistent persistent-path=/multibootusb/{iso-name}
"""
# Test rewrite of persistence-aware configuration.
# Only 'live-persistence' line should receive 'persistence-path'
# parameter.
print ("Testing if debian tweaker appends persistence params "
"to relevant lines only.")
content = """label live-forensic
menu label Live (^forensic mode)
linux /live/vmlinuz
initrd /live/initrd.img
append boot=live noconfig=sudo username=root hostname=kali noswap noautomount
label live-persistence
menu label ^Live USB Persistence (check kali.org/prst)
linux /live/vmlinuz
initrd /live/initrd.img
append boot=live noconfig=sudo username=root hostname=kali persistence
"""
assert debian_persistence_tweaker.tweak(content)=="""label live-forensic
menu label Live (^forensic mode)
linux /live/vmlinuz
initrd /live/initrd.img
append boot=live noconfig=sudo username=root hostname=kali noswap noautomount ignore_bootid live-media-path=/multibootusb/{iso-name}/live
label live-persistence
menu label ^Live USB Persistence (check kali.org/prst)
linux /live/vmlinuz
initrd /live/initrd.img
append boot=live noconfig=sudo username=root hostname=kali persistence ignore_bootid live-media-path=/multibootusb/{iso-name}/live persistence-path=/multibootusb/{iso-name}
"""
setup_params = ConfigTweakerParam(
'{iso-name}', '/multibootusb/{iso-name}',
0, '{usb-uuid}', usb_mount, usb_disk)
gentoo_tweaker = GentooConfigTweaker('gentoo', setup_params)
print ("Testing Gentoo-tweaker on syslinux config.")
content = """label pentoo
menu label Pentoo Defaults (verify)
kernel /isolinux/pentoo
append initrd=/isolinux/pentoo.igz root=/dev/ram0 init=/linuxrc nox nodhcp overlayfs max_loop=256 dokeymap looptype=squashfs loop=/image.squashfs cdroot video=uvesafb:mtrr:3,ywrap,1024x768-16 usbcore.autosuspend=1 console=tty0 net.ifnames=0 scsi_mod.use_blk_mq=1 ipv6.autoconf=0 verify
"""
assert gentoo_tweaker.tweak(content)=="""label pentoo
menu label Pentoo Defaults (verify)
kernel /isolinux/pentoo
append initrd=/isolinux/pentoo.igz root=/dev/ram0 init=/linuxrc nox nodhcp overlayfs max_loop=256 dokeymap looptype=squashfs loop=/multibootusb/{iso-name}/image.squashfs cdroot video=uvesafb:mtrr:3,ywrap,1024x768-16 usbcore.autosuspend=1 console=tty0 net.ifnames=0 scsi_mod.use_blk_mq=1 ipv6.autoconf=0 verify real_root=%s slowusb subdir=/multibootusb/{iso-name}
""" % usb_disk
print ("Testing Gentoo-tweaker on grub config.")
content = """insmod all_video
menuentry 'Boot LiveCD (kernel: pentoo)' --class gnu-linux --class os {
linux /isolinux/pentoo root=/dev/ram0 init=/linuxrc nox aufs max_loop=256 dokeymap looptype=squashfs loop=/image.squashfs cdroot cdroot_hash=xxx
initrd /isolinux/pentoo.igz
}
"""
assert gentoo_tweaker.tweak(content)=="""insmod all_video
menuentry 'Boot LiveCD (kernel: pentoo)' --class gnu-linux --class os {
linux /isolinux/pentoo root=/dev/ram0 init=/linuxrc nox max_loop=256 dokeymap looptype=squashfs loop=/multibootusb/{iso-name}/image.squashfs cdroot real_root=%s slowusb subdir=/multibootusb/{iso-name} overlayfs
initrd /isolinux/pentoo.igz
}
""" % usb_disk
print ("Testing centos tweaker on DVD-installer")
saved = os.path.exists
os.path.exists = lambda f: f.endswith(('/.treeinfo','\\.treeinfo')) \
or saved(f)
try:
content = r"""label linux
menu label ^Install CentOS 7
kernel vmlinuz
append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 quiet
"""
assert centos_tweaker.tweak(content)=="""label linux
menu label ^Install CentOS 7
kernel vmlinuz
append initrd=initrd.img inst.stage2=hd:UUID={usb-uuid}:/multibootusb/{iso-name} quiet inst.repo=hd:UUID={usb-uuid}:/multibootusb/{iso-name}/{iso-name}.iso
"""
finally:
os.path.exists = saved
print ("Testing centos tweaker on Net-installer")
assert centos_tweaker.tweak(content)=="""label linux
menu label ^Install CentOS 7
kernel vmlinuz
append initrd=initrd.img inst.stage2=hd:UUID={usb-uuid}:/multibootusb/{iso-name} quiet inst.repo=http://mirror.centos.org/centos/7/os/x86_64/
"""
content = r"""label linux0
menu label ^Start CentOS
kernel vmlinuz0
append initrd=initrd0.img root=live:CDLABEL=CentOS-7-x86_64-LiveGNOME-1708 rootfstype=auto ro rd.live.image quiet rhgb rd.luks=0 rd.md=0 rd.dm=0
menu default
"""
print ("Testing centos tweaker on Live")
assert centos_tweaker.tweak(content)=="""label linux0
menu label ^Start CentOS
kernel vmlinuz0
append initrd=initrd0.img root=live:UUID={usb-uuid} rootfstype=auto ro rd.live.image quiet rhgb rd.luks=0 rd.md=0 rd.dm=0 rd.live.dir=/multibootusb/{iso-name}/LiveOS
menu default
"""
print ("Testing persistent centos tweaker on non-persistence config.")
content = r"""label linux0
menu label ^Start CentOS
kernel vmlinuz0
append initrd=initrd0.img root=live:CDLABEL=CentOS-7-x86_64-LiveGNOME-1708 rootfstype=auto ro rd.live.image quiet rhgb rd.luks=0 rd.md=0 rd.dm=0
menu default
"""
assert centos_persistence_tweaker.tweak(content)=="""label linux0
menu label ^Start CentOS
kernel vmlinuz0
append initrd=initrd0.img root=live:UUID={usb-uuid} rootfstype=auto rd.live.image quiet rhgb rd.luks=0 rd.md=0 rd.dm=0 rd.live.dir=/multibootusb/{iso-name}/LiveOS rw rd.live.overlay=UUID={usb-uuid}
menu default
"""
print ("Testing persistent centos tweaker not touching "
"non-persistent line")
content = r"""label linux0
menu label ^Start CentOS
append kenel=vmlinuz0
append rd.live.overlay=UUID:2234-2223 ro rd.live.image
append initrd=initrd0.img root=live:CDLABEL=CentOS-7-x86_64-LiveGNOME-1708 rootfstype=auto ro rd.live.image quiet rhgb rd.luks=0 rd.md=0 rd.dm=0
menu default
"""
assert centos_persistence_tweaker.tweak(content)=="""label linux0
menu label ^Start CentOS
append kenel=vmlinuz0
append rd.live.overlay=UUID={usb-uuid} rd.live.image rd.live.dir=/multibootusb/{iso-name}/LiveOS rw
append initrd=initrd0.img root=live:UUID={usb-uuid} rootfstype=auto ro rd.live.image quiet rhgb rd.luks=0 rd.md=0 rd.dm=0 rd.live.dir=/multibootusb/{iso-name}/LiveOS
menu default
"""
print ("Testing salix tweaker on legacy tweaking")
content = """menu Old Salix
append initrd=/boot/initrd.img foobar=iso_path tail-param
"""
assert salix_tweaker.tweak(content)=="""menu Old Salix
append fromiso=/multibootusb/{iso-name}/{iso-name}.iso initrd=/boot/initrd.img foobar=/multibootusb/{iso-name}/{iso-name}.iso tail-param
"""
print ("Testing salix tweaker on new tweaking")
content = """menu New Salix
append initrd=/boot/initrd.img tail-param
"""
assert salix_tweaker.tweak(content)=="""menu New Salix
append initrd=/boot/initrd.img tail-param livemedia={usb-uuid}:/multibootusb/{iso-name}/{iso-name}.iso
"""
def do_test_abspath_rewrite():
content = """menuentry "Install Ubuntu" {
linux /casper/vmlinuz.efi file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity init=/linuxrc iso-scan/filename=${iso_path} quiet splash grub=/grub/grub.cfg ---
initrd /casper/initrd.lz
}"""
assert fix_abspath(
content, 'g:/multibootusb/ubuntu-14.04.5-desktop-amd64',
'ubuntu-14.04.5-desktop-amd64', 'test_abspath_rewrite')==\
"""menuentry "Install Ubuntu" {
linux /multibootusb/ubuntu-14.04.5-desktop-amd64/casper/vmlinuz file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity init=/linuxrc iso-scan/filename=${iso_path} quiet splash grub=/multibootusb/ubuntu-14.04.5-desktop-amd64/boot/grub/grub.cfg ---
initrd /multibootusb/ubuntu-14.04.5-desktop-amd64/casper/initrd.lz
}"""
def test_abspath_rewrite():
def os_path_exists(path):
path = path.replace('\\', '/')
if path.endswith('.efi'):
return False
if path.startswith('g:/multibootusb/ubuntu-14.04.5-desktop-amd64'
'/boot'):
return True
if path.endswith('/boot/grub/grub.cfg'):
return True
if path == '/grub/grub.cfg':
return False
if path.endswith('casper/vmlinuz'):
return True
if path.endswith('/casper/initrd.lz'):
return True
return False
saved = os.path.exists
try:
os.path.exists = os_path_exists
do_test_abspath_rewrite()
finally:
os.path.exists = saved