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