#!/bin/bash
#
# hackable1 automagic installer
#
# (c) 2009 Mike 'rysiek' Woźniak <rysiek@brama.elka.pw.edu.pl>
#     licensed under GPL ver.3 or any later
#
# installs hackable1 from given tarballs to a given uSD card device
#
# usage:
#   hackinstall.sh /dev/some_device /path/to/fat_kernel.tar.gz /path/to/ext2_partition.tar.gz [/path/to/optional_fix.tar.gz]
#
# WARNING: this script WILL re-partition a given device, and WILL cause data loss on that device!
#

# ToDo:
#  sanity checks!
#  - file existance;
#  - permissions;
#  - tools availability;
#  cleanup after fsckup!
#  tar file format discovery (gz/bz2)
#  wget support (hell, yeah!)

# variables
HI_DEVICE="$1"
HI_FATTGZ="$2"
HI_EXTTGZ="$3"

# UUID, meh ;)
HI_UUID="$( date "+%s.%N" )"

# mount points
HI_FAT_MP="/tmp/fat.$HI_UUID"
HI_EXT_MP="/tmp/ext.$HI_UUID"

# self identification
HI_ID="Hackable1 uSD Automated Installer"
HI_AUTHOR="(c) 2009 Michał 'rysiek' Woźniak <rysiek@brama.elka.pw.edu.pl>"
HI_GPL="    licensed under GPL ver.3 or any later"

# utils
function hi_usage() {
	echo
	echo "$HI_ID"
	echo "$HI_AUTHOR"
	echo "$HI_GPL"
	echo
	echo "usage:"
	echo -e " $0 /dev/some_device fat_kernel.tar.gz ext2_partition.tar.gz [optional_fix.tar.gz]"
	echo
}

function hi_exit_with_error() {
	echo -e "errors encountered:\n$1"
	exit $2
}

# do we have the optional fix?
if [[ -n "$4" ]]; then
	HI_FIXTGZ="$4"
fi

# sanity checks
if [[ "$1" == "-h" || "$1" == "--help" || -z "$HI_DEVICE" || -z "$HI_FATTGZ" || -z "$HI_EXTTGZ" ]]; then
	hi_usage
	exit 0
fi

# identify yourself
echo
echo "$HI_ID"
echo "$HI_AUTHOR"
echo "$HI_GPL"
echo

# is the user *sure*?
echo "If you choose to proceed, ALL AND ANY data on the $HI_DEVICE device"
echo "WILL BE IRREVERSIBLY DELETED! Choose wisely!"
echo
echo -n "proceed? (y/N): "
read HI_AGREE
if [[ "$HI_AGREE" != "y" && "$HI_AGREE" != "Y" ]]; then
	echo "aborted."
	exit 0
fi
echo "proceeding..."
echo

# partition the card
echo "+- re-partitioning $HI_DEVICE:"
HI_DBG_OUTPUT="$( (
	echo "set send_human {.1 .3 1 .05 2}"
	# spawning...
	echo "spawn fdisk \"$HI_DEVICE\""
	echo "expect \"Command (m for help):\""
	# clearing the partition table...
	echo "send_error \"   - clearing the partition table... \""
	echo "send -h \"o\r\""
	echo "expect \"Command (m for help):\""
	echo "send_error \"done\n\""
	# new partition for fat...
	echo "send_error \"   - creating the fat partition... \""
	echo "send -h \"n\r\""
	echo "expect \"primary partition (1-4)\""
	echo "send -h \"p\r\""
	echo "expect \"Partition number (1-4):\""
	echo "send -h \"1\r\""
	echo "expect \"First cylinder\""
	echo "send -h \r"
	echo "expect \"Last cylinder or +size or +sizeM or +sizeK\""
	echo "send -h \"+8M\r\""
	echo "expect \"Command (m for help):\""
	echo "send -h \"t\r\""
	echo "expect \"Hex code (type L to list codes)\""
	echo "send -h \"4\r\""
	echo "expect \"Command (m for help):\""
	echo "send_error \"done\n\""
	# new partition for ext...
	echo "send_error \"   - creating the ext partition... \""
	echo "send -h \"n\r\""
	echo "expect \"primary partition (1-4)\""
	echo "send -h \"p\r\""
	echo "expect \"Partition number (1-4):\""
	echo "send -h \"2\r\""
	echo "expect \"First cylinder\""
	echo "send -h \r"
	echo "expect \"Last cylinder or +size or +sizeM or +sizeK\""
	echo "send -h \r"
	echo "expect \"Command (m for help):\""
	echo "send_error \"done\n\""
	# writing to disk
	echo "send_error \"   - writing changes to disk... \""
	echo "send -h \"w\r\""
	echo "expect eof"
) | expect - )" 2>&1 || hi_exit_with_error "$HI_DBG_OUTPUT" 2
echo "done."

# finding partition device files
echo "+- discovering partition devices:"
HI_DEVICE_EXT="$( ls -1 "$HI_DEVICE"* | egrep -v "^$HI_DEVICE$" )"
HI_DEVICE_FAT="$( echo -ne "$HI_DEVICE_EXT" | head -n 1 )"
HI_DEVICE_EXT="$( echo -ne "$HI_DEVICE_EXT" | tail -n 1 )"
# fat partition
if [[ -z "$HI_DEVICE_FAT" ]]; then
	echo "   - fat partition device: not found! aborting..."
	exit 3
else
	echo "   - fat partition device: $HI_DEVICE_FAT"
fi
# ext partition
if [[ -z "$HI_DEVICE_EXT" ]]; then
	echo "   - ext partition device: not found! aborting..."
	exit 3
else
	echo "   - ext partition device: $HI_DEVICE_EXT"
fi
# not the same file, I assume?..
if [[ "$HI_DEVICE_FAT" == "$HI_DEVICE_EXT" ]]; then
	echo "    - fat and ext partition device paths must differ! aborting..."
	exit 3
fi

# create filesystems...
# ...fat...
echo "+- formatting:"
echo -n "   - $HI_DEVICE_FAT as vfat... "
HI_DBG_OUTPUT="$( mkfs.vfat "$HI_DEVICE_FAT" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 4
echo "done."
# ...ext2...
echo -n "   - $HI_DEVICE_EXT as ext2... "
HI_DBG_OUTPUT="$( mkfs.ext2 "$HI_DEVICE_EXT" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 4
echo "done."

# create mount points...
# ...fat...
echo "+- creating mount points:"
echo -n "   - $HI_FAT_MP... "
HI_DBG_OUTPUT="$( mkdir "$HI_FAT_MP" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 5
echo "done."
# ...ext2...
echo -n "   - $HI_EXT_MP... "
HI_DBG_OUTPUT="$( mkdir "$HI_EXT_MP" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 5
echo "done."

# mount the partitions...
# ...fat...
echo "+- mounting:"
echo -n "   - $HI_DEVICE_FAT to $HI_FAT_MP... "
HI_DBG_OUTPUT="$( mount "$HI_DEVICE_FAT" "$HI_FAT_MP" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 6
echo "done."
# ...ext2...
echo -n "   - $HI_DEVICE_EXT to $HI_EXT_MP... "
HI_DBG_OUTPUT="$( mount "$HI_DEVICE_EXT" "$HI_EXT_MP" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 6
echo "done."

# untaring...
echo "+- untaring:"
# ...fat kernel...
echo -n "   - $HI_FATTGZ to $HI_FAT_MP... "
HI_DBG_OUTPUT="$( tar -C "$HI_FAT_MP" -xomzf "$HI_FATTGZ" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 7
echo "done."

# ...ext partition...
echo -n "   - $HI_EXTTGZ to $HI_EXT_MP... "
HI_DBG_OUTPUT="$( tar -C "$HI_EXT_MP" -xzf "$HI_EXTTGZ" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 8
echo "done."

# ...optionally, the fix...
if [[ -n "$HI_FIXTGZ" ]]; then
	echo -n "   - $HI_FIXTGZ to $HI_EXT_MP... "
	HI_DBG_OUTPUT="$( tar -C "$HI_EXT_MP" -xzf "$HI_FIXTGZ" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 9
	echo "done."
fi

# umount
# ...fat...
echo "+- unmounting:"
echo -n "   - $HI_DEVICE_FAT... "
HI_DBG_OUTPUT="$( umount "$HI_DEVICE_FAT" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 10
echo "done."
# ...ext2...
echo -n "   - $HI_DEVICE_EXT... "
HI_DBG_OUTPUT="$( umount "$HI_DEVICE_EXT" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 10
echo "done."

# cleanup
echo "+- removing mountpoints:"
echo -n "   - $HI_FAT_MP... "
HI_DBG_OUTPUT="$( rm -rf "$HI_FAT_MP" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 11
echo "done."
echo -n "   - $HI_EXT_MP... "
HI_DBG_OUTPUT="$( rm -rf "$HI_EXT_MP" 2>&1 )" || hi_exit_with_error "$HI_DBG_OUTPUT" 11
echo "done."

# AOK, all done!
echo "all done."
exit 0
