#!/bin/sh
# /etc/init.d/fwinstall
#
### BEGIN INIT INFO
# Provides:          fwinstall
# Required-Start:    $local_fs
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: fwinstall
# Description:       fwinstall tool
### END INIT INFO

SMART_CACHE_PATH="/var/lib/smart/"
FIRMWARE_TEMP="installer_temp.zip"
FIRMWARE_CURRENT="installer_current.zip"
FIRMWARE_PREVIOUS="installer_previous.zip"
OTA_TEMP="ota_temp"
OTA_TEMP2="ota_temp2"
OTA_CURRENT="ota_current"
OTA_PREVIOUS="ota_previous"
VIPER4_LOCAL_CHANNEL="/var/lib/smart/local"
LICENSE_DIR="upload_license"
LICENSE_FILE_PATH="/etc/NOTICE"
RESUME_STEPS="/var/lib/smart/resume.install"
LOG_HISTORY="/var/lib/smart/history.log"
ERROR_FILE="ota_error.log"

REBOOT="false"
BRANCH="local"
REPOLOCATION=""
ROTATION="-a 0"
#need to set PATH variable for fcgi callers who have no environment
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

kill_child_processes() {

	isTopmost=$1
	curPid=$2
	childPids=`ps -o pid --no-headers --ppid ${curPid}`
	for childPid in $childPids
	do
		kill_child_processes 0 $childPid
	done
	if [ $isTopmost -eq 0 ]; then
		kill -9 $curPid 2> /dev/null
	fi
}

CheckRotation()
{
	/usr/sbin/prgmicro -orientation
	if [ $? -eq 32 ]; then #bit 5 of return value is the appliation return code, 1 for portrait 0 for landscape
		echo "Setting Rotation Portrait"
		ROTATION="-a 270"
	else
		echo "Setting Rotation Landscape"
		ROTATION="-a 0"
	fi
}

UploadLicenseCheck()
{
	UPLOAD_LICENSE_DIR=`find /media/usb* -type d -name $LICENSE_DIR | head -1`

	if [ "$UPLOAD_LICENSE_DIR" != "" ]; then
		cp -f $LICENSE_FILE_PATH $UPLOAD_LICENSE_DIR
		sync
	fi
}

ExtractRepo()
{
	rm -rf $VIPER4_LOCAL_CHANNEL
	mkdir -p $VIPER4_LOCAL_CHANNEL
	unzip ${SMART_CACHE_PATH}$1 -d $VIPER4_LOCAL_CHANNEL > /dev/null

	if [ $? -ne 0 ]; then
		echo "Error: Failed extracting zip file"
		rm -rf $VIPER4_LOCAL_CHANNEL
		rm ${SMART_CACHE_PATH}$1
		rm -rf ${RESUME_STEPS}
		sync

		exit 2
	fi
	
	TAR=`find $VIPER4_LOCAL_CHANNEL | grep arm.zip`
	if [ ! -z "${TAR}" ]; then
        unzip ${TAR} -d $VIPER4_LOCAL_CHANNEL > /dev/null
    
    	if [ $? -ne 0 ]; then
    		echo "Error extracting zip file"
    		rm -rf $VIPER4_LOCAL_CHANNEL
    		rm ${SMART_CACHE_PATH}$1
    		rm -rf ${RESUME_STEPS}
    		sync
    		
    		exit 2
    	fi
    	sync
    fi
}

RotateInstallers()
{
	if [ -f ${SMART_CACHE_PATH}$FIRMWARE_CURRENT ]; then
		mv ${SMART_CACHE_PATH}$FIRMWARE_CURRENT ${SMART_CACHE_PATH}$FIRMWARE_PREVIOUS
		/usr/bin/unzip -l ${SMART_CACHE_PATH}$FIRMWARE_PREVIOUS | grep \/packagegroup-fishspear-[0-9] | awk '{ print $4 }' | awk -F- '{ print $3 }' | tr -d '\n' > /usr/bin/raven/fishspearB/softwareversion.txt
	fi

	#erase old install
	if [ -d ${SMART_CACHE_PATH}$OTA_PREVIOUS ]; then
		rm -rf ${SMART_CACHE_PATH}$OTA_PREVIOUS
	fi
	if [ -d ${SMART_CACHE_PATH}$OTA_CURRENT ]; then
		mv ${SMART_CACHE_PATH}$OTA_CURRENT ${SMART_CACHE_PATH}$OTA_PREVIOUS
		VERSION=`ls ${SMART_CACHE_PATH}$OTA_PREVIOUS | grep packagegroup-fishspear-[0-9] | awk -F- '{ print $3 }' | tr -d '\n'`
		if [ "${VERSION}" ]; then
			echo -n "${VERSION}" > /usr/bin/raven/fishspearB/softwareversion.txt
		fi
	fi

	if [ -f ${SMART_CACHE_PATH}$FIRMWARE_TEMP ]; then
		mv ${SMART_CACHE_PATH}$FIRMWARE_TEMP ${SMART_CACHE_PATH}$FIRMWARE_CURRENT
		##TODO: This was a USB install, Do i need to clean up my OTA directories???
	else
		rm -f ${SMART_CACHE_PATH}$FIRMWARE_CURRENT
	fi

	if [ -d ${SMART_CACHE_PATH}$OTA_TEMP ]; then
		mv ${SMART_CACHE_PATH}$OTA_TEMP ${SMART_CACHE_PATH}$OTA_CURRENT
	fi

	#cleanup ota download directory
	rm -f ${SMART_CACHE_PATH}packages/*.rpm
	sync
}

Copy2Disk()
{
	cp $TARBALL ${SMART_CACHE_PATH}$FIRMWARE_TEMP
	sync
}

VerifyInstaller()
{
	MD5NEW=`md5sum $TARBALL | awk '{ print $1 }'`

	if [ -f ${SMART_CACHE_PATH}$FIRMWARE_CURRENT ]; then
		MD5OLD=`md5sum ${SMART_CACHE_PATH}$FIRMWARE_CURRENT | awk '{ print $1 }'`
	fi

	if [ "$MD5NEW" = "$MD5OLD" ]; then
		echo "Installer matches current version, exiting"
		exit 0
	fi
}

CacheRepo()
{

	##TODO:: create channel list to append to local installs

	#rm -rf ${SMART_CACHE_PATH}${OTA_TEMP}

	#download was called twice inbetween installs, we need to preserve this temp directory
	if [ -d ${SMART_CACHE_PATH}${OTA_TEMP} ]; then
		mv ${SMART_CACHE_PATH}${OTA_TEMP} ${SMART_CACHE_PATH}${OTA_TEMP2}
	fi

	if [ -d ${SMART_CACHE_PATH}${OTA_CURRENT} ]; then
		cp -R ${SMART_CACHE_PATH}$OTA_CURRENT ${SMART_CACHE_PATH}${OTA_TEMP}/
	else
		mkdir -p ${SMART_CACHE_PATH}${OTA_TEMP}
	fi

	if [ -d ${SMART_CACHE_PATH}${OTA_TEMP2} ]; then
		cp -R ${SMART_CACHE_PATH}${OTA_TEMP2}/* ${SMART_CACHE_PATH}${OTA_TEMP}/
		rm -rf ${SMART_CACHE_PATH}${OTA_TEMP2}
	fi

	echo "Saving Repo into ${SMART_CACHE_PATH}${OTA_TEMP}"

	#if [ -d "${SMART_CACHE_PATH}${OTA_TEMP}/repodata" ]; then
	#	rm -rf ${SMART_CACHE_PATH}${OTA_TEMP}/repodata
	#fi
	mkdir -p ${SMART_CACHE_PATH}${OTA_TEMP}/repodata

	cp -R ${SMART_CACHE_PATH}channels ${SMART_CACHE_PATH}${OTA_TEMP}/repodata.tmp
	if [ -f ${SMART_CACHE_PATH}${OTA_TEMP}/repodata.tmp/*filelists.xml.gz ]; then
		mv ${SMART_CACHE_PATH}${OTA_TEMP}/repodata.tmp/*filelists.xml.gz ${SMART_CACHE_PATH}${OTA_TEMP}/repodata/filelists.xml.gz
	fi

	if [ -f ${SMART_CACHE_PATH}${OTA_TEMP}/repodata.tmp/*primary.xml.gz ]; then
		mv ${SMART_CACHE_PATH}${OTA_TEMP}/repodata.tmp/*primary.xml.gz ${SMART_CACHE_PATH}${OTA_TEMP}/repodata/primary.xml.gz
	fi

	if [ -f ${SMART_CACHE_PATH}${OTA_TEMP}/repodata.tmp/*repomd.xml ]; then
		mv ${SMART_CACHE_PATH}${OTA_TEMP}/repodata.tmp/*repomd.xml ${SMART_CACHE_PATH}${OTA_TEMP}/repodata/repomd.xml
	fi

	rm -rf ${SMART_CACHE_PATH}${OTA_TEMP}/repodata.tmp

	cp ${SMART_CACHE_PATH}packages/*.rpm ${SMART_CACHE_PATH}${OTA_TEMP}/

	if [ -f ${SMART_CACHE_PATH}${OTA_TEMP}/repodata/primary.xml.gz ]; then

		gzip -dc < ${SMART_CACHE_PATH}${OTA_TEMP}/repodata/primary.xml.gz > ${SMART_CACHE_PATH}${OTA_TEMP}/repodata/primary.xml

		WD=`pwd`
		cd ${SMART_CACHE_PATH}${OTA_TEMP}
		for f in `ls *.rpm`; do		#this will throw an error if the current folder is empty... squelch this??
			FOUND=`cat ${SMART_CACHE_PATH}${OTA_TEMP}/repodata/primary.xml | grep $f`
			if [ "$FOUND" = "" ]; then
				echo "$f no longer used, removing"
				rm -f ${SMART_CACHE_PATH}${OTA_TEMP}/$f
			fi
		done

		cd ${WD}
		rm -f ${SMART_CACHE_PATH}${OTA_TEMP}/repodata/primary.xml
	fi
}

# Logs the current action, creates a resume file.
SetResume()
{
	STAMP=`echo -n "$1 $2  :  "; date;`
	echo "${STAMP}" >> ${LOG_HISTORY}
	echo "$1 $2" >> ${RESUME_STEPS}
}

# Log operations to a timestamped file.
StartLogging()
{
	# Always initialize logging
	exec 3>&1 4>&2 >/var/log/fwinstall-${timestamp}-${subcommand}.log 2>&1
	echo "$command"
	cat /usr/bin/raven/fishspear/softwareversion.txt
	echo
}

# Log all commands and some state as for maximum understanding on complex operations.
StartVerboseLogging()
{
	set -x
	StartLogging
}

timestamp=$(date +"%Y%m%dT%H%M%S")
command="$0 $@"
subcommand="$1"
archive="$2"

# Execute subcommand
case "$subcommand" in
  start)
  		StartVerboseLogging

		##TODO:: check here to see if there is the install started flag, and attempt to complete if so
		##is this as easy as calling smart upgrade since the channels should be left as they were previously??
		SetResume "$subcommand" "$archive"

		#UploadLicenseCheck

		if [ -f "$archive" ]; then
			echo "Manual install of package $archive"
			TARBALL="$archive"
		else
			echo "Error: Installer $archive not found"
			exit 1
		fi

		#VerifyInstaller

		echo "Caching installer..."
		Copy2Disk

		echo "Decompressing packages..."
		ExtractRepo ${FIRMWARE_TEMP}

		echo "Starting Firmware Install..."
		CheckRotation

		if [ "$archive" = "${SMART_CACHE_PATH}$FIRMWARE_PREVIOUS" ]; then
			echo "Reverting, not clearing ota_temp"
		else
			if [ -d ${SMART_CACHE_PATH}$OTA_TEMP ]; then
				rm -rf ${SMART_CACHE_PATH}$OTA_TEMP
			fi
		fi

		set -o pipefail
		/usr/sbin/update_firmware local  | /usr/sbin/update_firmware_gui ${ROTATION}

		##TODO check error code of install, and validate install
		RET=$?
		if [ $RET -eq 0 ]; then
			#hack job here, lets figure out what we should and shouldn't be able to convert between then removed cached copies accordingly
			if [ "$archive" = "${SMART_CACHE_PATH}$FIRMWARE_PREVIOUS" ]; then
				rm -f ${SMART_CACHE_PATH}$FIRMWARE_PREVIOUS
				rm -f /usr/bin/raven/fishspearB/softwareversion.txt
			fi
			sync
		fi

		rm -rf ${RESUME_STEPS}
		sync

		/sbin/shutdown -r now
	;;
  ota-checksize)
  		StartLogging

		trap "kill_child_processes 1 $$; exit 1" SIGTERM
		/usr/sbin/update_firmware ota getsize 2>${SMART_CACHE_PATH}/${ERROR_FILE}
		RET=$?
		/usr/sbin/update_firmware_sqlite --error ${SMART_CACHE_PATH}/${ERROR_FILE}
		exit $RET
  ;;
  ota-download)
  		StartLogging

		#todo save subcommand and resume on startup??

		trap "kill_child_processes 1 $$; exit 1" SIGTERM

		set -o pipefail
		/usr/sbin/update_firmware ota download 2>${SMART_CACHE_PATH}/${ERROR_FILE} | /usr/sbin/update_firmware_sqlite &
		cpid=$!
		wait $cpid
		RET=$?
		/usr/sbin/update_firmware_sqlite --error ${SMART_CACHE_PATH}/${ERROR_FILE}
		exit $RET
  ;;
  ota-install)
  		StartVerboseLogging

		CheckRotation

		SetResume "$subcommand" "$archive"

		/usr/sbin/update_firmware ota install  | /usr/sbin/update_firmware_gui ${ROTATION}

		rm -rf ${RESUME_STEPS}
		sync

		/sbin/shutdown -r now
	;;
  cleancache)
  		StartLogging

		#todo:: clean up the download directory and reset system states
		echo "Error: Unimplemented"
		exit 1
	;;
  rotate)
  		StartVerboseLogging

		echo "Rotating Installers"
		RotateInstallers
	;;
  cache)
  		StartLogging

		echo "Caching Repository to ota_temp"
		CacheRepo
	;;
  extract)
  		StartLogging

		ExtractRepo ${FIRMWARE_CURRENT}
	;;
  revert)
  		StartVerboseLogging

		SetResume "$subcommand" "$archive"
		if [ -f ${SMART_CACHE_PATH}$FIRMWARE_PREVIOUS ]; then

			rm -rf ${SMART_CACHE_PATH}${OTA_TEMP} #remove any partial installs or downloads

			if [ -d ${SMART_CACHE_PATH}${OTA_PREVIOUS} ]; then  #save the previous installer to temp if it exists so it gets rolled into current
				cp -R ${SMART_CACHE_PATH}${OTA_PREVIOUS} ${SMART_CACHE_PATH}${OTA_TEMP}
			fi

			if [ -f /usr/bin/raven/revertscript*.xml ]; then
				rm /usr/bin/raven/revertscript*
			fi
			if [ -f /var/lib/smart/revertscript*.xml ]; then
				cp /var/lib/smart/revertscript* /usr/bin/raven/
			fi

			/etc/init.d/fwinstall start ${SMART_CACHE_PATH}$FIRMWARE_PREVIOUS
		else
			echo "Rollback package not found"
			exit 1
		fi
	;;
  *)
	echo "Usage: /etc/init.d/$NAME {start|rotate|cache|extract|revert|ota-checksize|ota-download|ota-install}"
	exit 1
	;;
esac

exit 0
