Always remove temporary squashfs stderr file
[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 "$SQUASHFS_STDERR" ]  && rm -rf "$SQUASHFS_STDERR"
136   [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
137   [ -n "$1" ] && EXIT="$1" || EXIT="1"
138   [ -n "$2" ] && eerror "$2">&2
139   log "------------------------------------------------------------------------------"
140   exit "$EXIT"
141 }
142 trap bailout 1 2 3 3 6 9 14 15
143 # }}}
144
145 # log file stuff {{{
146 [ -n "$LOGFILE" ] || LOGFILE=/var/log/grml-live.log
147 touch $LOGFILE
148 chown root:adm $LOGFILE
149 chmod 664 $LOGFILE
150 # }}}
151
152 # some important functions {{{
153
154 # log output:
155 # usage: log "string to log"
156 log() { echo "$*" >> $LOGFILE ; }
157
158 # cut string at character number int = $1
159 # usage: cut_string 5 "1234567890" will output "12345"
160 cut_string() {
161   [ -n "$2" ] || return 1
162   echo "$2" | head -c "$1"; echo -ne "\n"
163 }
164
165 # prepend int = $1 spaces before string = $2
166 # usage: extend_string_begin 5 "123" will output "  123"
167 extend_string_begin() {
168   [ -n "$2" ] || return 1
169   local COUNT="$(echo $2 | wc -c)"
170   local FILL="$(expr $COUNT - $1)"
171   while [ "$FILL" -gt 1 ] ; do
172     echo -n " "
173     local FILL=$(expr $FILL - 1)
174   done
175   while [ "$FILL" -lt 1 ] ; do
176     echo -n " "
177     local FILL=$(expr $FILL + 1)
178   done
179   echo "$2" | head -c "$1"; echo -ne "\n"
180 }
181
182 # append int = $1 spaces to string = $2
183 # usage: extend_string_begin 5 "123" will output "123  "
184 extend_string_end() {
185   [ -n "$2" ] || return 1
186   echo -n "$2" | head -c "$1"
187   local COUNT="$(echo $2 | wc -c)"
188   local FILL="$(expr $COUNT - $1)"
189   while [ "$FILL" -gt 1 ] ; do
190     echo -n " "
191     local FILL=$(expr $FILL - 1)
192   done
193   while [ "$FILL" -lt 1 ] ; do
194     echo -n " "
195     local FILL=$(expr $FILL + 1)
196   done
197   echo -ne "\n"
198 }
199 # }}}
200
201 # read local (non-packaged) configuration {{{
202 LOCAL_CONFIG=/etc/grml/grml-live.local
203 if [ -r "$LOCAL_CONFIG" ] ; then
204    log "Sourcing $LOCAL_CONFIG"
205    . $LOCAL_CONFIG
206 else
207    log "No $LOCAL_CONFIG found, not sourcing it"
208    LOCAL_CONFIG=''
209 fi
210 # }}}
211
212 # command line parsing {{{
213 while getopts "a:C:c:g:i:I:o:r:s:t:v:bBFuqVz" opt; do
214   case "$opt" in
215     a) ARCH="$OPTARG" ;;
216     b) BUILD_ONLY=1 ;;
217     B) BUILD_DIRTY=1 ;;
218     c) CLASSES="$OPTARG" ;;
219     C) CONFIG="$OPTARG" ;;
220     g) GRML_NAME="$OPTARG" ;;
221     i) ISO_NAME="$OPTARG" ;;
222     I) CHROOT_INSTALL="$OPTARG" ;;
223     o) OUTPUT="$OPTARG" ;;
224     q) SKIP_MKSQUASHFS=1 ;;
225     r) RELEASENAME="$OPTARG" ;;
226     s) SUITE="$OPTARG" ;;
227     t) TEMPLATE_DIRECTORY="$OPTARG";;
228     v) VERSION="$OPTARG" ;;
229     F) FORCE=1 ;;
230     u) UPDATE=1 ;;
231     V) VERBOSE="-v" ;;
232     z) SQUASHFS_ZLIB="-nolzma" ;;
233     ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
234   esac
235 done
236 shift $(($OPTIND - 1))  # set ARGV to the first not parsed commandline parameter
237 # }}}
238
239 # assume sane defaults (if not set already) {{{
240 [ -n "$ARCH" ]             || ARCH="$(dpkg --print-architecture)"
241 [ -n "$BOOT_METHOD" ]      || BOOT_METHOD='isolinux'
242 [ -n "$BUILD_OUTPUT" ]     || BUILD_OUTPUT="$OUTPUT/grml_cd"
243 [ -n "$CHROOT_OUTPUT" ]    || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
244 [ -n "$CLASSES" ]          || CLASSES="GRMLBASE,GRML_MEDIUM,I386"
245 [ -n "$DISTRI_INFO" ]      || DISTRI_INFO='Grml - Live Linux for system administrators   '
246 [ -n "$DISTRI_NAME" ]      || DISTRI_NAME="grml"
247 [ -n "$DISTRI_SPLASH" ]    || DISTRI_SPLASH='grml.png'
248 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
249 [ -n "$GRML_FAI_CONFIG" ]  || GRML_FAI_CONFIG='/etc/grml/fai'
250 [ -n "$GRML_NAME" ]        || GRML_NAME='grml'
251 [ -n "$HOSTNAME" ]         || HOSTNAME='grml'
252 [ -n "$ISO_OUTPUT" ]       || ISO_OUTPUT="$OUTPUT/grml_isos"
253 [ -n "$NFSROOT_CONF" ]     || NFSROOT_CONF='/etc/grml/fai/make-fai-nfsroot.conf'
254 [ -n "$OUTPUT" ]           || OUTPUT='/grml/grml-live'
255 [ -n "$RELEASENAME" ]      || RELEASENAME='grml-live rocks'
256 [ -n "$SQUASHFS_EXCLUDES_FILE " ] || SQUASHFS_EXCLUDES_FILE='/etc/grml/fai/squashfs-excludes'
257 [ -n "$SUITE" ]            || SUITE='stable'
258 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
259 [ -n "$USERNAME" ]         || USERNAME='grml'
260 [ -n "$VERSION" ]          || VERSION='0.0.1'
261 [ -n "$WINDOWS_BINARIES" ] || WINDOWS_BINARIES='http://the.earth.li/~sgtatham/putty/latest/x86/'
262 # }}}
263
264 # some misc checks before executing FAI {{{
265 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
266 specify it on the command line using the -c option."
267 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
268 specify it on the command line using the -o option."
269
270 # set subdirectories according to $OUTPUT:
271 CHROOT_OUTPUT="$OUTPUT/grml_chroot"
272 BUILD_OUTPUT="$OUTPUT/grml_cd"
273 ISO_OUTPUT="$OUTPUT/grml_isos"
274
275 # trim characters that are known to cause problems inside $GRML_NAME;
276 # for example isolinux does not like '-' inside the directory name
277 [ -n "$GRML_NAME" ] && export SHORT_GRML_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
278
279 # export variables to have them available in fai scripts:
280 [ -n "$GRML_NAME" ]   && export GRML_NAME="$GRML_NAME"
281 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
282 # }}}
283
284 # clean/zero grml-live logfile {{{
285 if [ -n "$ZERO_LOGFILE" ] ; then
286    echo -n > $LOGFILE
287 fi
288 # }}}
289
290 # clean/zero/remove old FAI directory {{{
291 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
292    if [ -d /var/log/fai/"$HOSTNAME" ] ; then
293       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
294       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
295       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
296       rm -f /var/log/fai/"$HOSTNAME"/last \
297             /var/log/fai/"$HOSTNAME"/last-dirinstall \
298             /var/log/fai/"$HOSTNAME"/last-softupdate
299    fi
300 fi
301 # }}}
302
303 # ask user whether the setup is ok {{{
304 if [ -z "$FORCE" ] ; then
305    echo
306    echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
307    echo
308    echo "  FAI classes:       $CLASSES"
309    [ -r "$LOCAL_CONFIG" ]       && echo "  local config:      /etc/grml/grml-live.local"
310    [ -n "$CONFIG" ]             && echo "  configuration:     $CONFIG"
311    echo "  main directory:    $OUTPUT"
312    [ -n "$CHROOT_OUTPUT" ]      && echo "  chroot target:     $CHROOT_OUTPUT"
313    [ -n "$BUILD_OUTPUT" ]       && echo "  build target:      $BUILD_OUTPUT"
314    [ -n "$ISO_OUTPUT" ]         && echo "  ISO target:        $ISO_OUTPUT"
315    [ -n "$GRML_NAME" ]          && echo "  grml name:         $GRML_NAME"
316    [ -n "$RELEASENAME" ]        && echo "  release name:      $RELEASENAME"
317    [ -n "$VERSION" ]            && echo "  grml version:      $VERSION"
318    [ -n "$SUITE" ]              && echo "  Debian suite:      $SUITE"
319    [ -n "$ARCH" ]               && echo "  Architecture:      $ARCH"
320    [ -n "$BOOT_METHOD" ]        && echo "  Boot method:       $BOOT_METHOD"
321    [ -n "$TEMPLATE_DIRECTORY" ] && echo "  Template files:    $TEMPLATE_DIRECTORY"
322    [ -n "$CHROOT_INSTALL" ]     && echo "  Install files from directory to chroot:  $CHROOT_INSTALL"
323    [ -n "$FAI_ARGS" ]           && echo "  additional arguments for FAI: $FAI_ARGS"
324    [ -n "$LOGFILE" ]            && echo "  Logging to file:   $LOGFILE"
325    [ -n "$SQUASHFS_ZLIB" ]      && echo "  Using ZLIB (instead of LZMA) compression."
326    [ -n "$SQUASHFS_OPTIONS" ]   && echo "  Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
327    [ -n "$VERBOSE" ]            && echo "  Using VERBOSE mode."
328    [ -n "$UPDATE" ]             && echo "  Executing UPDATE instead of fresh installation."
329    [ -n "$SKIP_MKSQUASHFS" ]    && echo "  Skipping creation of SQUASHFS file."
330    [ -n "$BUILD_ONLY" ]         && echo "  Executing BUILD_ONLY instead of fresh installation or UPDATE."
331    [ -n "$BUILD_DIRTY" ]        && echo "  Executing BUILD_DIRTY to leave chroot untouched."
332    echo
333    echo -n "Is this ok for you? [y/N] "
334    read a
335    if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
336       bailout 1 "Exiting as requested."
337    fi
338    echo
339 fi
340
341 if [ -n "$CONFIG" ] ; then
342    if ! [ -f "$CONFIG" ] ; then
343       log "Sorry, $CONFIG could not be read. Exiting. [$(date)]"
344       eerror "Sorry, $CONFIG could not be read. Exiting."
345       bailout 1
346    else
347       log "Sourcing $CONFIG"
348       . $CONFIG
349    fi
350 fi
351
352 start_seconds=$(cut -d . -f 1 /proc/uptime)
353 log "------------------------------------------------------------------------------"
354 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
355 log "Executed grml-live command line:"
356 log "$CMDLINE"
357
358 einfo "Logging actions to logfile $LOGFILE"
359 # }}}
360
361 # on-the-fly configuration {{{
362 if [ -n "$MIRROR_DIRECTORY" ] ; then
363    if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
364       log "Sorry, $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
365       eerror "Sorry, $MIRROR_DIRECTORY/debian does not seem to exist. Exiting."
366       bailout 1
367    fi
368    cat > "$SOURCES_LIST_FILE" << EOF
369 # NOTE: This file is *NOT* meant for manual customisation! This file is
370 # modified by grml-live and any changes might be overriden.
371 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
372 # and using /etc/grml/fai/files/etc/apt instead!'
373 EOF
374    echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_FILE"
375    if [ -n "$GRML_LIVE_SOURCES" ] ; then
376       echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
377    fi
378 elif [ -n "$GRML_LIVE_SOURCES" ] ; then
379    cat > "$SOURCES_LIST_FILE" << EOF
380 # NOTE: This file is *NOT* meant for manual customisation! This file is
381 # modified by grml-live and any changes might be overriden.
382 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
383 # and using /etc/grml/fai/files/etc/apt instead!'
384 EOF
385    echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
386 fi
387
388 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
389    sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
390 fi
391
392 # does this suck? YES!
393 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
394 case $SUITE in
395    unstable) SUITE='sid' ;;
396    # make sure that we *NEVER* write any broken suite name to sources.list,
397    # otherwise we won't be able to adjust it one next (correct) execution
398    stable)   ;;
399    testing)  ;;
400    etch)     ;;
401    lenny)    ;;
402    squeeze)  ;;
403    sid)      ;;
404    *) echo "Sorry, $SUITE is not a valid Debian suite, exiting.">&2; bailout 1 ;;
405 esac
406
407 DIST=" etch\| stable\| lenny\| squeeze\| testing\| sid\| unstable"
408 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
409 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" ; do
410     if [ -n "$file" ] ; then
411        sed "s/^SUITE=.*/SUITE=\"$SUITE\"/" $file | sponge $file
412        sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$file" | sponge "$file"
413     fi
414 done
415
416 # notice: activate grml-live pool only if we are building against unstable:
417 if grep -qe unstable -qe sid "$SOURCES_LIST_FILE" ; then
418    grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" || \
419    grep grml-stable "$SOURCES_LIST_FILE" | \
420         sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_FILE"
421 else
422    grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" && \
423    sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
424 fi
425
426 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
427     if [ -n "$file" ] ; then
428        sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
429     fi
430 done
431
432 # validate whether the specified architecture class matches the
433 # architecture (option), otherwise installation of kernel will fail
434 if echo $CLASSES | grep -qi i386 ; then
435    if ! [[ "$ARCH" == "i386" ]] ; then
436       eerror "You specified the I386 class but are trying to build something else (AMD64?)."
437       eerror "-> Either invoke grml-live with '-i i386' or adjust the architecture class. Exiting."
438       bailout
439    fi
440 elif echo $CLASSES | grep -qi amd64 ; then
441    if ! [[ "$ARCH" == "amd64" ]] ; then
442       eerror "You specified the AMD64 class but are trying to build something else (I386?)."
443       eerror "-> Either invoke grml-live with '-i amd64' or adjust the architecture class. Exiting."
444       bailout
445    fi
446 fi
447
448 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
449    sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
450 else
451    sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
452 fi
453 # }}}
454
455 # CHROOT_OUTPUT - execute FAI {{{
456 if [ -n "$BUILD_DIRTY" ]; then
457   einfo "Skipping FAI" ; eend 0
458 else
459    [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
460
461    # provide inform fai about the ISO we build
462    [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
463    echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
464    [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
465    [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
466
467    if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
468       FAI_ACTION=softupdate
469    else
470       FAI_ACTION=dirinstall
471    fi
472
473    if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
474       if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
475          log "Error: does not look like you have a working chroot. Updating/building not possible."
476          eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
477          eend 1
478          bailout 20
479       fi
480    fi
481
482    if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
483       log "$CHROOT_OUTPUT exists already, skipping stage 'fai dirinstall'"
484       ewarn "$CHROOT_OUTPUT exists already, skipping stage 'fai dirinstall'" ; eend 0
485    else
486       mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
487
488       if [ -n "${MIRROR_DIRECTORY}" ] ; then
489          mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
490          mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
491       fi
492
493       log "Executed FAI command line:"
494       log "BUILD_ONLY=$BUILD_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
495       BUILD_ONLY="$BUILD_ONLY" fai $VERBOSE -C "$GRML_FAI_CONFIG" -c"$CLASSES" -u \
496       "$HOSTNAME" $FAI_ACTION "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
497       RC="$PIPESTATUS" # notice: bash-only
498
499       FORCE_ISO_REBUILD=true
500
501       if [ "$RC" != 0 ] ; then
502          log "Error while executing fai [exit code ${RC}]. Exiting."
503          eerror "Error while executing fai [exit code ${RC}]. Exiting." ; eend 1
504          bailout 1
505       else
506          log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$ISO_DATE]"
507          echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$ISO_DATE]" > $CHROOT_OUTPUT/etc/grml_version
508          chmod 644 $CHROOT_OUTPUT/etc/grml_version
509          einfo "Rebuilding initramfs"
510          # make sure new /etc/grml_version reaches the initramfs:
511          chroot $CHROOT_OUTPUT update-initramfs -u -t
512          eend $?
513       fi
514
515       # Remove all FAI logs from chroot if class RELEASE is used:
516       if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
517          rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
518       fi
519
520       # make sure we don't leave any mounts - FAI doesn't remove them always
521       umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
522       umount $CHROOT_OUTPUT/sys  2>/dev/null || /bin/true
523       umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
524       umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
525
526       [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
527
528       # notice: 'fai dirinstall' does not seem to exit appropriate, so:
529       ERROR=''
530       CHECKLOG=/var/log/fai/$HOSTNAME/last
531       if [ -r "$CHECKLOG/software.log" ] ; then
532          # 1 errors during executing of commands
533          grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
534          grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
535          grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
536          grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
537          grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
538       fi
539
540       if [ -r "$CHECKLOG/shell.log" ] ; then
541          grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=2
542       fi
543
544       if [ -n "$ERROR" ] ; then
545          log "There was an error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
546          eerror "There was an error during execution of stage 'fai dirinstall'"
547          echo "   Check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
548          eend 1
549          bailout 1
550       else
551          log "Finished execution of stage 'fai dirinstall' [$(date)]"
552          einfo "Finished execution of stage 'fai dirinstall'"
553       fi
554
555       einfo "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)."
556       log   "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)."
557       eend 0
558    fi
559 fi # BUILD_DIRTY?
560 # }}}
561
562 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
563 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
564 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
565
566 # i386:
567 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
568    if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
569       log "$BUILD_OUTPUT/boot/isolinux exists already, skipping stage 'boot'"
570       ewarn "$BUILD_OUTPUT/boot/isolinux exists already, skipping stage 'boot'" ; eend 0
571    else
572       # booting stuff:
573       [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
574       [ -d "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}"
575
576       if [ -z "$NO_ADDONS" ] ; then
577          [ -d "$BUILD_OUTPUT"/boot/addons   ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
578          if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then
579             log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest"
580             cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest
581          elif [ -r /boot/memtest86+.bin ] ; then
582             log "Installing /boot/memtest86+.bin"
583             cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
584          else
585             ewarn "No memtest binary found, skipping."
586             log "No memtest binary found, skipping."
587             eend 0
588          fi
589       fi
590
591       # if we don't have an initrd we a) can't boot and b) there was an error
592       # during build, so check for the file:
593       INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
594       if [ -n "$INITRD" ] ; then
595          cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}"/initrd.gz
596          find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
597       else
598          log "No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
599          eerror "No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
600          bailout 10
601       fi
602
603       KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
604       if [ -n "$KERNEL_IMAGE" ] ; then
605          cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}"/linux26
606       else
607          log "No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
608          eerror "No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
609          bailout 11
610       fi
611
612       [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
613       if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
614          log "${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
615          eerror "${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
616          bailout 8
617       fi
618
619       cp ${TEMPLATE_DIRECTORY}/boot/isolinux/*  "$BUILD_OUTPUT"/boot/isolinux/
620
621       if [ -n "$NO_ADDONS" ] ; then
622          log "Skipping installation boot addons requested via \$NO_ADDONS."
623          einfo "Skipping installation boot addons requested via \$NO_ADDONS."
624          eend 0
625       else
626          if ! [ -d /usr/share/grml-live/templates/boot/addons/bsd4grml ] ; then
627            ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
628          else
629            # copy only files so we can handle bsd4grml on its own
630            for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
631                test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
632            done
633
634            if [ -z "$NO_ADDONS_BSD4GRML" ] ; then
635               cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
636            fi
637          fi
638       fi
639
640       if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
641          cp -a ${TEMPLATE_DIRECTORY}/boot/grub  "$BUILD_OUTPUT"/boot/
642       fi
643       # make sure we have recent template files available, otherwise updating
644       # the strings like $GRML_NAME and $VERSION might be out of date
645       cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
646
647       if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
648          log "${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
649          eerror "${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
650          bailout 9
651       fi
652
653       [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
654       cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
655
656       # adjust boot splash information:
657       RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
658       RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
659       RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
660
661       sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
662       sed -i "s/%DATE%/$ISO_DATE/"             "$BUILD_OUTPUT"/GRML/grml-version
663
664       sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/" "$BUILD_OUTPUT"/boot/isolinux/boot.msg
665       sed -i "s/%DATE%/$ISO_DATE/"             "$BUILD_OUTPUT"/boot/isolinux/boot.msg
666
667       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/isolinux/isolinux.cfg
668       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/isolinux/syslinux.cfg
669
670       sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/" "$BUILD_OUTPUT"/boot/isolinux/boot-beep.msg
671       sed -i "s/%DATE%/$ISO_DATE/"             "$BUILD_OUTPUT"/boot/isolinux/boot-beep.msg
672
673       sed -i "s/%VERSION%/$VERSION/"           "$BUILD_OUTPUT"/boot/grub/menu.lst
674       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/grub/menu.lst
675
676       sed -i "s/%VERSION%/$VERSION/"           "$BUILD_OUTPUT"/boot/grub/grub.cfg
677       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/grub/grub.cfg
678
679       if [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] ; then
680          sed -i "s/%VERSION%/$VERSION/"            "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
681          sed -i "s/%GRML_LONG_NAME%/$DISTRI_NAME/" "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
682          sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/"  "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
683          sed -i "s/%ARCH%/$ARCH/"                  "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
684       fi
685
686       sed -i "s/%VERSION%/$VERSION/"           "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
687       sed -i "s/%GRML_LONG_NAME%/$GRML_NAME/"  "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
688       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
689       sed -i "s/%ARCH%/$ARCH/"                 "$BUILD_OUTPUT"/boot/isolinux/grml.cfg
690
691       sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/" "$BUILD_OUTPUT"/boot/isolinux/vesamenu.cfg
692       sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/" "$BUILD_OUTPUT"/boot/isolinux/vesamenu.cfg
693
694       # make sure the squashfs filename is set accordingly:
695       GRML_NAME_SQUASHFS="$GRML_NAME.squashfs"
696       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/isolinux.cfg
697       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/syslinux.cfg
698       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/grub/menu.lst
699
700       GRML_NAME_SQUASHFS="$(cut_string 20 "$GRML_NAME_SQUASHFS")"
701       GRML_NAME_SQUASHFS="$(extend_string_end 20 "$GRML_NAME_SQUASHFS")"
702       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/f4
703       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/f5
704
705       if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
706          log "including grml.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
707          echo "include grml.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
708          [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
709       else # assume we are building a custom distribution:
710          log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
711          einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
712          if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
713            log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
714            eindent
715            einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
716            eoutdent
717            eend $?
718         else
719            log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
720            echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
721            [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
722          fi
723       fi
724
725       # use old style console based isolinux method only if requested:
726       if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
727          log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
728          einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
729          if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
730            einfo "include for console.cfg already foud, nothing to do."
731            eend 0
732          else
733            log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
734            einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
735            echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
736            eend $?
737          fi
738       else
739          log 'Using graphical boot menu.'
740          if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
741            log "include for vesamenu.cfg already foud, nothing to do."
742          else
743            log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
744            echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
745          fi
746       fi
747
748       # jump back to grub from bsd4grml:
749       if [ -e "$BUILD_OUTPUT"/boot/grub/stage2 ]; then
750          GRUB_LEGACY=stage2
751       else
752          GRUB_LEGACY=stage2_eltorito
753       fi
754       if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
755          if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
756             GRUB_VERSION=2
757          else
758             GRUB_VERSION=1
759          fi
760
761          # why not ed(1)?
762          for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
763                      "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg; do
764              sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
765                     -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
766          done
767
768          sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
769       fi
770       if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then
771          sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst
772          sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg
773       else
774          sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst
775          sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg
776       fi
777
778       # autostart for Windows:
779       if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
780          cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
781       fi
782
783       # windows-binaries:
784       if [ -n "$NO_WINDOWS_BINARIES" ] ; then
785          log "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
786          einfo "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
787          eend 0
788       else
789          if [ -f "$BUILD_OUTPUT"/windows/putty.exe ] ; then
790             log "$BUILD_OUTPUT/windows exists already, skipping stage 'WINDOWS_BINARIES'"
791             ewarn "$BUILD_OUTPUT/windows exists already, skipping stage 'WINDOWS_BINARIES'" ; eend 0
792          else
793             if ! [ -d "$BUILD_OUTPUT"/windows ] ; then
794                mkdir "$BUILD_OUTPUT"/windows
795                ( cd "$BUILD_OUTPUT"/windows
796                  for file in pageant plink pscp psftp putty puttygen ; do
797                     wget -O ${file}.exe ${WINDOWS_BINARIES}/${file}.exe
798                     md5sum ${file}.exe > ${file}.exe.md5
799                  done )
800             fi
801          fi
802          log "Finished execution of stage 'WINDOWS_BINARIES' [$(date)]"
803          einfo "Finished execution of stage 'WINDOWS_BINARIES'" ; eend 0
804       fi
805
806    FORCE_ISO_REBUILD=true
807    einfo "Finished execution of stage 'boot'" ; eend 0
808    fi
809 else
810    log 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
811    eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
812 fi
813
814 # support installation of local files into the chroot/ISO
815 if [ -n "$CHROOT_INSTALL" ] ; then
816   if ! [ -d "$CHROOT_INSTALL" ] ; then
817      log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
818      ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
819   else
820      log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
821      einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
822      rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
823      eend $?
824      einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
825      FORCE_ISO_REBUILD=true
826   fi
827 fi
828
829 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
830    log "$BUILD_OUTPUT/live exists already, skipping stage 'squashfs'"
831    ewarn "$BUILD_OUTPUT/live exists already, skipping stage 'squashfs'" ; eend 0
832 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
833    log "Skipping stage 'squashfs' as requested via option -q"
834    ewarn "Skipping stage 'squashfs' as requested via option -q" ; eend 0
835 else
836    [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
837    # make sure we don't leave (even an empty) base.tgz:
838    [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
839
840    # make sure mksquashfs can handle the according option:
841    if [ -n "$SQUASHFS_ZLIB" ] ; then
842       mksquashfs --help 2>&1 | grep -q -- "$SQUASHFS_ZLIB" || SQUASHFS_ZLIB=''
843    fi
844
845    if echo "$SQUASHFS_OPTIONS" | grep -q -- "-nolzma" ; then
846       if ! mksquashfs --help 2>&1 | grep -q -- '-nolzma' ; then
847          ewarn "mksquashfs does NOT support the nolzma option, just using default zlib mode."
848          SQUASHFS_OPTIONS="$(echo $SQUASHFS_OPTIONS | sed 's/-nolzma//g')"
849          eend 0
850       fi
851    fi
852
853    if echo "$SQUASHFS_OPTIONS" | grep -q -- "-lzma" ; then
854       if ! mksquashfs --help 2>&1 | grep -q -- '-lzma' ; then
855          ewarn "mksquashfs does NOT support the lzma option, falling back to zlib mode."
856          SQUASHFS_OPTIONS="$(echo $SQUASHFS_OPTIONS | sed 's/-lzma//g')"
857          eend 0
858       fi
859    fi
860
861    # support exclusion of files via exclude-file:
862    if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
863       SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE"
864    fi
865
866    # get rid of unnecessary files when building grml-small for final release:
867    if echo "$CLASSES" | grep -q GRML_SMALL ; then
868       SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
869    fi
870
871    SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
872
873    log "mksquashfs $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB"
874    if mksquashfs $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
875       -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB 2>"${SQUASHFS_STDERR}" ; then
876       echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
877       log "Finished execution of stage 'squashfs' [$(date)]"
878       einfo "Finished execution of stage 'squashfs'" ; eend 0
879    else
880       log "There was an error executing stage 'squashfs' [$(date)]:"
881       log "$(cat $SQUASHFS_STDERR)"
882       eerror "There was an error executing stage 'squashfs':" ; eend 1
883       cat "${SQUASHFS_STDERR}"
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