Improve error handling.
[grml2usb.git] / grml2usb
index 3ca38a5..fa820bf 100755 (executable)
--- a/grml2usb
+++ b/grml2usb
@@ -41,6 +41,9 @@ GRML_DEFAULT = None
 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
@@ -312,10 +315,7 @@ def check_uid_root():
 
 
 def check_boot_flag(device):
-    if device[-1:].isdigit():
-        boot_dev = re.match(r'(.*?)\d*$', device).group(1)
-    else:
-        boot_dev = device
+    boot_dev, x = get_device_from_partition(device)
 
     with open(boot_dev, 'r') as image:
         data = image.read(512)
@@ -437,10 +437,7 @@ def install_grub(device):
                 # 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
 
@@ -666,6 +663,7 @@ def unmount(target, unmount_options):
         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)
@@ -1052,7 +1050,7 @@ def copy_bootloader_files(iso_mount, target, grml_flavour):
         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.")
@@ -1116,6 +1114,19 @@ def install_iso_files(grml_flavour, iso_mount, device, target):
     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
     """
@@ -1462,7 +1473,7 @@ def install(image, device):
         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:
@@ -1523,7 +1534,7 @@ def install_grml(mountpoint, device):
 
 
 def remove_mountpoint(mountpoint):
-    """remove a registred mountpoint
+    """remove a registered mountpoint
     """
 
     try:
@@ -1545,12 +1556,9 @@ def handle_mbr(device):
         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
@@ -1698,6 +1706,11 @@ def check_programs():
 
 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()