Drop oudated tarball-online make target and support prepare-release instead
[grml2usb.git] / grml2iso
1 #!/usr/bin/env bash
2 # Filename:      grml2iso
3 # Purpose:       create a multiboot grml ISO using grml2usb
4 # Authors:       Michael Prokop <mika@grml.org>,
5 #                Thorsten Glaser <tg@mirbsd.org>
6 # Bug-Reports:   see http://grml.org/bugs/
7 # License:       This file is licensed under the GPL v2 or any later version.
8 ################################################################################
9
10 # define function getfilesize before "set -e" {{{
11   if stat --help >/dev/null 2>&1; then
12     getfilesize='stat -c %s'        # GNU stat
13   else
14     getfilesize='stat -f %z'        # BSD stat
15   fi
16 # }}}
17
18 # adjust variables if necessary through environment {{{
19 # path to the grml2usb script you'd like to use
20   [ -n "$GRML2USB" ] || GRML2USB='grml2usb'
21 # work directory for creating the filesystem
22   [ -n "$WRKDIR" ]   || WRKDIR='/tmp/grml2iso.tmp'
23 # support mkisofs as well as genisoimage
24 if which xorriso >/dev/null 2>&1 ; then
25   MKISOFS='xorriso -as mkisofs'
26 elif which mkisofs >/dev/null 2>&1; then
27   MKISOFS='mkisofs'
28 elif which genisoimage >/dev/null 2>&1; then
29   MKISOFS='genisoimage'
30 else
31   echo >&2 "Error: neither mkisofs nor genisoimage available - can not create ISO."
32   exit 1
33 fi
34 # }}}
35
36 # helper stuff {{{
37   set -e
38
39   usage() {
40     echo >&2 "Usage: $0 [OPTIONS] -o target.iso source1.iso [source2.iso ...]"
41     echo >&2 "
42 Options:
43      -b Boot Params      Additional boot parameters passed to grml2usb
44      -c Directory        Copy files from directory to generated ISO
45      -f                  Force overwrite of existing target.iso
46      -r BootParam        Remove specified boot params.
47                          Could be specfied multiple times.
48      -p <grml2usb param> Add the specified parameter to the grml2usb
49                          commandline. For a list of valid parameters have
50                          a look at the grml2usb manpage.
51                          Can be specified multiple times.
52      -s URI              Generate a small ISO file which downloads the squashfs
53                          file from the specified URI. Please note that due to
54                          restrictions in the bootprocess only IPs are allowed.
55                          Supported protocols are: http and ftp
56
57      Examples:
58      $0 -s http://192.168.23.42:8000/grml/ -o small.iso grml64_2010.12.iso
59
60      Will generate a file small.iso which tries to download the squashfs file from
61      http://192.168.23.42:8000/grml/ - the squashfs file is placed in the same
62      output directory as the ISO file.
63 "
64     [ -n "$1" ] && exit $1 || exit 1
65   }
66 # }}}
67
68 # command line handling {{{
69   [[ $# -gt 2 ]] || usage 1
70
71   ISOFILE=''
72   DIR=''
73   ADD_OPTS=''
74   FORCE=''
75   URI=''
76   typeset -a GRML2USB_OPTS
77   while getopts fb:c:o:r:p:s: name; do
78     case $name in
79       o)   ISOFILE="$OPTARG";;
80       b)   GRML2USB_OPTS+=(--bootoptions="$OPTARG");;
81       c)   DIR="$(readlink -f "$OPTARG")";;
82       f)   FORCE='true';;
83       r)   GRML2USB_OPTS+=(--remove-bootoption="$OPTARG");;
84       p)   GRML2USB_OPTS+=("$OPTARG");;
85       s)   URI="$OPTARG";;
86       ?)   usage 2;;
87     esac
88   done
89   # test for specified URI
90   if [ -n "$URI" ] ; then
91     GRML2USB_OPTS+=(--bootoptions="fetch=$URI")
92   fi
93
94 # make sure -o is specified
95   [ -n "$ISOFILE" ] || usage 1
96
97 # we don't to override any files by accident
98   if [ -e "$ISOFILE" -a ! -n "$FORCE" ]; then
99     echo "Error: target file $ISOFILE exists already." >&2
100     exit 1
101   fi
102
103   if [ ! -z "$DIR" -a ! -d "$DIR" ] ; then
104      echo "Error: specified parameter for -c is not a directory" >&2
105      exit 1
106   fi
107 # }}}
108
109 # we need root permissions for executing grml2usb {{{
110   if [[ $(id -u) != 0 ]]; then
111     echo >&2 "Error: please run $0 as root."
112     exit 1
113   fi
114 # }}}
115
116 # check for grml2usb {{{
117   if [ ! -x "$(which $GRML2USB)" ] && [ ! -x "$GRML2USB" ] ; then
118     echo >&2 "Error: Could not find grml2usb"
119     if [ -x "./$GRML2USB" ] ; then
120       echo >&2 "If you executed grml2iso from the grml2usb repository use"
121       echo >&2 "GRML2USB=./grml2usb $0 $*"
122     fi
123     exit 1
124   fi
125 # }}}
126
127 # variables {{{
128   ORIG_DIR="$(pwd)"
129
130 # normalise path
131   case $ISOFILE in
132     /*) ;;
133     *) ISOFILE=$ORIG_DIR/$ISOFILE ;;
134   esac
135 # }}}
136
137 # create necessary stuff under WRKDIR {{{
138   [ -d "$WRKDIR" ] && WRKDIR_EXISTED='true' || WRKDIR_EXISTED='false'
139   rm -rf "$WRKDIR/cddir" "$WRKDIR/grub_tmp"
140   mkdir -p "$WRKDIR/cddir"
141 # }}}}
142
143 # execute grml2usb with all ISOs you'd like to install {{{
144   # remove all parameters
145   shift $(($OPTIND - 1))
146
147   $GRML2USB "${GRML2USB_OPTS[@]}" "$@" "$WRKDIR/cddir"
148 # }}}
149
150 # move syslinux to isolinux {{{
151   mv "$WRKDIR"/cddir/boot/syslinux "$WRKDIR"/cddir/boot/isolinux
152
153   cd "$WRKDIR/cddir"
154   echo "menu label ^Isolinux prompt" > boot/isolinux/promptname.cfg
155   echo "include hd.cfg" >> boot/isolinux/grmlmain.cfg
156 # }}}
157
158 # efi boot {{{
159   # default, independent of UEFI support
160   BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
161
162   case "$MKISOFS" in
163     xorriso*)
164       echo "Using xorriso for ISO generation."
165       if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
166         echo "Disabling (U)EFI boot support since xorriso version is not recent enough."
167       else
168         echo "xorriso with -eltorito-alt-boot support present"
169
170         if ! [ -r "${WRKDIR}/cddir/boot/efi.img" ] ; then
171           echo "File /boot/efi.img not found, not extending boot arguments for (U)EFI boot."
172         else
173           echo "/boot/efi.img found, extending boot arguments for (U)EFI boot."
174           BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
175         fi
176       fi
177       ;;
178   esac
179 # }}}
180
181 # adjust ISO for small output if necessary {{{
182   if [ -n "$URI" ] ; then
183      bootloader_files=$(find . -name "*.cfg" -type f)
184      bootloader_files+=" "
185      bootloader_files+=$(find . -name "*.lst" -type f)
186      output_dir=$(dirname "$ISOFILE")
187      for squashfs in $(find . -name *.squashfs) ; do
188         media_path="$(dirname "$squashfs")"
189         filename="$(basename "$squashfs")"
190         target="$output_dir/$filename"
191         if [ -f "$target" ] && [ ! -n "$FORCE" ] ; then
192            echo >&2 "Warning: $target already exists, and -force not specified, not overwriting"
193         else
194            mv $squashfs $target
195            OUTPUT_FILES+=("$target")
196         fi
197         sed -i -e "s#^\(^.*$media_path.*\)\($URI\)\(.*$\)#\1$URI/$filename\3#g" $bootloader_files
198
199    done
200   fi
201 # }}}
202
203 # copy specified directory to cd {{{
204   if [ -n "$DIR" ] ; then
205      echo >&2 "Copying ${DIR} to generated ISO"
206      for param in GRML_NAME VERSION RELEASENAME DATE SHORT_NAME \
207          VERSION BOOTID RELEASE_INFO ; do
208        EXCLUDE_PARAM="$EXCLUDE_PARAM --exclude **%${param}%**"
209      done
210      rsync -a ${DIR}/ $EXCLUDE_PARAM .
211   fi
212
213   # adjust files from overlay directory
214   for GRML_VERSION_FILE in $(find . -name grml-version) ; do
215     GRML_NAME=$(awk '{print $1}' "$GRML_VERSION_FILE")
216     VERSION=$(awk '{print $2}' "$GRML_VERSION_FILE")
217     RELEASENAME=$(sed 's/.*- \(.*\).*\[.*/\1/' "$GRML_VERSION_FILE")
218     DATE=$(sed 's/.*\[\(.*\)].*/\1/' "$GRML_VERSION_FILE")
219     SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
220     RELEASE_INFO="$GRML_NAME $VERSION - $RELEASENAME"
221     BOOTID=$(cat conf/bootid.txt)
222
223     for param in GRML_NAME VERSION RELEASENAME DATE SHORT_NAME \
224         RELEASE_INFO BOOTID  ; do
225       value="$(eval echo '$'"$param")"
226
227       # copy parameterized files from the overlay directory
228       for file in $(find ${DIR} -name "*%$param%*") ; do
229         file=${file##$DIR/}
230         target_dir="$(dirname ${file})"
231         mkdir -p "$target_dir" || true
232         cp -r ${DIR}/${file} ./${target_dir}/"$(basename ${file/\%${param}\%/$value})"
233       done
234
235       # adjust config files
236       for file in ./boot/isolinux/*.cfg ./boot/isolinux/*.msg \
237         ./boot/grub/*.cfg ; do
238         sed -i "s/%$param%/$value/g" ${file} 2>/dev/null || true
239       done
240     done
241   done
242 # }}}
243
244 # generate the CD/DVD ISO {{{
245   $MKISOFS -V 'grml-multiboot' -l -r -J -no-pad $BOOT_ARGS \
246     -o "$ISOFILE" .
247 # }}}
248
249 # pad the output ISO to multiples of 256 KiB for partition table support {{{
250   siz=$($getfilesize "$ISOFILE")
251   cyls=$(($siz / 512 / 32 / 16 + 1))  # C=$cyls H=16 S=32
252   ofs=$(($cyls * 16 * 32 * 512 - 1))  # padding offset (size - 1)
253   dd if=/dev/zero bs=1 count=1 seek=$ofs of="$ISOFILE" 2>/dev/null
254 # }}}
255
256 # cleanup {{{
257   cd "$ORIG_DIR"
258   sync
259   rm -rf "$WRKDIR/cddir" "$WRKDIR/grub_tmp"
260   [[ $WRKDIR_EXISTED = 'false' ]] && rmdir "$WRKDIR"
261   echo "Generated $ISOFILE"
262   if [ -n "$URI" ] ; then
263      echo "
264 Information:
265 ==============
266 You requested to generate a small ISO image. Your generated
267 ISO image $ISOFILE does _not_ contain the squashfs files from
268 the source ISO images.
269
270 You have to provide the extracted squashfs files under $URI.
271
272 ISO image: $ISOFILE
273 Squashfs files: ${OUTPUT_FILES[@]}
274 URI: $URI
275 "
276   fi
277 # }}}
278
279 ## EOF #########################################################################
280 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3