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