ce61ca7338a54cf1a3fbca02e3481198ab01fc9e
[grml-live.git] / grml-live
1 #!/bin/bash
2 # Filename:      grml-live
3 # Purpose:       build process script for generating a (grml based) Linux Live-ISO
4 # Authors:       grml-team (grml.org),
5 #                (c) Michael Prokop <mika@grml.org>,
6 #                (c) Thorsten Glaser <tg@mirbsd.org>
7 # Bug-Reports:   see http://grml.org/bugs/
8 # License:       This file is licensed under the GPL v2 or any later version.
9 ################################################################################
10
11 # some misc and global stuff {{{
12 export LANG=C
13 export LC_ALL=C
14
15 # define function getfilesize before "set -e"
16 if stat --help >/dev/null 2>&1; then
17   getfilesize='stat -c %s'  # GNU stat
18 else
19   getfilesize='stat -f %z'  # BSD stat
20 fi
21
22 # exit on any error:
23 set -e
24
25 # global variables
26 GRML_LIVE_VERSION='0.9.21'
27 PN="$(basename $0)"
28 CMDLINE="$0 $@"
29 ISO_DATE="$(date +%Y-%m-%d)"
30 SOURCES_LIST_FILE='/etc/grml/fai/apt/sources.list'
31 # }}}
32
33 # usage information {{{
34 usage()
35 {
36   echo "
37 $PN - build process script for generating a (grml based) Linux Live-ISO
38
39 Usage: $PN [options, see as follows]
40
41    -a <architecture>       architecture; available values: i386 and amd64
42    -b                      build the ISO without updating the chroot via FAI
43    -B                      build the ISO without touching the chroot (skips cleanup)
44    -c <classe[s]>          classes to be used for building the ISO via FAI
45    -C <configfile>         configuration file for grml-live
46    -F                      force execution without prompting
47    -g <grml_name>]         set the grml flavour name
48    -h                      display short usage information and exit
49    -i <iso_name>           name of ISO
50    -o <output_directory>   main output directory of the build process
51    -q                      skip mksquashfs
52    -r <release_name<       release name
53    -s <suite>              Debian suite; values: etch, lenny, squeeze, sid
54    -t <template_directory> place of the templates
55    -u                      update existing chroot instead of rebuilding it from scratch
56    -v <version_number>     specify version number of the release
57    -V                      increase verbosity in the build process
58    -z                      use ZLIB instead of LZMA compression (depends on
59                            squashfs-tools version)
60
61 Usage examples:
62
63     $PN
64     $PN -c GRMLBASE,GRML_MEDIUM,I386 -o /dev/shm/grml
65     $PN -c GRMLBASE,GRML_SMALL,REMOVE_DOCS,I386 -g grml-small -v 1.0
66     $PN -c GRMLBASE,GRML_FULL,I386 -i grml_0.0-1.iso -v 0.0-1
67     $PN -c GRMLBASE,GRML_FULL,I386 -s sid -V -r 'grml-live rocks'
68
69 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
70               http://grml.org/grml-live/
71
72 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
73 "
74 }
75
76 # make sure it's possible to get usage information without being
77 # root or actually executing the script
78 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
79    usage
80    [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
81    exit 0
82 fi
83 # }}}
84
85 # some runtime checks {{{
86 # we need root permissions for the build-process:
87 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
88    echo "Error: please run this script with uid 0 (root)." >&2
89    exit 1
90 fi
91
92 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
93    echo "/usr/sbin/fai already running or was aborted before.">&2
94    echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
95    exit 1
96 fi
97
98 # see #449236
99 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
100    echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
101    echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
102    exit 1
103 fi
104 # }}}
105
106 # lsb-functions and configuration stuff {{{
107 # make sure they are not set by default
108 VERBOSE=''
109 FORCE=''
110 UPDATE=''
111 BUILD_ONLY=''
112 BUILD_DIRTY=''
113 HOSTNAME=''
114
115 if [ -r /etc/grml/lsb-functions ] ; then
116    . /etc/grml/lsb-functions
117 else
118    einfo()  { echo "  [*] $*" ;}
119    eerror() { echo "  [!] $*">&2 ;}
120    ewarn()  { echo "  [x] $*" ;}
121    eend()   { return 0 ;}
122 fi
123
124 # source main configuration file:
125 LIVE_CONF=/etc/grml/grml-live.conf
126 . $LIVE_CONF
127 # }}}
128
129 # clean exit {{{
130 bailout() {
131   rm -f /var/run/fai/fai_softupdate_is_running \
132         /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
133   [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
134   [ -n "$1" ] && EXIT="$1" || EXIT="1"
135   [ -n "$2" ] && eerror "$2">&2
136   log "------------------------------------------------------------------------------"
137   exit "$EXIT"
138 }
139 trap bailout 1 2 3 3 6 9 14 15
140 # }}}
141
142 # log file stuff {{{
143 [ -n "$LOGFILE" ] || LOGFILE=/var/log/grml-live.log
144 touch $LOGFILE
145 chown root:adm $LOGFILE
146 chmod 664 $LOGFILE
147 # }}}
148
149 # some important functions {{{
150
151 # log output:
152 # usage: log "string to log"
153 log() { echo "$*" >> $LOGFILE ; }
154
155 # cut string at character number int = $1
156 # usage: cut_string 5 "1234567890" will output "12345"
157 cut_string() {
158   [ -n "$2" ] || return 1
159   echo "$2" | head -c "$1"; echo -ne "\n"
160 }
161
162 # prepend int = $1 spaces before string = $2
163 # usage: extend_string_begin 5 "123" will output "  123"
164 extend_string_begin() {
165   [ -n "$2" ] || return 1
166   local COUNT="$(echo $2 | wc -c)"
167   local FILL="$(expr $COUNT - $1)"
168   while [ "$FILL" -gt 1 ] ; do
169     echo -n " "
170     local FILL=$(expr $FILL - 1)
171   done
172   while [ "$FILL" -lt 1 ] ; do
173     echo -n " "
174     local FILL=$(expr $FILL + 1)
175   done
176   echo "$2" | head -c "$1"; echo -ne "\n"
177 }
178
179 # append int = $1 spaces to string = $2
180 # usage: extend_string_begin 5 "123" will output "123  "
181 extend_string_end() {
182   [ -n "$2" ] || return 1
183   echo -n "$2" | head -c "$1"
184   local COUNT="$(echo $2 | wc -c)"
185   local FILL="$(expr $COUNT - $1)"
186   while [ "$FILL" -gt 1 ] ; do
187     echo -n " "
188     local FILL=$(expr $FILL - 1)
189   done
190   while [ "$FILL" -lt 1 ] ; do
191     echo -n " "
192     local FILL=$(expr $FILL + 1)
193   done
194   echo -ne "\n"
195 }
196 # }}}
197
198 # read local (non-packaged) configuration {{{
199 LOCAL_CONFIG=/etc/grml/grml-live.local
200 if [ -r "$LOCAL_CONFIG" ] ; then
201    log "Sourcing $LOCAL_CONFIG"
202    . $LOCAL_CONFIG
203 else
204    log "No $LOCAL_CONFIG found, not sourcing it"
205    LOCAL_CONFIG=''
206 fi
207 # }}}
208
209 # command line parsing {{{
210 while getopts "a:C:c:g:i:o:r:s:t:v:bBFuqVz" opt; do
211   case "$opt" in
212     a) ARCH="$OPTARG" ;;
213     b) BUILD_ONLY=1 ;;
214     B) BUILD_DIRTY=1 ;;
215     c) CLASSES="$OPTARG" ;;
216     C) CONFIG="$OPTARG" ;;
217     g) GRML_NAME="$OPTARG" ;;
218     i) ISO_NAME="$OPTARG" ;;
219     o) OUTPUT="$OPTARG" ;;
220     q) SKIP_MKSQUASHFS=1 ;;
221     r) RELEASENAME="$OPTARG" ;;
222     s) SUITE="$OPTARG" ;;
223     t) TEMPLATE_DIRECTORY="$OPTARG";;
224     v) VERSION="$OPTARG" ;;
225     F) FORCE=1 ;;
226     u) UPDATE=1 ;;
227     V) VERBOSE="-v" ;;
228     z) SQUASHFS_ZLIB="-nolzma" ;;
229     ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
230   esac
231 done
232 shift $(($OPTIND - 1))  # set ARGV to the first not parsed commandline parameter
233 # }}}
234
235 # assume sane defaults (if not set already) {{{
236 [ -n "$ARCH" ]            || ARCH="$(dpkg --print-architecture)"
237 [ -n "$BOOT_METHOD" ]     || BOOT_METHOD='isolinux'
238 [ -n "$CLASSES" ]         || CLASSES='GRML,I386'
239 [ -n "$DISTRI_INFO" ]     || DISTRI_INFO='Grml - Live Linux for system administrators   '
240 [ -n "$DISTRI_NAME" ]     || DISTRI_NAME="grml"
241 [ -n "$DISTRI_SPLASH" ]   || DISTRI_SPLASH='grml.png'
242 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG='/etc/grml/fai'
243 [ -n "$GRML_NAME" ]       || GRML_NAME='grml'
244 [ -n "$HOSTNAME" ]        || HOSTNAME='grml'
245 [ -n "$NFSROOT_CONF" ]    || NFSROOT_CONF='/etc/grml/fai/make-fai-nfsroot.conf'
246 [ -n "$RELEASENAME" ]     || RELEASENAME='grml-live rocks'
247 [ -n "$SUITE" ]           || SUITE='stable'
248 [ -n "$USERNAME" ]        || USERNAME='grml'
249 [ -n "$VERSION" ]         || VERSION='0.0.1'
250 # }}}
251
252 # some misc checks before executing FAI {{{
253 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
254 specify it on the command line using the -c option."
255 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
256 specify it on the command line using the -o option."
257
258 # set subdirectories according to $OUTPUT:
259 CHROOT_OUTPUT="$OUTPUT/grml_chroot"
260 BUILD_OUTPUT="$OUTPUT/grml_cd"
261 ISO_OUTPUT="$OUTPUT/grml_isos"
262
263 # trim characters that are known to cause problems inside $GRML_NAME;
264 # for example isolinux does not like '-' inside the directory name
265 [ -n "$GRML_NAME" ] && export SHORT_GRML_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
266
267 # export variables to have them available in fai scripts:
268 [ -n "$GRML_NAME" ]   && export GRML_NAME="$GRML_NAME"
269 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
270 # }}}
271
272 # clean/zero grml-live logfile {{{
273 if [ -n "$ZERO_LOGFILE" ] ; then
274    echo -n > $LOGFILE
275 fi
276 # }}}
277
278 # clean/zero/remove old FAI directory {{{
279 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
280    if [ -d /var/log/fai/"$HOSTNAME" ] ; then
281       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
282       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
283       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
284       rm -f /var/log/fai/"$HOSTNAME"/last \
285             /var/log/fai/"$HOSTNAME"/last-dirinstall \
286             /var/log/fai/"$HOSTNAME"/last-softupdate
287    fi
288 fi
289 # }}}
290
291 # ask user whether the setup is ok {{{
292 if [ -z "$FORCE" ] ; then
293    echo
294    echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
295    echo
296    echo "  FAI classes:       $CLASSES"
297    [ -r "$LOCAL_CONFIG" ]       && echo "  local config:      /etc/grml/grml-live.local"
298    [ -n "$CONFIG" ]             && echo "  configuration:     $CONFIG"
299    echo "  main directory:    $OUTPUT"
300    [ -n "$CHROOT_OUTPUT" ]      && echo "  chroot target:     $CHROOT_OUTPUT"
301    [ -n "$BUILD_OUTPUT" ]       && echo "  build target:      $BUILD_OUTPUT"
302    [ -n "$ISO_OUTPUT" ]         && echo "  ISO target:        $ISO_OUTPUT"
303    [ -n "$GRML_NAME" ]          && echo "  grml name:         $GRML_NAME"
304    [ -n "$RELEASENAME" ]        && echo "  release name:      $RELEASENAME"
305    [ -n "$VERSION" ]            && echo "  grml version:      $VERSION"
306    [ -n "$SUITE" ]              && echo "  Debian suite:      $SUITE"
307    [ -n "$ARCH" ]               && echo "  Architecture:      $ARCH"
308    [ -n "$BOOT_METHOD" ]        && echo "  Boot method:       $BOOT_METHOD"
309    [ -n "$TEMPLATE_DIRECTORY" ] && echo "  Template files:    $TEMPLATE_DIRECTORY"
310    [ -n "$FAI_ARGS" ]           && echo "  additional arguments for FAI: $FAI_ARGS"
311    [ -n "$LOGFILE" ]            && echo "  Logging to file:   $LOGFILE"
312    [ -n "$SQUASHFS_ZLIB" ]      && echo "  Using ZLIB (instead of LZMA) compression."
313    [ -n "$SQUASHFS_OPTIONS" ]   && echo "  Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
314    [ -n "$VERBOSE" ]            && echo "  Using VERBOSE mode."
315    [ -n "$UPDATE" ]             && echo "  Executing UPDATE instead of fresh installation."
316    [ -n "$SKIP_MKSQUASHFS" ]    && echo "  Skipping creation of SQUASHFS file."
317    [ -n "$BUILD_ONLY" ]         && echo "  Executing BUILD_ONLY instead of fresh installation or UPDATE."
318    [ -n "$BUILD_DIRTY" ]        && echo "  Executing BUILD_DIRTY to leave chroot untouched."
319    echo
320    echo -n "Is this ok for you? [y/N] "
321    read a
322    if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
323       bailout 1 "Exiting as requested."
324    fi
325    echo
326 fi
327
328 if [ -n "$CONFIG" ] ; then
329    if ! [ -f "$CONFIG" ] ; then
330       log "Sorry, $CONFIG could not be read. Exiting. [$(date)]"
331       eerror "Sorry, $CONFIG could not be read. Exiting."
332       bailout 1
333    else
334       log "Sourcing $CONFIG"
335       . $CONFIG
336    fi
337 fi
338
339 start_seconds=$(cut -d . -f 1 /proc/uptime)
340 log "------------------------------------------------------------------------------"
341 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
342 log "Executed grml-live command line:"
343 log "$CMDLINE"
344
345 einfo "Logging actions to logfile $LOGFILE"
346 # }}}
347
348 # on-the-fly configuration {{{
349 if [ -n "$MIRROR_DIRECTORY" ] ; then
350    if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
351       log "Sorry, $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
352       eerror "Sorry, $MIRROR_DIRECTORY/debian does not seem to exist. Exiting."
353       bailout 1
354    fi
355    cat > "$SOURCES_LIST_FILE" << EOF
356 # NOTE: This file is *NOT* meant for manual customisation! This file is
357 # modified by grml-live and any changes might be overriden.
358 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
359 # and using /etc/grml/fai/files/etc/apt instead!'
360 EOF
361    echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_FILE"
362    if [ -n "$GRML_LIVE_SOURCES" ] ; then
363       echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
364    fi
365 elif [ -n "$GRML_LIVE_SOURCES" ] ; then
366    cat > "$SOURCES_LIST_FILE" << EOF
367 # NOTE: This file is *NOT* meant for manual customisation! This file is
368 # modified by grml-live and any changes might be overriden.
369 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
370 # and using /etc/grml/fai/files/etc/apt instead!'
371 EOF
372    echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
373 fi
374
375 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
376    sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
377 fi
378
379 # does this suck? YES!
380 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
381 case $SUITE in
382    unstable) SUITE='sid' ;;
383    # make sure that we *NEVER* write any broken suite name to sources.list,
384    # otherwise we won't be able to adjust it one next (correct) execution
385    stable)   ;;
386    testing)  ;;
387    etch)     ;;
388    lenny)    ;;
389    squeeze)  ;;
390    sid)      ;;
391    *) echo "Sorry, $SUITE is not a valid Debian suite, exiting.">&2; bailout 1 ;;
392 esac
393
394 DIST=" etch\| stable\| lenny\| squeeze\| testing\| sid\| unstable"
395 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
396 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" ; do
397     if [ -n "$file" ] ; then
398        sed "s/^SUITE=.*/SUITE=\"$SUITE\"/" $file | sponge $file
399        sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$file" | sponge "$file"
400     fi
401 done
402
403 # notice: activate grml-live pool only if we are building against unstable:
404 if grep -qe unstable -qe sid "$SOURCES_LIST_FILE" ; then
405    grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" || \
406    grep grml-stable "$SOURCES_LIST_FILE" | \
407         sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_FILE"
408 else
409    grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" && \
410    sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
411 fi
412
413 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
414     if [ -n "$file" ] ; then
415        sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
416     fi
417 done
418
419 # validate whether the specified architecture class matches the
420 # architecture (option), otherwise installation of kernel will fail
421 if echo $CLASSES | grep -qi i386 ; then
422    if ! [[ "$ARCH" == "i386" ]] ; then
423       eerror "You specified the I386 class but are trying to build something else (AMD64?)."
424       eerror "-> Either invoke grml-live with '-i i386' or adjust the architecture class. Exiting."
425       bailout
426    fi
427 elif echo $CLASSES | grep -qi amd64 ; then
428    if ! [[ "$ARCH" == "amd64" ]] ; then
429       eerror "You specified the AMD64 class but are trying to build something else (I386?)."
430       eerror "-> Either invoke grml-live with '-i amd64' or adjust the architecture class. Exiting."
431       bailout
432    fi
433 fi
434
435 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
436    sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
437 else
438    sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
439 fi
440 # }}}
441
442 # CHROOT_OUTPUT - execute FAI {{{
443 if [ -n "$BUILD_DIRTY" ]; then
444   einfo "Skipping FAI" ; eend 0
445 else
446    [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
447
448    # provide inform fai about the ISO we build
449    [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
450    echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
451    [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
452    [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
453
454    if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
455       FAI_ACTION=softupdate
456    else
457       FAI_ACTION=dirinstall
458    fi
459
460    if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
461       if ! [ -r "$CHROOT_OUTPUT/etc/grml_version" ] ; then
462          log "Error: does not look like you have a working chroot. Updating/building not possible."
463          eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
464          eend 1
465          bailout 20
466       fi
467    fi
468
469    if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
470       log "$CHROOT_OUTPUT exists already, skipping stage 'fai dirinstall'"
471       ewarn "$CHROOT_OUTPUT exists already, skipping stage 'fai dirinstall'" ; eend 0
472    else
473       mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
474
475       if [ -n "${MIRROR_DIRECTORY}" ] ; then
476          mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
477          mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
478       fi
479
480       log "Executed FAI command line:"
481       log "BUILD_ONLY=$BUILD_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
482       BUILD_ONLY="$BUILD_ONLY" fai $VERBOSE -C "$GRML_FAI_CONFIG" -c"$CLASSES" -u \
483       "$HOSTNAME" $FAI_ACTION "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
484       RC="$PIPESTATUS" # notice: bash-only
485
486       if [ "$RC" != 0 ] ; then
487          log "Error while executing fai [exit code ${RC}]. Exiting."
488          eerror "Error while executing fai [exit code ${RC}]. Exiting." ; eend 1
489          bailout 1
490       else
491          log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$ISO_DATE]"
492          echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$ISO_DATE]" > $CHROOT_OUTPUT/etc/grml_version
493          chmod 644 $CHROOT_OUTPUT/etc/grml_version
494          einfo "Rebuilding initramfs"
495          # make sure new /etc/grml_version reaches the initramfs:
496          chroot $CHROOT_OUTPUT update-initramfs -u -t
497          eend $?
498       fi
499
500       # Remove all FAI logs from chroot if class RELEASE is used:
501       if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
502          rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
503       fi
504
505       # make sure we don't leave any mounts - FAI doesn't remove them always
506       umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
507       umount $CHROOT_OUTPUT/sys  2>/dev/null || /bin/true
508       umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
509       umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
510
511       [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
512
513       # notice: 'fai dirinstall' does not seem to exit appropriate, so:
514       ERROR=''
515       CHECKLOG=/var/log/fai/$HOSTNAME/last
516       if [ -r "$CHECKLOG/software.log" ] ; then
517          # 1 errors during executing of commands
518          grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
519          grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
520          grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
521          grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
522          grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
523       fi
524
525       if [ -r "$CHECKLOG/shell.log" ] ; then
526          grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=2
527       fi
528
529       if [ -n "$ERROR" ] ; then
530          log "There was an error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
531          eerror "There was an error during execution of stage 'fai dirinstall'"
532          echo "   Check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
533          eend 1
534          bailout 1
535       else
536          log "Finished execution of stage 'fai dirinstall' [$(date)]"
537          einfo "Finished execution of stage 'fai dirinstall'"
538       fi
539
540    fi
541 fi # BUILD_DIRTY?
542 # }}}
543
544 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
545 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
546 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
547
548 # i386:
549 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
550    if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
551       log "$BUILD_OUTPUT/boot/isolinux exists already, skipping stage 'boot'"
552       ewarn "$BUILD_OUTPUT/boot/isolinux exists already, skipping stage 'boot'" ; eend 0
553    else
554       # booting stuff:
555       [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
556       [ -d "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}"
557
558       if [ -z "$NO_ADDONS" ] ; then
559          [ -d "$BUILD_OUTPUT"/boot/addons   ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
560          cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
561       fi
562
563       # if we don't have an initrd we a) can't boot and b) there was an error
564       # during build, so check for the file:
565       INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
566       if [ -n "$INITRD" ] ; then
567          cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}"/initrd.gz
568          find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
569       else
570          log "No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
571          eerror "No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
572          bailout 10
573       fi
574
575       KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
576       if [ -n "$KERNEL_IMAGE" ] ; then
577          cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}"/linux26
578       else
579          log "No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
580          eerror "No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
581          bailout 11
582       fi
583
584       [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
585       if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
586          log "${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
587          eerror "${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
588          bailout 8
589       fi
590
591       cp ${TEMPLATE_DIRECTORY}/boot/isolinux/*  "$BUILD_OUTPUT"/boot/isolinux/
592
593       if [ -z "$NO_ADDONS" ] ; then
594          if ! [ -d /usr/share/grml-live/templates/boot/addons/bsd4grml ] ; then
595            ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
596          else
597            # copy only files so we can handle bsd4grml on its own
598            for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
599                test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
600            done
601
602            if [ -z "$NO_ADDONS_BSD4GRML" ] ; then
603               cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
604            fi
605          fi
606       fi
607
608       if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
609          cp -a ${TEMPLATE_DIRECTORY}/boot/grub  "$BUILD_OUTPUT"/boot/
610       fi
611       # make sure we have recent template files available, otherwise updating
612       # the strings like $GRML_NAME and $VERSION might be out of date
613       cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
614
615       if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
616          log "${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
617          eerror "${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
618          bailout 9
619       fi
620
621       [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
622       cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
623
624       # adjust boot splash information:
625       RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
626       RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
627       RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
628
629       sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
630       sed -i "s/%DATE%/$ISO_DATE/"             "$BUILD_OUTPUT"/GRML/grml-version
631
632       sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/" "$BUILD_OUTPUT"/boot/isolinux/boot.msg
633       sed -i "s/%DATE%/$ISO_DATE/"             "$BUILD_OUTPUT"/boot/isolinux/boot.msg
634
635       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/isolinux/isolinux.cfg
636       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/isolinux/syslinux.cfg
637
638       sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/" "$BUILD_OUTPUT"/boot/isolinux/boot-beep.msg
639       sed -i "s/%DATE%/$ISO_DATE/"             "$BUILD_OUTPUT"/boot/isolinux/boot-beep.msg
640
641       sed -i "s/%VERSION%/$VERSION/"           "$BUILD_OUTPUT"/boot/grub/menu.lst
642       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/grub/menu.lst
643
644       sed -i "s/%VERSION%/$VERSION/"           "$BUILD_OUTPUT"/boot/grub/grub.cfg
645       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/grub/grub.cfg
646
647       sed -i "s/%VERSION%/$VERSION/"           "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
648       sed -i "s/%GRML_NAME%/$GRML_NAME/"       "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
649       sed -i "s/%ARCH%/$ARCH/"                 "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
650
651       sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/" "$BUILD_OUTPUT"/boot/isolinux/vesamenu.cfg
652       sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/" "$BUILD_OUTPUT"/boot/isolinux/vesamenu.cfg
653
654       # make sure the squashfs filename is set accordingly:
655       GRML_NAME_SQUASHFS="$GRML_NAME.squashfs"
656       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/isolinux.cfg
657       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/syslinux.cfg
658       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/grub/menu.lst
659
660       GRML_NAME_SQUASHFS="$(cut_string 20 "$GRML_NAME_SQUASHFS")"
661       GRML_NAME_SQUASHFS="$(extend_string_end 20 "$GRML_NAME_SQUASHFS")"
662       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/f4
663       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/f5
664
665       if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] ; then
666          log "including grml.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
667          echo "include grml.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
668          [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
669       else # assume we are building a custom distribution:
670          log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
671          einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
672          if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
673            log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
674            einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
675            eend $?
676         else
677            log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
678            echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
679            [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
680          fi
681       fi
682
683       # use old style console based isolinux method only if requested:
684       if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
685          log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
686          einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
687          if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
688            einfo "include for console.cfg already foud, nothing to do."
689            eend 0
690          else
691            log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
692            einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
693            echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
694            eend $?
695          fi
696       else
697          log 'Using graphical boot menu.'
698          if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
699            log "include for vesamenu.cfg already foud, nothing to do."
700          else
701            log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
702            echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
703          fi
704       fi
705
706       # jump back to grub from bsd4grml:
707       if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
708          if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
709             GRUB_VERSION=2
710          else
711             GRUB_VERSION=1
712          fi
713          if [ -e "$BUILD_OUTPUT"/boot/grub/stage2 ]; then
714             GRUB_LEGACY=stage2
715          else
716             GRUB_LEGACY=stage2_eltorito
717          fi
718
719          # why not ed(1)?
720          for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
721                      "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg; do
722              sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
723                     -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
724          done
725       fi
726
727       # autostart for Windows:
728       if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
729          cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
730       fi
731
732       # windows-binaries:
733       if [ -n "$WINDOWS_BINARIES" ] ; then
734          if [ -f "$BUILD_OUTPUT"/windows/putty.exe ] ; then
735             log "$BUILD_OUTPUT/windows exists already, skipping stage 'WINDOWS_BINARIES'"
736             ewarn "$BUILD_OUTPUT/windows exists already, skipping stage 'WINDOWS_BINARIES'" ; eend 0
737          else
738             if ! [ -d "$BUILD_OUTPUT"/windows ] ; then
739                mkdir "$BUILD_OUTPUT"/windows
740                ( cd "$BUILD_OUTPUT"/windows
741                  for file in pageant plink pscp psftp putty puttygen ; do
742                     wget -O ${file}.exe ${WINDOWS_BINARIES}/${file}.exe
743                     md5sum ${file}.exe > ${file}.exe.md5
744                  done )
745             fi
746          fi
747       log "Finished execution of stage 'WINDOWS_BINARIES' [$(date)]"
748       einfo "Finished execution of stage 'WINDOWS_BINARIES'" ; eend 0
749       fi
750    einfo "Finished execution of stage 'boot'" ; eend 0
751    fi
752 # ppc:
753 elif [ "$ARCH" = powerpc ] ; then
754     ewarn 'Warning: formorer, it is your turn. :)'>&2
755 # unsuported:
756 else
757    eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
758 fi
759
760 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
761    log "$BUILD_OUTPUT/live exists already, skipping stage 'squashfs'"
762    ewarn "$BUILD_OUTPUT/live exists already, skipping stage 'squashfs'" ; eend 0
763 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
764    log "Skipping stage 'squashfs' as requested via option -q"
765    ewarn "Skipping stage 'squashfs' as requested via option -q" ; eend 0
766 else
767    [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
768    # make sure we don't leave (even an empty) base.tgz:
769    [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
770
771    # make sure mksquashfs can handle the according option:
772    if [ -n "$SQUASHFS_ZLIB" ] ; then
773       mksquashfs --help 2>&1 | grep -q -- "$SQUASHFS_ZLIB" || SQUASHFS_ZLIB=''
774    fi
775
776    if echo "$SQUASHFS_OPTIONS" | grep -q -- "-nolzma" ; then
777       if ! mksquashfs --help 2>&1 | grep -q -- '-nolzma' ; then
778          ewarn "mksquashfs does NOT support the nolzma option, just using default zlib mode."
779          SQUASHFS_OPTIONS="$(echo $SQUASHFS_OPTIONS | sed 's/-nolzma//g')"
780          eend 0
781       fi
782    fi
783
784    if echo "$SQUASHFS_OPTIONS" | grep -q -- "-lzma" ; then
785       if ! mksquashfs --help 2>&1 | grep -q -- '-lzma' ; then
786          ewarn "mksquashfs does NOT support the lzma option, falling back to zlib mode."
787          SQUASHFS_OPTIONS="$(echo $SQUASHFS_OPTIONS | sed 's/-lzma//g')"
788          eend 0
789       fi
790    fi
791
792    # support exclusion of files via exclude-file:
793    if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
794       SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE"
795    fi
796
797    # get rid of unnecessary files when building grml-small for final release:
798    if echo "$CLASSES" | grep -q GRML_SMALL ; then
799       SQUASHFS_OPTIONS="$SQUASHFS_OUTPUT -e initrd.img* vmlinuz*"
800    fi
801
802    SQUASHFS_OUTPUT="$(mktemp -t grml-live.XXXXXX)"
803    log "mksquashfs $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB"
804    if mksquashfs $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
805       -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB 2>"${SQUASHFS_OUTPUT}" ; then
806       echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
807       log "Finished execution of stage 'squashfs' [$(date)]"
808       einfo "Finished execution of stage 'squashfs'" ; eend 0
809       rm -f "${SQUASHFS_OUTPUT}"
810    else
811       log "There was an error executing stage 'squashfs' [$(date)]:"
812       log "$(cat $SQUASHFS_OUTPUT)"
813       eerror "There was an error executing stage 'squashfs':" ; eend 1
814       cat "${SQUASHFS_OUTPUT}"
815       rm -f "${SQUASHFS_OUTPUT}"
816       bailout
817    fi
818 fi
819
820 # create md5sum file:
821 ( cd $BUILD_OUTPUT/GRML &&
822 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
823 # }}}
824
825 # ISO_OUTPUT - mkisofs {{{
826 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
827 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
828
829 if [ "$BOOT_METHOD" = "isolinux" ] ; then
830    BOOT_FILE="boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
831 elif [ "$BOOT_METHOD" = "grub" ] ; then
832    BOOT_FILE="boot/grub/stage2_eltorito"
833 fi
834
835 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
836    log "$ISO_OUTPUT exists already, skipping stage 'iso build'"
837    ewarn "$ISO_OUTPUT exists already, skipping stage 'iso build'" ; eend 0
838 else
839    mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
840
841    # support mkisofs as well as genisoimage
842    if which mkisofs >/dev/null 2>&1; then
843       MKISOFS='mkisofs'
844    elif which genisoimage >/dev/null 2>&1; then
845       MKISOFS='genisoimage'
846    else
847       log "Sorry, neither mkisofs nor genisoimage available - can not create ISO."
848       eerror "Sorry, neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
849       bailout
850    fi
851
852    CURRENT_DIR=$(pwd)
853    if cd "$BUILD_OUTPUT" ; then
854       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} ."
855       "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
856               -l -r -J -no-emul-boot -boot-load-size 4 -boot-info-table    \
857               -b $BOOT_FILE -no-pad \
858               -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
859
860       # pad the output ISO to multiples of 256 KiB for partition table support
861       siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
862       cyls=$((siz / 512 / 32 / 16 + 1))   # C=$cyls H=16 S=32
863       siz=$((cyls * 16 * 32 * 512))   # size after padding
864       dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
865          of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
866
867       # support disabling hybrid ISO image
868       if [ "$HYBRID_METHOD" = "disable" ] ; then\
869          log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
870          einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
871          eend 0
872       # use isohybrid only on request
873       elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
874          if ! which isohybrid >/dev/null 2>&1 ; then
875            bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
876          else
877            log "Creating hybrid ISO file with isohybrid method"
878            einfo "Creating hybrid ISO file with isohybrid method"
879            isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
880            eend $?
881          fi
882       # by default use our manifold boot method:
883       else
884          if ! [ -r boot/grub/core.img ] ; then
885            ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
886          else
887            log "Creating hybrid ISO file with manifold method"
888            einfo "Creating hybrid ISO file with manifold method"
889            echo 1 63 | \
890                mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 1 -p 0x83 -g $cyls:16:32 | \
891                cat - boot/grub/core.img | \
892                dd conv=notrunc of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
893            eend $?
894          fi
895       fi
896
897       # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
898       case $CLASSES in *RELEASE*)
899          [ "$RC" = 0 ] && \
900          (
901            if cd $ISO_OUTPUT ; then
902              md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
903              touch -r ${ISO_NAME} ${ISO_NAME}.md5
904              sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
905              touch -r ${ISO_NAME} ${ISO_NAME}.sha1
906            fi
907          )
908          ;;
909       esac
910
911       cd $CURRENT_DIR
912    fi
913
914    if [ "$RC" = 0 ] ; then
915       log "Finished execution of stage 'iso build' [$(date)]"
916       einfo "Finished execution of stage 'iso build'" ; eend 0
917    else
918       log "There was an error ($RC) executing stage 'iso build' [$(date)]"
919       eerror "There was an error executing stage 'iso build'" ; eend 1
920       bailout $RC
921    fi
922 fi
923 # }}}
924
925 # finalize {{{
926 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
927 einfo "Successfully finished execution of $PN [running ${SECONDS} seconds]" ; eend 0
928 log "Successfully finished execution of $PN [running ${SECONDS} seconds]"
929 bailout 0
930 # }}}
931
932 ## END OF FILE #################################################################
933 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3