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