#!/bin/bash

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# The upgrade rules are:
# 1. Upgrade always means to load new software to a persistent memory and
#    execute it from there.
# 2. If a new manifest doesn't exist, no upgrade.
# 3. If any archive doesn't exist, no upgrade
# 4. If a length of any archive doesn't match a new manifest, no upgrade.
# 5. If an old manifest doesn't exist, force upgrade.
#
# This script returns following exit values:
# 0 - nothing to upgrade
# 1 - upgraded
# 2 - you have to be root to run this script.
# 3 - serverip unknown
# 4 - couldn't access server
# 5 - archive on server missing
# 6 - manifest on server doesn't match archives on server
#

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Function definitions
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function verbose() {
	logger "$*"
	if [ "$verbose" == "v" ] ; then
		echo $*
	fi
}
function failure() {
	local e=$1
	shift
	logger "$*"
	echo $* >&2
	rm -f ${upgrade_lock}$$ 
	exit $e
}
# Set variables that reflect setting of the environment stored in EEPROM
function param() {
	if [ -e /etc/ubootenv/$1 ] ; then
		export $1=`cat "/etc/ubootenv/$1"`
	else
		export "$1"="$2"
	fi
}
# Get directory contents to a file
function get_dir() {
	rm -f $1
	curl -o $1 -s -P - -u ${user}:${pass} ftp://${serverip}/tsu/
}
# Get a file
function get_file() {
	rm -f $1
	local mode="-s -S -P -"
	curl -o $1 $mode -u ${user}:${pass} ftp://${serverip}/tsu/$2
	err_got=$?
	if [ $err_got -ne 0 ] ; then
		verbose "cannot read $2.err $err_got retrying from server $serverip"
		sleep 1
		curl -o $1 $mode -u ${user}:${pass} ftp://${serverip}/tsu/$2
	fi
}
# Get an archive
function get_archive() {
	rm -f $1
	local mode="-s -S -P -"
	nice -n 10 curl -o $1 $mode -u ${user}:${pass} ftp://${serverip}/tsu/$2
	err_got=$?
	if [ $err_got -ne 0 ] ; then
		verbose "cannot read $2.err $err_got retrying from server $serverip"
		sleep 1
		nice -n 10 curl -o $1 $mode -u ${user}:${pass} ftp://${serverip}/tsu/$2
		[[ $? -eq 0 ]] || failure 4 "Cannot read $2"
	fi

	[[ "$(cat $newmanifest | grep $2 | cut -d ' ' -f 3)"\
		== "$(md5sum $1 | cut -d ' ' -f 1)" ]] || \
		failure 6 "The checksum of $2 doesn't match the manifest"
}


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# The real script begins here.
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
param debug ''
if [ -n "$(echo $debug | grep b)" -o -n "$(echo $debug | grep v)" ] ; then
	exec 1>&-
	exec 2>&-
	exec 1>/dev/console
	exec 2>&1
fi

trace=0
[[ -n $(echo $debug | grep b) ]] && {
	trace=1
	set -x
}

verbose=s
[[ -n $(echo $debug | grep v) ]] && verbose=v

arg=""
for a in $* ; do
	case $a in
	-v|--verbose)	verbose=v ;;
	1|restart)		arg=restart ;;
	2|reboot)		arg=reboot ;;
	3|burnflash)	arg=burnflash ;;
	*)				failure 2 "Usage: upgrade [-v] 1|2|3" ;;
	esac
done

verbose "Preparing to check for a possible upgrade"
# You have to be root and a parameter has to have a value 1, 2, or 3.
[[ "$UID" -ne 0 ]] && failure 2 "Bad user"
[[ -z "$arg" ]]    && failure 2 "Bad or missing argument"

# Check for possible multiple instances that BTW are not allowed
# Clean possible "poops"
upgrade_lock="/var/lock/upgrade_"
upgrade_var=no
touch ${upgrade_lock}$$
for f in ${upgrade_lock}* ; do
	ff=$(echo ${f##${upgrade_lock}})
	[[ "$ff" == "$$" ]] && continue
	if [ -d "/proc/$ff" ] ; then
		upgrade_var="yes"
	else
		rm -f $f
	fi
done
[[ "$upgrade_var" == "yes" ]] && failure 2 "Upgrade is already running1G"

param user anonymous
param pass ucb
param ftpsrv
if [ -n "$ftpsrv" ] ; then
	serverip="$ftpsrv"
else
	param serverip
fi
[[ -n "$serverip" ]] || failure 3 "Server IP unknown"
verbose "upgrade server $serverip"
wrkdir=/tmp/ucb_upgrade
rm -rf $wrkdir
mkdir $wrkdir
tmpfile=$wrkdir/tmpfile
newmanifest=$wrkdir/manifest

# get the new manifest and remove possible ctrl-M-s
get_file $tmpfile manifest
cat $tmpfile | sed 's/\r//' > $newmanifest
rm $tmpfile

get_archive $wrkdir/sys_img.tbz sys_img.tbz
nice -n 10 tar xj${v}f $wrkdir/sys_img.tbz -C $wrkdir sbin/st_upgrade
[[ $? -eq 0 ]] || failure 7 "failed unpacking"
cp $wrkdir/sbin/st_upgrade /tmp/st_upgrade
chmod 777 /tmp/st_upgrade
# copy signing certificates
nice -n 10 tar xj${v}f $wrkdir/sys_img.tbz -C $wrkdir usr/lib/ssl/certs/*.0
cp $wrkdir/usr/lib/ssl/certs/*.0 /usr/lib/ssl/certs/
rm -rf $wrkdir
exec /tmp/st_upgrade $arg

# The code below won't execute. The exit is just in case. :-)
# We do not remove upgrade_lock; it will be removed by st_upgrade
exit 0

