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