Merge branch 'master' of ssh://git.grml.org/grml-live
[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.11.0'
27 PN="$(basename $0)"
28 CMDLINE="$0 $@"
29 SOURCES_LIST_FILE='/etc/grml/fai/apt/sources.list'
30 ADDONS_LIST_FILE='/boot/isolinux/addons_list.cfg'
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    -d <date>               use specified date instead of build time as date of release
47    -F                      force execution without prompting
48    -g <grml_name>          set the grml flavour name
49    -h                      display short usage information and exit
50    -i <iso_name>           name of ISO
51    -I <src_directory>      directory which provides files that should become
52                            part of the chroot/ISO
53    -n                      skip generation of ISO
54    -o <output_directory>   main output directory of the build process
55    -q                      skip mksquashfs
56    -r <release_name>       release name
57    -s <suite>              Debian suite; values: etch, lenny, squeeze, sid
58    -t <template_directory> place of the templates
59    -u                      update existing chroot instead of rebuilding it from scratch
60    -v <version_number>     specify version number of the release
61    -V                      increase verbosity in the build process
62    -z                      use ZLIB instead of LZMA compression (depends on
63                            squashfs-tools version)
64
65 Usage examples:
66
67     $PN
68     $PN -c GRMLBASE,GRML_MEDIUM,I386 -o /dev/shm/grml
69     $PN -c GRMLBASE,GRML_SMALL,REMOVE_DOCS,I386 -g grml-small -v 1.0
70     $PN -c GRMLBASE,GRML_FULL,I386 -i grml_0.0-1.iso -v 0.0-1
71     $PN -c GRMLBASE,GRML_FULL,I386 -s sid -V -r 'grml-live rocks'
72
73 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
74               http://grml.org/grml-live/
75
76 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
77 "
78 }
79
80 # make sure it's possible to get usage information without being
81 # root or actually executing the script
82 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
83    usage
84    [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
85    exit 0
86 fi
87 # }}}
88
89 # some runtime checks {{{
90 # we need root permissions for the build-process:
91 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
92    echo "Error: please run this script with uid 0 (root)." >&2
93    exit 1
94 fi
95
96 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
97    echo "/usr/sbin/fai already running or was aborted before.">&2
98    echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
99    exit 1
100 fi
101
102 # see #449236
103 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
104    echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
105    echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
106    exit 1
107 fi
108 # }}}
109
110 # lsb-functions and configuration stuff {{{
111 # make sure they are not set by default
112 VERBOSE=''
113 FORCE=''
114 UPDATE=''
115 BUILD_ONLY=''
116 BUILD_DIRTY=''
117 HOSTNAME=''
118
119 if [ -r /etc/grml/lsb-functions ] ; then
120    . /etc/grml/lsb-functions
121 else
122    einfo()  { echo "  [*] $*" ;}
123    eerror() { echo "  [!] $*">&2 ;}
124    ewarn()  { echo "  [x] $*" ;}
125    eend()   { return 0 ;}
126    eindent()  { return 0 ;}
127    eoutdent() { return 0 ;}
128 fi
129
130 # source main configuration file:
131 LIVE_CONF=/etc/grml/grml-live.conf
132 . $LIVE_CONF
133 # }}}
134
135 # clean exit {{{
136 bailout() {
137   rm -f /var/run/fai/fai_softupdate_is_running \
138         /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
139   [ -n "$SQUASHFS_STDERR" ]  && rm -rf "$SQUASHFS_STDERR"
140   [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
141   [ -n "$1" ] && EXIT="$1" || EXIT="1"
142   [ -n "$2" ] && eerror "$2">&2
143   log "------------------------------------------------------------------------------"
144   exit "$EXIT"
145 }
146 trap bailout 1 2 3 3 6 9 14 15
147 # }}}
148
149 # log file stuff {{{
150 [ -n "$LOGFILE" ] || LOGFILE=/var/log/grml-live.log
151 touch $LOGFILE
152 chown root:adm $LOGFILE
153 chmod 664 $LOGFILE
154 # }}}
155
156 # some important functions {{{
157
158 # log output:
159 # usage: log "string to log"
160 log() { echo "$*" >> $LOGFILE ; }
161
162 # cut string at character number int = $1
163 # usage: cut_string 5 "1234567890" will output "12345"
164 cut_string() {
165   [ -n "$2" ] || return 1
166   echo "$2" | head -c "$1"; echo -ne "\n"
167 }
168
169 # prepend int = $1 spaces before string = $2
170 # usage: extend_string_begin 5 "123" will output "  123"
171 extend_string_begin() {
172   [ -n "$2" ] || return 1
173   local COUNT="$(echo $2 | wc -c)"
174   local FILL="$(expr $COUNT - $1)"
175   while [ "$FILL" -gt 1 ] ; do
176     echo -n " "
177     local FILL=$(expr $FILL - 1)
178   done
179   while [ "$FILL" -lt 1 ] ; do
180     echo -n " "
181     local FILL=$(expr $FILL + 1)
182   done
183   echo "$2" | head -c "$1"; echo -ne "\n"
184 }
185
186 # append int = $1 spaces to string = $2
187 # usage: extend_string_begin 5 "123" will output "123  "
188 extend_string_end() {
189   [ -n "$2" ] || return 1
190   echo -n "$2" | head -c "$1"
191   local COUNT="$(echo $2 | wc -c)"
192   local FILL="$(expr $COUNT - $1)"
193   while [ "$FILL" -gt 1 ] ; do
194     echo -n " "
195     local FILL=$(expr $FILL - 1)
196   done
197   while [ "$FILL" -lt 1 ] ; do
198     echo -n " "
199     local FILL=$(expr $FILL + 1)
200   done
201   echo -ne "\n"
202 }
203 # }}}
204
205 # read local (non-packaged) configuration {{{
206 LOCAL_CONFIG=/etc/grml/grml-live.local
207 if [ -r "$LOCAL_CONFIG" ] ; then
208    log "Sourcing $LOCAL_CONFIG"
209    . $LOCAL_CONFIG
210 else
211    log "No $LOCAL_CONFIG found, not sourcing it"
212    LOCAL_CONFIG=''
213 fi
214 # }}}
215
216 # command line parsing {{{
217 while getopts "a:C:c:d:g:i:I:o:r:s:t:v:bBFnquVz" opt; do
218   case "$opt" in
219     a) ARCH="$OPTARG" ;;
220     b) BUILD_ONLY=1 ;;
221     B) BUILD_DIRTY=1 ;;
222     c) CLASSES="$OPTARG" ;;
223     C) CONFIG="$OPTARG" ;;
224     d) DATE="$OPTARG" ;;
225     g) GRML_NAME="$OPTARG" ;;
226     i) ISO_NAME="$OPTARG" ;;
227     I) CHROOT_INSTALL="$OPTARG" ;;
228     n) SKIP_MKISOFS=1 ;;
229     o) OUTPUT="$OPTARG" ;;
230     q) SKIP_MKSQUASHFS=1 ;;
231     r) RELEASENAME="$OPTARG" ;;
232     s) SUITE="$OPTARG" ;;
233     t) TEMPLATE_DIRECTORY="$OPTARG";;
234     v) VERSION="$OPTARG" ;;
235     F) FORCE=1 ;;
236     u) UPDATE=1 ;;
237     V) VERBOSE="-v" ;;
238     z) SQUASHFS_ZLIB="true" ;;
239     ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
240   esac
241 done
242 shift $(($OPTIND - 1))  # set ARGV to the first not parsed commandline parameter
243 # }}}
244
245 # assume sane defaults (if not set already) {{{
246 [ -n "$ARCH" ]             || ARCH="$(dpkg --print-architecture)"
247 [ -n "$BOOT_METHOD" ]      || BOOT_METHOD='isolinux'
248 [ -n "$CLASSES" ]          || CLASSES="GRMLBASE,GRML_MEDIUM,I386"
249 [ -n "$DATE" ]             || DATE="$(date +%Y-%m-%d)"
250 [ -n "$DISTRI_INFO" ]      || DISTRI_INFO='Grml - Live Linux for system administrators   '
251 [ -n "$DISTRI_NAME" ]      || DISTRI_NAME="grml"
252 [ -n "$DISTRI_SPLASH" ]    || DISTRI_SPLASH='grml.png'
253 [ -n "$FORCE_ISO_REBUILD" ] || FORCE_ISO_REBUILD="false"
254 [ -n "$GRML_FAI_CONFIG" ]  || GRML_FAI_CONFIG='/etc/grml/fai'
255 [ -n "$GRML_NAME" ]        || GRML_NAME='grml'
256 [ -n "$HOSTNAME" ]         || HOSTNAME='grml'
257 [ -n "$NFSROOT_CONF" ]     || NFSROOT_CONF='/etc/grml/fai/make-fai-nfsroot.conf'
258 [ -n "$RELEASENAME" ]      || RELEASENAME='grml-live rocks'
259 [ -n "$SQUASHFS_EXCLUDES_FILE " ] || SQUASHFS_EXCLUDES_FILE='/etc/grml/fai/squashfs-excludes'
260 [ -n "$SUITE" ]            || SUITE='lenny'
261 [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
262 [ -n "$USERNAME" ]         || USERNAME='grml'
263 [ -n "$VERSION" ]          || VERSION='0.0.1'
264 [ -n "$WINDOWS_BINARIES" ] || WINDOWS_BINARIES='http://the.earth.li/~sgtatham/putty/latest/x86/'
265
266 # output specific stuff, depends on $OUTPUT (iff not set):
267 [ -n "$OUTPUT" ]           || OUTPUT='/grml/grml-live'
268 [ -n "$BUILD_OUTPUT" ]     || BUILD_OUTPUT="$OUTPUT/grml_cd"
269 [ -n "$CHROOT_OUTPUT" ]    || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
270 [ -n "$ISO_OUTPUT" ]       || ISO_OUTPUT="$OUTPUT/grml_isos"
271 # }}}
272
273 # some misc checks before executing FAI {{{
274 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
275 specify it on the command line using the -c option."
276 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
277 specify it on the command line using the -o option."
278
279 # trim characters that are known to cause problems inside $GRML_NAME;
280 # for example isolinux does not like '-' inside the directory name
281 [ -n "$GRML_NAME" ] && export SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
282
283 # export variables to have them available in fai scripts:
284 [ -n "$GRML_NAME" ]   && export GRML_NAME="$GRML_NAME"
285 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
286 # }}}
287
288 # ZERO_LOGFILE - check for backwards compatibility reasons {{{
289 # this was default behaviour until grml-live 0.9.34:
290 if [ -n "$ZERO_LOGFILE" ] ; then
291    PRESERVE_LOGFILE='' # make sure it's cleaned then
292    ewarn "Please consider disabling the \$ZERO_LOGFILE option as grml-live clears..."
293    ewarn "... the logfile $LOGFILE by default (unless \$PRESERVE_LOGFILE is set) nowadays."
294    eend 0
295 fi
296 # }}}
297
298 # ask user whether the setup is ok {{{
299 if [ -z "$FORCE" ] ; then
300    echo
301    echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
302    echo
303    echo "  FAI classes:       $CLASSES"
304    [ -r "$LOCAL_CONFIG" ]        && echo "  Local config:      /etc/grml/grml-live.local"
305    [ -n "$CONFIG" ]              && echo "  Configuration:     $CONFIG"
306    echo "  main directory:    $OUTPUT"
307    [ -n "$CHROOT_OUTPUT" ]       && echo "  Chroot target:     $CHROOT_OUTPUT"
308    [ -n "$BUILD_OUTPUT" ]        && echo "  Build target:      $BUILD_OUTPUT"
309    [ -n "$ISO_OUTPUT" ]          && echo "  ISO target:        $ISO_OUTPUT"
310    [ -n "$GRML_NAME" ]           && echo "  Grml name:         $GRML_NAME"
311    [ -n "$RELEASENAME" ]         && echo "  Release name:      $RELEASENAME"
312    [ -n "$DATE" ]                && echo "  Build date:        $DATE"
313    [ -n "$VERSION" ]             && echo "  Grml version:      $VERSION"
314    [ -n "$SUITE" ]               && echo "  Debian suite:      $SUITE"
315    [ -n "$ARCH" ]                && echo "  Architecture:      $ARCH"
316    [ -n "$BOOT_METHOD" ]         && echo "  Boot method:       $BOOT_METHOD"
317    [ -n "$TEMPLATE_DIRECTORY" ]  && echo "  Template files:    $TEMPLATE_DIRECTORY"
318    [ -n "$CHROOT_INSTALL" ]      && echo "  Install files from directory to chroot:  $CHROOT_INSTALL"
319    [ -n "$BOOTID" ]              && echo "  Boot identifier:   $BOOTID"
320    [ -n "$NO_BOOTID" ]           && echo "  Skipping bootid feature."
321    [ -n "$DEFAULT_BOOTOPTIONS" ] && echo "  Adding default bootoptions: \"$DEFAULT_BOOTOPTIONS\""
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 "$SKIP_MKISOFS" ]        && echo "  Skipping creation of ISO 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
342 # clean/zero/remove logfiles {{{
343
344 if [ -n "$PRESERVE_LOGFILE" ] ; then
345    echo "Preserving logfile $LOGFILE as requested via \$PRESERVE_LOGFILE"
346 else
347    # make sure it is empty (as it is e.g. appended to grml-live-db)
348    echo -n > $LOGFILE
349 fi
350
351 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
352    if [ -d /var/log/fai/"$HOSTNAME" ] ; then
353       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
354       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
355       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
356       rm -f /var/log/fai/"$HOSTNAME"/last \
357             /var/log/fai/"$HOSTNAME"/last-dirinstall \
358             /var/log/fai/"$HOSTNAME"/last-softupdate
359    fi
360 fi
361 # }}}
362
363 # source config and startup {{{
364 if [ -n "$CONFIG" ] ; then
365    if ! [ -f "$CONFIG" ] ; then
366       log    "Error: $CONFIG could not be read. Exiting. [$(date)]"
367       eerror "Error: $CONFIG could not be read. Exiting." ; eend 1
368       bailout 1
369    else
370       log "Sourcing $CONFIG"
371       . $CONFIG
372    fi
373 fi
374
375 start_seconds=$(cut -d . -f 1 /proc/uptime)
376 log "------------------------------------------------------------------------------"
377 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
378 log "Executed grml-live command line:"
379 log "$CMDLINE"
380
381 einfo "Logging actions to logfile $LOGFILE"
382 # }}}
383
384 # on-the-fly configuration {{{
385 if [ -n "$MIRROR_DIRECTORY" ] ; then
386    if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
387       log    "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
388       eerror "Error: $MIRROR_DIRECTORY/debian does not seem to exist. Exiting." ; eend 1
389       bailout 1
390    fi
391    cat > "$SOURCES_LIST_FILE" << EOF
392 # NOTE: This file is *NOT* meant for manual customisation! This file is
393 # modified by grml-live and any changes might be overridden.
394 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
395 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
396 EOF
397    echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_FILE"
398    if [ -n "$GRML_LIVE_SOURCES" ] ; then
399       echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
400    fi
401 elif [ -n "$GRML_LIVE_SOURCES" ] ; then
402    cat > "$SOURCES_LIST_FILE" << EOF
403 # NOTE: This file is *NOT* meant for manual customisation! This file is
404 # modified by grml-live and any changes might be overridden.
405 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
406 # or FAI's fcopy command with /etc/grml/fai/config/files instead!
407 EOF
408    echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
409 fi
410
411 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
412    sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
413 fi
414
415 # does this suck? YES!
416 # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
417 case $SUITE in
418    unstable) SUITE='sid' ;;
419    # make sure that we *NEVER* write any broken suite name to sources.list,
420    # otherwise we won't be able to adjust it one next (correct) execution
421    stable)   ;;
422    testing)  ;;
423    etch)     ;;
424    lenny)    ;;
425    squeeze)  ;;
426    sid)      ;;
427    *) echo "Sorry, $SUITE is not a valid Debian suite, exiting.">&2; bailout 1 ;;
428 esac
429
430 DIST=" etch\| stable\| lenny\| squeeze\| testing\| sid\| unstable"
431 sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
432 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" ; do
433     if [ -n "$file" ] ; then
434        sed "s/^SUITE=.*/SUITE=\"$SUITE\"/" $file | sponge $file
435        sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$file" | sponge "$file"
436     fi
437 done
438
439 # notice: activate grml-live pool only if we are building against unstable:
440 if grep -qe unstable -qe sid "$SOURCES_LIST_FILE" ; then
441    grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" || \
442    grep grml-stable "$SOURCES_LIST_FILE" | \
443         sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_FILE"
444 else
445    grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" && \
446    sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
447 fi
448
449 for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
450     if [ -n "$file" ] ; then
451        sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
452     fi
453 done
454
455 # validate whether the specified architecture class matches the
456 # architecture (option), otherwise installation of kernel will fail
457 if echo $CLASSES | grep -qi i386 ; then
458    if ! [[ "$ARCH" == "i386" ]] ; then
459       log    "Error: You specified the I386 class but are trying to build something else (AMD64?)."
460       eerror "Error: You specified the I386 class but are trying to build something else (AMD64?)."
461       eerror "Tip:   Either invoke grml-live with '-a i386' or adjust the architecture class. Exiting."
462       eend 1
463       bailout
464    fi
465 elif echo $CLASSES | grep -qi amd64 ; then
466    if ! [[ "$ARCH" == "amd64" ]] ; then
467       log    "Error: You specified the AMD64 class but are trying to build something else (I386?)."
468       eerror "Error: You specified the AMD64 class but are trying to build something else (I386?)."
469       eerror "Tip:   Either invoke grml-live with '-a amd64' or adjust the architecture class. Exiting."
470       eend 1
471       bailout
472    fi
473 fi
474
475 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
476    sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
477 else
478    sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
479 fi
480 # }}}
481
482 # CHROOT_OUTPUT - execute FAI {{{
483 if [ -n "$BUILD_DIRTY" ]; then
484    log   "Skipping stage 'fai' as requested via option -B"
485    ewarn "Skipping stage 'fai' as requested via option -B" ; eend 0
486 else
487    [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
488
489    # provide inform fai about the ISO we build
490    [ -d "$CHROOT_OUTPUT/etc/" ] || mkdir -p "$CHROOT_OUTPUT/etc/"
491    echo '# This file has been generated by grml-live.' > "$CHROOT_OUTPUT/etc/grml_live_version"
492    [ -n "$GRML_LIVE_VERSION" ] && echo "GRML_LIVE_VERSION=$GRML_LIVE_VERSION" >> "$CHROOT_OUTPUT/etc/grml_live_version"
493    [ -n "$SUITE" ] && echo "SUITE=$SUITE" >> "$CHROOT_OUTPUT/etc/grml_live_version"
494
495    if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
496       FAI_ACTION=softupdate
497    else
498       FAI_ACTION=dirinstall
499    fi
500
501    if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
502       if ! [ -r "$CHROOT_OUTPUT/etc/debian_version" ] ; then
503          log    "Error: does not look like you have a working chroot. Updating/building not possible."
504          eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
505          eend 1
506          bailout 20
507       fi
508    fi
509
510    if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
511       log   "Skiping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already."
512       ewarn "Skiping stage 'fai dirinstall' as $CHROOT_OUTPUT exists already." ; eend 0
513    else
514       mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
515
516       if [ -n "${MIRROR_DIRECTORY}" ] ; then
517          mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
518          mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
519       fi
520
521       log "Executed FAI command line:"
522       log "BUILD_ONLY=$BUILD_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
523       BUILD_ONLY="$BUILD_ONLY" fai $VERBOSE -C "$GRML_FAI_CONFIG" -c"$CLASSES" -u \
524       "$HOSTNAME" $FAI_ACTION "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
525       RC="$PIPESTATUS" # notice: bash-only
526
527       FORCE_ISO_REBUILD=true
528
529       if [ "$RC" != 0 ] ; then
530          log    "Error: critical error while executing fai [exit code ${RC}]. Exiting."
531          eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
532          bailout 1
533       else
534          log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]"
535          echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$DATE]" > $CHROOT_OUTPUT/etc/grml_version
536          chmod 644 $CHROOT_OUTPUT/etc/grml_version
537          einfo "Rebuilding initramfs"
538          # make sure new /etc/grml_version reaches the initramfs:
539          # chroot $CHROOT_OUTPUT update-initramfs -u -t => might break when using kernel-package :(
540          chroot $CHROOT_OUTPUT update-initramfs -u -k all
541          eend $?
542       fi
543
544       # Remove all FAI logs from chroot if class RELEASE is used:
545       if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
546          rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
547       fi
548
549       # make sure we don't leave any mounts - FAI doesn't remove them always
550       umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
551       umount $CHROOT_OUTPUT/sys  2>/dev/null || /bin/true
552       umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
553       umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
554
555       [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
556
557       # notice: 'fai dirinstall' does not seem to exit appropriate, so:
558       ERROR=''
559       CHECKLOG=/var/log/fai/$HOSTNAME/last
560       if [ -r "$CHECKLOG/software.log" ] ; then
561          # 1 errors during executing of commands
562          grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
563          grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
564          grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
565          grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
566          grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
567       fi
568
569       if [ -r "$CHECKLOG/shell.log" ] ; then
570          grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=2
571       fi
572
573       if [ -n "$ERROR" ] ; then
574          log    "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
575          eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
576          eerror "Note:  check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
577          eend 1
578          bailout 1
579       else
580          log "Finished execution of stage 'fai dirinstall' [$(date)]"
581          einfo "Finished execution of stage 'fai dirinstall'"
582       fi
583
584       einfo "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
585       log   "Find FAI build logs at $(readlink -f /var/log/fai/$HOSTNAME/last)"
586       eend 0
587    fi
588 fi # BUILD_DIRTY?
589 # }}}
590
591 # package validator {{{
592 CHECKLOG=/var/log/fai/$HOSTNAME/last
593 # package validator
594 if [ -r "$CHECKLOG/package_errors.log" ] && grep -q '[a-z]' "$CHECKLOG/package_errors.log" ; then
595
596    if [ -n "$EXIT_ON_MISSING_PACKAGES" -a -z "$BUILD_DIRTY" ] ; then
597       eerror "The following packages were requested for installation but could not be processed:"
598       cat $CHECKLOG/package_errors.log
599       eerror "... exiting as requested via \$EXIT_ON_MISSING_PACKAGES."
600       eend 1
601       bailout 13
602    else
603       ewarn "The following packages were requested for installation but could not be processed:"
604       cat $CHECKLOG/package_errors.log
605       eend 0
606    fi
607 fi
608 # }}}
609
610 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
611 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
612 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
613
614 # i386:
615 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
616    if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
617       log   "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
618       ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
619    else
620       # booting stuff:
621       [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
622       [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
623
624       if [ -z "$NO_ADDONS" ] ; then
625          [ -d "$BUILD_OUTPUT"/boot/addons   ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
626          if [ -r "$TEMPLATE_DIRECTORY"/boot/addons/memtest ] ; then
627             log "Installing $TEMPLATE_DIRECTORY/boot/addons/memtest"
628             cp "$TEMPLATE_DIRECTORY"/boot/addons/memtest "$BUILD_OUTPUT"/boot/addons/memtest
629          elif [ -r /boot/memtest86+.bin ] ; then
630             log "Installing /boot/memtest86+.bin"
631             cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
632          else
633             ewarn "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
634             log "No memtest binary found (either install package grml-live-addons or memtest86+), skipping."
635             eend 0
636          fi
637       fi
638
639       # if we don't have an initrd we a) can't boot and b) there was an error
640       # during build, so check for the file:
641       INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
642       if [ -n "$INITRD" ] ; then
643          cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.gz
644          find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
645       else
646          log    "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
647          eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
648          bailout 10
649       fi
650
651       KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
652       if [ -n "$KERNEL_IMAGE" ] ; then
653          cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/linux26
654       else
655          log    "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
656          eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
657          bailout 11
658       fi
659
660       [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
661       if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
662          log    "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
663          eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
664          bailout 8
665       fi
666
667       # *always* copy files to output directory so the variables
668       # get adjusted according to the build
669       cp ${TEMPLATE_DIRECTORY}/boot/isolinux/*  "$BUILD_OUTPUT"/boot/isolinux/
670
671       if [ -n "$NO_ADDONS" ] ; then
672          log   "Skipping installation of boot addons as requested via \$NO_ADDONS."
673          einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
674       else
675          if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
676            log   "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
677            ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
678          else
679            # copy only files so we can handle bsd4grml on its own
680            for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
681              test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
682            done
683
684            if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
685               log   "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
686               einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
687            else
688               if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
689                 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
690               else
691                 log   "bsd4grml addon not found, skipping therefore."
692                 ewarn "bsd4grml addon not found, skipping therefore." ; eend 0
693               fi
694            fi
695
696          fi # no "$TEMPLATE_DIRECTORY"/boot/addons
697       fi # NO_ADDONS
698
699       if ! [ -d ${TEMPLATE_DIRECTORY}/boot/grub ] ; then
700          log   "grub templates do not exist, skipping therefore."
701          ewarn "grub templates do not exist, skipping therefore." ; eend 0
702       else
703          if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
704             cp -a ${TEMPLATE_DIRECTORY}/boot/grub  "$BUILD_OUTPUT"/boot/
705          fi
706
707          # make sure we have recent template files available, otherwise updating
708          # the strings like $GRML_NAME and $VERSION might be out of date
709          cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
710       fi
711
712       if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
713          log    "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
714          eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
715          bailout 9
716       fi
717
718       [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
719       cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
720
721       # adjust boot splash information:
722       RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
723       RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
724       RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
725
726       if [ -r "$BUILD_OUTPUT"/GRML/grml-version ] ; then
727          sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
728          sed -i "s/%DATE%/$DATE/"                                      "$BUILD_OUTPUT"/GRML/grml-version
729       fi
730
731       # make sure the squashfs filename is set accordingly:
732       SQUASHFS_NAME="$GRML_NAME.squashfs"
733
734       if [ -n "$NO_BOOTID" ] ; then
735          log   'Skipping bootid feature as requested via $NO_BOOTID.'
736          einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
737       else
738          [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
739          [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
740          einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
741          log   "Generating /conf/bootid.txt with entry ${BOOTID}."
742          echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
743          eend $?
744       fi
745
746       # adjust all variables in the templates with the according distribution information
747       for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
748                   "${BUILD_OUTPUT}"/boot/grub/* ; do
749         if [ -r "${file}" ] ; then
750           sed -i "s/%ARCH%/$ARCH/g"                    "${file}"
751           sed -i "s/%DATE%/$DATE/g"                    "${file}"
752           sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g"      "${file}"
753           sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g"      "${file}"
754           sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g"  "${file}"
755           sed -i "s/%GRML_NAME%/$GRML_NAME/g"          "${file}"
756           sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g"  "${file}"
757           sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g"    "${file}"
758           sed -i "s/%SHORT_NAME%/$SHORT_NAME/g"        "${file}"
759           sed -i "s/%VERSION%/$VERSION/g"              "${file}"
760
761           [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s/ boot=live/ boot=live $DEFAULT_BOOTOPTIONS/"  "${file}"
762
763           if [ -n "$NO_BOOTID" ] ; then
764              sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
765           else
766              sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
767           fi
768         fi
769       done
770
771       # adjust bootsplash accordingly but make sure the string has the according lenght
772       SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
773       SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
774       for file in f4 f5 ; do
775          if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
776             sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
777             sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
778          fi
779       done
780
781       # generate addon list
782       rm "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
783       for name in $(ls "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg) ; do
784         include_name=$(basename "$name")
785         echo "include $include_name"  >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
786       done
787
788       if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
789          log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
790          echo "include grmlmain.cfg"    >  "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
791          echo "include default.cfg"     >  "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
792          echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
793          echo "include grml.cfg"        >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
794
795          for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
796            echo "include $(basename $f)"     >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
797          done
798
799          echo "include options.cfg"     >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
800          if [ ! -n "$NO_ADDONS" ] ; then
801            echo "include addons.cfg"    >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
802          fi
803          echo "include isoprompt.cfg"   >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
804          echo "include hd.cfg"          >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
805          echo "include hidden.cfg"      >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
806       else # assume we are building a custom distribution:
807          log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
808          einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
809          if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
810            log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
811            eindent
812            einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
813            eoutdent
814            eend $?
815         else
816            log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
817            echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
818            [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
819          fi
820       fi
821
822       # use old style console based isolinux method only if requested:
823       if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
824          log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
825          einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
826          if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
827            einfo "include for console.cfg already foud, nothing to do."
828            eend 0
829          else
830            log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
831            einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
832            echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
833            eend $?
834          fi
835       else
836          log 'Using graphical boot menu.'
837          if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
838            log "include for vesamenu.cfg already foud, nothing to do."
839          else
840            log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
841            echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
842          fi
843       fi
844
845       # jump back to grub from bsd4grml (/boot/grub/stage2):
846       GRUB_LEGACY=stage2
847
848       if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
849          if [ -e "$BUILD_OUTPUT"/boot/grub/core.img ]; then
850             GRUB_VERSION=2
851          else
852             GRUB_VERSION=1
853          fi
854
855          for file in "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 \
856                      "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.cfg \
857                      "$BUILD_OUTPUT"/boot/isolinux/*.cfg \
858                      "$BUILD_OUTPUT"/boot/grub/grub.cfg \
859                      "$BUILD_OUTPUT"/boot/grub/menu.lst ; do
860              if [ -e "$file" ] ; then
861                sed -i -e "s!%GRUB_VERSION%!$GRUB_VERSION!g" \
862                       -e "s!%GRUB_LEGACY%!$GRUB_LEGACY!g" "$file"
863              fi
864          done
865
866          sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
867       fi
868
869       if [ -e "$BUILD_OUTPUT"/boot/grub/$GRUB_LEGACY ]; then
870          sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/menu.lst
871          sed -i "s/%GRUB_LEGACY%/$GRUB_LEGACY/g" "$BUILD_OUTPUT"/boot/grub/grub.cfg
872       elif [ -e "$BUILD_OUTPUT"/boot/grub/menu.lst -a -e "$BUILD_OUTPUT"/boot/grub/grub.cfg ] ; then
873          sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/menu.lst
874          sed -i "/%GRUB_LEGACY%/d" "$BUILD_OUTPUT"/boot/grub/grub.cfg
875       fi
876
877       DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
878       if ! [ -r "$DPKG_LIST" ] ; then
879          ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
880       else
881          einfo "Storing package list information as /GRML/${GRML_NAME}-packages.txt on ISO."
882          cp "$DPKG_LIST" "${BUILD_OUTPUT}/GRML/${GRML_NAME}-packages.txt"
883          eend $?
884       fi
885
886       # autostart for Windows:
887       if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
888          cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
889       fi
890
891       # windows-binaries:
892       if [ -n "$NO_WINDOWS_BINARIES" ] ; then
893          log   "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
894          einfo "Skipping download of windows binaries as requested via \$NO_WINDOWS_BINARIES."
895          eend 0
896       else
897          if [ -f "$BUILD_OUTPUT"/windows/putty.exe ] ; then
898             log   "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already."
899             ewarn "Skipping stage 'WINDOWS_BINARIES' as $BUILD_OUTPUT/windows exists already." ; eend 0
900          else
901             if ! [ -d "$BUILD_OUTPUT"/windows ] ; then
902                mkdir "$BUILD_OUTPUT"/windows
903                ( cd "$BUILD_OUTPUT"/windows
904                  for file in pageant plink pscp psftp putty puttygen ; do
905                     wget -O ${file}.exe ${WINDOWS_BINARIES}/${file}.exe
906                     md5sum ${file}.exe > ${file}.exe.md5
907                  done )
908             fi
909
910             log "Finished execution of stage 'WINDOWS_BINARIES' [$(date)]"
911             einfo "Finished execution of stage 'WINDOWS_BINARIES'" ; eend 0
912          fi
913       fi
914
915    FORCE_ISO_REBUILD=true
916    einfo "Finished execution of stage 'boot'" ; eend 0
917    fi
918 else
919    log    'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
920    eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
921    bailout
922 fi
923
924 # support installation of local files into the chroot/ISO
925 if [ -n "$CHROOT_INSTALL" ] ; then
926   if ! [ -d "$CHROOT_INSTALL" ] ; then
927      log "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
928      ewarn "Configuration variable \$CHROOT_INSTALL is set but not a directory; ignoring"
929   else
930      log "Copying local files to chroot as requested via \$CHROOT_INSTALL"
931      einfo "Copying local files to chroot as requested via \$CHROOT_INSTALL"
932      rsync -avz --inplace "$CHROOT_INSTALL"/ "$CHROOT_OUTPUT/"
933      eend $?
934      einfo "Make sure to run squashfs stage, otherwise your local files won't be part of the ISO."
935      FORCE_ISO_REBUILD=true
936   fi
937 fi
938
939 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
940    log   "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already."
941    ewarn "Skipping stage 'squashfs' as $BUILD_OUTPUT/live exists already." ; eend 0
942 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
943    log   "Skipping stage 'squashfs' as requested via option -q"
944    ewarn "Skipping stage 'squashfs' as requested via option -q" ; eend 0
945 else
946    [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
947    # make sure we don't leave (even an empty) base.tgz:
948    [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
949
950    # $SQUASHFS_BINARY is specified in the configuration:
951    if [ -n "$SQUASHFS_BINARY" ] ; then
952       if which "$SQUASHFS_BINARY" >/dev/null 2>&1 ; then
953          log    "Using specified mksquashfs binary ${SQUASHFS_BINARY}"
954          einfo  "Using specified mksquashfs binary ${SQUASHFS_BINARY}" ; eend 0
955       else
956          log    "Error: specified mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting."
957          eerror "Error: specified mksquashfs binary ($SQUASHFS_BINARY) not found. Exiting." ; eend 1
958          bailout
959       fi
960    # no $SQUASHFS_BINARY configured, let's find the according binary:
961    else
962       # Note: this is ALL for backward compatibility and yes: it's serious PITA.
963       # We'll definitely drop this once people build >=2.6.35-grml* only and
964       # the squashfs-tools vs. squashfs-lzma-tools vs. squashfs-lzma-tools4 and
965       # zlib/gzip vs. lzma situation is settling with new squashfs file format (v4)
966
967       if ls $CHROOT_OUTPUT/boot/vmlinuz* >/dev/null 2>&1 ; then
968         KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
969       else
970         KERNEL_IMAGE="unset"
971       fi
972
973       case $KERNEL_IMAGE in
974          *vmlinuz-2.6.31-grml*|*vmlinuz-2.6.33-grml*)
975            SQUASHFS_BINARY='mksquashfs-lzma'
976
977            # if using zlib compression kernel 2.6.3{1,3}-grml can be used with
978            # mksquashfs as well, therefore try to fall back if mksquashfs-lzma
979            # is NOT available
980            if ! which $SQUASHFS_BINARY >/dev/null 2>&1 && [ -n "$SQUASHFS_ZLIB" ] ; then
981              log "Squashfs binary $SQUASHFS_BINARY not available but building with zlib..."
982              log "\`-> trying to fall back to mksquashfs."
983              ewarn "Squashfs binary $SQUASHFS_BINARY not available but building with zlib..."
984              ewarn "\`-> trying to fall back to mksquashfs."
985              SQUASHFS_BINARY='mksquashfs'
986              eend 0
987            fi
988            ;;
989
990          *vmlinuz-2.6.35-grml*)
991            SQUASHFS_BINARY='mksquashfs-lzma4'
992
993            # if using zlib compression kernel 2.6.35-grml can be used with
994            # mksquashfs-lzma as well, therefore try to fall back if
995            # mksquashfs-lzma4 is NOT available
996            if ! which $SQUASHFS_BINARY >/dev/null 2>&1 && [ -n "$SQUASHFS_ZLIB" ] ; then
997              log "Squashfs binary $SQUASHFS_BINARY not available but building with zlib..."
998              log "\`-> trying to fall back to mksquashfs-lzma."
999              ewarn "Squashfs binary $SQUASHFS_BINARY not available but building with zlib..."
1000              ewarn "\`-> trying to fall back to mksquashfs-lzma."
1001              SQUASHFS_BINARY='mksquashfs-lzma'
1002              eend 0
1003            fi
1004
1005            # squashfs-tools 1:4.0-x work with 2.6.35-grml as well with default
1006            # options, they just lack proper LZMA compression, so fall back as
1007            # last option and inform user
1008            if ! which $SQUASHFS_BINARY >/dev/null 2>&1 ; then
1009              log   "Squashfs binary $SQUASHFS_BINARY not available either..."
1010              log   "\`-> trying to fall back to mksquashfs, WARNING: very probably lacks LZMA compression."
1011              ewarn "Squashfs binary $SQUASHFS_BINARY not available either..."
1012              ewarn "\`-> trying to fall back to mksquashfs, WARNING: very probably lacks LZMA compression."
1013              SQUASHFS_BINARY='mksquashfs'
1014              eend 0
1015            fi
1016            ;;
1017
1018          *vmlinuz-2.6.23-grml*|*vmlinuz-2.6.26-grml*|*vmlinuz-2.6.28-grml*)
1019             log    "Strongly outdated kernel version detected: $KERNEL_IMAGE"
1020             eerror "Strongly outdated kernel version detected: $KERNEL_IMAGE"
1021             eerror "|-> please update kernel version of live system to at *least* 2.6.31-grml[64]..."
1022             eerror "\`-> or otherwise (not recommended though) set SQUASHFS_BINARY accordingly."
1023             eend 1
1024             bailout
1025             ;;
1026
1027          *)
1028            SQUASHFS_BINARY='mksquashfs'
1029            log   "Could not detect grml kernel version and SQUASHFS_BINARY is unset."
1030            ewarn "Could not detect grml kernel version and SQUASHFS_BINARY is unset."
1031            ewarn "\`-> Assuming you want to use mksquashfs binary, if it fails please override with \$SQUASHFS_BINARY."
1032            eend 0
1033            ;;
1034       esac
1035
1036       # check whether we have the according binary available:
1037       if ! which $SQUASHFS_BINARY >/dev/null 2>&1 ; then
1038          log    "Error: required mksquashfs binary (${SQUASHFS_BINARY}) could not be found. Exiting."
1039          eerror "Error: required mksquashfs binary (${SQUASHFS_BINARY}) could not be found. Exiting."
1040          eerror "|-> Make sure to install squashfs-tool, squashfs-lzma-tools and/or squashfs-lzma-tools4..."
1041          eerror "|-> ... and set \$SQUASHFS_BINARY accordingly to the kernel version."
1042          eerror "\`-> Visit http://grml.org/grml-live/#current_state for further details."
1043          eend 1
1044          bailout
1045       fi
1046
1047    fi # end of SQUASHFS_BINARY handling
1048
1049    # use sane defaults if $SQUASHFS_OPTIONS isn't set
1050    if [ -z "$SQUASHFS_OPTIONS" ] ; then
1051      # use blocksize 256k as this gives best result with regards to time + compression
1052      [[ "$SQUASHFS_BINARY" == mksquashfs-lzma* ]] && SQUASHFS_OPTIONS="-b 256k"
1053
1054      # set lzma compression by default, unless -z option has been specified on command line
1055      if [ -z "$SQUASHFS_ZLIB" ] ; then
1056        case "$SQUASHFS_BINARY" in
1057          mksquashfs-lzma)  SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -lzma";;
1058          mksquashfs-lzma4) SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -comp lzma";;
1059        esac
1060      fi
1061
1062    fi
1063
1064    # support exclusion of files via exclude-file:
1065    if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
1066       SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE"
1067    fi
1068
1069    # get rid of unnecessary files when building grml-small for final release:
1070    if echo "$CLASSES" | grep -q GRML_SMALL ; then
1071       SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -e initrd.img* vmlinuz*"
1072    fi
1073
1074    # be backwards compatible, for squashfs-tools 1:3.2r2-9exp1 and squashfs-lzma-tools 3.3-1,
1075    # make sure to drop the -nolzma option if it's not available:
1076    if echo "$SQUASHFS_OPTIONS" | grep -q -- "-nolzma" ; then
1077      if ! $SQUASHFS_BINARY --help 2>&1 | grep -q -- '-nolzma' ; then
1078        log   "The $SQUASHFS_BINARY binary does NOT support the nolzma option, dropping it and using default mode."
1079        ewarn "The $SQUASHFS_BINARY binary does NOT support the nolzma option, dropping it and using default mode."
1080        SQUASHFS_OPTIONS="$(echo $SQUASHFS_OPTIONS | sed 's/-nolzma//g')"
1081        eend 0
1082      fi
1083    fi
1084
1085    # if user doesn't want to use LZMA (e.g. running grml-live -z ...):
1086    if [ -n "$SQUASHFS_ZLIB" ] ; then
1087      if $SQUASHFS_BINARY --help 2>&1 | grep -q -- "-nolzma" ; then
1088         SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -nolzma"
1089      fi
1090    fi
1091
1092    # log stuff
1093    SQUASHFS_STDERR="$(mktemp -t grml-live.XXXXXX)"
1094
1095    # informational stuff
1096    [ -n "$SQUASHFS_OPTIONS" ]  && SQUASHFS_INFO_MSG="$SQUASHFS_OPTIONS"
1097    [ -n "$SQUASHFS_ZLIB" ]     && SQUASHFS_INFO_MSG="$SQUASHFS_INFO_MSG $SQUASHFS_ZLIB"
1098    [ -n "$SQUASHFS_INFO_MSG" ] && SQUASHFS_INFO_MSG="using options: $SQUASHFS_INFO_MSG"
1099    einfo "Squashfs build information: running binary $SQUASHFS_BINARY $SQUASHFS_INFO_MSG"
1100
1101    log "$SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB"
1102
1103    if $SQUASHFS_BINARY $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
1104       -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB 2>"${SQUASHFS_STDERR}" ; then
1105       echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
1106       log "Finished execution of stage 'squashfs' [$(date)]"
1107       einfo "Finished execution of stage 'squashfs'" ; eend 0
1108    else
1109       log    "Error: there was a critical error executing stage 'squashfs' [$(date)]:"
1110       log    "$(cat $SQUASHFS_STDERR)"
1111       eerror "Error: there was a critical error executing stage 'squashfs':"
1112       cat    "${SQUASHFS_STDERR}"
1113       eend 1
1114       bailout
1115    fi
1116
1117    FORCE_ISO_REBUILD=true
1118 fi
1119
1120 # create md5sum file:
1121 ( cd $BUILD_OUTPUT/GRML &&
1122 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
1123 # }}}
1124
1125 # ISO_OUTPUT - mkisofs {{{
1126 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
1127 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
1128
1129 if [ "$BOOT_METHOD" = "isolinux" ] ; then
1130    BOOT_FILE="boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
1131 elif [ "$BOOT_METHOD" = "grub" ] ; then
1132    BOOT_FILE="boot/grub/stage2"
1133 fi
1134
1135 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" -a "$FORCE_ISO_REBUILD" = "false" ]  ; then
1136    log   "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already."
1137    ewarn "Skipping stage 'iso build' as $ISO_OUTPUT/${ISO_NAME} exists already." ; eend 0
1138 elif [ -n "$SKIP_MKISOFS" ] ; then
1139    log   "Skipping stage 'iso build' as requested via option -n"
1140    ewarn "Skipping stage 'iso build' as requested via option -n" ; eend 0
1141 else
1142    mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
1143
1144    if $FORCE_ISO_REBUILD && ! [ -f "${ISO_OUTPUT}/${ISO_NAME}" ] ; then
1145       log   "Forcing rebuild of ISO because files on ISO have been modified."
1146       einfo "Forcing rebuild of ISO because files on ISO have been modified."
1147    fi
1148
1149    # support mkisofs as well as genisoimage
1150    if which mkisofs >/dev/null 2>&1; then
1151       MKISOFS='mkisofs'
1152    elif which genisoimage >/dev/null 2>&1; then
1153       MKISOFS='genisoimage'
1154    else
1155       log    "Error: neither mkisofs nor genisoimage available - can not create ISO."
1156       eerror "Error: neither mkisofs nor genisoimage available - can not create ISO." ; eend 1
1157       bailout
1158    fi
1159
1160    CURRENT_DIR=$(pwd)
1161    if cd "$BUILD_OUTPUT" ; then
1162       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} ."
1163       "$MKISOFS" -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
1164               -l -r -J -no-emul-boot -boot-load-size 4 -boot-info-table    \
1165               -b $BOOT_FILE -no-pad \
1166               -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
1167
1168       # pad the output ISO to multiples of 256 KiB for partition table support
1169       siz=$($getfilesize "${ISO_OUTPUT}/${ISO_NAME}")
1170       cyls=$((siz / 512 / 32 / 16 + 1))   # C=$cyls H=16 S=32
1171       siz=$((cyls * 16 * 32 * 512))   # size after padding
1172       dd if=/dev/zero bs=1 count=1 seek=$((siz - 1)) \
1173          of="${ISO_OUTPUT}/${ISO_NAME}" 2>/dev/null
1174
1175       # support disabling hybrid ISO image
1176       if [ "$HYBRID_METHOD" = "disable" ] ; then\
1177          log   "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1178          einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
1179          eend 0
1180       # use isohybrid only on request
1181       elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
1182          if ! which isohybrid >/dev/null 2>&1 ; then
1183            bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
1184          else
1185            log "Creating hybrid ISO file with isohybrid method"
1186            einfo "Creating hybrid ISO file with isohybrid method"
1187            # Notes for consideration:
1188            # "-entry 4 -type 1c"
1189            # * using 4 as the partition number is supposed to help with BIOSes
1190            #   that only support USB-Zip boot
1191            # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
1192            #   (hidden NTFS, IIRC), as the partition type is sometimes needed
1193            #   to get the BIOS even look at the partition created by isohybrid
1194            isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
1195            eend $?
1196          fi
1197       # by default use our manifold boot method:
1198       else
1199          if ! [ -r boot/grub/core.img ] ; then
1200            ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
1201          else
1202            log "Creating hybrid ISO file with manifold method"
1203            einfo "Creating hybrid ISO file with manifold method"
1204            (
1205                # 512 bytes: MBR, partition table, load GRUB 2
1206                echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
1207                # pad to a whole of 2048 bytes (one CD sector)
1208                dd if=/dev/zero bs=512 count=3 2>/dev/null
1209                # append GRUB 2 (must be <=30720 bytes)
1210                cat boot/grub/core.img
1211            ) | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
1212            eend $?
1213          fi
1214       fi
1215
1216       # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
1217       case $CLASSES in *RELEASE*)
1218          [ "$RC" = 0 ] && \
1219          (
1220            if cd $ISO_OUTPUT ; then
1221              md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
1222              touch -r ${ISO_NAME} ${ISO_NAME}.md5
1223              sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
1224              touch -r ${ISO_NAME} ${ISO_NAME}.sha1
1225            fi
1226          )
1227          ;;
1228       esac
1229
1230       cd $CURRENT_DIR
1231    fi
1232
1233    if [ "$RC" = 0 ] ; then
1234       log   "Finished execution of stage 'iso build' [$(date)]"
1235       einfo "Finished execution of stage 'iso build'" ; eend 0
1236    else
1237       log    "Error: there was a critical error ($RC) executing stage 'iso build' [$(date)]"
1238       eerror "Error: there was a critical error executing stage 'iso build'" ; eend 1
1239       bailout $RC
1240    fi
1241 fi
1242 # }}}
1243
1244 # log build information to database if grml-live-db is installed and enabled {{{
1245 dpkg_to_db() {
1246 if [ -d /usr/share/grml-live-db ] ; then
1247
1248   # safe defaults
1249   DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot:
1250   [ -n "$DPKG_DATABASE" ]  || DPKG_DATABASE=/var/log/grml-live.db
1251   [ -n "$DPKG_DBSCRIPT" ]  || DPKG_DBSCRIPT=/usr/share/grml-live-db/scripts/dpkg-to-db
1252   [ -n "$DPKG_DBOPTIONS" ] || DPKG_DBOPTIONS="--database $DPKG_DATABASE --logfile $LOGFILE --flavour $GRML_NAME --dpkg $DPKG_LIST"
1253
1254   if ! [ -x "$DPKG_DBSCRIPT" ] ; then
1255     log "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information."
1256     eerror "Error: $DPKG_DBSCRIPT is not executable, can not log dpkg information." ; eend 1
1257     bailout 14
1258   fi
1259
1260   # disable by default for now, not sure whether really everyone is using a local db file
1261   #if ! touch "$DPKG_DATABASE" ; then
1262   #  eerror "Error: can not write to ${DPKG_DATABASE}, can not log dpkg information." ; eend 1
1263   #  bailout 14
1264   #fi
1265
1266   if ! [ -r "$DPKG_LIST" ] ; then
1267      log   "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)"
1268      ewarn "Warning: can not read $DPKG_LIST - can not provide information to $DPKG_DBSCRIPT (dirty build?)" ; eend 0
1269   else
1270      einfo "Logging $DPKG_LIST to database $DPKG_DATABASE"
1271      log "Logging $DPKG_LIST to database $DPKG_DATABASE"
1272      log "Executing $DPKG_DBSCRIPT $DPKG_DBOPTIONS"
1273      eindent
1274
1275      if DB_INFO=$("$DPKG_DBSCRIPT" $DPKG_DBOPTIONS 2>&1) ; then
1276        einfo "$DB_INFO"
1277        eend 0
1278      else
1279        eerror "$DB_INFO"
1280        eend 1
1281      fi
1282
1283      eoutdent
1284   fi
1285
1286 fi
1287 }
1288 # }}}
1289
1290 # finalize {{{
1291 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
1292 log "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]"
1293
1294 dpkg_to_db # make sure we catch the last log line as well, therefore execute between log + einfo
1295
1296 einfo "Successfully finished execution of $PN [$(date) - running ${SECONDS} seconds]" ; eend 0
1297 bailout 0
1298 # }}}
1299
1300 ## END OF FILE #################################################################
1301 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3