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