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