#!/bin/sh

# Version 0.2BETA	
# 2010-08-29	Peter.Jonsson@tg.lth.se	
# 2011-01-13	v 0.2	
	

# This is where the terrameter program lives in the LS including executable's name
TARGET="/usr/bin/terrameter"

# Name and filename of executable (no path, just the filename)
EXECUTABLE="terrameter"
EXECUTABLEFILEMODE="755"

# Where the temporary backup is stored
TARGETBACKUP="/updates/old_terrameter"

# Actions logged here
LOGFILE="/updates/terrameterupdate.log"

# Temporary work place
WORKDIR="/tmp/terrameterupdate"

# Place for script to roll back older version at reboot, if needed
ROLLBACKFILE="/etc/rc5.d/S95RollbackTerrameterBackup"

# After work script
POST="/updates/postinstall.sh"


#-------------------------------------------------------------------------------------------
# Changes below this line should be needed only if the commands are in places
#-------------------------------------------------------------------------------------------
_ECHO="/bin/echo"
_DATE="/bin/date"
_RM="/bin/rm"
_MV="/bin/mv"
_MKDIR="/bin/mkdir"
_CHMOD="/bin/chmod"
_SLEEP="/bin/sleep"
_PS="/bin/ps"
_GREP="/bin/grep"
_UNZIP="/bin/gunzip"
_KILLALL="/usr/bin/killall"
#0.2
_SHELL="/bin/bash"




#-------------------------------------------------------------------------------------------
# Changes below this line should be needed only if/when bugs are found or the 
# functionality shall be changed
#-------------------------------------------------------------------------------------------


status_return()	{

	if [ $1 -eq 0 ]
	then
		status="0"
	else
		status="1"
	fi
}


#-------------------------------------------------------------------------------------------
#	Logs $1 to a file and optionally to stdout
#-------------------------------------------------------------------------------------------
log()	{


	logitem=$1
	logtime=`$_DATE`
		$_ECHO $logitem	

	$_ECHO -n $logtime >> $LOGFILE
	$_ECHO -n ": "  >> $LOGFILE
	$_ECHO $logitem  >> $LOGFILE
}

#-------------------------------------------------------------------------------------------
#	Writes $1 to a ROLLBACKFILE which is a script that restores the backup of the
#	executable at reboot (runlevel determined by name of script -- rxX.d-style)
#-------------------------------------------------------------------------------------------
rbwrite()	{
	
	$_ECHO "$1" >> $ROLLBACKFILE
	#$_ECHO "$1" 
}
	
#-------------------------------------------------------------------------------------------
#	Creates a script to roll back old version on failure
#-------------------------------------------------------------------------------------------
create_rollback_on_reboot()	{
	
	# Create file. This is the text in the script---------------------------------------
	$_ECHO "#! /bin/sh" > $ROLLBACKFILE
	
	rbwrite "if [ -e $TARGETBACKUP ]"
	rbwrite "then" 
	rbwrite "	$_MV $TARGETBACKUP $TARGET"	
	rbwrite "	if [ \$? -eq 0 ]"
	rbwrite "	then"
	rbwrite " 		$_ECHO \"Roll back from update $UPDATE succeeded\" >> $LOGFILE"
	rbwrite " 		$_RM $ROLLBACKFILE"      	
	rbwrite " 		if [ \$? -eq 0 ]"
	rbwrite " 		then"
	rbwrite " 			$_ECHO \"Roll back at upstart was disarmed\" >> $LOGFILE"
	rbwrite " 		else"
	rbwrite " 			$_ECHO \"Roll back at upstart still active\" >> $LOGFILE"
	rbwrite "		fi"
	rbwrite "	else"
	rbwrite " 		$_ECHO \"Roll back of update $UPDATE failed\" >> $LOGFILE"
	rbwrite " 		$_ECHO \"Roll back at upstart was not removed\" >> $LOGFILE"
	rbwrite "	fi"
	rbwrite "fi"
	# This is the end of the text in the script------------------------------------------

	# Test it
	if [ -e $ROLLBACKFILE ]
	then
		$_CHMOD $EXECUTABLEFILEMODE $ROLLBACKFILE
	
		if [ -x $ROLLBACKFILE ]
		then
			log "Roll back was set up"
			status_return 0
		else
			log "Roll back could not be set up"
			status_return 1
		fi
	else
		log "Roll back file could not be found"
		status_return 1
	fi
}

#-------------------------------------------------------------------------------------------
#	Removes ROLLBACKFILE so it's not executed at next reboot
#-------------------------------------------------------------------------------------------
remove_rollback_on_reboot()	{

	$_RM $ROLLBACKFILE

	if [ -e $ROLLBACKFILE ]
	then
		log "Could not remove roll back at reboot" 
		status_return 1
	else
		log "Removed roll back at reboot" 
		status_return 0
	fi
}
#-------------------------------------------------------------------------------------------
#		Stub for cpu version check
#-------------------------------------------------------------------------------------------
check_if_g45()	{

#        A=`$_PS -C $EXECUTABLE|$_GREP "$EXECUTABLE" 1> /dev/null && $_ECHO "0"`
        cat /proc/cpuinfo |$_GREP "9g45" 1> /dev/null

	if [ $? -eq 0 ]
	then
		log "Assume LSv2"
		status_return 0
	else
		log "Assume LSv1"
		status_return 1
	fi
}

#-------------------------------------------------------------------------------------------
#		Stub for integrity check
#-------------------------------------------------------------------------------------------
test_integrity_of_archive()	{

	#$_UNZIP -t $UPDATE 1> /tmp/tmp.tmp 2> /dev/null
	$_UNZIP -t $UPDATE

    if [ $? -eq 0 ]
	then
		log "Archive checks out OK"
		status_return 0
	else	
		log "There seems to be something wrong with the archive"
		status_return 1
	fi
}


#-------------------------------------------------------------------------------------------
#	Tests if the if the archive is OK and if the update file is there
#-------------------------------------------------------------------------------------------

test_and_unpack_archive()	{

	log "Begin testing and unpacking of archive"
	
	# First of all, see if the update is there at all
	if [ -e $UPDATE ]
	then
		log "The zip archive $UPDATE exists"

		# Then check the integrity of the zip archive
		test_integrity_of_archive

		if [ $status = "0" ]
		then
			log "The zip archive $UPDATE seems to be OK"
	
			# Uncompress to the working directory
	
			if [ ! -d $WORKDIR ]
			then
				$_MKDIR $WORKDIR
			fi
	
			$_UNZIP -c $UPDATE >$WORKDIR/$EXECUTABLE
	
			if [ -s $WORKDIR/$EXECUTABLE ]
			then
				log "Unpacked $UPDATE to $WORKDIR."
				$_CHMOD $EXECUTABLEFILEMODE $WORKDIR/$EXECUTABLE
				if [ -x $WORKDIR/$EXECUTABLE ]
				then
					log "Made new $EXECUTABLE executable"
					status_return 0
				else
					log "Could not make new $EXECUTABLE executable"
					status_return 1
				fi 
			else
				log "Could not unpack $UPDATE to $WORKDIR"
				status_return 1
			fi
						
		else
			log "There is an error in the zip archive $UPDATE"
			status_return 1
		fi
	else
		log "The zip archive $UPDATE could not be found"
		status_return 1
	fi

}	

#-------------------------------------------------------------------------------------------
# Try to roll back the update now
#-------------------------------------------------------------------------------------------

rollback()	{

	$_MV $TARGETBACKUP $TARGET
	if [ -e $TARGET ]
	then
		test_executable
		if [ $status = "0" ]
		then
			log "The old target was restored as $TARGET" 
		else
			log "Could not verify restored $TARGET" 
			status_return 1
		fi
	else
		log "Could not restore the executable after failure" 
		status_return 1
	fi

}

#-------------------------------------------------------------------------------------------
# Tests if there is a running terrameter instance
#-------------------------------------------------------------------------------------------
check_if_executable_is_running()	{

#        A=`$_PS -C $EXECUTABLE|$_GREP "$EXECUTABLE" 1> /dev/null && $_ECHO "0"`
#        $_PS -C $EXECUTABLE|$_GREP "$EXECUTABLE" 1> /dev/null
        $_PS |$_GREP "$EXECUTABLE " | grep -v grep 1> /dev/null
	if [ $? -eq 0 ]
	then
		log "$EXECUTABLE is running"
		status_return 1
	else
		log "$EXECUTABLE is not running"
		status_return 0
	fi
}

#-------------------------------------------------------------------------------------------
# Stops a running terrameter instance
#-------------------------------------------------------------------------------------------

stop_executable()	{

    check_if_g45
    if [ $status = "0" ]
    then
        STOPCOMMAND="/etc/init.d/xserver-nodm stop"
    else
        STOPCOMMAND= "/etc/init.d/gpe-dm stop"
    fi
    $STOPCOMMAND
    $_SLEEP 5
    check_if_executable_is_running
    if [ $status = "0" ]
    then
	log "Killed $EXECUTABLE"
	status_return 0
    else
	log "Could not kill $EXECUTABLE"
	status_return 1
    fi
    
}

#-------------------------------------------------------------------------------------------
# Swaps the old executable and the new with some security measures
#-------------------------------------------------------------------------------------------

swap_executables()	{

	log "Begin swap"
	
	if [ -e $WORKDIR/$EXECUTABLE ]
	then
		# Save the old target
		if [ -e $TARGET ]
		then
			$_MV $TARGET $TARGETBACKUP
			if [ $? -eq 0 ]
			then
				log "$TARGET exists and was moved to $TARGETBACKUP" 
			else
				log "$TARGET could not be moved to $TARGETBACKUP" 
				status_return 1
			fi
		else
			log "$TARGET did not exist"
		fi
		
		
		# Set up roll back and do the swap
		create_rollback_on_reboot
		if [ $status = "0" ]
		then
			# Move in the new one
			$_MV $WORKDIR/$EXECUTABLE $TARGET
			if [ $? -eq 0 ]
			then
				log "New $WORKDIR/$EXECUTABLE was moved to $TARGET" 
				test_executable
				if [ $status = "0" ]
				then
					remove_rollback_on_reboot
					log "The new $TARGET seems to be OK" 
					status_return 0
				else
					log "Could not verify restored $TARGET" 
					status_return 1
				fi
			else
				log "Could not move $WORKDIR/$EXECUTABLE to $TARGET" 
				rollback
				status_return 1
			fi
		else
			log "Failed to move $WORKDIR/$EXECUTABLE to $TARGET" 
			status_return 1
		fi
	else
		log "$WORKDIR/$EXECUTABLE did not exist" 
		status_return 1
	
	fi
}


#-------------------------------------------------------------------------------------------
# Run the post-install script	(0.2)
#-------------------------------------------------------------------------------------------

post_install()	{

	log "Begin post installation activities"
	
	if [ -e $POST ]
	then
            log "Try file $POST"
            chmod +x $POST
            chown root $POST
            $POST $POSTARGS
	    log "Returned from $POST"
	else
	    log "No $POST file" 
	    status_return 1
	fi
}



#-------------------------------------------------------------------------------------------
# Test the executable
#-------------------------------------------------------------------------------------------

test_executable()	{

	log "Begin test"
	
	if [ -x $TARGET ]
	then
		status_return 0
	else	
		status_return 1
	fi

}

#-------------------------------------------------------------------------------------------
# Start the executable
#-------------------------------------------------------------------------------------------

start_executable()	{


	if [ -x $TARGET ]
	then
            check_if_g45
            if [ $status = "0" ]
            then
                STARTCOMMAND="/etc/init.d/xserver-nodm start"
            else
                STARTCOMMAND="/etc/init.d/gpe-dm start"
            fi
            
		$STARTCOMMAND
		$_SLEEP 5
	
		check_if_executable_is_running
		if [ $status = "0" ]
		then
			log "$EXECUTABLE was restarted" 
			status_return 0
		else
			log "$EXECUTABLE could not be restarted" 
			status_return 1
		fi
	else
		log "$EXECUTABLE could not be found at restart" 	
		status_return 1
	fi
	
}


#-------------------------------------------------------------------------------------------
# Cleanup leftovers
#-------------------------------------------------------------------------------------------

cleanup_after_success()	{
	
	if [ -d $WORKDIR ]
	then
		log "Remove temporary files"
		$_CHMOD -R 777 $WORKDIR 
		$_RM -rf $WORKDIR
	fi
	
	if [ -e $UPDATE ]
	then	
		log "Remove update archive"
		$_CHMOD 777 $UPDATE
		$_RM -rf $UPDATE
	fi
	
	if [ -e $ROLLBACKFILE ]
	then
		log "Remove roll back"
		$_CHMOD 777 $ROLLBACKFILE
		$_RM $ROLLBACKFILE
	fi
	
	if [ -e $TARGETBACKUP ]
	then
		log "Remove backup of old executable"
		$_CHMOD 777 $TARGETBACKUP
		$_RM $TARGETBACKUP
	fi

	if [ -e $CONTAINER ]
	then
		log "Remove uploaded .tar from Terrameter "
		$_CHMOD 777 $CONTAINER
		$_RM $CONTAINER
	fi

	if [ -e $SELF ]
	then
		log "Remove update script "
		$_CHMOD 777 $SELF
		$_RM $SELF
	fi

}



#-------------------------------------------------------------------------------------------
# Cleanup leftovers, but leave roll back script and backup behind
#-------------------------------------------------------------------------------------------

cleanup_after_failure()	{

	if [ -d $WORKDIR ]
	then
		log "Remove temporary files"
		$_CHMOD -R 777 $WORKDIR 
		$_RM -rf $WORKDIR
	fi
	
		if [ -e $UPDATE ]
	then	
		log "Remove update archive"
		$_CHMOD 777 $UPDATE
		$_RM $UPDATE
	fi
}

#-------------------------------------------------------------------------------------------
# MAIN
#-------------------------------------------------------------------------------------------

if [ $# -ne 1 ]
then
    echo "Must provide basename for upgrade"
    log "Must provide basename for upgrade"
    exit
fi	

BASENAME=$1

# Container name (the one uploaded from the PC)
CONTAINER="/updates/$BASENAME.tar"

# This is the name of the update 
UPDATE="/updates/$BASENAME.gz"			

# This is the name of this script
SELF="/updates/$BASENAME.sh"  

log "Start working on $BASENAME"

echo $BASENAME | grep "terrameter-v2-" 1> /dev/null
if [ $? -eq 0 ]
then
    log "This software package is for LS v2"
    check_if_g45
    if [ $status = "0" ]
    then
        echo "ok"
        POSTARGS="at91g45"
    else
        echo "fail"
        exit 
    fi
else
    log "This software package is for LS v1 9263"
    check_if_g45
    if [ $status = "0" ]
    then
        echo "fail"
        exit 
    else
        POSTARGS="at91sam9263"
        echo "ok"
    fi

fi


# Set up the new version
test_and_unpack_archive

if [ $status = "0" ] 
then
	# Stop running executable
	stop_executable

	if [ $status = "0" ] 
	then
		# This will backup the old, create a roll back routine, and install the new.
		# If it fails, try to undo - either now or at next reboot. 
		swap_executables
		
		# 0.2 begin
		# Do post-installation stuff if it went well
		if [ $status = "0" ] 
		then
			post_install
		fi
			

		if [ $status = "0" ] 
		then
			# Re-start the program
			start_executable
			cleanup_after_success
			log "Update of $TARGET performed"
		else
			log "Could not update $TARGET"
			cleanup_after_failure
			start_executable
		fi
	else
		log "Could not stop $EXECUTABLE. Aborted. Your Terrameter LS is untouched"
	fi
else
	log "Aborted. Your Terrameter LS is untouched"
fi

