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