Check for existence of $target/etc/apt/important_note.txt before operating on it
[grml-live.git] / grml-live
index babdd4e..dc36d24 100755 (executable)
--- a/grml-live
+++ b/grml-live
@@ -1,7 +1,9 @@
 #!/bin/bash
 # Filename:      grml-live
 # Purpose:       build process script for generating a (grml based) Linux Live-ISO
-# Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
+# Authors:       grml-team (grml.org),
+#                (c) Michael Prokop <mika@grml.org>,
+#                (c) Thorsten Glaser <tg@mirbsd.org>
 # Bug-Reports:   see http://grml.org/bugs/
 # License:       This file is licensed under the GPL v2 or any later version.
 ################################################################################
 export LANG=C
 export LC_ALL=C
 
+# define function getfilesize before "set -e"
+if stat --help >/dev/null 2>&1; then
+       getfilesize='stat -c %s'        # GNU stat
+else
+       getfilesize='stat -f %z'        # BSD stat
+fi
+
 # exit on any error:
 set -e
 
-GRML_LIVE_VERSION='0.9.9'
+GRML_LIVE_VERSION='0.9.20'
 PN="$(basename $0)"
 CMDLINE="$0 $@"
 ISO_DATE="$(date +%Y-%m-%d)"
@@ -221,11 +230,7 @@ while getopts "a:C:c:g:i:o:r:s:t:v:bBFuqVz" opt; do
     C) CONFIG="$OPTARG" ;;
     g) GRML_NAME="$OPTARG" ;;
     i) ISO_NAME="$OPTARG" ;;
-    o) OUTPUT="$OPTARG"
-       CHROOT_OUTPUT="$OUTPUT/grml_chroot"
-       BUILD_OUTPUT="$OUTPUT/grml_cd"
-       ISO_OUTPUT="$OUTPUT/grml_isos"
-       ;;
+    o) OUTPUT="$OPTARG" ;;
     q) SKIP_MKSQUASHFS=1 ;;
     r) RELEASENAME="$OPTARG" ;;
     s) SUITE="$OPTARG" ;;
@@ -247,6 +252,11 @@ specify it on the command line using the -c option."
 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
 specify it on the command line using the -o option."
 
+# set subdirectories according to $OUTPUT:
+CHROOT_OUTPUT="$OUTPUT/grml_chroot"
+BUILD_OUTPUT="$OUTPUT/grml_cd"
+ISO_OUTPUT="$OUTPUT/grml_isos"
+
 # trim characters that are known to cause problems inside $GRML_NAME;
 # for example isolinux does not like '-' inside the directory name
 [ -n "$GRML_NAME" ] && export SHORT_GRML_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
@@ -369,6 +379,15 @@ if [ -n "$SUITE" ] ; then
    # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
    case $SUITE in
       unstable) SUITE='sid' ;;
+      # make sure that we *NEVER* write any broken suite name to sources.list,
+      # otherwise we won't be able to adjust it one next (correct) execution
+      stable)   ;;
+      testing)  ;;
+      etch)     ;;
+      lenny)    ;;
+      squeeze)  ;;
+      sid)      ;;
+      *) echo "Sorry, $SUITE is not a valid Debian suite, exiting.">&2; bailout 1 ;;
    esac
 
    DIST=" etch\| stable\| lenny\| squeeze\| testing\| sid\| unstable"
@@ -397,6 +416,22 @@ if [ -n "$SUITE" ] ; then
    done
 fi
 
+# validate whether the specified architecture class matches the
+# architecture (option), otherwise installation of kernel will fail
+if echo $CLASSES | grep -qi i386 ; then
+   if ! [[ "$ARCH" == "i386" ]] ; then
+      eerror "You specified the I386 class but are trying to build something else (AMD64?)."
+      eerror "-> Either invoke grml-live with '-i i386' or adjust the architecture class. Exiting."
+      bailout
+   fi
+elif echo $CLASSES | grep -qi amd64 ; then
+   if ! [[ "$ARCH" == "amd64" ]] ; then
+      eerror "You specified the AMD64 class but are trying to build something else (I386?)."
+      eerror "-> Either invoke grml-live with '-i amd64' or adjust the architecture class. Exiting."
+      bailout
+   fi
+fi
+
 # set $ARCH
 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
@@ -412,6 +447,11 @@ if [ -n "$BUILD_DIRTY" ]; then
 else
    [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
 
+   # provide inform fai about the ISO we build
+   echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
+   [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
+   [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
+
    if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
       FAI_ACTION=softupdate
    else
@@ -552,19 +592,26 @@ if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
       cp ${TEMPLATE_DIRECTORY}/boot/isolinux/*  "$BUILD_OUTPUT"/boot/isolinux/
 
       if [ -z "$NO_ADDONS" ] ; then
-         # copy only files so we can handle bsd4grml on its own
-         for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
-             test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
-         done
+         if ! [ -d /usr/share/grml-live/templates/boot/addons/bsd4grml ] ; then
+           ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
+         else
+           # copy only files so we can handle bsd4grml on its own
+           for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
+               test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
+           done
 
-         if [ -z "$NO_ADDONS_BSD4GRML" ] ; then
-            cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
+           if [ -z "$NO_ADDONS_BSD4GRML" ] ; then
+              cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
+           fi
          fi
       fi
 
       if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
          cp -a ${TEMPLATE_DIRECTORY}/boot/grub  "$BUILD_OUTPUT"/boot/
       fi
+      # make sure we have recent template files available, otherwise updating
+      # the strings like $GRML_NAME and $VERSION might be out of date
+      cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
 
       if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
          log "${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
@@ -595,14 +642,40 @@ if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
       sed -i "s/%VERSION%/$VERSION/"           "$BUILD_OUTPUT"/boot/grub/menu.lst
       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/grub/menu.lst
 
+      sed -i "s/%VERSION%/$VERSION/"           "$BUILD_OUTPUT"/boot/grub/grub.cfg
+      sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/grub/grub.cfg
+
       # make sure the squashfs filename is set accordingly:
       GRML_NAME_SQUASHFS="$GRML_NAME.squashfs"
       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/isolinux.cfg
       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/syslinux.cfg
+      sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/grub/menu.lst
 
       GRML_NAME_SQUASHFS="$(cut_string 20 "$GRML_NAME_SQUASHFS")"
       GRML_NAME_SQUASHFS="$(extend_string_end 20 "$GRML_NAME_SQUASHFS")"
       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/f4
+      sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/f5
+
+      # jump back to grub from bsd4grml:
+      if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
+         if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
+            GRUB_VERSION=2
+         else
+            GRUB_VERSION=1
+         fi
+         if [ -e "$BUILD_OUTPUT"/boot/grub/stage2 ]; then
+            GRUB_LEGACY=stage2
+         else
+            GRUB_LEGACY=stage2_eltorito
+         fi
+
+         # why not ed(1)?
+         for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
+                     "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg; do
+             sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
+                    -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
+         done
+      fi
 
       # autostart for Windows:
       if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
@@ -718,14 +791,62 @@ if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$
 else
    mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
 
+   # support mkisofs as well as genisoimage
+   if which mkisofs >/dev/null 2>&1; then
+      MKISOFS='mkisofs'
+   elif which genisoimage >/dev/null 2>&1; then
+      MKISOFS='genisoimage'
+   else
+      log "Sorry, neither mkisofs nor genisoimage available - can not create ISO."
+      eerror "Sorry, neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
+      bailout
+   fi
+
    CURRENT_DIR=$(pwd)
    if cd "$BUILD_OUTPUT" ; then
-      log "mkisofs -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J -no-emul-boot -boot-load-size 4 -boot-info-table -b $BOOT_FILE -o ${ISO_OUTPUT}/${ISO_NAME} ."
-      mkisofs -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
+      log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J -no-emul-boot -boot-load-size 4 -boot-info-table -b $BOOT_FILE -o ${ISO_OUTPUT}/${ISO_NAME} ."
+      "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
               -l -r -J -no-emul-boot -boot-load-size 4 -boot-info-table    \
-              -b $BOOT_FILE \
+              -b $BOOT_FILE -no-pad \
               -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
 
+      # pad the output ISO to multiples of 256 KiB for partition table support
+      siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
+      cyls=$((siz / 512 / 32 / 16 + 1))                # C=$cyls H=16 S=32
+      siz=$((cyls * 16 * 32 * 512))            # size after padding
+      dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
+         of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
+
+      # support disabling hybrid ISO image
+      if [ "$HYBRID_METHOD" = "disable" ] ; then\
+         log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
+         einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
+         eend 0
+      # use isohybrid only on request
+      elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
+         if ! which isohybrid >/dev/null 2>&1 ; then
+           bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
+         else
+           log "Creating hybrid ISO file with isohybrid method"
+           einfo "Creating hybrid ISO file with isohybrid method"
+           isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
+           eend $?
+         fi
+      # by default use our manifold boot method:
+      else
+         if ! [ -r boot/grub/core.img ] ; then
+           ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
+         else
+           log "Creating hybrid ISO file with manifold method"
+           einfo "Creating hybrid ISO file with manifold method"
+           echo 1 63 | \
+               mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 1 -p 0x83 -g $cyls:16:32 | \
+               cat - boot/grub/core.img | \
+               dd conv=notrunc of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
+           eend $?
+         fi
+      fi
+
       # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
       case $CLASSES in *RELEASE*)
          [ "$RC" = 0 ] && \
@@ -756,8 +877,8 @@ fi
 
 # finalize {{{
 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
-einfo "Sucessfully finished execution of $PN [running ${SECONDS} seconds]" ; eend 0
-log "Sucessfully finished execution of $PN [running ${SECONDS} seconds]"
+einfo "Successfully finished execution of $PN [running ${SECONDS} seconds]" ; eend 0
+log "Successfully finished execution of $PN [running ${SECONDS} seconds]"
 bailout 0
 # }}}