Support more Syslinux module locations
[grml2usb.git] / grml2usb
index 1e502e7..c53f58b 100755 (executable)
--- a/grml2usb
+++ b/grml2usb
@@ -32,7 +32,22 @@ import uuid
 import shutil
 
 # The line following this line is patched by debian/rules and tarball.sh.
-PROG_VERSION = '***UNRELEASED***'
+PROG_VERSION = '***UNKNOWN***'
+
+# when running from inside git, try to report version information via git-describe
+try:
+    git_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
+    with open(os.devnull, 'w') as devnull:
+        PROG_VERSION = subprocess.check_output(["git",
+                                                "-C",
+                                                git_dir,
+                                                "describe",
+                                                "--always",
+                                                "--dirty"],
+                                                stderr=devnull).strip().decode('utf-8', errors='replace') + \
+                                                " (git)"
+except Exception:
+    pass
 
 # global variables
 MOUNTED = set()   # register mountpoints
@@ -41,7 +56,10 @@ DATESTAMP = time.mktime(datetime.datetime.now().timetuple())  # unique identifie
 GRML_FLAVOURS = set()  # which flavours are being installed?
 GRML_DEFAULT = None
 UUID = None
-SYSLINUX_LIBS = "/usr/lib/syslinux/"
+SYSLINUX_LIBS = [
+    "/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
 
@@ -123,6 +141,8 @@ parser.add_option("--syslinux", dest="syslinux", action="callback", default=True
                   help="install syslinux bootloader (deprecated as it's the default)")
 parser.add_option("--syslinux-mbr", dest="syslinuxmbr", action="store_true",
                   help="install syslinux master boot record (MBR) instead of default")
+parser.add_option("--syslinux-libs", dest="syslinuxlibs", action="append", default=[],
+                  help="syslinux modules directory path")
 parser.add_option("--tmpdir", dest="tmpdir", default="/tmp",
                   help="directory to be used for temporary files")
 parser.add_option("--verbose", dest="verbose", action="store_true",
@@ -389,7 +409,7 @@ def check_boot_flag(device):
     except ImportError as e:
         logging.debug("could not import parted, falling back to old bootflag detection")
 
-    with open(boot_dev, 'r') as image:
+    with open(boot_dev, 'rb') as image:
         data = image.read(520)
         bootcode = data[440:]
         gpt_data = bootcode[70:80]
@@ -789,9 +809,7 @@ def check_for_fat(partition):
                 " (wrong UID/permissions or device/directory not present?)" % partition)
 
     try:
-        udev_info = subprocess.Popen(["/sbin/blkid", "-s", "TYPE", "-o", "value", partition],
-                                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        filesystem = udev_info.communicate()[0].rstrip()
+        filesystem = subprocess.check_output(["/sbin/blkid", "-s", "TYPE", "-o", "value", partition]).decode().rstrip()
 
         if filesystem != "vfat":
             raise CriticalException(
@@ -799,7 +817,7 @@ def check_for_fat(partition):
                     "(Use --fat16 or run mkfs.vfat %s)" % (partition, partition))
 
     except OSError:
-        raise CriticalException("Sorry, /sbin/blkid not available (install e2fsprogs?)")
+        raise CriticalException("Sorry, /sbin/blkid not available (install util-linux?)")
 
 
 def mkdir(directory):
@@ -984,22 +1002,6 @@ def copy_grml_files(grml_flavour, iso_mount, target):
         logging.warn("Warning: could not find flavour directory for %s ", grml_flavour)
 
 
-def handle_addon_copy(filename, dst, iso_mount, ignore_errors=False):
-    """handle copy of optional addons
-
-    @filename: filename of the addon
-    @dst: destination directory
-    @iso_mount: location of the iso mount
-    @ignore_errors: don't report missing files
-    """
-    file_location = search_file(filename, iso_mount)
-    if file_location is None:
-        if not ignore_errors:
-            logging.warn("Warning: %s not found (that's fine if you don't need it)", filename)
-    else:
-        exec_rsync(file_location, dst)
-
-
 def copy_addons(iso_mount, target):
     """copy grml's addons files (like allinoneimg, bsd4grml,..) to a given target
 
@@ -1009,33 +1011,11 @@ def copy_addons(iso_mount, target):
     addons = target + '/boot/addons/'
     execute(mkdir, addons)
 
-    # grub all-in-one image
-    handle_addon_copy('allinone.img', addons, iso_mount)
-
-    # bsd image
-    handle_addon_copy('bsd4grml', addons, iso_mount)
-
-    # DOS image
-    handle_addon_copy('balder10.imz', addons, iso_mount)
-
-    # syslinux + pci.ids for hdt
-    for expr in '*.c32', 'pci.ids':
-        glob_and_copy(iso_mount + '/boot/addons/' + expr, addons)
-
-    # memdisk image
-    handle_addon_copy('memdisk', addons, iso_mount)
-
-    # memtest86+ image
-    handle_addon_copy('memtest', addons, iso_mount)
-
-    # gpxe.lkrn: got replaced by ipxe
-    handle_addon_copy('gpxe.lkrn', addons, iso_mount, ignore_errors=True)
-
-    # ipxe.lkrn
-    handle_addon_copy('ipxe.lkrn', addons, iso_mount)
-
-    # netboot.xyz
-    handle_addon_copy('netboot.xyz.lkrn', addons, iso_mount)
+    for addon_file in glob.glob(iso_mount + '/boot/addons/*'):
+        filename = os.path.basename(addon_file)
+        src_file = iso_mount + "/boot/addons/" + os.path.basename(addon_file)
+        logging.debug("Copying addon file %s" % filename)
+        exec_rsync(src_file, addons)
 
 
 def build_loopbackcfg(target):
@@ -1152,8 +1132,11 @@ def copy_bootloader_files(iso_mount, target, grml_flavour):
       'prompt.cfg', 'vesamenu.cfg', 'grml.png', '*.c32':
         glob_and_copy(iso_mount + source_dir + expr, syslinux_target)
 
-    for filename in glob.glob1(syslinux_target, "*.c32"):
-        copy_if_exist(os.path.join(SYSLINUX_LIBS, filename), syslinux_target)
+    for modules_dir in options.syslinuxlibs + SYSLINUX_LIBS:
+        if os.path.isdir(modules_dir):
+            for filename in glob.glob1(syslinux_target, "*.c32"):
+                copy_if_exist(os.path.join(modules_dir, filename), syslinux_target)
+            break
 
     # copy the addons_*.cfg file to the new syslinux directory
     glob_and_copy(iso_mount + source_dir + 'addon*.cfg', syslinux_target)
@@ -1713,7 +1696,7 @@ def handle_mbr(device):
                 mbrcode = mbrpath
                 break
 
-        if mbrcode is "":
+        if not mbrcode:
             str_locations = " or ".join(['"%s"' % l for l in mbr_locations])
             logging.error('Cannot find syslinux MBR, install it at %s)',
                           str_locations)
@@ -1855,14 +1838,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():