#!/bin/bash

# $Id: build_bootable_USB.sh 3498 2011-12-03 01:28:47Z skylar $

# This file is part of BCCD, an open-source live CD for computational science
# education.
# 
# Copyright (C) 2010 Andrew Fitz Gibbon, Paul Gray, Kevin Hunter, Dave Joiner, 
#   Sam Leeman-Munk, Tom Murphy, Charlie Peck, Skylar Thompson, & Aaron Weeden 

# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

#This script must be run as superuser
if [ `id -u` != 0 ]; then
	echo "$0: ERROR: superuser privileges required."
	exit
fi 

#Parse command line args
if [ $2 ]; then
	DRIVE=$1
	ISO_PATH=$2
else
	echo -e "USAGE:\n $0 <USB DRIVE> <ISO>"
	exit
fi

#Verify that files exist
if [ ! -e $DRIVE ]; then
	echo -e "$0: ERROR: $DRIVE: file not found."
	exit
fi
if [ ! -f $ISO_PATH ]; then
	echo -e "$0: ERROR: $ISO_PATH: file not found."
	exit
fi

echo '---> Checking dependencies'
for dep in mkfs.vfat parted syslinux rsync du fdisk; do
	if test -z `which $dep`; then
		echo "$0: ERROR: Missing dependency: $dep"
		exit
	else
		if [ $dep == "mkfs.vfat" ]; then
			mkfs=`which $dep`
		else
			eval $dep=`which $dep`
		fi
	fi
done

#Get sizes of drive and ISO
echo '---> Get drive/iso sizes'
DRIVE_SIZE=$((`$fdisk -l $DRIVE | grep "^Disk $DRIVE" | awk '{print $5}'`/1024))
ISO_SIZE=`$du -k $ISO_PATH | awk '{print $1}'`

#Exit if ISO is too big for drive
if [ $ISO_SIZE -gt $DRIVE_SIZE ]; then
	echo "$0: ERROR: ISO is too big for drive"
	exit
fi

echo "---> Ensuring ${DRIVE}1 is not mounted"
umount ${DRIVE}1

echo '---> Removing existing partitions'
PARTITIONS=`$parted $DRIVE print | grep ^\ [0-9] | awk '{print $1}'`
if [ "$PARTITIONS" ]; then
	for i in $PARTITIONS; do
		echo "removing partition $i:"
		$parted $DRIVE rm $i;
	done
fi

echo '---> Creating the partition'
# parted parses -1 as end of $DRIVE. Double quoted to make sure parted doesn't
# read it as a command-line option.
$parted $DRIVE mkpart primary "1 -1"

echo "---> Wait for ${DRIVE}1 to manifest"
while ! test -b ${DRIVE}1; do sleep 1; done

echo '---> Format the partition'
$mkfs ${DRIVE}1

echo '---> Making partition bootable'
$parted $DRIVE set 1 boot on

echo "---> Wait for ${DRIVE}1 to come back again"
while ! test -b ${DRIVE}1; do sleep 1; done

echo '---> Copying mbr.bin'
mbr=`find /usr/lib -name mbr.bin | head -1`
cat $mbr >> $DRIVE

echo '---> Running syslinux'
$syslinux "${DRIVE}1"
if [ $? != 0 ]; then
	echo '---> ERROR: Installing syslinux bootloader failed.'
fi

echo '---> Making temporary directories'
ISO_DIR=`mktemp -d iso-XXXXXXXX`
USB_DIR=`mktemp -d usb-XXXXXXXX`

echo '---> Mounting image and partition to temporary directories'
mount -o loop $ISO_PATH $ISO_DIR/
mount ${DRIVE}1 $USB_DIR/

echo '---> Copying files from image to partition'
echo '---> This will take a while...'
$rsync -Plarv $ISO_DIR/ $USB_DIR/
cp $ISO_DIR/boot/isolinux/* $USB_DIR/
mv $USB_DIR/isolinux.cfg $USB_DIR/syslinux.cfg

echo '---> Unmounting image and partition'
umount $ISO_DIR/
umount $USB_DIR/

echo '---> Removing temporary directories'
rm -r $ISO_DIR/
rm -r $USB_DIR/

echo '---> Script finished.'
