Integrate grub2 for hybrid boot
[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), (c) Michael Prokop <mika@grml.org>
5 # Bug-Reports:   see http://grml.org/bugs/
6 # License:       This file is licensed under the GPL v2 or any later version.
7 ################################################################################
8
9 # read configuration files, set some misc variables {{{
10
11 export LANG=C
12 export LC_ALL=C
13
14 # exit on any error:
15 set -e
16
17 GRML_LIVE_VERSION='0.9.18'
18 PN="$(basename $0)"
19 CMDLINE="$0 $@"
20 ISO_DATE="$(date +%Y-%m-%d)"
21 SOURCES_LIST_FILE='/etc/grml/fai/apt/sources.list'
22
23 # usage information {{{
24 usage()
25 {
26   echo "
27 $PN - build process script for generating a (grml based) Linux Live-ISO
28
29 Usage: $PN [options, see as follows]
30
31    -a <architecture>       architecture; available values: i386 and amd64
32    -b                      build the ISO without updating the chroot via FAI
33    -B                      build the ISO without touching the chroot (skips cleanup)
34    -c <classe[s]>          classes to be used for building the ISO via FAI
35    -C <configfile>         configuration file for grml-live
36    -F                      force execution without prompting
37    -g <grml_name>]         set the grml flavour name
38    -h                      display short usage information and exit
39    -i <iso_name>           name of ISO
40    -o <output_directory>   main output directory of the build process
41    -q                      skip mksquashfs
42    -r <release_name<       release name
43    -s <suite>              Debian suite; values: etch, lenny, squeeze, sid
44    -t <template_directory> place of the templates
45    -u                      update existing chroot instead of rebuilding it from scratch
46    -v <version_number>     specify version number of the release
47    -V                      increase verbosity in the build process
48    -z                      use ZLIB instead of LZMA compression (depends on
49                            squashfs-tools version)
50
51 Usage examples:
52
53     $PN
54     $PN -c GRMLBASE,GRML_MEDIUM,I386 -o /dev/shm/grml
55     $PN -c GRMLBASE,GRML_SMALL,REMOVE_DOCS,I386 -g grml-small -v 1.0
56     $PN -c GRMLBASE,GRML_FULL,I386 -i grml_0.0-1.iso -v 0.0-1
57     $PN -c GRMLBASE,GRML_FULL,I386 -s sid -V -r 'grml-live rocks'
58
59 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
60               http://grml.org/grml-live/
61
62 Please send your bug reports and feedback to the grml-team: http://grml.org/bugs/
63 "
64 }
65
66 # make sure it's possible to get usage information without being
67 # root or actually executing the script
68 if [ "$1" = '-h' -o "$1" = '--help' ] ; then
69    usage
70    [ "$(id -u 2>/dev/null)" != 0 ] && echo "Please notice that this script requires root permissions."
71    exit 0
72 fi
73 # }}}
74
75 # we need root permissions for the build-process:
76 if [ "$(id -u 2>/dev/null)" != 0 ] ; then
77    echo "Error: please run this script with uid 0 (root)." >&2
78    exit 1
79 fi
80
81 if [ -r /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ] ; then
82    echo "/usr/sbin/fai already running or was aborted before.">&2
83    echo "You may remove /var/run/fai/FAI_INSTALLATION_IN_PROGRESS and try again.">&2
84    exit 1
85 fi
86
87 # see #449236
88 if [ -r /var/run/fai/fai_softupdate_is_running ] ; then
89    echo "/usr/sbin/fai softupdate already running or was aborted before.">&2
90    echo "You may remove /var/run/fai/fai_softupdate_is_running and try again.">&2
91    exit 1
92 fi
93
94 # make sure they are not set by default
95 VERBOSE=''
96 FORCE=''
97 UPDATE=''
98 BUILD_ONLY=''
99 BUILD_DIRTY=''
100 HOSTNAME=''
101
102 if [ -r /etc/grml/lsb-functions ] ; then
103    . /etc/grml/lsb-functions
104 else
105    einfo()  { echo "  [*] $*" ;}
106    eerror() { echo "  [!] $*">&2 ;}
107    ewarn()  { echo "  [x] $*" ;}
108    eend()   { return 0 ;}
109 fi
110
111 # source main configuration file:
112 LIVE_CONF=/etc/grml/grml-live.conf
113 . $LIVE_CONF
114
115 # }}}
116
117 # clean exit {{{
118 bailout() {
119   rm -f /var/run/fai/fai_softupdate_is_running \
120         /var/run/fai/FAI_INSTALLATION_IN_PROGRESS
121   [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
122   [ -n "$1" ] && EXIT="$1" || EXIT="1"
123   [ -n "$2" ] && eerror "$2">&2
124   log "------------------------------------------------------------------------------"
125   exit "$EXIT"
126 }
127 trap bailout 1 2 3 3 6 9 14 15
128 # }}}
129
130 # check for important variables {{{
131 [ -n "$GRML_FAI_CONFIG" ] || GRML_FAI_CONFIG=/etc/grml/fai
132 [ -n "$HOSTNAME" ] || HOSTNAME=grml
133 [ -n "$USERNAME" ] || USERNAME=grml
134 [ -n "$CLASSES" ]  || CLASSES="GRML,I386"
135 [ -n "$BOOT_METHOD" ] || BOOT_METHOD='isolinux'
136 [ -n "$OUTPUT" ] || bailout 1 "${PN}: \$OUTPUT not specified. Please adjust $LIVE_CONF. Exiting."
137
138 [ -n "$VERSION" ]  || VERSION="0.0.1"
139 [ -n "$RELEASENAME" ] || RELEASENAME="grml-live rocks"
140 [ -n "$GRML_NAME" ] || GRML_NAME='grml'
141
142 # logfile:
143 if [ -z "$LOGFILE" ] ; then
144    LOGFILE=/var/log/grml-live.log
145 fi
146 touch $LOGFILE
147 chown root:adm $LOGFILE
148 chmod 664 $LOGFILE
149
150 NFSROOT_CONF=/etc/grml/fai/make-fai-nfsroot.conf
151
152 # }}}
153
154 # some important functions {{{
155
156 # log output:
157 # usage: log "string to log"
158 log() { echo "$*" >> $LOGFILE ; }
159
160 # cut string at character number int = $1
161 # usage: cut_string 5 "1234567890" will output "12345"
162 cut_string() {
163   [ -n "$2" ] || return 1
164   echo "$2" | head -c "$1"; echo -ne "\n"
165 }
166
167 # prepend int = $1 spaces before string = $2
168 # usage: extend_string_begin 5 "123" will output "  123"
169 extend_string_begin() {
170   [ -n "$2" ] || return 1
171   local COUNT="$(echo $2 | wc -c)"
172   local FILL="$(expr $COUNT - $1)"
173   while [ "$FILL" -gt 1 ] ; do
174     echo -n " "
175     local FILL=$(expr $FILL - 1)
176   done
177   while [ "$FILL" -lt 1 ] ; do
178     echo -n " "
179     local FILL=$(expr $FILL + 1)
180   done
181   echo "$2" | head -c "$1"; echo -ne "\n"
182 }
183
184 # append int = $1 spaces to string = $2
185 # usage: extend_string_begin 5 "123" will output "123  "
186 extend_string_end() {
187   [ -n "$2" ] || return 1
188   echo -n "$2" | head -c "$1"
189   local COUNT="$(echo $2 | wc -c)"
190   local FILL="$(expr $COUNT - $1)"
191   while [ "$FILL" -gt 1 ] ; do
192     echo -n " "
193     local FILL=$(expr $FILL - 1)
194   done
195   while [ "$FILL" -lt 1 ] ; do
196     echo -n " "
197     local FILL=$(expr $FILL + 1)
198   done
199   echo -ne "\n"
200 }
201 # }}}
202
203 # read local (non-packaged) configuration {{{
204 LOCAL_CONFIG=/etc/grml/grml-live.local
205 if [ -r "$LOCAL_CONFIG" ] ; then
206    log "Sourcing $LOCAL_CONFIG"
207    . $LOCAL_CONFIG
208 else
209    log "No $LOCAL_CONFIG found, not sourcing it"
210    LOCAL_CONFIG=''
211 fi
212 # }}}
213
214 # command line parsing {{{
215 while getopts "a:C:c:g:i:o:r:s:t:v:bBFuqVz" opt; do
216   case "$opt" in
217     a) ARCH="$OPTARG" ;;
218     b) BUILD_ONLY=1 ;;
219     B) BUILD_DIRTY=1 ;;
220     c) CLASSES="$OPTARG" ;;
221     C) CONFIG="$OPTARG" ;;
222     g) GRML_NAME="$OPTARG" ;;
223     i) ISO_NAME="$OPTARG" ;;
224     o) OUTPUT="$OPTARG"
225        CHROOT_OUTPUT="$OUTPUT/grml_chroot"
226        BUILD_OUTPUT="$OUTPUT/grml_cd"
227        ISO_OUTPUT="$OUTPUT/grml_isos"
228        ;;
229     q) SKIP_MKSQUASHFS=1 ;;
230     r) RELEASENAME="$OPTARG" ;;
231     s) SUITE="$OPTARG" ;;
232     t) TEMPLATE_DIRECTORY="$OPTARG";;
233     v) VERSION="$OPTARG" ;;
234     F) FORCE=1 ;;
235     u) UPDATE=1 ;;
236     V) VERBOSE="-v" ;;
237     z) SQUASHFS_ZLIB="-nolzma" ;;
238     ?) echo "invalid option -$OPTARG" >&2; bailout 1 ;;
239   esac
240 done
241 shift $(($OPTIND - 1))  # set ARGV to the first not parsed commandline parameter
242 # }}}
243
244 # some misc checks before executing FAI {{{
245 [ -n "$CLASSES" ] || bailout 1 "Error: \$CLASSES unset, please set it in $LIVE_CONF or
246 specify it on the command line using the -c option."
247 [ -n "$OUTPUT" ] || bailout 1 "Error: \$OUTPUT unset, please set it in $LIVE_CONF or
248 specify it on the command line using the -o option."
249
250 # trim characters that are known to cause problems inside $GRML_NAME;
251 # for example isolinux does not like '-' inside the directory name
252 [ -n "$GRML_NAME" ] && export SHORT_GRML_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
253
254 # export variables to have them available in fai scripts:
255 [ -n "$GRML_NAME" ]   && export GRML_NAME="$GRML_NAME"
256 [ -n "$RELEASENAME" ] && export RELEASENAME="$RELEASENAME"
257 # }}}
258
259 # clean/zero grml-live logfile {{{
260 if [ -n "$ZERO_LOGFILE" ] ; then
261    echo -n > $LOGFILE
262 fi
263 # }}}
264
265 # clean/zero/remove old FAI directory {{{
266 if [ -n "$ZERO_FAI_LOGFILE" ] ; then
267    if [ -d /var/log/fai/"$HOSTNAME" ] ; then
268       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last)"
269       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-dirinstall)"
270       rm -rf /var/log/fai/"$HOSTNAME"/"$(readlink /var/log/fai/"$HOSTNAME"/last-softupdate)"
271       rm -f /var/log/fai/"$HOSTNAME"/last \
272             /var/log/fai/"$HOSTNAME"/last-dirinstall \
273             /var/log/fai/"$HOSTNAME"/last-softupdate
274    fi
275 fi
276 # }}}
277
278 # ask user whether the setup is ok {{{
279 if [ -z "$FORCE" ] ; then
280    echo
281    echo "${PN} [${GRML_LIVE_VERSION}]: check your configuration (or use -F to force execution):"
282    echo
283    echo "  FAI classes:       $CLASSES"
284    [ -r "$LOCAL_CONFIG" ]       && echo "  local config:      /etc/grml/grml-live.local"
285    [ -n "$CONFIG" ]             && echo "  configuration:     $CONFIG"
286    echo "  main directory:    $OUTPUT"
287    [ -n "$CHROOT_OUTPUT" ]      && echo "  chroot target:     $CHROOT_OUTPUT"
288    [ -n "$BUILD_OUTPUT" ]       && echo "  build target:      $BUILD_OUTPUT"
289    [ -n "$ISO_OUTPUT" ]         && echo "  ISO target:        $ISO_OUTPUT"
290    [ -n "$GRML_NAME" ]          && echo "  grml name:         $GRML_NAME"
291    [ -n "$RELEASENAME" ]        && echo "  release name:      $RELEASENAME"
292    [ -n "$VERSION" ]            && echo "  grml version:      $VERSION"
293    [ -n "$SUITE" ]              && echo "  Debian suite:      $SUITE"
294    [ -n "$ARCH" ]               && echo "  Architecture:      $ARCH"
295    [ -n "$BOOT_METHOD" ]        && echo "  Boot method:       $BOOT_METHOD"
296    [ -n "$TEMPLATE_DIRECTORY" ] && echo "  Template files:    $TEMPLATE_DIRECTORY"
297    [ -n "$FAI_ARGS" ]           && echo "  additional arguments for FAI: $FAI_ARGS"
298    [ -n "$LOGFILE" ]            && echo "  Logging to file:   $LOGFILE"
299    [ -n "$SQUASHFS_ZLIB" ]      && echo "  Using ZLIB (instead of LZMA) compression."
300    [ -n "$SQUASHFS_OPTIONS" ]   && echo "  Using SQUASHFS_OPTIONS ${SQUASHFS_OPTIONS}"
301    [ -n "$VERBOSE" ]            && echo "  Using VERBOSE mode."
302    [ -n "$UPDATE" ]             && echo "  Executing UPDATE instead of fresh installation."
303    [ -n "$SKIP_MKSQUASHFS" ]    && echo "  Skipping creation of SQUASHFS file."
304    [ -n "$BUILD_ONLY" ]         && echo "  Executing BUILD_ONLY instead of fresh installation or UPDATE."
305    [ -n "$BUILD_DIRTY" ]        && echo "  Executing BUILD_DIRTY to leave chroot untouched."
306    echo
307    echo -n "Is this ok for you? [y/N] "
308    read a
309    if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
310       bailout 1 "Exiting as requested."
311    fi
312    echo
313 fi
314
315 if [ -n "$CONFIG" ] ; then
316    if ! [ -f "$CONFIG" ] ; then
317       log "Sorry, $CONFIG could not be read. Exiting. [$(date)]"
318       eerror "Sorry, $CONFIG could not be read. Exiting."
319       bailout 1
320    else
321       log "Sourcing $CONFIG"
322       . $CONFIG
323    fi
324 fi
325
326 start_seconds=$(cut -d . -f 1 /proc/uptime)
327 log "------------------------------------------------------------------------------"
328 log "Starting grml-live [${GRML_LIVE_VERSION}] run on $(date)"
329 log "Executed grml-live command line:"
330 log "$CMDLINE"
331
332 einfo "Logging actions to logfile $LOGFILE"
333 # }}}
334
335 # on-the-fly configuration {{{
336 if [ -n "$MIRROR_DIRECTORY" ] ; then
337    if ! [ -d "$MIRROR_DIRECTORY/debian" ] ; then
338       log "Sorry, $MIRROR_DIRECTORY/debian does not seem to exist. Exiting. [$(date)]"
339       eerror "Sorry, $MIRROR_DIRECTORY/debian does not seem to exist. Exiting."
340       bailout 1
341    fi
342    cat > "$SOURCES_LIST_FILE" << EOF
343 # NOTE: This file is *NOT* meant for manual customisation! This file is
344 # modified by grml-live and any changes might be overriden.
345 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
346 # and using /etc/grml/fai/files/etc/apt instead!'
347 EOF
348    echo "$MIRROR_SOURCES" >> "$SOURCES_LIST_FILE"
349    if [ -n "$GRML_LIVE_SOURCES" ] ; then
350       echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
351    fi
352 elif [ -n "$GRML_LIVE_SOURCES" ] ; then
353    cat > "$SOURCES_LIST_FILE" << EOF
354 # NOTE: This file is *NOT* meant for manual customisation! This file is
355 # modified by grml-live and any changes might be overriden.
356 # You might consider using GRML_LIVE_SOURCES in /etc/grml/grml-live.conf*
357 # and using /etc/grml/fai/files/etc/apt instead!'
358 EOF
359    echo "$GRML_LIVE_SOURCES" >> "$SOURCES_LIST_FILE"
360 fi
361
362 if [ -n "$FAI_DEBOOTSTRAP" ] ; then
363    sed "s#^FAI_DEBOOTSTRAP=.*#FAI_DEBOOTSTRAP=\"$FAI_DEBOOTSTRAP\"#" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
364 fi
365
366 # does this suck? YES!
367 if [ -n "$SUITE" ] ; then
368
369    # /usr/share/debootstrap/scripts/unstable does not exist, instead use 'sid':
370    case $SUITE in
371       unstable) SUITE='sid' ;;
372    esac
373
374    DIST=" etch\| stable\| lenny\| squeeze\| testing\| sid\| unstable"
375    sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
376    for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" ; do
377        if [ -n "$file" ] ; then
378           sed "s/^SUITE=.*/SUITE=\"$SUITE\"/" $file | sponge $file
379           sed "s/\(^deb .\+\)\([ \t]*\)\($DIST\)\([ \t]*\)\(main \)/\1 \2$SUITE\4\5/" "$file" | sponge "$file"
380        fi
381    done
382
383    # notice: activate grml-live pool only if we are building against unstable:
384    if grep -qe unstable -qe sid "$SOURCES_LIST_FILE" ; then
385       grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" || \
386       grep grml-stable "$SOURCES_LIST_FILE" | \
387            sed 's/grml-stable/grml-live/' >> "$SOURCES_LIST_FILE"
388    else
389       grep -q 'grml-live.*main' "$SOURCES_LIST_FILE" && \
390       sed 's/.*grml-live.*/# removed grml-live repository/' "$SOURCES_LIST_FILE" | sponge "$SOURCES_LIST_FILE"
391    fi
392
393    for file in "$LIVE_CONF" "$CONFIG" "$LOCAL_CONFIG" "$NFSROOT_CONF" ; do
394        if [ -n "$file" ] ; then
395           sed "s|^FAI_DEBOOTSTRAP=\"[a-z]* |FAI_DEBOOTSTRAP=\"$SUITE |" "$file" | sponge "$file"
396        fi
397    done
398 fi
399
400 # set $ARCH
401 [ -n "$ARCH" ] || ARCH="$(dpkg --print-architecture)"
402 if grep -q -- 'FAI_DEBOOTSTRAP_OPTS.*--arch' "$NFSROOT_CONF" ; then
403    sed "s/--arch [a-z0-9]* /--arch $ARCH /" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
404 else
405    sed "s|^FAI_DEBOOTSTRAP_OPTS=\"\(.*\)|FAI_DEBOOTSTRAP_OPTS=\"--arch $ARCH \1|" "$NFSROOT_CONF" | sponge "$NFSROOT_CONF"
406 fi
407 # }}}
408
409 # CHROOT_OUTPUT - execute FAI {{{
410 if [ -n "$BUILD_DIRTY" ]; then
411   einfo "Skipping FAI" ; eend 0
412 else
413    [ -n "$CHROOT_OUTPUT" ] || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
414
415    if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
416       FAI_ACTION=softupdate
417    else
418       FAI_ACTION=dirinstall
419    fi
420
421    if [ -n "$UPDATE" -o -n "$BUILD_ONLY" ] ; then
422       if ! [ -r "$CHROOT_OUTPUT/etc/grml_version" ] ; then
423          log "Error: does not look like you have a working chroot. Updating/building not possible."
424          eerror "Error: does not look like you have a working chroot. Updating/building not possible. (Drop -u/-b option?)"
425          eend 1
426          bailout 20
427       fi
428    fi
429
430    if [ -d "$CHROOT_OUTPUT/bin" -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
431       log "$CHROOT_OUTPUT exists already, skipping stage 'fai dirinstall'"
432       ewarn "$CHROOT_OUTPUT exists already, skipping stage 'fai dirinstall'" ; eend 0
433    else
434       mkdir -p "$CHROOT_OUTPUT" || bailout 5 "Problem with creating $CHROOT_OUTPUT for FAI"
435
436       if [ -n "${MIRROR_DIRECTORY}" ] ; then
437          mkdir -p "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
438          mount --bind "${MIRROR_DIRECTORY}" "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
439       fi
440
441       log "Executed FAI command line:"
442       log "BUILD_ONLY=$BUILD_ONLY fai $VERBOSE -C $GRML_FAI_CONFIG -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
443       BUILD_ONLY="$BUILD_ONLY" fai $VERBOSE -C "$GRML_FAI_CONFIG" -c"$CLASSES" -u \
444       "$HOSTNAME" $FAI_ACTION "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
445       RC="$PIPESTATUS" # notice: bash-only
446
447       if [ "$RC" != 0 ] ; then
448          log "Error while executing fai [exit code ${RC}]. Exiting."
449          eerror "Error while executing fai [exit code ${RC}]. Exiting." ; eend 1
450          bailout 1
451       else
452          log "Setting /etc/grml_version to $GRML_NAME $VERSION Release Codename $RELEASENAME [$ISO_DATE]"
453          echo "$GRML_NAME $VERSION Release Codename $RELEASENAME [$ISO_DATE]" > $CHROOT_OUTPUT/etc/grml_version
454          chmod 644 $CHROOT_OUTPUT/etc/grml_version
455          einfo "Rebuilding initramfs"
456          # make sure new /etc/grml_version reaches the initramfs:
457          chroot $CHROOT_OUTPUT update-initramfs -u -t
458          eend $?
459       fi
460
461       # Remove all FAI logs from chroot if class RELEASE is used:
462       if [ -f "$CHROOT_OUTPUT"/etc/grml_fai_release ] ; then
463          rm -rf "$CHROOT_OUTPUT"/var/log/fai/*
464       fi
465
466       # make sure we don't leave any mounts - FAI doesn't remove them always
467       umount $CHROOT_OUTPUT/proc 2>/dev/null || /bin/true
468       umount $CHROOT_OUTPUT/sys  2>/dev/null || /bin/true
469       umount $CHROOT_OUTPUT/dev/pts 2>/dev/null || /bin/true
470       umount $CHROOT_OUTPUT/dev 2>/dev/null || /bin/true
471
472       [ -n "$MIRROR_DIRECTORY" ] && umount "${CHROOT_OUTPUT}/${MIRROR_DIRECTORY}"
473
474       # notice: 'fai dirinstall' does not seem to exit appropriate, so:
475       ERROR=''
476       CHECKLOG=/var/log/fai/$HOSTNAME/last
477       if [ -r "$CHECKLOG/software.log" ] ; then
478          # 1 errors during executing of commands
479          grep 'dpkg: error processing' $CHECKLOG/software.log >> $LOGFILE && ERROR=1
480          grep 'E: Method http has died unexpectedly!' $CHECKLOG/software.log >> $LOGFILE && ERROR=2
481          grep 'ERROR: chroot' $CHECKLOG/software.log >> $LOGFILE && ERROR=3
482          grep 'E: Failed to fetch' $CHECKLOG/software.log >> $LOGFILE && ERROR=4
483          grep 'Unable to write mmap - msync (28 No space left on device)' $CHECKLOG/software.log >> $LOGFILE && ERROR=5
484       fi
485
486       if [ -r "$CHECKLOG/shell.log" ] ; then
487          grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=2
488       fi
489
490       if [ -n "$ERROR" ] ; then
491          log "There was an error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
492          eerror "There was an error during execution of stage 'fai dirinstall'"
493          echo "   Check out ${CHECKLOG}/ for details. [exit ${ERROR}]"
494          eend 1
495          bailout 1
496       else
497          log "Finished execution of stage 'fai dirinstall' [$(date)]"
498          einfo "Finished execution of stage 'fai dirinstall'"
499       fi
500
501    fi
502 fi # BUILD_DIRTY?
503 # }}}
504
505 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
506 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
507 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
508
509 # i386:
510 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
511    if [ -d "$BUILD_OUTPUT"/boot -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
512       log "$BUILD_OUTPUT/boot exists already, skipping stage 'boot'"
513       ewarn "$BUILD_OUTPUT/boot exists already, skipping stage 'boot'" ; eend 0
514    else
515       # booting stuff:
516       [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
517       [ -d "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}"
518
519       if [ -z "$NO_ADDONS" ] ; then
520          [ -d "$BUILD_OUTPUT"/boot/addons   ] || mkdir -p "$BUILD_OUTPUT"/boot/addons
521          cp /boot/memtest86+.bin "$BUILD_OUTPUT"/boot/addons/memtest
522       fi
523
524       # if we don't have an initrd we a) can't boot and b) there was an error
525       # during build, so check for the file:
526       INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
527       if [ -n "$INITRD" ] ; then
528          cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}"/initrd.gz
529          find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
530       else
531          log "No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
532          eerror "No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
533          bailout 10
534       fi
535
536       KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
537       if [ -n "$KERNEL_IMAGE" ] ; then
538          cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_GRML_NAME}"/linux26
539       else
540          log "No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
541          eerror "No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
542          bailout 11
543       fi
544
545       [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
546       if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
547          log "${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
548          eerror "${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
549          bailout 8
550       fi
551
552       cp ${TEMPLATE_DIRECTORY}/boot/isolinux/*  "$BUILD_OUTPUT"/boot/isolinux/
553
554       if [ -z "$NO_ADDONS" ] ; then
555          if ! [ -d /usr/share/grml-live/templates/boot/addons/bsd4grml ] ; then
556            ewarn "Boot addons not found, skipping therefor. (Consider installing package grml-live-addons)" ; eend 0
557          else
558            # copy only files so we can handle bsd4grml on its own
559            for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
560                test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
561            done
562
563            if [ -z "$NO_ADDONS_BSD4GRML" ] ; then
564               cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
565            fi
566          fi
567       fi
568
569       if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
570          cp -a ${TEMPLATE_DIRECTORY}/boot/grub  "$BUILD_OUTPUT"/boot/
571       fi
572       # make sure we have recent template files available, otherwise updating
573       # the strings like $GRML_NAME and $VERSION might be out of date
574       cp ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
575
576       if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
577          log "${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
578          eerror "${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
579          bailout 9
580       fi
581
582       [ -d "$BUILD_OUTPUT"/GRML ] || mkdir "$BUILD_OUTPUT"/GRML
583       cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/
584
585       # adjust boot splash information:
586       RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
587       RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
588       RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
589
590       sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/grml-version
591       sed -i "s/%DATE%/$ISO_DATE/"             "$BUILD_OUTPUT"/GRML/grml-version
592
593       sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/" "$BUILD_OUTPUT"/boot/isolinux/boot.msg
594       sed -i "s/%DATE%/$ISO_DATE/"             "$BUILD_OUTPUT"/boot/isolinux/boot.msg
595
596       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/isolinux/isolinux.cfg
597       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/isolinux/syslinux.cfg
598
599       sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/" "$BUILD_OUTPUT"/boot/isolinux/boot-beep.msg
600       sed -i "s/%DATE%/$ISO_DATE/"             "$BUILD_OUTPUT"/boot/isolinux/boot-beep.msg
601
602       sed -i "s/%VERSION%/$VERSION/"           "$BUILD_OUTPUT"/boot/grub/menu.lst
603       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/grub/menu.lst
604
605       sed -i "s/%VERSION%/$VERSION/"           "$BUILD_OUTPUT"/boot/grub/grub.cfg
606       sed -i "s/%GRML_NAME%/$SHORT_GRML_NAME/" "$BUILD_OUTPUT"/boot/grub/grub.cfg
607
608       # make sure the squashfs filename is set accordingly:
609       GRML_NAME_SQUASHFS="$GRML_NAME.squashfs"
610       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/isolinux.cfg
611       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/syslinux.cfg
612       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/grub/menu.lst
613
614       GRML_NAME_SQUASHFS="$(cut_string 20 "$GRML_NAME_SQUASHFS")"
615       GRML_NAME_SQUASHFS="$(extend_string_end 20 "$GRML_NAME_SQUASHFS")"
616       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/f4
617       sed -i "s/%GRML_NAME_SQUASHFS%/$GRML_NAME_SQUASHFS/" "$BUILD_OUTPUT"/boot/isolinux/f5
618
619       # autostart for Windows:
620       if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
621          cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
622       fi
623
624       # windows-binaries:
625       if [ -n "$WINDOWS_BINARIES" ] ; then
626          if [ -f "$BUILD_OUTPUT"/windows/putty.exe ] ; then
627             log "$BUILD_OUTPUT/windows exists already, skipping stage 'WINDOWS_BINARIES'"
628             ewarn "$BUILD_OUTPUT/windows exists already, skipping stage 'WINDOWS_BINARIES'" ; eend 0
629          else
630             if ! [ -d "$BUILD_OUTPUT"/windows ] ; then
631                mkdir "$BUILD_OUTPUT"/windows
632                ( cd "$BUILD_OUTPUT"/windows
633                  for file in pageant plink pscp psftp putty puttygen ; do
634                     wget -O ${file}.exe ${WINDOWS_BINARIES}/${file}.exe
635                     md5sum ${file}.exe > ${file}.exe.md5
636                  done )
637             fi
638          fi
639       log "Finished execution of stage 'WINDOWS_BINARIES' [$(date)]"
640       einfo "Finished execution of stage 'WINDOWS_BINARIES'" ; eend 0
641       fi
642    einfo "Finished execution of stage 'boot'" ; eend 0
643    fi
644 # ppc:
645 elif [ "$ARCH" = powerpc ] ; then
646     ewarn 'Warning: formorer, it is your turn. :)'>&2
647 # unsuported:
648 else
649    eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
650 fi
651
652 if [ -f "$BUILD_OUTPUT"/live/${GRML_NAME}.squashfs -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
653    log "$BUILD_OUTPUT/live exists already, skipping stage 'squashfs'"
654    ewarn "$BUILD_OUTPUT/live exists already, skipping stage 'squashfs'" ; eend 0
655 elif [ -n "$SKIP_MKSQUASHFS" ] ; then
656    log "Skipping stage 'squashfs' as requested via option -q"
657    ewarn "Skipping stage 'squashfs' as requested via option -q" ; eend 0
658 else
659    [ -d "$BUILD_OUTPUT"/live ] || mkdir "$BUILD_OUTPUT"/live
660    # make sure we don't leave (even an empty) base.tgz:
661    [ -f "$CHROOT_OUTPUT/base.tgz" ] && rm -f "$CHROOT_OUTPUT/base.tgz"
662
663    # make sure mksquashfs can handle the according option:
664    if [ -n "$SQUASHFS_ZLIB" ] ; then
665       mksquashfs --help 2>&1 | grep -q -- "$SQUASHFS_ZLIB" || SQUASHFS_ZLIB=''
666    fi
667
668    if echo "$SQUASHFS_OPTIONS" | grep -q -- "-nolzma" ; then
669       if ! mksquashfs --help 2>&1 | grep -q -- '-nolzma' ; then
670          ewarn "mksquashfs does NOT support the nolzma option, just using default zlib mode."
671          SQUASHFS_OPTIONS="$(echo $SQUASHFS_OPTIONS | sed 's/-nolzma//g')"
672          eend 0
673       fi
674    fi
675
676    if echo "$SQUASHFS_OPTIONS" | grep -q -- "-lzma" ; then
677       if ! mksquashfs --help 2>&1 | grep -q -- '-lzma' ; then
678          ewarn "mksquashfs does NOT support the lzma option, falling back to zlib mode."
679          SQUASHFS_OPTIONS="$(echo $SQUASHFS_OPTIONS | sed 's/-lzma//g')"
680          eend 0
681       fi
682    fi
683
684    # support exclusion of files via exclude-file:
685    if [ -n "$SQUASHFS_EXCLUDES_FILE" -a "$SQUASHFS_EXCLUDES_FILE" ] ; then
686       SQUASHFS_OPTIONS="$SQUASHFS_OPTIONS -ef $SQUASHFS_EXCLUDES_FILE"
687    fi
688
689    # get rid of unnecessary files when building grml-small for final release:
690    if echo "$CLASSES" | grep -q GRML_SMALL ; then
691       SQUASHFS_OPTIONS="$SQUASHFS_OUTPUT -e initrd.img* vmlinuz*"
692    fi
693
694    SQUASHFS_OUTPUT="$(mktemp -t grml-live.XXXXXX)"
695    log "mksquashfs $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/${GRML_NAME}.squashfs -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB"
696    if mksquashfs $CHROOT_OUTPUT/* $BUILD_OUTPUT/live/"${GRML_NAME}".squashfs \
697       -noappend $SQUASHFS_OPTIONS $SQUASHFS_ZLIB 2>"${SQUASHFS_OUTPUT}" ; then
698       echo "${GRML_NAME}.squashfs" > $BUILD_OUTPUT/live/filesystem.module
699       log "Finished execution of stage 'squashfs' [$(date)]"
700       einfo "Finished execution of stage 'squashfs'" ; eend 0
701       rm -f "${SQUASHFS_OUTPUT}"
702    else
703       log "There was an error executing stage 'squashfs' [$(date)]:"
704       log "$(cat $SQUASHFS_OUTPUT)"
705       eerror "There was an error executing stage 'squashfs':" ; eend 1
706       cat "${SQUASHFS_OUTPUT}"
707       rm -f "${SQUASHFS_OUTPUT}"
708       bailout
709    fi
710 fi
711
712 # create md5sum file:
713 ( cd $BUILD_OUTPUT/GRML &&
714 find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
715 # }}}
716
717 # ISO_OUTPUT - mkisofs {{{
718 [ -n "$ISO_OUTPUT" ] || ISO_OUTPUT="$OUTPUT/grml_isos"
719 [ -n "$ISO_NAME" ] || ISO_NAME="${GRML_NAME}_${VERSION}.iso"
720
721 if [ "$BOOT_METHOD" = "isolinux" ] ; then
722    BOOT_FILE="boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
723 elif [ "$BOOT_METHOD" = "grub" ] ; then
724    BOOT_FILE="boot/grub/stage2_eltorito"
725 fi
726
727 if [ -f "${ISO_OUTPUT}/${ISO_NAME}" -a -z "$UPDATE" -a -z "$BUILD_ONLY" -a -z "$BUILD_DIRTY" ] ; then
728    log "$ISO_OUTPUT exists already, skipping stage 'iso build'"
729    ewarn "$ISO_OUTPUT exists already, skipping stage 'iso build'" ; eend 0
730 else
731    mkdir -p "$ISO_OUTPUT" || bailout 6 "Problem with creating $ISO_OUTPUT for stage 'iso build'"
732
733    CURRENT_DIR=$(pwd)
734    if cd "$BUILD_OUTPUT" ; then
735       log "mkisofs -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J -no-emul-boot -boot-load-size 4 -boot-info-table -b $BOOT_FILE -o ${ISO_OUTPUT}/${ISO_NAME} ."
736       mkisofs -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
737               -l -r -J -no-emul-boot -boot-load-size 4 -boot-info-table    \
738               -b $BOOT_FILE \
739               -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
740
741       # support disabling hybrid ISO image
742       if [ "$HYBRID_METHOD" = "disable" ] ; then\
743          log "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
744          einfo "Skipping creation of hybrid ISO file as requested via HYBRID_METHOD=disable"
745          eend 0
746       # use isohybrid only on request
747       elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
748          if ! which isohybrid >/dev/null 2>&1 ; then
749            bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
750          else
751            log "Creating hybrid ISO file with isohybrid method"
752            einfo "Creating hybrid ISO file with isohybrid method"
753            isohybrid "${ISO_OUTPUT}/${ISO_NAME}"
754            eend $?
755          fi
756       # by default use our manifold boot method:
757       else
758          if ! [ -r boot/grub/core.img ] ; then
759            ewarn "boot/grub/core.img not found, not creating manifold boot ISO file"
760          else
761            log "Creating hybrid ISO file with manifold method"
762            einfo "Creating hybrid ISO file with manifold method"
763            echo 1 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh | cat - boot/grub/core.img | dd conv=notrunc of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc
764            eend $?
765          fi
766       fi
767
768       # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
769       case $CLASSES in *RELEASE*)
770          [ "$RC" = 0 ] && \
771          (
772            if cd $ISO_OUTPUT ; then
773              md5sum ${ISO_NAME} > ${ISO_NAME}.md5 && \
774              touch -r ${ISO_NAME} ${ISO_NAME}.md5
775              sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
776              touch -r ${ISO_NAME} ${ISO_NAME}.sha1
777            fi
778          )
779          ;;
780       esac
781
782       cd $CURRENT_DIR
783    fi
784
785    if [ "$RC" = 0 ] ; then
786       log "Finished execution of stage 'iso build' [$(date)]"
787       einfo "Finished execution of stage 'iso build'" ; eend 0
788    else
789       log "There was an error ($RC) executing stage 'iso build' [$(date)]"
790       eerror "There was an error executing stage 'iso build'" ; eend 1
791       bailout $RC
792    fi
793 fi
794 # }}}
795
796 # finalize {{{
797 [ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
798 einfo "Sucessfully finished execution of $PN [running ${SECONDS} seconds]" ; eend 0
799 log "Sucessfully finished execution of $PN [running ${SECONDS} seconds]"
800 bailout 0
801 # }}}
802
803 ## END OF FILE #################################################################
804 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3