Release new version 0.9.30.
[grml2usb.git] / grml2usb
index 13c8249..9191e85 100755 (executable)
--- a/grml2usb
+++ b/grml2usb
@@ -7,7 +7,7 @@ grml2usb
 
 This script installs a grml system (either a running system or ISO[s]) to a USB device
 
-:copyright: (c) 2009 by Michael Prokop <mika@grml.org>
+:copyright: (c) 2009, 2010, 2011 by Michael Prokop <mika@grml.org>
 :license: GPL v2 or any later version
 :bugreports: http://grml.org/bugs/
 
@@ -22,13 +22,14 @@ import uuid
 import struct
 
 # global variables
-PROG_VERSION = "0.9.27"
+PROG_VERSION = "0.9.30"
 MOUNTED = set()  # register mountpoints
 TMPFILES = set() # register tmpfiles
 DATESTAMP = time.mktime(datetime.datetime.now().timetuple()) # unique identifier for syslinux.cfg
 GRML_FLAVOURS = set() # which flavours are being installed?
 GRML_DEFAULT = None
 UUID = None
+SYSLINUX_LIBS = "/usr/lib/syslinux/"
 
 def syslinux_warning(option, opt, value, opt_parser):
     """A helper function for printing a warning about deprecated option
@@ -323,7 +324,7 @@ if loadfont /boot/grub/ascii.pf2 ; then
    set gfxmode=640x480
    insmod gfxterm
    insmod vbe
-   if terminal_output.gfxterm ; then true ; else
+   if terminal_output gfxterm ; then true ; else
     # For backward compatibility with versions of terminal.mod that don't
     # understand terminal_output
     terminal gfxterm
@@ -358,17 +359,48 @@ menuentry "Boot FreeDOS" {
     initrd  /boot/addons/balder10.imz
 }
 
-menuentry "Boot MirOS bsd4grml" {
-    multiboot /boot/addons/bsd4grml/ldbsd.com
-    module    /boot/addons/bsd4grml/bsd.rd
-    module    /boot/addons/bsd4grml/boot.1
-    module    /boot/addons/bsd4grml/boot.2
-    module    /boot/addons/bsd4grml/boot.3
-    module    /boot/addons/bsd4grml/boot.4
-    module    /boot/addons/bsd4grml/boot.5
-    module    /boot/addons/bsd4grml/boot.6
-    module    /boot/addons/bsd4grml/boot.cfg
-}
+if [ ${iso_path} ] ; then
+    # assume loopback.cfg boot
+    if [ -e /boot/addons/bsd4grml/loopback.0 ] ; then
+        # bsd4grml 20100815 and later
+        menuentry "Boot MirOS bsd4grml" {
+            multiboot /boot/addons/bsd4grml/ldbsd.com
+            module /boot/addons/bsd4grml/bsd.rd bsd
+            module /boot/addons/bsd4grml/loopback.0 boot.cfg
+            module /boot/addons/bsd4grml/loopback.1 boot.1
+            module /boot/addons/bsd4grml/loopback.2 boot.2
+            module /boot/addons/bsd4grml/loopback.3 boot.3
+            module /boot/addons/bsd4grml/loopback.4 boot.4
+            module /boot/addons/bsd4grml/loopback.5 boot.5
+            module /boot/addons/bsd4grml/loopback.6 boot.6
+        }
+    else
+        # old bsd4grml
+        menuentry "Boot MirOS bsd4grml" {
+            multiboot /boot/addons/bsd4grml/ldbsd.com
+            module /boot/addons/bsd4grml/bsd.rd bsd.rd
+            module /boot/addons/bsd4grml/boot.cfg boot.cfg
+            module /boot/addons/bsd4grml/boot.1 boot.1
+            module /boot/addons/bsd4grml/boot.2 boot.2
+            module /boot/addons/bsd4grml/boot.3 boot.3
+            module /boot/addons/bsd4grml/boot.4 boot.4
+            module /boot/addons/bsd4grml/boot.5 boot.5
+        }
+    fi
+else
+    # assume grub.cfg boot
+    menuentry "Boot MirOS bsd4grml" {
+        multiboot /boot/addons/bsd4grml/ldbsd.com
+        module /boot/addons/bsd4grml/bsd.rd bsd.rd
+        module /boot/addons/bsd4grml/boot.cfg boot.cfg
+        module /boot/addons/bsd4grml/boot.1 boot.1
+        module /boot/addons/bsd4grml/boot.2 boot.2
+        module /boot/addons/bsd4grml/boot.3 boot.3
+        module /boot/addons/bsd4grml/boot.4 boot.4
+        module /boot/addons/bsd4grml/boot.5 boot.5
+        module /boot/addons/bsd4grml/boot.6 boot.6
+    }
+fi
 
 menuentry "Boot OS of first partition on first disk" {
     set root=(hd0,1)
@@ -649,12 +681,16 @@ def install_grub(device):
                     grub_device = device
 
                 logging.info("Installing grub as bootloader")
-                logging.debug("grub-install --recheck --force --no-floppy --root-directory=%s %s",
-                              device_mountpoint, grub_device)
-                proc = subprocess.Popen(["grub-install", "--recheck", "--force", "--no-floppy",
-                                         "--root-directory=%s" % device_mountpoint, grub_device],
-                                        stdout=file(os.devnull, "r+"))
-                proc.wait()
+                for opt in ["", "--force" ]:
+                    logging.debug("grub-install --recheck %s --no-floppy --root-directory=%s %s",
+                                  opt, device_mountpoint, grub_device)
+                    proc = subprocess.Popen(["grub-install", "--recheck", opt, "--no-floppy",
+                                             "--root-directory=%s" % device_mountpoint, grub_device],
+                                            stdout=file(os.devnull, "r+"))
+                    proc.wait()
+                    if proc.returncode == 0:
+                        break
+
                 if proc.returncode != 0:
                     # raise Exception("error executing grub-install")
                     logging.critical("Fatal: error executing grub-install "
@@ -1066,7 +1102,8 @@ def copy_system_files(grml_flavour, iso_mount, target):
 
     squashfs = search_file(grml_flavour + '.squashfs', iso_mount)
     if squashfs is None:
-        logging.critical("Fatal: squashfs file not found")
+        logging.critical("Fatal: squashfs file not found"
+        ", please check that your iso is not corrupt")
         raise CriticalException("error locating squashfs file")
     else:
         squashfs_target = target + '/live/' + grml_flavour + '/'
@@ -1116,26 +1153,37 @@ def update_grml_versions(iso_mount, target):
     @target: path of the target mount point
     """
     grml_target = target + '/grml/'
-    new_grml_version = search_file('grml-version', grml_target)
-    if new_grml_version:
-        orig_grml_version = search_file('grml-version', iso_mount)
-        if not orig_grml_version:
-            logging.warn("Warning: %s could not be found - can not install it", orig_grml_version)
+    target_grml_version_file = search_file('grml-version', grml_target)
+    if target_grml_version_file:
+        iso_grml_version_file = search_file('grml-version', iso_mount)
+        if not iso_grml_version_file:
+            logging.warn("Warning: %s could not be found - can not install it", iso_grml_version_file)
             return False
         try:
-            new_file = open(new_grml_version, 'a+')
-            new_flavours = [ get_flavour(l) for l in new_file.readlines() ]
-
-            old_file = open(orig_grml_version, 'r')
-            old_lines = old_file.readlines()
-            for line in old_lines:
-                if not get_flavour(line) in new_flavours:
-                    new_file.write(line)
+            # read the flavours from the iso image
+            iso_versions = {}
+            iso_file = open(iso_grml_version_file, 'r')
+            for line in iso_file:
+                iso_versions[get_flavour(line)] = line.strip()
+
+            # 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():
+                    print iso_versions.pop(flavour)
+                else:
+                    print line.strip()
+            fileinput.close()
+
+            target_file = open(target_grml_version_file, 'a')
+            # add the new flavours from the current iso
+            for flavour in iso_versions:
+                target_file.write("%s\n" % iso_versions[flavour])
         except IOError:
             logging.warn("Warning: Could not write file")
         finally:
-            new_file.close()
-            old_file.close()
+            iso_file.close()
+            target_file.close()
         return True
     else:
         return False
@@ -1193,7 +1241,7 @@ def handle_addon_copy(filename, dst, iso_mount):
     if file_location is None:
         logging.warn("Warning: %s not found (that's fine if you don't need it)",  filename)
     else:
-        exec_rsync(file_location, dst + filename)
+        exec_rsync(file_location, dst)
 
 
 def copy_addons(iso_mount, target):
@@ -1310,9 +1358,13 @@ def copy_bootloader_files(iso_mount, target, grml_flavour):
     for expr in name, 'distri.cfg', \
         defaults_file, 'grml.png', 'hd.cfg', 'isolinux.cfg', 'isolinux.bin', \
         'isoprompt.cfg', 'options.cfg', \
-        'prompt.cfg', 'vesamenu.c32', 'vesamenu.cfg', 'grml.png', '*.c32':
+        '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)
+
+
     # copy the addons_*.cfg file to the new syslinux directory
     glob_and_copy(iso_mount + source_dir + 'addon*.cfg', syslinux_target)
 
@@ -1493,7 +1545,7 @@ def handle_grub2_config(grml_flavour, grub_target, bootopt):
 
     # grub2 config
     grub2_cfg = grub_target + 'grub.cfg'
-    logging.debug("Creating grub2 configuration file (grub.lst)")
+    logging.debug("Creating grub2 configuration file (grub.cfg)")
 
     global GRML_DEFAULT
 
@@ -1868,10 +1920,11 @@ def install_grml(mountpoint, device):
             except CriticalException, error:
                 logging.critical("Fatal: %s", error)
                 raise
-    global GRML_FLAVOURS
     try:
         grml_flavours = identify_grml_flavour(mountpoint)
         for flavour in set(grml_flavours):
+            if not flavour:
+                logging.warning("No valid flavour found, please check your iso")
             logging.info("Identified grml flavour \"%s\".", flavour)
             install_iso_files(flavour, mountpoint, device, device_mountpoint)
             GRML_FLAVOURS.add(flavour)
@@ -2032,6 +2085,24 @@ def check_options(opts):
         sys.exit(1)
 
 
+def check_programs():
+    """check if all needed programs are installed"""
+    if options.grub:
+        if not which("grub-install"):
+            logging.critical("Fatal: grub-install not available (please install the "
+                             + "grub package or drop the --grub option)")
+            sys.exit(1)
+
+    if options.syslinux:
+        if not which("syslinux"):
+            logging.critical("Fatal: syslinux not available (please install the "
+                             + "syslinux package or use the --grub option)")
+            sys.exit(1)
+
+    if not which("rsync"):
+        logging.critical("Fatal: rsync not available, can not continue - sorry.")
+        sys.exit(1)
+
 def main():
     """Main function [make pylint happy :)]"""
 
@@ -2055,6 +2126,8 @@ def main():
     if options.dryrun:
         logging.info("Running in simulation mode as requested via option dry-run.")
 
+    check_programs()
+
     # specified arguments
     device = args[len(args) - 1]
     isos = args[0:len(args) - 1]
@@ -2068,21 +2141,6 @@ def main():
             logging.critical("Fatal: installation on raw device not supported. (BIOS won't support it.)")
             sys.exit(1)
 
-    if options.grub:
-        if not which("grub-install"):
-            logging.critical("Fatal: grub-install not available (please install the "
-                             + "grub package or drop the --grub option)")
-            sys.exit(1)
-
-    if options.syslinux:
-        if not which("syslinux"):
-            logging.critical("Fatal: syslinux not available (please install the "
-                             + "syslinux package or use the --grub option)")
-            sys.exit(1)
-
-    if not which("rsync"):
-        logging.critical("Fatal: rsync not available, can not continue - sorry.")
-        sys.exit(1)
 
     # provide upgrade path
     handle_compat_warning(device)