Some minor cleanups in Debian packaging
[grml2usb.git] / grml2usb
1 #!/bin/sh
2 # Filename:      grml2usb
3 # Purpose:       install grml-system to usb-device
4 # Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
5 # Bug-Reports:   see http://grml.org/bugs/
6 # License:       This file is licensed under the GPL v2.
7 # Latest change: Sun May 25 01:29:21 CEST 2008 [mika]
8 ################################################################################
9
10 # colors {{{
11   CRE="\r\e[K"
12   NORMAL="\e[0;39m"
13   RED="\e[1;31m"
14   GREEN="\e[1;32m"
15   YELLOW="\e[1;33m"
16   BLUE="\e[1;34m"
17   MAGENTA="\e[1;35m"
18   CYAN="\e[1;36m"
19   WHITE="\e[1;37m"
20 # }}}
21
22 # usercheck {{{
23   if ! [ -x "$(which syslinux)" ] ; then
24     echo "${RED}Error: syslinux is not available. Please install it before running this script.${NORMAL}" >&2; exit 2
25   fi
26
27   if [ "$(id -u)" != 0 ];  then
28     echo "${RED}Error: please run this script with uid 0 (root).${NORMAL}" >&2 ; exit 1
29   fi
30 # }}}
31
32 # set variables  {{{
33   if [ -n "$DEBUG" ]; then
34     # set -x
35     debugit(){
36       echo $*
37     }
38   else
39     debugit(){
40       echo >/dev/null
41     }
42   fi
43
44   if [ "$1" = "uninstall" ] ; then
45      UNINSTALL=1
46   fi
47
48   LANG='C'
49   LANGUAGE='C'
50   LC_ALL='C'
51   PROGRAMNAME=${0##*/}
52   VERSION='0.9.0'
53   ISO="$1"
54   DEVICE="$2"
55
56   [ -n "$TMPMNT" ] || TMPMNT='/mnt/test/'
57   [ -d "$TMPMNT" ] || mkdir -p $TMPMNT
58 # }}}
59
60 # helper functions {{{
61 bailout(){
62   echo
63   echo "Exiting - umounting /mnt/test and $DEVICE"
64   umount $TMPMNT 2>/dev/null
65   umount $DEVICE 2>/dev/null
66   exit 2
67 }
68
69 usage()
70 {
71   echo 1>&2 "$PROGRAMNAME $VERSION - install grml-system to usb-device
72
73 This program installs a grml-iso to an usb-device to be able to boot
74 from usb. Make sure you have a grml-iso, syslinux (just run
75 'apt-get install syslinux' on Debian-based systems) and root access.
76
77 Usage:
78   $PROGRAMNAME grml.iso /mount/point
79
80   Notice: /mount/point is the mountpoint set up for your USB device in /etc/fstab
81           /mount/point should not be mounted at the time running $PROGRAMNAME
82
83 Usage example - install grml-small to usb-device on /mnt/usb-sdb1:
84   $PROGRAMNAME grml_1.1.iso /mnt/usb-sdb1
85
86 Usage example - install currently running grml to usb-device on /mnt/usb-sdb1:
87   $PROGRAMNAME /live/image /mnt/usb-sdb1
88
89 Usage example - delete grml-installation from /mnt/usb-sdb1:
90   $PROGRAMNAME uninstall /mnt/usb-sdb1
91
92 For more information take a look at http://wiki.grml.org/doku.php?id=usb
93 Report bugs, send wishes and feedback to the grml team:
94 http://grml.org/bugs/ - contact (at) grml.org
95 "
96 }
97
98 notice(){
99   echo "
100 Installing grml to $DEVICE should have been successful!
101
102 Please take a look at http://wiki.grml.org/doku.php?id=usb
103 for more information or if you have problems with booting from usb."
104 }
105
106 info(){
107   echo "$PROGRAMNAME ${VERSION} - install grml-system to usb-device"
108   echo
109 }
110
111 vfat_warning(){
112   DEV=$(echo ${DEVICE%/})
113   TMPDEV=$(grep "[[:space:]]${DEV}[[:space:]]" /etc/fstab | grep -vh '^[[:space:]]*#' | awk '{print $1}')
114   SYSDEV=$(echo ${TMPDEV%/})
115   if [ -x /lib/udev/vol_id ] ; then
116      /lib/udev/vol_id $SYSDEV | grep -q 'FS_TYPE=vfat' || VFAT=1
117      /lib/udev/vol_id $SYSDEV | grep -q 'ID_FS_VERSION=FAT16' || VFAT=1
118   else
119      VFAT=1
120   fi
121   if [ -n "$VFAT" ] ; then
122      echo 'WARNING: make sure that your usb-device is preformated with vfat.'
123      echo "Format your device (erases all data) via:  mkfs.vfat -F 16 -v $SYSDEV"
124      echo
125   fi
126 }
127
128 mount_device(){
129   if grep -q ${DEVICE} /proc/mounts ; then
130     echo "Notice: ${WHITE}${DEVICE} already mounted - continuing anyway${NORMAL}" >&2
131   else
132     echo -n "Mounting ${DEVICE}: "
133     debugit "debug: mount $DEVICE"
134     mount $DEVICE && echo "${WHITE}done${NORMAL}" || bailout
135   fi
136 }
137
138 mount_iso(){
139   echo -n "Mounting ${ISO} to ${TMPMNT}: "
140   local mount_opts_="-o loop"
141   if [ -d $ISO ]; then
142       mount_opts_="--bind"
143   elif [ -b $ISO ]; then
144       mount_opts_=""
145   fi
146   debugit "debug: mount $mount_opts_ ${ISO} ${TMPMNT}"
147   if mount $mount_opts_ "${ISO}" ${TMPMNT} ; then
148      echo "${WHITE}done${NORMAL}"
149   else
150      echo "${RED}Problem? You got an error saying 'mount: could not find any free loop device'?
151 Possible solution: losetup -d /dev/loop/0${NORMAL}" >&2
152     exit 3
153   fi
154 }
155
156 unmount(){
157   echo -n "Unmounting ${DEVICE} and ${TMPMNT}: "
158   umount ${TMPMNT}
159   umount ${DEVICE} && echo "done" || echo "failed"
160 }
161
162 copyit(){
163   echo -n "Installing data from ${ISO} to ${DEVICE} (will take some time): "
164   debugit "debug: cp -dR --preserve=mode,timestamps ${TMPMNT}/* ${DEVICE}"
165   debugit "debug: mv ${DEVICE}/boot/isolinux/* ${DEVICE}/"
166
167   if cp -dR --preserve=mode,timestamps ${TMPMNT}/* ${DEVICE} ; then
168     echo "# filelist of $PROGRAMNAME on $(date) using $ISO on ${DEVICE}:" > $DEVICE/grml2usb.filelist
169
170     find  ${TMPMNT} -type f | sed "s#${TMPMNT}##" | \
171           sed "s#boot/## ; s#isolinux/## ; s#.*initrd.gz#initrd.gz# ; s#.*linux26#linux26#" | \
172           tr A-Z a-z >> $DEVICE/grml2usb.filelist
173
174     # make sure we have a valid syslinux.cfg, if not use isolinux.cfg as base
175     if ! [ -f "${DEVICE}"/boot/isolinux/syslinux.cfg ] ; then
176        cp ${DEVICE}/boot/isolinux/isolinux.cfg ${DEVICE}/boot/isolinux/syslinux.cfg && \
177        echo 'syslinux.cfg' >> $DEVICE/grml2usb.filelist
178     fi
179
180     if mv ${DEVICE}/boot/isolinux/* ${DEVICE}/ ; then
181        rmdir ${DEVICE}/boot/isolinux
182     fi
183     echo boot >> $DEVICE/grml2usb.filelist
184
185     # syslinux creates a file named ldlinux.sys:
186     echo "ldlinux.sys" >> ${DEVICE}/grml2usb.filelist
187
188     if ! [ -r ${DEVICE}/live/filesystem.module ] ; then
189        GRML_NAME=grml
190     else
191        GRML_NAME=$(cat ${DEVICE}/live/filesystem.module)
192        GRML_NAME=${GRML_NAME%%.squashfs}
193        GRML_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
194     fi
195
196     KERNEL=$(find ${TMPMNT}/boot/ -maxdepth 2 -name linux26)
197     INITRD=$(find ${TMPMNT}/boot/ -maxdepth 2 -name initrd.gz)
198
199     case $KERNEL in
200       */boot/${GRML_NAME}/linux26*)   mv ${DEVICE}/boot/${GRML_NAME}/linux26 ${DEVICE}/
201       ;;
202     esac
203
204     case $INITRD in
205       */boot/${GRML_NAME}/initrd.gz*) mv ${DEVICE}/boot/${GRML_NAME}/initrd.gz ${DEVICE}/
206       ;;
207     esac
208
209     if [ -d "${DEVICE}"/boot/addons ] ; then
210        [ -d "${DEVICE}/addons" ] || mkdir ${DEVICE}/addons
211        mv ${DEVICE}/boot/addons/* ${DEVICE}/addons/
212     fi
213
214     if [ -d "${DEVICE}"/boot/grub ] ; then
215        [ -d "${DEVICE}/grub" ] || mkdir ${DEVICE}/grub
216        mv ${DEVICE}/boot/grub/* ${DEVICE}/grub/
217     fi
218
219     rmdir ${DEVICE}/boot 2>/dev/null
220
221     sync && echo "${WHITE}done${NORMAL}"
222   else
223     unmount
224     return 1
225   fi
226 }
227
228 run_syslinux(){
229   DEV=$(echo ${DEVICE%/})
230   TMPDEV=$(grep "[[:space:]]${DEV}[[:space:]]" /etc/fstab | grep -vh '^[[:space:]]*#' | awk '{print $1}')
231   SYSDEV=$(echo ${TMPDEV%/})
232   echo -n "Running syslinux on ${SYSDEV}: "
233   debugit "debug: syslinux ${SYSDEV}"
234
235   if syslinux ${SYSDEV} ; then
236      echo "${WHITE}done${NORMAL}"
237   else
238      echo "${RED}Problem when running syslinux?" >&2
239      echo "Try to call it manually via 'syslinux $SYSDEV' if you installed grml to ${SYSDEV}${NORMAL}" >&2
240      return 1
241   fi
242 }
243
244 # }}}
245
246 # main program {{{
247 trap bailout 1 2 3 15
248
249 if [ "$#" != 2 ]; then
250   usage ; exit 4
251 fi
252
253 if [ -n "$UNINSTALL" ] ; then
254    echo "$PROGRAMNAME - ${VERSION}"
255    echo
256
257    echo -n "Are you sure you want to erase all grml related data on ${DEVICE}? [y/N] "
258    read a
259    if ! [ "$a" = 'y' -o "$a" = 'Y' ] ; then
260       echo "Exiting as requested."
261       exit 1
262    fi
263
264    echo "Uninstalling grml from ${DEVICE} based on ${DEVICE}/grml2usb.filelist${NORMAL}"
265    if mount_device ; then
266       if ! [ -f "${DEVICE}"/grml2usb.filelist ] ; then
267          echo "${RED}File ${DEVICE}/grml2usb.filelist not found."
268          echo "I have nothing to delete therefor. Exiting.${NORMAL}"
269          bailout
270       else
271          echo
272          for file in $(grep -v '^#' "${DEVICE}/grml2usb.filelist") ; do
273              if [ -f "${DEVICE}/${file}" ] ; then
274                 echo -n "removing file ${file} on ${DEVICE}: "
275                 rm ${DEVICE}/${file} && echo "${WHITE}done${NORMAL}" || echo "${RED}error${NORMAL}"
276              fi
277          done
278
279          for dir in $(grep -v '^#' "${DEVICE}/grml2usb.filelist" | sed 's#/.*##' | sort -u) ; do
280              if [ -d "${DEVICE}/$dir" ] ; then
281                 echo -n "removing directory ${dir} on ${DEVICE}: "
282                 rmdir "${DEVICE}/${dir}"/* 2>/dev/null
283                 rmdir "${DEVICE}/${dir}" && echo "${WHITE}done${NORMAL}" || echo "${RED}error${NORMAL}"
284              fi
285          done
286
287          echo -n "removing filelist grml2usb.filelist on ${DEVICE}: "
288          rm ${DEVICE}/grml2usb.filelist && echo "${WHITE}done${NORMAL}" || echo "${RED}error${NORMAL}"
289
290          echo
291
292          echo -n "Unmounting ${DEVICE}: "
293          umount $DEVICE && echo "${WHITE}done${NORMAL}" || echo "${RED}error${NORMAL}"
294       fi
295    fi
296 else
297    info
298    vfat_warning && \
299    mount_iso    && \
300    mount_device && \
301    copyit       && \
302    unmount      && \
303    run_syslinux && \
304    notice
305 fi
306 # }}}
307
308 ## END OF FILE #################################################################
309 # vim:foldmethod=marker ts=2 ft=sh ai expandtab sw=3