X-Git-Url: http://git.grml.org/?p=grml-live.git;a=blobdiff_plain;f=grml-live;h=d04f6f57f7ae4c404ae2382f1a4f146eb18a13dd;hp=0055cc6982241b33e6575f7338bbd3c229b7e64e;hb=220ee724598d82ded6a43144f0c10e7cb927abeb;hpb=7741716c921420a1c8d8d63e9eadf0c80a3b3b51 diff --git a/grml-live b/grml-live index 0055cc6..d04f6f5 100755 --- a/grml-live +++ b/grml-live @@ -20,13 +20,13 @@ else fi # exit on any error: -set -e +# disable for now since it seems to cause some problems +# set -e # global variables -GRML_LIVE_VERSION='0.12.1' +GRML_LIVE_VERSION='0.16.1' PN="$(basename $0)" CMDLINE="$0 $@" -SOURCES_LIST_FILE='/etc/grml/fai/apt/sources.list' ADDONS_LIST_FILE='/boot/isolinux/addons_list.cfg' # }}} @@ -39,11 +39,13 @@ $PN - build process script for generating a (grml based) Linux Live-ISO Usage: $PN [options, see as follows] -a architecture; available values: i386 and amd64 + -A ensure clean build and pack artifacts -b build the ISO without updating the chroot via FAI -B build the ISO without touching the chroot (skips cleanup) -c classes to be used for building the ISO via FAI -C configuration file for grml-live -d use specified date instead of build time as date of release + -D use specified configuration directory instead of /etc/grml/fai -F force execution without prompting -g set the grml flavour name -h display short usage information and exit @@ -51,23 +53,24 @@ Usage: $PN [options, see as follows] -I directory which provides files that should become part of the chroot/ISO -n skip generation of ISO + -N bootstrap (build chroot) only, do not create files for ISO -o main output directory of the build process -q skip mksquashfs -r release name -s Debian suite; values: etch, lenny, squeeze, sid -t place of the templates -u update existing chroot instead of rebuilding it from scratch + -U arrange output to be owned by specified username -v specify version number of the release -V increase verbosity in the build process - -z use ZLIB instead of LZMA compression + -z use ZLIB instead of LZMA/XZ compression Usage examples: $PN - $PN -c GRMLBASE,GRML_MEDIUM,I386 -o /dev/shm/grml - $PN -c GRMLBASE,GRML_SMALL,REMOVE_DOCS,I386 -g grml-small -v 1.0 - $PN -c GRMLBASE,GRML_FULL,I386 -i grml_0.0-1.iso -v 0.0-1 - $PN -c GRMLBASE,GRML_FULL,I386 -s sid -V -r 'grml-live rocks' + $PN -c GRMLBASE,GRML_FULL,AMD64 -o /dev/shm/grml + $PN -c GRMLBASE,GRML_FULL,AMD64 -i grml_0.0-1.iso -v 0.0-1 + $PN -c GRMLBASE,GRML_FULL,AMD64 -s sid -V -r 'grml-live rocks' More details: man grml-live + /usr/share/doc/grml-live/grml-live.html http://grml.org/grml-live/ @@ -113,8 +116,15 @@ FORCE='' UPDATE='' BUILD_ONLY='' BUILD_DIRTY='' +BOOTSTRAP_ONLY='' HOSTNAME='' +# don't use colors/escape sequences +if [ -r /lib/lsb/init-functions ] ; then + . /lib/lsb/init-functions + ! log_use_fancy_output && NOCOLORS=true +fi + if [ -r /etc/grml/lsb-functions ] ; then . /etc/grml/lsb-functions else @@ -131,25 +141,55 @@ LIVE_CONF=/etc/grml/grml-live.conf . $LIVE_CONF # }}} +# umount all directories {{{ +umount_all() { + # make sure we don't leave any mounts - FAI doesn't remove them always + umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true + umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true + umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true + umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true + + # certain FAI versions sadly leave a ramdisk behind, so better safe than sorry + if [ -x /usr/lib/fai/mkramdisk ] ; then + /usr/lib/fai/mkramdisk -u "$(realpath ${CHROOT_OUTPUT}/var/lib/dpkg)" >/dev/null 2>&1 || /bin/true + fi + + umount "${CHROOT_OUTPUT}/grml-live/sources/" 2>/dev/null || /bin/true + [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}" +} +# }}} + # clean exit {{{ bailout() { rm -f /var/run/fai/fai_softupdate_is_running \ /var/run/fai/FAI_INSTALLATION_IN_PROGRESS [ -n "$SQUASHFS_STDERR" ] && rm -rf "$SQUASHFS_STDERR" - [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}" + umount_all [ -n "$1" ] && EXIT="$1" || EXIT="1" [ -n "$2" ] && eerror "$2">&2 + if [ -n "$PACK_ARTIFACTS" ]; then + log "Cleaning up" + einfo "Cleaning up" + [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}" + [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}" + eend 0 + fi + if [ -n "$CHOWN_USER" ]; then + log "Setting ownership" + einfo "Setting ownership" + [ -n "${OUTPUT}" -a -d "${OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${OUTPUT}" + [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${BUILD_OUTPUT}" + [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_OUTPUT}" + [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${ISO_OUTPUT}" + [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && chown -R "${CHOWN_USER}:" "${LOG_OUTPUT}" + [ -n "${CHROOT_ARCHIVE}" -a -f "${CHROOT_ARCHIVE}" ] && chown -R "${CHOWN_USER}:" "${CHROOT_ARCHIVE}" + eend 0 + fi log "------------------------------------------------------------------------------" exit "$EXIT" } trap bailout 1 2 3 3 6 9 14 15 -# }}} - -# log file stuff {{{ -[ -n "$LOGFILE" ] || LOGFILE=/var/log/grml-live.log -touch $LOGFILE -chown root:adm $LOGFILE -chmod 664 $LOGFILE +trap umount_all EXIT # }}} # some important functions {{{ @@ -199,32 +239,80 @@ extend_string_end() { done echo -ne "\n" } + +# Copy addonfile $1 from either +# * the chroot (via $2, the system path), +# * or from TEMPLATE_DIRECTORY/compat (if exists), +# * or from the host system (again, using $2), +# or warn about the missing file. +# +# This is because: +# * We assume that the chroot always has a "good" version of +# the file. Also it makes sources handling easier. +# * On unstable, we Recommend the Debian packages containing +# these files. The user can override them by putting his +# "better" version into the chroot. +# * On stable, the Debian packages are probably not available, +# or outdated, so we look in TEMPLATE_DIRECTORY/compat first, where +# our grml-live-compat package installs current file versions. +copy_addon_file() { + DEST="${BUILD_OUTPUT}/boot/$3" + if [ ! -d "${DEST}/" ]; then + mkdir -p "${DEST}" + fi + if [ -e "$CHROOT_OUTPUT/$2/$1" ]; then + log "Copying $1 from chroot" + cp "$CHROOT_OUTPUT/$2/$1" "${DEST}/" + return $? + fi + if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then + log "Copying $1 from grml-live-compat" + cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/" + return $? + fi + if [ -e "$2/$1" ]; then + log "Copying $1 from system" + cp "$2/$1" "${DEST}/" + return $? + fi + + msg="Missing addon file: \"$1\"" + ewarn "$msg" ; eend 1 + log "copy_addon_file: $msg" +} # }}} # read local (non-packaged) configuration {{{ LOCAL_CONFIG=/etc/grml/grml-live.local if [ -r "$LOCAL_CONFIG" ] ; then - log "Sourcing $LOCAL_CONFIG" . $LOCAL_CONFIG else - log "No $LOCAL_CONFIG found, not sourcing it" LOCAL_CONFIG='' fi + +if [ -n "${GRML_LIVE_SOURCES:-}" ] ; then + eerror "Config variable \$GRML_LIVE_SOURCES is set. This variable has been deprecated." + ewarn "Please set up ${GRML_FAI_CONFIG}/config/files/etc/apt/sources.list.d/* instead." + bailout 1 +fi # }}} # command line parsing {{{ -while getopts "a:C:c:d:g:i:I:o:r:s:t:v:bBFnquVz" opt; do +while getopts "a:C:c:d:D:g:i:I:o:r:s:t:U:v:AbBFnNquVz" opt; do case "$opt" in a) ARCH="$OPTARG" ;; + A) PACK_ARTIFACTS=1 ;; b) BUILD_ONLY=1 ;; B) BUILD_DIRTY=1 ;; c) CLASSES="$OPTARG" ;; C) CONFIG="$OPTARG" ;; d) DATE="$OPTARG" ;; + D) GRML_FAI_CONFIG="$OPTARG" ;; g) GRML_NAME="$OPTARG" ;; i) ISO_NAME="$OPTARG" ;; I) CHROOT_INSTALL="$OPTARG" ;; n) SKIP_MKISOFS=1 ;; + N) BOOTSTRAP_ONLY=1; SKIP_MKISOFS=1; SKIP_MKSQUASHFS=1 ;; o) OUTPUT="$OPTARG" ;; q) SKIP_MKSQUASHFS=1 ;; r) RELEASENAME="$OPTARG" ;; @@ -233,8 +321,9 @@ while getopts "a:C:c:d:g:i:I:o:r:s:t:v:bBFnquVz" opt; do v) VERSION="$OPTARG" ;; F) FORCE=1 ;; u) UPDATE=1 ;; + U) CHOWN_USER="$OPTARG" ;; V) VERBOSE="-v" ;; - z) SQUASHFS_ZLIB="true" ;; + z) SQUASHFS_ZLIB=1 ;; ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;; esac done @@ -242,31 +331,33 @@ shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter # }}} # assume sane defaults (if not set already) {{{ -[ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)" -[ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux' -[ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_MEDIUM,I386" -[ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)" -[ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators ' -[ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml" -[ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png' -[ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false" -[ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai' -[ -n "$GRML_NAME" ] || GRML_NAME='grml' -[ -n "$HOSTNAME" ] || HOSTNAME='grml' -[ -n "$NFSROOT_CONF" ] || NFSROOT_CONF='/etc/grml/fai/make-fai-nfsroot.conf' -[ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks' -[ -n "$SQUASHFS_EXCLUDES_FILE " ] || SQUASHFS_EXCLUDES_FILE='/etc/grml/fai/squashfs-excludes' -[ -n "$SUITE" ] || SUITE='lenny' -[ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates' -[ -n "$USERNAME" ] || USERNAME='grml' -[ -n "$VERSION" ] || VERSION='0.0.1' -[ -n "$WINDOWS_BINARIES" ] || WINDOWS_BINARIES='http://the.earth.li/~sgtatham/putty/latest/x86/' +[ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)" +[ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux' +[ -n "$CLASSES" ] || CLASSES="GRMLBASE,GRML_FULL,$(echo ${ARCH} | tr 'a-z' 'A-Z')" +[ -n "$DATE" ] || DATE="$(date +%Y-%m-%d)" +[ -n "$DISTRI_INFO" ] || DISTRI_INFO='Grml - Live Linux for system administrators ' +[ -n "$DISTRI_NAME" ] || DISTRI_NAME="grml" +[ -n "$DISTRI_SPLASH" ] || DISTRI_SPLASH='grml.png' +[ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false" +[ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai' +[ -n "$GRML_NAME" ] || GRML_NAME='grml' +[ -n "$HOSTNAME" ] || HOSTNAME='grml' +[ -n "$HYBRID_METHOD" ] || HYBRID_METHOD='manifold' +[ -n "$NFSROOT_CONF" ] || NFSROOT_CONF="${GRML_FAI_CONFIG}/make-fai-nfsroot.conf" +[ -n "$RELEASENAME" ] || RELEASENAME='grml-live rocks' +[ -n "$SQUASHFS_EXCLUDES_FILE" ] || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes" +[ -n "$SUITE" ] || SUITE='squeeze' +[ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates' +[ -n "$USERNAME" ] || USERNAME='grml' +[ -n "$VERSION" ] || VERSION='0.0.1' # output specific stuff, depends on $OUTPUT (iff not set): [ -n "$OUTPUT" ] || OUTPUT='/grml/grml-live' [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd" [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot" +[ -n "$CHROOT_ARCHIVE" ] || CHROOT_ARCHIVE="$OUTPUT/$(basename $CHROOT_OUTPUT).tgz" [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos" +[ -n "$LOG_OUTPUT" ] || LOG_OUTPUT="$OUTPUT/grml_logs" # }}} # some misc checks before executing FAI {{{ @@ -302,6 +393,7 @@ if [ -z "$FORCE" ] ; then echo " FAI classes: $CLASSES" [ -r "$LOCAL_CONFIG" ] && echo " Local config: /etc/grml/grml-live.local" [ -n "$CONFIG" ] && echo " Configuration: $CONFIG" + [ -n "$GRML_FAI_CONFIG" ] && echo " Config directory: $GRML_FAI_CONFIG" echo " main directory: $OUTPUT" [ -n "$CHROOT_OUTPUT" ] && echo " Chroot target: $CHROOT_OUTPUT" [ -n "$BUILD_OUTPUT" ] && echo " Build target: $BUILD_OUTPUT" @@ -313,21 +405,28 @@ if [ -z "$FORCE" ] ; then [ -n "$SUITE" ] && echo " Debian suite: $SUITE" [ -n "$ARCH" ] && echo " Architecture: $ARCH" [ -n "$BOOT_METHOD" ] && echo " Boot method: $BOOT_METHOD" + [ -n "$HYBRID_METHOD" ] && echo " Hybrid method: $HYBRID_METHOD" [ -n "$TEMPLATE_DIRECTORY" ] && echo " Template files: $TEMPLATE_DIRECTORY" [ -n "$CHROOT_INSTALL" ] && echo " Install files from directory to chroot: $CHROOT_INSTALL" [ -n "$BOOTID" ] && echo " Boot identifier: $BOOTID" [ -n "$NO_BOOTID" ] && echo " Skipping bootid feature." + [ -n "$CHOWN_USER" ] && echo " Output owner: $CHOWN_USER" [ -n "$DEFAULT_BOOTOPTIONS" ] && echo " Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\"" [ -n "$FAI_ARGS" ] && echo " Additional arguments for FAI: $FAI_ARGS" [ -n "$LOGFILE" ] && echo " Logging to file: $LOGFILE" - [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA) compression." + [ -n "$SQUASHFS_ZLIB" ] && echo " Using ZLIB (instead of LZMA/XZ) compression." [ -n "$SQUASHFS_OPTIONS" ] && echo " Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}" [ -n "$VERBOSE" ] && echo " Using VERBOSE mode." + [ -n "$PACK_ARTIFACTS" ] && echo " Will prepare packed artifacts and ensure clean build." [ -n "$UPDATE" ] && echo " Executing UPDATE instead of fresh installation." - [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file." - [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file." - [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE." - [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched." + if [ -n "$BOOTSTRAP_ONLY" ] ; then + echo " Bootstrapping only and not building (files for) ISO." + else + [ -n "$SKIP_MKSQUASHFS" ] && echo " Skipping creation of SQUASHFS file." + [ -n "$SKIP_MKISOFS" ] && echo " Skipping creation of ISO file." + [ -n "$BUILD_ONLY" ] && echo " Executing BUILD_ONLY instead of fresh installation or UPDATE." + [ -n "$BUILD_DIRTY" ] && echo " Executing BUILD_DIRTY to leave chroot untouched." + fi echo echo -n "Is this ok for you? [y/N] " read a @@ -338,6 +437,25 @@ if [ -z "$FORCE" ] ; then fi # }}} +# clean up before start {{{ +if [ -n "${PACK_ARTIFACTS}" ]; then + echo "Wiping old artifacts" + [ -n "${CHROOT_OUTPUT}" -a -d "${CHROOT_OUTPUT}" ] && rm -r "${CHROOT_OUTPUT}" + [ -n "${BUILD_OUTPUT}" -a -d "${BUILD_OUTPUT}" ] && rm -r "${BUILD_OUTPUT}" + [ -n "${ISO_OUTPUT}" -a -d "${ISO_OUTPUT}" ] && rm -r "${ISO_OUTPUT}" + [ -n "${LOG_OUTPUT}" -a -d "${LOG_OUTPUT}" ] && rm -r "${LOG_OUTPUT}" + [ -n "${CHROOT_ARCHIVE}" -a -f "${CHROOT_ARCHIVE}" ] && rm "${CHROOT_ARCHIVE}" +fi +# }}} + +# create log file {{{ +[ -n "$LOGFILE" ] || LOGFILE=${LOG_OUTPUT}/grml-live.log +mkdir -p $(dirname "${LOGFILE}") +touch $LOGFILE +chown root:adm $LOGFILE +chmod 664 $LOGFILE +# }}} + # clean/zero/remove logfiles {{{ if [ -n "$PRESERVE_LOGFILE" ] ; then @@ -374,6 +492,9 @@ fi start_seconds=$(cut -d . -f 1 /proc/uptime) log "------------------------------------------------------------------------------" log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)" +if [ -n "$LOCAL_CONFIG" ]; then + log "Using local config file: $LOCAL_CONFIG" +fi log "Executed grml-live command line:" log "$CMDLINE" @@ -381,69 +502,17 @@ einfo "Logging actions to logfile $LOGFILE" # }}} # on-the-fly configuration {{{ -if [ -n "$MIRROR_DIRECTORY" ] ; then - if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then - log "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]" - eerror "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting." ; eend 1 - bailout 1 - fi - cat > "$SOURCES_LIST_FILE" << EOF -# NOTE: This file is *NOT* meant for manual customisation! This file is -# modified by grml-live and any changes might be overridden. -# You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf* -# or FAI's fcopy command with /etc/grml/fai/config/files instead! -EOF - echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_FILE" - if [ -n "$GRML_LIVE_SOURCES" ] ; then - echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE" - fi -elif [ -n "$GRML_LIVE_SOURCES" ] ; then - cat > "$SOURCES_LIST_FILE" << EOF -# NOTE: This file is *NOT* meant for manual customisation! This file is -# modified by grml-live and any changes might be overridden. -# You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf* -# or FAI's fcopy command with /etc/grml/fai/config/files instead! -EOF - echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE" -fi - if [ -n "$FAI_DEBOOTSTRAP" ] ; then - sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF" + sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF" fi # does this suck? YES! # /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 ;; + unstable) SUITE='sid' ; CLASSES="DEBIAN_UNSTABLE,$CLASSES" ;; + *) CLASSES="DEBIAN_$(echo $SUITE | tr 'a-z' 'A-Z'),$CLASSES";; esac - -DIST=" etch\| stable\| lenny\| squeeze\| testing\| sid\| unstable" -sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE" -for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" ; do - if [ -n "$file" ] ; then - sed "s/^SUITE=.*/SUITE=\"$SUITE\"/" $file | sponge $file - sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$file" | sponge "$file" - fi -done - -# notice: activate grml-live pool only if we are building against unstable: -if grep -qe unstable -qe sid "$SOURCES_LIST_FILE" ; then - grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" || \ - grep grml-stable "$SOURCES_LIST_FILE" | \ - sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_FILE" -else - grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" && \ - sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE" -fi +export SUITE # make sure it's available in FAI scripts for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do if [ -n "$file" ] ; then @@ -507,8 +576,8 @@ else fi if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then - log "Skiping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." - ewarn "Skiping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0 + log "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." + ewarn "Skipping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0 else mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI" @@ -517,12 +586,22 @@ else mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}" fi + mkdir -p "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/" + mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/" + + # tell dpkg to use "unsafe io" during the build + [ -d "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d" ] || mkdir -p "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d" + echo force-unsafe-io > "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io" + log "Executed FAI command line:" - log "BUILD_ONLY=$BUILD_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS" - BUILD_ONLY="$BUILD_ONLY" fai $VERBOSE -C "$GRML_FAI_CONFIG" -c"$CLASSES" -u \ - "$HOSTNAME" $FAI_ACTION "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE + log "BUILD_ONLY=$BUILD_ONLY BOOTSTRAP_ONLY=$BOOTSTRAP_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -s file:///$GRML_FAI_CONFIG/config -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS" + BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" fai $VERBOSE \ + -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \ + -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE RC="$PIPESTATUS" # notice: bash-only + rm -f "$CHROOT_OUTPUT/etc/dpkg/dpkg.cfg.d/unsafe-io" + FORCE_ISO_REBUILD=true if [ "$RC" != 0 ] ; then @@ -530,28 +609,36 @@ else eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1 bailout 1 else - log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" + einfo "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" + log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" > $CHROOT_OUTPUT/etc/grml_version chmod 644 $CHROOT_OUTPUT/etc/grml_version einfo "Rebuilding initramfs" - # make sure new /etc/grml_version reaches the initramfs: + # make sure new /etc/grml_version reaches initramfs, iterate over all + # present kernel versions (note: we can't really handle more than one + # kernel version anyway right now) # chroot $CHROOT_OUTPUT update-initramfs -u -t => might break when using kernel-package :( - chroot $CHROOT_OUTPUT update-initramfs -u -k all + for initrd in "$(basename $CHROOT_OUTPUT/boot/vmlinuz-*)" ; do + if ! chroot $CHROOT_OUTPUT update-initramfs -k "${initrd##vmlinuz-}" -c ; then + einfo "Creating fresh initrd did not work, trying update instead:" + log "Creating fresh initrd did not work, trying update instead:" + chroot $CHROOT_OUTPUT update-initramfs -k "${initrd##vmlinuz-}" -u + fi + done eend $? fi - # Remove all FAI logs from chroot if class RELEASE is used: - if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then - rm -rf "$CHROOT_OUTPUT"/var/log/fai/* - fi + # move fai logs into grml_logs directory + mkdir -p "$LOG_OUTPUT"/fai/ + cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/ + chown root:adm "$LOG_OUTPUT"/fai/* + chmod 664 "$LOG_OUTPUT"/fai/* + rm -rf "$CHROOT_OUTPUT"/var/log/fai - # make sure we don't leave any mounts - FAI doesn't remove them always - umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true - umount $CHROOT_OUTPUT/sys 2>/dev/null || /bin/true - umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true - umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true + # Remove all FAI logs from chroot if class RELEASE is used: + rm -f "$CHROOT_OUTPUT"/var/log/install_packages.list - [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}" + umount_all # notice: 'fai dirinstall' does not seem to exit appropriate, so: ERROR='' @@ -610,310 +697,279 @@ fi [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd" mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH" -# i386: +# prepare ISO if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then - if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then - log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." - ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0 - else - # booting stuff: - [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux - [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" - - if [ -z "$NO_ADDONS" ] ; then - [ -d "$BUILD_OUTPUT"/boot/addons ] || mkdir -p "$BUILD_OUTPUT"/boot/addons - if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then - log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest" - cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest - elif [ -r /boot/memtest86+.bin ] ; then - log "Installing /boot/memtest86+.bin" - cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest - else - ewarn "No memtest binary found (either install package grml-live-addons or memtest86+), skipping." - log "No memtest binary found (either install package grml-live-addons or memtest86+), skipping." - eend 0 - fi - fi - - # if we don't have an initrd we a) can't boot and b) there was an error - # during build, so check for the file: - INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)" - if [ -n "$INITRD" ] ; then - cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz - find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \; - else - log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" - eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1 - bailout 10 - fi - - KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)" - if [ -n "$KERNEL_IMAGE" ] ; then - cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26 - else - log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" - eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1 - bailout 11 - fi - - [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates' - if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then - log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." - eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1 - bailout 8 - fi - - # *always* copy files to output directory so the variables - # get adjusted according to the build - cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/ + if [ -n "$BOOTSTRAP_ONLY" ] ; then + log "Skipping stage 'boot' as building with bootstrap only." + ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0 + else + if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then + log "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." + ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0 + else + # booting stuff: + [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux + [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" + + # if we don't have an initrd we a) can't boot and b) there was an error + # during build, so check for the file: + INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)" + if [ -n "$INITRD" ] ; then + cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz + find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \; + else + log "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" + eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1 + bailout 10 + fi + + KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)" + if [ -n "$KERNEL_IMAGE" ] ; then + cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26 + else + log "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" + eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1 + bailout 11 + fi + + [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates' + if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then + log "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." + eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1 + bailout 8 + fi + + # copy _required_ isolinux files + for file in ifcpu64.c32 isolinux.bin vesamenu.c32; do + copy_addon_file "${file}" /usr/lib/syslinux isolinux + done + + # *always* copy files to output directory so the variables + # get adjusted according to the build. + cp ${TEMPLATE_DIRECTORY}/boot/isolinux/* "$BUILD_OUTPUT"/boot/isolinux/ + + if [ -n "$NO_ADDONS" ] ; then + log "Skipping installation of boot addons as requested via \$NO_ADDONS." + einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0 + else + if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then + log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" + ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0 + else + # copy addons from system packages or grml-live-compat + copy_addon_file ipxe.lkrn /usr/lib/ipxe addons + copy_addon_file pci.ids /usr/share/misc addons + copy_addon_file memtest86+.bin /boot addons + for file in memdisk chain.c32 hdt.c32 menu.c32; do + copy_addon_file "${file}" /usr/lib/syslinux addons + done + + # make memtest filename FAT16/8.3 compatible + mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \ + "${BUILD_OUTPUT}/boot/addons/memtest" + + # 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 [ -n "$NO_ADDONS_BSD4GRML" ] ; then + log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML." + einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0 + else + if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then + cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/ + else + log "Missing addon file: bsd4grml" + ewarn "Missing addon file: bsd4grml" ; eend 0 + fi + fi - if [ -n "$NO_ADDONS" ] ; then - log "Skipping installation of boot addons as requested via \$NO_ADDONS." - einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0 - else - if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then - log "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" - ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0 + fi # no "$TEMPLATE_DIRECTORY"/boot/addons + fi # NO_ADDONS + + if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then + mkdir -p "${BUILD_OUTPUT}/boot/grub" + fi + cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/ + + if [ -e ${TEMPLATE_DIRECTORY}/compat/grub/linux.mod ]; then + cp "${TEMPLATE_DIRECTORY}"/compat/grub/* "${BUILD_OUTPUT}"/boot/grub/ + else + if ! which "grub-mkimage" >/dev/null 2>&1 ; then + log "grub-mkimage not found, skipping Grub step therefore." ; eend 0 + ewarn "grub-mkimage not found, skipping Grub step therefore." + ewarn "Please install grub-pc-bin or grub-common >= 1.98+20100804-14." ; eend 0 + elif ! grub-mkimage --help | grep -q -- --format ; then + log "grub-mkimage does not support --format=i386-pc, skipping Grub step therefore." ; eend 0 + ewarn "grub-mkimage does not support --format=i386-pc, skipping Grub step therefore." + ewarn "Please install grub-common >= 1.98+20100804-14 or grub-pc-bin." ; 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 [ -n "$NO_ADDONS_BSD4GRML" ] ; then - log "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML." - einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0 + # copy system grub files if grml-live-compat is not installed + cp -a /usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/ + cp -a /usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/ + cp -a /usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/ + cp -a /usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/ + grub-mkimage -d /usr/lib/grub/*-pc -o \ + "${BUILD_OUTPUT}/boot/grub/core.img" biosdisk iso9660 --format=i386-pc + fi + fi + + if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then + log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." + eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1 + bailout 9 + fi + + [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML + cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/ + + # adjust boot splash information: + RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME" + RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")" + RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")" + + if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then + sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version + sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version + fi + + # make sure the squashfs filename is set accordingly: + SQUASHFS_NAME="$GRML_NAME.squashfs" + + if [ -n "$NO_BOOTID" ] ; then + log 'Skipping bootid feature as requested via $NO_BOOTID.' + einfo 'Skipping bootid feature as requested via $NO_BOOTID.' + else + [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')" + [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf + einfo "Generating /conf/bootid.txt with entry ${BOOTID}." + log "Generating /conf/bootid.txt with entry ${BOOTID}." + echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt + eend $? + fi + + # adjust all variables in the templates with the according distribution information + for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \ + "${BUILD_OUTPUT}"/boot/grub/* ; do + if [ -r "${file}" ] ; then + sed -i "s/%ARCH%/$ARCH/g" "${file}" + sed -i "s/%DATE%/$DATE/g" "${file}" + sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}" + sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}" + sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}" + sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}" + sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}" + sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}" + sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}" + sed -i "s/%VERSION%/$VERSION/g" "${file}" + + [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}" + + if [ -n "$NO_BOOTID" ] ; then + sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption else - if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then - cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/ - else - log "bsd4grml addon not found, skipping therefore." - ewarn "bsd4grml addon not found, skipping therefore." ; eend 0 - fi + sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument fi - - fi # no "$TEMPLATE_DIRECTORY"/boot/addons - fi # NO_ADDONS - - if ! [ -d ${TEMPLATE_DIRECTORY}/boot/grub ] ; then - log "grub templates do not exist, skipping therefore." - ewarn "grub templates do not exist, skipping therefore." ; eend 0 - else - 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/ - fi - - if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then - log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." - eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1 - bailout 9 - fi - - [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML - cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/ - - # adjust boot splash information: - RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME" - RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")" - RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")" - - if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then - sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version - sed -i "s/%DATE%/$DATE/" "$BUILD_OUTPUT"/GRML/grml-version - fi - - # make sure the squashfs filename is set accordingly: - SQUASHFS_NAME="$GRML_NAME.squashfs" - - if [ -n "$NO_BOOTID" ] ; then - log 'Skipping bootid feature as requested via $NO_BOOTID.' - einfo 'Skipping bootid feature as requested via $NO_BOOTID.' - else - [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')" - [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf - einfo "Generating /conf/bootid.txt with entry ${BOOTID}." - log "Generating /conf/bootid.txt with entry ${BOOTID}." - echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt - eend $? - fi - - # adjust all variables in the templates with the according distribution information - for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \ - "${BUILD_OUTPUT}"/boot/grub/* ; do - if [ -r "${file}" ] ; then - sed -i "s/%ARCH%/$ARCH/g" "${file}" - sed -i "s/%DATE%/$DATE/g" "${file}" - sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g" "${file}" - sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g" "${file}" - sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g" "${file}" - sed -i "s/%GRML_NAME%/$GRML_NAME/g" "${file}" - sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g" "${file}" - sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g" "${file}" - sed -i "s/%SHORT_NAME%/$SHORT_NAME/g" "${file}" - sed -i "s/%VERSION%/$VERSION/g" "${file}" - - [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/" "${file}" - - if [ -n "$NO_BOOTID" ] ; then - sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption - else - sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument + done + + # adjust bootsplash accordingly but make sure the string has the according lenght + SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")" + SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")" + for file in f4 f5 ; do + if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then + sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}" + sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}" fi - fi - done - - # adjust bootsplash accordingly but make sure the string has the according lenght - SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")" - SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")" - for file in f4 f5 ; do - if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then - sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}" - sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}" - fi - done - - # generate addon list - rm "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}" - for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do - include_name=$(basename "$name") - echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}" - done - - if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then - log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg" - echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" - echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" - echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" - echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" - - for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do - echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" - done - - echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" - if [ ! -n "$NO_ADDONS" ] ; then - echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" - fi - echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" - echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" - echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" - else # assume we are building a custom distribution: - log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it." - einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it." - if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then - log "include for ${DISTRI_NAME}.cfg already present, nothing to do." - eindent - einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do." - eoutdent - eend $? - else - log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg" - echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" - [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" - fi - fi - - # use old style console based isolinux method only if requested: - if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then - log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.' - einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.' - if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then - einfo "include for console.cfg already foud, nothing to do." - eend 0 - else - log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" - einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" - echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" - eend $? - fi - else - log 'Using graphical boot menu.' - if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then - log "include for vesamenu.cfg already foud, nothing to do." - else - log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" - echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" - fi - fi - - # jump back to grub from bsd4grml (/boot/grub/stage2): - GRUB_LEGACY=stage2 - - 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 - - for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \ - "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg \ - "$BUILD_OUTPUT"/boot/isolinux/*.cfg \ - "$BUILD_OUTPUT"/boot/grub/grub.cfg \ - "$BUILD_OUTPUT"/boot/grub/menu.lst ; do - if [ -e "$file" ] ; then - sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \ - -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file" - fi - done - - sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 - fi - - if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then - sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst - sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg - elif [ -e "$BUILD_OUTPUT"/boot/grub/menu.lst -a -e "$BUILD_OUTPUT"/boot/grub/grub.cfg ] ; then - sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst - sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg - fi - - DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot - if ! [ -r "$DPKG_LIST" ] ; then - ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore." - else - einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO." - cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt" - eend $? - fi - - # autostart for Windows: - if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then - cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/ - fi - - # windows-binaries: - if [ -n "$NO_WINDOWS_BINARIES" ] ; then - log "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES." - einfo "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES." - eend 0 - else - if [ -f "$BUILD_OUTPUT"/windows/putty.exe ] ; then - log "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already." - ewarn "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already." ; eend 0 + done + + # generate addon list + rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}" + for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do + include_name=$(basename "$name") + echo "include $include_name" >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}" + done + + if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then + log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg" + echo "include grmlmain.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" + echo "include default.cfg" > "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" + echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" + echo "include grml.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" + + for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do + echo "include $(basename $f)" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" + done + + echo "include options.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" + if [ ! -n "$NO_ADDONS" ] ; then + echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" + fi + echo "include isoprompt.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" + echo "include hd.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" + echo "include hidden.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg" + else # assume we are building a custom distribution: + log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it." + einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it." + if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then + log "include for ${DISTRI_NAME}.cfg already present, nothing to do." + eindent + einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do." + eoutdent + eend $? else - if ! [ -d "$BUILD_OUTPUT"/windows ] ; then - mkdir "$BUILD_OUTPUT"/windows - ( cd "$BUILD_OUTPUT"/windows - for file in pageant plink pscp psftp putty puttygen ; do - wget -O ${file}.exe ${WINDOWS_BINARIES}/${file}.exe - md5sum ${file}.exe > ${file}.exe.md5 - done ) - fi - - log "Finished execution of stage 'WINDOWS_BINARIES' [$(date)]" - einfo "Finished execution of stage 'WINDOWS_BINARIES'" ; eend 0 - fi - fi - - FORCE_ISO_REBUILD=true - einfo "Finished execution of stage 'boot'" ; eend 0 - fi + log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg" + echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" + [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" + fi + fi + + # use old style console based isolinux method only if requested: + if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then + log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.' + einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.' + if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then + einfo "include for console.cfg already found, nothing to do." + eend 0 + else + log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" + einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" + echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" + eend $? + fi + else + log 'Using graphical boot menu.' + if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then + log "include for vesamenu.cfg already found, nothing to do." + else + log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" + echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" + fi + fi + + if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then + sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 + fi + + DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot + if ! [ -r "$DPKG_LIST" ] ; then + ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore." + else + einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO." + cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt" + eend $? + fi + + # autostart for Windows: + if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then + cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/ + fi + + FORCE_ISO_REBUILD=true + einfo "Finished execution of stage 'boot'" ; eend 0 + fi + fi # BOOTSTRAP_ONLY else log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1 @@ -939,8 +995,8 @@ if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD log "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0 elif [ -n "$SKIP_MKSQUASHFS" ] ; then - log "Skipping stage 'squashfs' as requested via option -q" - ewarn "Skipping stage 'squashfs' as requested via option -q" ; eend 0 + log "Skipping stage 'squashfs' as requested via option -q or -N" + ewarn "Skipping stage 'squashfs' as requested via option -q or -N" ; eend 0 else [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live # make sure we don't leave (even an empty) base.tgz: @@ -965,15 +1021,17 @@ else # use blocksize 256k as this gives best result with regards to time + compression SQUASHFS_OPTIONS="-b 256k" - # set lzma compression by default, unless -z option has been specified on command line + # set lzma/xz compression by default, unless -z option has been specified on command line if [ -z "$SQUASHFS_ZLIB" ] ; then - SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp lzma" + SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp xz" + else + SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp gzip" fi fi # support exclusion of files via exclude-file: if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then - SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE" + SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE -wildcards" fi # get rid of unnecessary files when building grml-small for final release: @@ -986,14 +1044,13 @@ else # informational stuff [ -n "$SQUASHFS_OPTIONS" ] && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS" - [ -n "$SQUASHFS_ZLIB" ] && SQUASHFS_INFO_MSG="$SQUASHFS_INFO_MSG $SQUASHFS_ZLIB" [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG" einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG" - log "$SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB" + log "$SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS" - if $SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \ - -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB 2>"${SQUASHFS_STDERR}" ; then + if $SQUASHFS_BINARY $CHROOT_OUTPUT/ $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \ + -noappend $SQUASHFS_OPTIONS 2>"${SQUASHFS_STDERR}" ; then echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module log "Finished execution of stage 'squashfs' [$(date)]" einfo "Finished execution of stage 'squashfs'" ; eend 0 @@ -1010,8 +1067,10 @@ else fi # create md5sum file: -( cd $BUILD_OUTPUT/GRML && -find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums ) +if [ -z "$BOOTSTRAP_ONLY" ] ; then + ( cd $BUILD_OUTPUT/GRML && + find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums ) +fi # }}} # ISO_OUTPUT - mkisofs {{{ @@ -1020,18 +1079,25 @@ find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > if [ "$BOOT_METHOD" = "isolinux" ] ; then BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat" -elif [ "$BOOT_METHOD" = "grub" ] ; then - BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/grub/stage2" elif [ "$BOOT_METHOD" = "grub2" ] ; then BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin" fi +# Just until http://bts.grml.org/grml/issue945 has been resolved. +# HYBRID_METHOD defaults to manifold, so make sure the default works OOTB. +if [[ $BOOT_METHOD != isolinux && ($HYBRID_METHOD = isohybrid || $HYBRID_METHOD = manifold) ]]; then + log "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet." + ewarn "Setting HYBRID_METHOD to grub2 as hybrid mode does not work with isohybrid yet." + HYBRID_METHOD='grub2' + eend 0 +fi + if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ] ; then log "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0 elif [ -n "$SKIP_MKISOFS" ] ; then - log "Skipping stage 'iso build' as requested via option -n" - ewarn "Skipping stage 'iso build' as requested via option -n" ; eend 0 + log "Skipping stage 'iso build' as requested via option -n or -N" + ewarn "Skipping stage 'iso build' as requested via option -n or -N" ; eend 0 else mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'" @@ -1152,6 +1218,16 @@ else fi # }}} +# pack artifacts {{{ +if [ -n "$PACK_ARTIFACTS" ]; then + log "Packing artifcats" + einfo "Packing artifacts" + [ -f "${CHROOT_ARCHIVE}" ] && rm -r "${CHROOT_ARCHIVE}" + tar -c -a -f ${CHROOT_ARCHIVE} --preserve-permissions -C "$(dirname ${CHROOT_OUTPUT})" "$(basename ${CHROOT_OUTPUT})" + eend 0 +fi +# }}} + # log build information to database if grml-live-db is installed and enabled {{{ dpkg_to_db() { if [ -d /usr/share/grml-live-db ] ; then @@ -1209,4 +1285,4 @@ bailout 0 # }}} ## END OF FILE ################################################################# -# vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3 +# vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2