UUID = None
SYSLINUX_LIBS = "/usr/lib/syslinux/"
+RE_PARTITION = re.compile(r'([a-z/]*?)(\d+)$')
+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):
"""A helper function for printing a warning about deprecated option
setattr(opt_parser.values, 'syslinux', False)
# cmdline parsing
-USAGE = "Usage: %prog [options] <[ISO[s] | /live/image]> </dev/sdX#>\n\
+USAGE = "Usage: %prog [options] <[ISO[s] | /lib/live/mount/medium]> </dev/sdX#>\n\
\n\
-%prog installs grml ISO[s] to an USB device to be able to boot from it.\n\
-Make sure you have at least one grml ISO or a running grml system (/live/image),\n\
+%prog installs Grml ISO[s] to an USB device to be able to boot from it.\n\
+Make sure you have at least one Grml ISO or a running Grml system (/lib/live/mount/medium),\n\
grub or syslinux and root access.\n\
\n\
Run %prog --help for usage hints, further information via: man grml2usb"
@Exception: message"""
pass
+class VerifyException(Exception):
+ """Throw critical exception if there is an fatal error when verifying something.
+
+ @Exception: message"""
+ pass
+
# The following two functions help to operate on strings as
# array (list) of bytes (octets). In Python 3000, the bytes
sys.exit("Error: please run this script with uid 0 (root).")
+def check_boot_flag(device):
+ boot_dev, x = get_device_from_partition(device)
+
+ with open(boot_dev, 'r') as image:
+ data = image.read(512)
+ bootcode = data[440:]
+ if bootcode[6] == '\x80':
+ logging.debug("bootflag is enabled")
+ else:
+ logging.debug("bootflag is NOT enabled")
+ raise VerifyException("Device %s does not have the bootflag set. "
+ "Please enable it to be able to boot." % boot_dev)
+
+
def mkfs_fat16(device):
"""Format specified device with VFAT/FAT16 filesystem.
# If using --grub-mbr then make sure we install grub in MBR instead of PBR
if options.grubmbr:
logging.debug("Using option --grub-mbr ...")
- if device[-1:].isdigit():
- grub_device = re.match(r'(.*?)\d*$', device).group(1)
- else:
- grub_device = device
+ grub_device, x = get_device_from_partition(device)
else:
grub_device = device
proc = subprocess.Popen(["umount"] + list(unmount_options) + [target])
proc.wait()
if proc.returncode != 0:
+ logging.critical("Error executing umount")
raise Exception("Error executing umount")
else:
logging.debug("unregister_mountpoint(%s)", target)
logging.critical("Fatal: file default.cfg could not be found.")
logging.critical("Note: this grml2usb version requires an ISO generated by grml-live >=0.9.24 ...")
logging.critical(" ... either use grml releases >=2009.10 or switch to an older grml2usb version.")
- raise
+ raise CriticalException("file default.cfg could not be found.")
if not os.path.exists(iso_mount + '/boot/grub/footer.cfg'):
logging.warning("Warning: Grml releases older than 2011.12 support only one flavour in grub.")
proc.wait()
+def get_device_from_partition(partition):
+ device = partition
+ partition_number = None
+ if partition[-1].isdigit() and not RE_LOOP_DEVICE.match(partition):
+ m = RE_P_PARTITION.match(partition)
+ if not m:
+ m = RE_PARTITION.match(partition)
+ if m:
+ device = m.group(1)
+ partition_number = int(m.group(2)) - 1
+ return (device, partition_number)
+
+
def get_flavour(flavour_str):
"""Returns the flavour of a grml version string
"""
version_files = search_file('grml-version', mountpath, lst_return=True)
if not version_files:
- logging.critical("Error: could not find grml-version file.")
- raise
+ if mountpath.startswith("/lib/live/mount/medium"):
+ logging.critical("Error: could not find grml-version file.")
+ logging.critical("Looks like your system is running from RAM but required files are not available.")
+ logging.critical("Please either boot without toram=... or use boot option toram instead of toram=...")
+ cleanup()
+ sys.exit(1)
+ else:
+ logging.critical("Error: could not find grml-version file.")
+ cleanup()
+ sys.exit(1)
flavours = []
logging.debug("version_files = %s", version_files)
logging.info("Using %s as install base", image)
else:
logging.info("Using ISO %s", image)
- iso_mountpoint = tempfile.mkdtemp(prefix="grml2usb", dir=options.tmpdir)
+ iso_mountpoint = tempfile.mkdtemp(prefix="grml2usb", dir=os.path.abspath(options.tmpdir))
register_tmpfile(iso_mountpoint)
remove_image_mountpoint = True
try:
def install_grml(mountpoint, device):
"""Main logic for copying files of the currently running grml system.
- @mountpoin: directory where currently running live system resides (usually /live/image)
+ @mountpoint: directory where currently running live system resides (usually /lib/live/mount/medium)
@device: partition where the specified ISO should be installed to"""
device_mountpoint = device
remove_device_mountpoint = True
try:
check_for_fat(device)
+ check_boot_flag(device)
mount(device, device_mountpoint, ['-o', 'utf8,iocharset=iso8859-1'])
+ except VerifyException, error:
+ logging.critical("Fatal: %s", error)
+ raise
except CriticalException, error:
try:
mount(device, device_mountpoint, "")
def remove_mountpoint(mountpoint):
- """remove a registred mountpoint
+ """remove a registered mountpoint
"""
try:
logging.info("Would install MBR")
return 0
- if device[-1:].isdigit():
- mbr_device = re.match(r'(.*?)\d*$', device).group(1)
- partition_number = int(device[-1:]) - 1
- else:
+ mbr_device, partition_number = get_device_from_partition(device)
+ if partition_number is None:
logging.warn("Could not detect partition number, not activating partition")
- partition_number = None
# 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
def load_loop():
"""Runs modprobe loop and throws away it's output"""
+ if not which("modprobe"):
+ logging.critical("Fatal: modprobe not available, can not continue - sorry.")
+ logging.critical("Hint: is /sbin missing in PATH?")
+ sys.exit(1)
+
proc = subprocess.Popen(["modprobe", "loop"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc.wait()