379ef68cc4c66e3eb10de9ae6de2ceffced8b4f0
[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 mkisofs >/dev/null 2>&1; then
25     MKISOFS='mkisofs'
26   elif which genisoimage >/dev/null 2>&1; then
27     MKISOFS='genisoimage'
28   else
29     echo >&2 "Error: neither mkisofs nor genisoimage available - can not create ISO."
30     exit 1
31 fi
32 # }}}
33
34 # helper stuff {{{
35   set -e
36
37   usage() {
38     echo >&2 "Usage: $0 [OPTIONS] -o target.iso source1.iso [source2.iso ...]"
39     echo >&2 "
40 Options:
41      -b Boot Params      Additional boot parameters passed to grml2usb
42      -c Directory        Copy files from directory to generated iso
43      -f                  Force overwrite of existing target.iso
44      -r BootParam        Remove specified boot params.
45                          Could be specfied multiple times.
46      -p <grml2usb param> Add the specified parameter to the grml2usb
47                          commandline. For a list of valid parameters have
48                          a look at the grml2usb manpage.
49                          Could be specfied multiple times.
50      -s URI              Generate a small iso file which downloads the squashfs
51                          file from the specified URI. Please note that due to
52                          restrictions in the bootprocess only IPs are allowed.
53                          Supported protocols are: http and ftp
54
55      Examples:
56      $0 -s http://192.168.23.42:8000/grml/ -o small.iso grml64_2010.12.iso
57
58      Will generate a file small.iso which tries to download the squashfs file from
59      http://192.168.23.42:8000/grml/ The squashfs file is located in the output
60      directory as the iso file.
61 "
62     [ -n "$1" ] && exit $1 || exit 1
63   }
64 # }}}
65
66 # command line handling {{{
67   [[ $# -gt 2 ]] || usage 1
68
69   ISOFILE=''
70   DIR=''
71   ADD_OPTS=''
72   FORCE=''
73   URI=''
74   typeset -a GRML2USB_OPTS
75   while getopts fb:c:o:r:p:s: name; do
76     case $name in
77       o)   ISOFILE="$OPTARG";;
78       b)   GRML2USB_OPTS+=(--bootoptions="$OPTARG");;
79       c)   DIR="$OPTARG";;
80       f)   FORCE='true';;
81       r)   GRML2USB_OPTS+=(--remove-bootoption="$OPTARG");;
82       p)   GRML2USB_OPTS+=("$OPTARG");;
83       s)   URI="$OPTARG";;
84       ?)   usage 2;;
85     esac
86   done
87   # test for specified URI
88   if [ -n "$URI" ] ; then
89     GRML2USB_OPTS+=(--bootoptions="fetch=$URI")
90   fi
91
92 # make sure -o is specified
93   [ -n "$ISOFILE" ] || usage 1
94
95 # we don't to override any files by accident
96   if [ -e "$ISOFILE" -a ! -n "$FORCE" ]; then
97     echo "Error: target file $ISOFILE exists already." >&2
98     exit 1
99   fi
100
101   if [ ! -z "$DIR" -a ! -d "$DIR" ] ; then
102      echo "Error: specified parameter for -c is not a directory" >&2
103      exit 1
104   fi
105 # }}}
106
107 # we need root permissions for executing grml2usb {{{
108   if [[ $(id -u) != 0 ]]; then
109     echo >&2 "Error: please run $0 as root."
110     exit 1
111   fi
112 # }}}
113
114 # check for grml2usb {{{
115   if [ ! -x "$(which $GRML2USB)" ] || [ ! -x "$GRML2USB" ] ; then
116     echo >&2 "Error: Could not find grml2usb"
117     if [ -x "./$GRML2USB" ] ; then
118       echo >&2 "If you executed grml2iso from the grml2usb repository use"
119       echo >&2 "GRML2USB=./grml2usb $0 $*"
120     fi
121     exit 1
122   fi
123 # }}}
124
125 # variables {{{
126   ORIG_DIR="$(pwd)"
127   # note: grub-pc_1.96+20090603-1 seems to be b0rken
128   GRUB_VERSION="grub-pc_1.96+20080724-16"
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
151 # move syslinux to isolinux {{{
152   mv "$WRKDIR"/cddir/boot/syslinux "$WRKDIR"/cddir/boot/isolinux
153
154   cd "$WRKDIR/cddir"
155   echo "menu label ^Isolinux prompt" > boot/isolinux/promptname.cfg
156   echo "include hd.cfg" >> boot/isolinux/grmlmain.cfg
157 # }}}
158
159 # adjust iso for small output if necessary [{{
160   if [ -n "$URI" ] ; then
161      bootloader_files=$(find . -name "*.cfg" -type f)
162      bootloader_files+=" "
163      bootloader_files+=$(find . -name "*.lst" -type f)
164      output_dir=$(dirname "$ISOFILE")
165      for squashfs in $(find . -name *.squashfs) ; do
166         media_path="$(dirname "$squashfs")"
167         filename="$(basename "$squashfs")"
168         target="$output_dir/$filename"
169         if [ -f "$target" ] && [ ! -n "$FORCE" ] ; then
170            echo >&2 "Warning: $target already exists, and -force not specified, not overwriting"
171         else
172            mv $squashfs $target
173            OUTPUT_FILES+=("$target")
174         fi
175         sed -i -e "s#^\(^.*$media_path.*\)\($URI\)\(.*$\)#\1$URI/$filename\3#g" $bootloader_files
176
177    done
178   fi
179 # }}}
180
181 # copy specified directory to cd {{{
182   if [ -n "$DIR" ] ; then
183      echo >&2 "Copying ${DIR} to generated iso"
184      rsync -a ${DIR}/ .
185   fi
186
187 # }}}
188
189 # generate the CD/DVD ISO {{{
190   $MKISOFS -V 'grml-multiboot' -l -r -J -no-pad \
191     -no-emul-boot -boot-load-size 4 -boot-info-table \
192     -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
193     -o "$ISOFILE" .
194 # }}}
195
196 # pad the output ISO to multiples of 256 KiB for partition table support {{{
197   siz=$($getfilesize "$ISOFILE")
198   cyls=$(echo "$siz / 512 / 32 / 16 + 1" | bc)  # C=$cyls H=16 S=32
199   ofs=$(echo "$cyls * 16 * 32 * 512 - 1" | bc)  # padding offset (size - 1)
200   dd if=/dev/zero bs=1 count=1 seek=$ofs of="$ISOFILE" 2>/dev/null
201 # }}}
202
203
204 # cleanup {{{
205   cd "$ORIG_DIR"
206   sync
207   rm -rf "$WRKDIR/cddir" "$WRKDIR/grub_tmp"
208   [[ $WRKDIR_EXISTED = 'false' ]] && rmdir "$WRKDIR"
209   echo "Generated $ISOFILE"
210   if [ -n "$URI" ] ; then
211      echo "
212 Information:
213 ==============
214 You requested to generate a small iso image. Your generated
215 iso image $ISOFILE does _not_ contain the squashfs files from
216 the source iso images.
217
218 You have to provide the extracted squashfs files under $URI.
219
220 ISO image: $ISOFILE
221 Squashfs files: ${OUTPUT_FILES[@]}
222 URI: $URI
223 "
224   fi
225 # }}}
226
227 ## EOF #########################################################################
228 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3