5a9eed020ac7e8547aa531a3eaf0e97ce4182c7a
[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: Don Sep 13 01:38:26 CEST 2007 [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 1>&2 "${RED}Error: syslinux is not available. Please install it before running this script.${NORMAL}" ; exit 2
25   fi
26
27   if [ "$(id -u)" != 0 ];  then
28     echo 1>&2 "${RED}Error: please run this script with uid 0 (root).${NORMAL}" ; 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.7.6'
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 "${BLUE}$PROGRAMNAME $VERSION${NORMAL} - 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-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/external1:
84   $PROGRAMNAME grml_small_0.4.iso /mnt/external1
85
86 Usage example - install currently running grml to usb-device on /mnt/external1:
87   $PROGRAMNAME /cdrom /mnt/external1
88
89 Usage example - delete grml-installation from /mnt/external1:
90   $PROGRAMNAME uninstall /mnt/external1
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 Tips:
103
104   Use the usb cheatcode on bootprompt if you experience any problems with
105   booting grml via usb/firewire, so boot with 'grml scandelay' on bootprompt.
106   This adds a 'sleep' while trying to access the usb-stick and the module
107   should have enough time to access it. Using scandeleay=seconds is possible
108   as well, use 'grml scandelay=20' to wait 20 seconds before trying to access
109   the external device with grml on it.
110
111   Also make sure you have tested all available modes of USB-boot in
112   the BIOS of your computer. Often found as USB-HDD, USB-FDD and
113   USB-ZIP in the bootmenu.
114
115   Take a look at http://wiki.grml.org/doku.php?id=usb for more information."
116 }
117
118 info(){
119   echo "${BLUE}$PROGRAMNAME ${VERSION}${NORMAL} - install grml-system to usb-device"
120   echo
121 }
122
123 vfat_warning(){
124   DEV=$(echo ${DEVICE%/})
125   TMPDEV=$(grep ${DEV} /etc/fstab | awk '{print $1}')
126   SYSDEV=$(echo ${TMPDEV%/})
127   if [ -x /lib/udev/vol_id ] ; then
128      /lib/udev/vol_id $SYSDEV | grep -q 'FS_TYPE=vfat' || VFAT=1
129      /lib/udev/vol_id $SYSDEV | grep -q 'ID_FS_VERSION=FAT16' || VFAT=1
130   else
131      VFAT=1
132   fi
133   if [ -n "$VFAT" ] ; then
134      echo 'Warning: make sure that your usb-device is preformated with vfat.'
135      echo "If not please run it e.g. via:  mkfs.vfat -F 16 -v $SYSDEV"
136      echo
137   fi
138 }
139
140 mount_device(){
141   if grep -q ${DEVICE} /proc/mounts ; then
142     echo echo 1>&2 "${WHITE}${DEVICE} already mounted${NORMAL}"
143   else
144     echo -n "Mounting ${DEVICE}: "
145     debugit "debug: mount $DEVICE"
146     mount $DEVICE && echo "${WHITE}done${NORMAL}" || bailout
147   fi
148 }
149
150 mount_iso(){
151   echo -n "Mounting ${ISO} to ${TMPMNT}: "
152   local mount_opts_="-o loop"
153   if [ -d $ISO ]; then
154       mount_opts_="--bind"
155   elif [ -b $ISO ]; then
156       mount_opts_=""
157   fi
158   debugit "debug: mount $mount_opts_ ${ISO} ${TMPMNT}"
159   if mount $mount_opts_ "${ISO}" ${TMPMNT} ; then
160      echo "${WHITE}done${NORMAL}"
161   else
162      echo 1>&2 "${RED}Problem? You got an error saying 'mount: could not find any free loop device'?
163 Possible solution: losetup -d /dev/loop/0${NORMAL}"
164     exit 3
165   fi
166 }
167
168 unmount(){
169   echo -n "Unmounting ${DEVICE} and ${TMPMNT}: "
170   umount ${TMPMNT}
171   umount ${DEVICE} && echo "done" || echo "failed"
172 }
173
174 copyit(){
175   echo -n "Installing data from ${ISO} to ${DEVICE} (will take some time): "
176   debugit "debug: cp -dR --preserve=mode,timestamps ${TMPMNT}/* ${DEVICE}"
177   debugit "debug: mv ${DEVICE}/boot/isolinux/* ${DEVICE}/"
178   if cp -dR --preserve=mode,timestamps ${TMPMNT}/* ${DEVICE} ; then
179     echo "# filelist of $PROGRAMNAME on $(date) using $ISO on ${DEVICE}:" > $DEVICE/grml2usb.filelist
180     find  ${TMPMNT} -type f | grep -v isolinux | sed 's#^${TMPMNT}##' | tr A-Z a-z >> $DEVICE/grml2usb.filelist && \
181     find  ${DEVICE}/boot/isolinux -type f | sed 's#.*isolinux/##'      | tr A-Z a-z >> $DEVICE/grml2usb.filelist && \
182     # make sure we have a valid syslinux.cfg, if not use isolinux.cfg as base
183     if ! [ -f "${DEVICE}"/boot/isolinux/syslinux.cfg ] ; then
184        cp ${DEVICE}/boot/isolinux/isolinux.cfg ${DEVICE}/boot/isolinux/syslinux.cfg && \
185        echo 'syslinux.cfg' >> $DEVICE/grml2usb.filelist
186     fi
187     mv    ${DEVICE}/boot/isolinux/* ${DEVICE}/    && \
188     rmdir ${DEVICE}/boot/isolinux                 && \
189     rmdir ${DEVICE}/boot/
190     sync && echo "${WHITE}done${NORMAL}"
191   else
192     unmount
193     return 1
194   fi
195 }
196
197 run_syslinux(){
198   DEV=$(echo ${DEVICE%/})
199   TMPDEV=$(grep ${DEV} /etc/fstab | awk '{print $1}')
200   SYSDEV=$(echo ${TMPDEV%/})
201   echo -n "Running syslinux on ${SYSDEV}: "
202   debugit "debug: syslinux ${SYSDEV}"
203   if syslinux ${SYSDEV} ; then
204      echo "${WHITE}done${NORMAL}"
205   else
206      echo 1>&2 "${RED}Problem when running syslinux?
207 Try to call it manually via "syslinux $SYSDEV" if you installed grml to $SYSDEV'${NORMAL}"
208      return 1
209   fi
210 }
211
212 # }}}
213
214 # main program {{{
215 trap bailout 1 2 3 15
216
217 if [ "$#" != 2 ]; then
218   usage ; exit 4
219 fi
220
221 if [ -n "$UNINSTALL" ] ; then
222   echo "${BLUE}$PROGRAMNAME - ${VERSION}${NORMAL}"
223   echo
224   echo "Uninstalling grml from ${DEVICE} based on ${DEVICE}/grml2usb.filelist.${NORMAL}"
225   if mount_device ; then
226      if [ -f ${DEVICE}/grml2usb.filelist ] ; then
227         for file in `cat $DEVICE/grml2usb.filelist | grep -v '^#'` ; do
228           echo -n "removing ${file} on ${DEVICE}: "
229           rm ${DEVICE}/${file} && echo "${WHITE}done${NORMAL}" || echo "${RED}error${NORMAL}"
230         done
231         echo -n "removing directory grml/images/ on ${DEVICE}: "
232         rmdir ${DEVICE}/grml/images/ && echo "${WHITE}done${NORMAL}" || echo "${RED}error${NORMAL}"
233         echo -n "removing directory grml/ on ${DEVICE}: "
234         rmdir ${DEVICE}/grml && echo "${WHITE}done${NORMAL}" || echo "${RED}error${NORMAL}"
235         echo -n "removing filelist grml2usb.filelist on ${DEVICE}: "
236         rm ${DEVICE}/grml2usb.filelist && echo "${WHITE}done${NORMAL}" || echo "${RED}error${NORMAL}"
237         echo -n "Unmounting ${DEVICE}:"
238         umount $DEVICE && echo "${WHITE}done${NORMAL}" || echo "${RED}error${NORMAL}"
239      else
240         echo 1>&2 "${RED}File ${DEVICE}/grml2usb.filelist not found. I have nothing to delete therefor. Exiting.${NORMAL}"
241      fi
242   fi
243 else
244   info
245   vfat_warning && \
246   mount_iso    && \
247   mount_device && \
248   copyit       && \
249   unmount      && \
250   run_syslinux && \
251   notice
252 fi
253 # }}}
254
255 ## END OF FILE #################################################################
256 # vim:foldmethod=marker