Canonicalize overlay directory
[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      rsync -a ${DIR}/ .
207   fi
208
209 # }}}
210
211 # generate the CD/DVD ISO {{{
212   $MKISOFS -V 'grml-multiboot' -l -r -J -no-pad $BOOT_ARGS \
213     -o "$ISOFILE" .
214 # }}}
215
216 # pad the output ISO to multiples of 256 KiB for partition table support {{{
217   siz=$($getfilesize "$ISOFILE")
218   cyls=$(echo "$siz / 512 / 32 / 16 + 1" | bc)  # C=$cyls H=16 S=32
219   ofs=$(echo "$cyls * 16 * 32 * 512 - 1" | bc)  # padding offset (size - 1)
220   dd if=/dev/zero bs=1 count=1 seek=$ofs of="$ISOFILE" 2>/dev/null
221 # }}}
222
223 # cleanup {{{
224   cd "$ORIG_DIR"
225   sync
226   rm -rf "$WRKDIR/cddir" "$WRKDIR/grub_tmp"
227   [[ $WRKDIR_EXISTED = 'false' ]] && rmdir "$WRKDIR"
228   echo "Generated $ISOFILE"
229   if [ -n "$URI" ] ; then
230      echo "
231 Information:
232 ==============
233 You requested to generate a small ISO image. Your generated
234 ISO image $ISOFILE does _not_ contain the squashfs files from
235 the source ISO images.
236
237 You have to provide the extracted squashfs files under $URI.
238
239 ISO image: $ISOFILE
240 Squashfs files: ${OUTPUT_FILES[@]}
241 URI: $URI
242 "
243   fi
244 # }}}
245
246 ## EOF #########################################################################
247 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=3