Release new version 0.16.7
[grml2usb.git] / grml2usb
index 1c2ed5b..3585976 100755 (executable)
--- a/grml2usb
+++ b/grml2usb
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 # pylint: disable-msg=C0302
 """
@@ -7,13 +7,13 @@ grml2usb
 
 This script installs a Grml system (either a running system or ISO[s]) to a USB device
 
-:copyright: (c) 2009, 2010, 2011 by Michael Prokop <mika@grml.org>
+:copyright: (c) 2009-2019 by Michael Prokop <mika@grml.org>
 :license: GPL v2 or any later version
 :bugreports: http://grml.org/bugs/
 
 """
 
-from __future__ import print_function
+
 from optparse import OptionParser
 from inspect import isroutine, isclass
 import datetime
@@ -69,10 +69,10 @@ def grub_option(option, opt, value, opt_parser):
 
 
 # cmdline parsing
-USAGE = "Usage: %prog [options] <[ISO[s] | /lib/live/mount/medium]> </dev/sdX#>\n\
+USAGE = "Usage: %prog [options] <[ISO[s] | /run/live/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 (/lib/live/mount/medium),\n\
+Make sure you have at least one Grml ISO or a running Grml system (/run/live/medium),\n\
 grub or syslinux and root access.\n\
 \n\
 Run %prog --help for usage hints, further information via: man grml2usb"
@@ -187,7 +187,7 @@ def cleanup():
         try:
             unmount(device, "")
             logging.debug('Unmounted %s' % device)
-        except StandardError:
+        except Exception:
             logging.debug('RuntimeError while umount %s, ignoring' % device)
 
     for tmppath in TMPFILES.copy():
@@ -202,7 +202,7 @@ def cleanup():
                 os.unlink(tmppath)
                 logging.debug('temporary file %s deleted' % tmppath)
                 unregister_tmpfile(tmppath)
-        except StandardError:
+        except Exception:
             msg = 'RuntimeError while removing temporary %s, ignoring'
             logging.debug(msg % tmppath)
 
@@ -315,7 +315,7 @@ def get_defaults_file(iso_mount, flavour, name):
     return ('', '')
 
 
-def search_file(filename, search_path='/bin' + os.pathsep + '/usr/bin', lst_return=False):
+def search_file(filename, search_path='/bin' + os.pathsep + '/usr/bin', lst_return=False, required=False):
     """Given a search path, find file
 
     @filename: name of file to search for
@@ -344,6 +344,10 @@ def search_file(filename, search_path='/bin' + os.pathsep + '/usr/bin', lst_retu
                 retval.append(os.path.abspath(os.path.join(current_dir, filename)))
                 if not lst_return:
                     break
+
+    if required and not retval:
+        raise CriticalException("Required file %s not found in %s" % (filename, search_path))
+
     if lst_return:
         return retval
     elif retval:
@@ -940,7 +944,7 @@ def update_grml_versions(iso_mount, target):
             # 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 iso_versions.keys():
+                if flavour in list(iso_versions.keys()):
                     print(iso_versions.pop(flavour))
                 else:
                     print(line.strip())
@@ -1108,7 +1112,7 @@ def copy_bootloader_files(iso_mount, target, grml_flavour):
     grub_target = target + '/boot/grub/'
     execute(mkdir, grub_target)
 
-    logo = search_file('logo.16', iso_mount)
+    logo = search_file('logo.16', iso_mount, required=True)
     exec_rsync(logo, syslinux_target + 'logo.16')
 
     bootx64_efi = search_file('bootx64.efi', iso_mount)
@@ -1227,7 +1231,7 @@ def identify_grml_flavour(mountpath):
     version_files = search_file('grml-version', mountpath, lst_return=True)
 
     if not version_files:
-        if mountpath.startswith("/lib/live/mount/medium"):
+        if mountpath.startswith("/run/live/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=...")
@@ -1300,6 +1304,10 @@ def handle_grub_config(grml_flavour, device, target):
                 if shortname in filename:
                     line = live_media_path_re.sub('', line)
                     line = line.rstrip() + ' live-media-path=/live/%s/ ' % (grml_flavour)
+                if bootopt.strip():
+                    line = line.replace(' {} '.format(bootopt.strip()), ' ')
+                    if line.endswith(bootopt):
+                        line = line[:-len(bootopt)]
                 line = line.rstrip() + r' bootid=%s %s ' % (UUID, bootopt)
                 for regex in remove_regexes:
                     line = regex.sub(' ', line)
@@ -1552,7 +1560,7 @@ def handle_secure_boot(target, efi_img):
         logging.debug('Unmounted %s' % efi_mountpoint)
         os.rmdir(efi_mountpoint)
         logging.debug('Removed directory %s' % efi_mountpoint)
-    except StandardError:
+    except Exception:
         logging.critical('RuntimeError while umount %s' % efi_mountpoint)
         sys.exit(1)
 
@@ -1597,7 +1605,7 @@ def install(image, device):
         if options.force or os.path.exists(os.path.join(image, 'live')):
             logging.info("Using %s as install base", image)
         else:
-            q = raw_input("%s does not look like a Grml system. "
+            q = input("%s does not look like a Grml system. "
                 "Do you really want to use this image? y/N " % image)
             if q.lower() == 'y':
                 logging.info("Using %s as install base", image)
@@ -1628,7 +1636,7 @@ def install(image, device):
 def install_grml(mountpoint, device):
     """Main logic for copying files of the currently running Grml system.
 
-    @mountpoint: directory where currently running live system resides (usually /lib/live/mount/medium)
+    @mountpoint: directory where currently running live system resides (usually /run/live/medium)
     @device: partition where the specified ISO should be installed to"""
 
     device_mountpoint = device
@@ -1737,7 +1745,7 @@ def handle_vfat(device):
             print("Forcing mkfs.fat16 on %s as requested via option --force." % device)
         else:
             # make sure the user is aware of what he is doing
-            f = raw_input("Are you sure you want to format the specified partition with fat16? y/N ")
+            f = input("Are you sure you want to format the specified partition with fat16? y/N ")
             if f == "y" or f == "Y":
                 logging.info("Note: you can skip this question using the option --force")
             else:
@@ -1762,7 +1770,7 @@ def handle_vfat(device):
 
     if not os.path.isdir(device) and not check_for_usbdevice(device) and not options.force:
         print("Warning: the specified device %s does not look like a removable usb device." % device)
-        f = raw_input("Do you really want to continue? y/N ")
+        f = input("Do you really want to continue? y/N ")
         if f.lower() != "y":
             sys.exit(1)
 
@@ -1778,7 +1786,7 @@ def handle_compat_warning(device):
         print("Instead of using grml2usb /path/to/iso %s you might" % device)
         print("want to use grml2usb /path/to/iso /dev/... instead.")
         print("Please check out the grml2usb manpage for details.")
-        f = raw_input("Do you really want to continue? y/N ")
+        f = input("Do you really want to continue? y/N ")
         if f.lower() != "y":
             sys.exit(1)
 
@@ -1847,14 +1855,14 @@ def check_programs():
 
 
 def load_loop():
-    """Runs modprobe loop and throws away it's output"""
+    """Runs modprobe loop and throws away its 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()
+    proc.communicate()
 
 
 def main():
@@ -1924,6 +1932,8 @@ def main():
 
     except Exception as error:
         logging.critical("Fatal: %s", str(error))
+        if options.verbose:
+            logging.exception("Exception:")
         sys.exit(1)