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