#!/bin/bash
#
# Usage: install.sh <imagefile>
#
# VERSION=14
# CHANGES="userappfs: commented out checks for kernel, firmware, rootfs"

BEROCONF=/usr/fallback/beroconf
rebootflag=$2
file=$1
image_dir=/tmp/images

function log
{
	echo ">> ${1}"
}

function fix_old_image_dir {

	mount -o remount,rw /

	if [ -d /mnt/images ]; then
		rm -rf /mnt/images
	fi

	ln -s /tmp /mnt/images

	mount -o remount,ro /
}

function tmp_cleanup {

	if [ -f /tmp/VERSION ]; then
		rm -f /tmp/VERSION
	fi

	if [ -f /tmp/content.txt ]; then
		rm -f /tmp/content.txt
	fi

	if [ -f /tmp/compare-content.txt ]; then
		rm -f /tmp/compare-content.txt
	fi
}

function cron_daemon {

	/etc/init.d/S45cron ${1} > /dev/null
}

mkdir -p ${image_dir}

if [ -z "${file}" ] ; then
	log "No filename given."
	exit 1
fi

if [ ! -f "${image_dir}/${file}" ] ; then
	log "File ${image_dir}/${file} not found"
	exit 1
fi

log "Getting VERSION file"
cd /tmp && tar zxf ${image_dir}/${file} VERSION
. /tmp/VERSION

if [ ! -L /mnt/images ]; then
	log "/mnt/images is not a symlink, fixing that."
	fix_old_image_dir
fi

log "Installing file: ${file}, type: ${TYPE}."

case "${TYPE}" in
	fpga)
		log "unpacking fpga image"
		cd /tmp && tar zxf ${image_dir}/${file} fpga.img

		/sbin/insmod /usr/local/modules/bfpga.ko
		if [ -f /tmp/fpga.img ] ; then
			log "updating version file"
			mv /tmp/VERSION /usr/conf/VERSION.fpga

			log "installing fpga image, please stand by. This process may take 3 minutes. Do NOT turn off beroFix!"
			dd if=/tmp/fpga.img of=/dev/bfpga bs=512k count=1
		fi
	;;
	firmware)
		log "unpacking firmware"
		cd /tmp && tar zxf ${image_dir}/${file} firmware.axf

		log "updating firmware"
		dd if=/tmp/firmware.axf of=/dev/mtdblock3

		log "removing temporary file"
		rm /tmp/firmware.axf

		log "updating version file"
		mv /tmp/VERSION /usr/conf/VERSION.firmware
	;;
	kernel)
		log "unpacking kernel"
		cd /tmp && tar zxf ${image_dir}/${file} zImage

		log "updating kernel"
		dd if=/tmp/zImage of=/dev/mtdblock4

		log "removing temporary file"
		rm /tmp/zImage

		log "updating version file"
		mv /tmp/VERSION /usr/conf/VERSION.kernel
	;;
	rootfs)
		log "stopping services"
		/etc/init.d/S90app stop
		/etc/init.d/S60httpd stop

		log "loading berofix module"
		insmod /usr/local/modules/berofix.ko

		if [ -f /etc/ssh_host_key ]
		then
			log "copying ssh keys to conf partition"
			[ ! -d /usr/conf/ssh ] && mkdir /usr/conf/ssh
			cp -a /etc/ssh_host* /usr/conf/ssh/
		fi

		log "unpacking new rootfs"
		rm -rf /tmp/newroot
		mkdir /tmp/newroot || exit 1
		cd /tmp/newroot
		tar zxf ${image_dir}/${file} root.jffs2 || exit 1

		log "writing new rootfs to flash memory"
		dd if=root.jffs2 of=/dev/mtdblock5

		log "rebooting"
		dd if=/proc/RESET of=/dev/null
	;;
	userappfs)
		USERAPP_ROOT=/apps
		USERAPP_HOME=/home/admin

		if [ -z ${NAME} ]; then
			log "[userapp] Name of this UserApp is empty, leaving."
			exit 1
		fi

		log "[userapp] Cleaning up /tmp/."
		tmp_cleanup

		log "[userapp] Installing UserApp ${NAME}"
		log "[userapp] Description: ${DESCRIPTION}"

		log "[userapp] checking archive integrity"
		cd /tmp
		tar zxf ${image_dir}/${file} content.txt 2> /dev/null
		if [ ! -f /tmp/content.txt ]; then
			log "[userapp] FAILED: archive not compatible!"
			exit 1
		fi
		tar tzf ${image_dir}/${file}  > /tmp/compare-content.txt
		for i in $(cat /tmp/content.txt | sed "s/\/$//" )  ; do
			if ! grep "$i" compare-content.txt > /dev/null ; then
				log "[userapp] FAILED: file '${i}' missing in archive, leaving."
				exit 1
			fi
		done

		log "[userapp] checking versions"
#		# check kernel
#		if [ -f /usr/conf/VERSION.kernel ] ; then
#			. /usr/conf/VERSION.kernel
#		else
#			KERNEL=1
#		fi
#		if [ ${NEED_KERNEL} -gt ${KERNEL} ] ; then
#			log "[userapp] FAILED: please update kernel to version ${NEED_KERNEL} and try again!"
#			exit 1
#		fi
#
#		# check rootfs
#		if [ -f /VERSION ] ; then
#			. /VERSION
#		else
#			ROOTFS=1
#		fi
#		if [ ${NEED_ROOTFS} -gt ${ROOTFS} ] ; then
#			log "[userapp] FAILED: please update rootfs to version ${NEED_ROOTFS} and try again!"
#			exit 1
#		fi
#
#		# check firmware
#		if [ -f /usr/conf/VERSION.firmware ]; then
#			. /usr/conf/VERSION.firmware
#		else
#			FIRMWARE=1
#		fi
#		if [ ${NEED_FIRMWARE} -gt ${FIRMWARE} ]; then
#			log "[userapp] FAILED: please update firmware to version ${NEED_FIRMWARE} and try again!"
#			exit 1
#		fi

		# check appfs
		if [ -f /usr/local/VERSION ]; then
			APPFS_FIL="$(cat /usr/local/VERSION)"
			APPFS=$(expr match "${APPFS_FIL}" ".*APPFS=\([0-9]*\)")
			unset APPFS_FIL
		else
			APPFS=1
		fi
		if [ ${NEED_APPFS} -gt ${APPFS} ]; then
			log "[userapp] FAILED: please update firmware to version ${NEED_APPFS} and try again!"
			exit 1
		fi

		# check if there are enough slots left
		if [ -x /home/admin/setup/get_slots_used.sh ]; then

			userapp_used_slots=$(/home/admin/setup/get_slots_used.sh ${NAME})
			let userapp_total_slots=${userapp_used_slots}+${SLOTS}

			if [ ${userapp_total_slots} -gt 8 ]; then
				log "[userapp] FAILED: this userapp uses too many slots (${SLOTS} + ${userapp_used_slots} > 8)."
				exit 1
			fi

			log "[userapp] INFO: Package ${NAME} uses ${SLOTS} slots."
			log "[userapp] INFO: After installation ${userapp_total_slots} slots will be marked as used."
		fi

		cron_daemon stop

		log "[userapp] stopping services"
		/etc/init.d/S91userapp stop

		log "[userapp] mount userapp partition (rw)"
		/bin/mount -oremount,rw ${USERAPP_HOME} || exit 1

		if [ -d ${USERAPP_ROOT}/${NAME} ]; then
			log "[userapp] executing userapp pre_remove script"
			[ -x /home/admin/setup/pre_remove.sh ] && /home/admin/setup/pre_remove.sh ${NAME}

			log "[userapp] cleanup package ${NAME}"
			rm -rf ${USERAPP_ROOT}/${NAME}
		fi

		log "[userapp] extract new image (${file})"
		cd ${USERAPP_ROOT} && tar zxf ${image_dir}/${file} || exit 1

		log "[userapp] executing post_install script"
		[ -x /home/admin/setup/post_install.sh ] &&  /home/admin/setup/post_install.sh ${NAME}

		log "[userapp] updating PATH and LD_LIBRARY_PATH variables in .bash_profile"
		for i in $(ls /apps/); do
			path_str_bin="${path_str_bin}:/apps/${i}/bin"
			path_str_lib="${path_str_lib}:/apps/${i}/lib"
		done
		path_str_bin=$(echo ${path_str_bin} | sed -e 's/\([[\/.*]\|\]\)/\\&/g')
		path_str_lib=$(echo ${path_str_lib} | sed -e 's/\([[\/.*]\|\]\)/\\&/g')
		sed "s/APPS_PATHS/${path_str_bin}/g" /home/admin/bash_profile_skel > /tmp/admin_bash_profile.tmp
		sed "s/LIBS_PATHS/${path_str_lib}/g" /tmp/admin_bash_profile.tmp > /home/admin/.bash_profile
		rm -f /tmp/admin_bash_profile.tmp

		log "[userapp] setting permissions"
		chown -R admin:admin ${USERAPP_ROOT}/${NAME}

		log "[userapp] wait and sync"
		sleep 1; sync; sync; sleep 1

		log "[userapp] mount partition (ro)"
		/bin/mount -oremount,ro ${USERAPP_HOME} || exit 1

		log "[userapp] Cleaning up /tmp/."
		tmp_cleanup

		log "[userapp] starting services"
		/etc/init.d/S91userapp start

		cron_daemon start
		;;
	*)
		DOWNGRADE_IND=$(echo ${file} | grep "downgrade")

		if [ -z "${DOWNGRADE_IND}" ]; then
			log "Checking for archive integrity."
			cd /tmp && tar zxf ${image_dir}/${file} content.txt 2>/dev/null
			if [ ! -f /tmp/content.txt ]; then
				log "FAILED: Archive not compatible!"
				exit 1
			fi
			tar tzf ${image_dir}/${file} > /tmp/compare-content.txt
			for i in $(cat /tmp/content.txt | sed "s/\/$//" ); do
				if ! grep "$i" compare-content.txt > /dev/null; then
					log "FAILED: Missing Files in Archive!"
					exit 1
				fi
			done

			cd /tmp
			if ! grep bnxanalog content.txt 2>/dev/null ; then
				DOWNGRADE_IND=1
			fi
		fi

		rm -rf /tmp/content.txt
                rm -rf /tmp/compare-content.txt

		log "Checking versions."
		if [ -f /usr/conf/VERSION.kernel ] ; then . /usr/conf/VERSION.kernel ; else KERNEL=1 ; fi
		if [ -f /usr/conf/VERSION.firmware ] ; then . /usr/conf/VERSION.firmware ; else FIRMWARE=1 ; fi
		if [ -f /VERSION ] ; then . /VERSION ; else ROOTFS=1 ; fi

		if [ $NEED_KERNEL -gt $KERNEL ]; then log "FAILED: please update kernel to version $NEED_KERNEL and try again!" ; exit 1 ; fi
		if [ $NEED_FIRMWARE -gt $FIRMWARE ]; then log "FAILED: please update firmware to version $NEED_FIRMWARE and try again!" ; exit 1 ; fi
		if [ $NEED_ROOTFS -gt $ROOTFS ]; then log "FAILED: please update rootfs to version $NEED_ROOTFS and try again!" ; exit 1 ; fi

		cron_daemon stop

                log "Stopping UserAppFS services."
                /etc/init.d/S91userapp stop

		log "Stopping AppFS services."
		/etc/init.d/S90app stop

		log "Remounting AppFS partition (rw)."
		mount -o remount,rw /usr/local || exit 1

		log "Executing pre_remove script."
		[ -x /usr/local/setup/pre_remove.sh ] && /usr/local/setup/pre_remove.sh

		log "Removing old version file."
		[ -f /usr/local/FILENAME ] && rm -f /usr/local/FILENAME

		log "Cleaning up AppFS partition."
		cd /usr/local && ls | grep -v lost | xargs rm -rf

		log "Extracting new AppFS image."
		cd /usr/local && tar zxf ${image_dir}/${file} || exit 1
		chown -R root:root /usr/local/*

		log "Writing new version file."
		echo "$file" > /usr/local/FILENAME

		if [ ! -z "${DOWNGRADE_IND}" ]; then
			log "Cleaning up downgrade-incompatible configuration files."
			rm -f /usr/conf/isgw.gsm
		fi

		log "Waiting and syncing."
		sleep 1
		sync; sync
		sleep 1

                log "Removing uploaded appfs."
                rm -f ${image_dir}/${file}
		if [ -f /home/admin/${file} ]; then
			mount -oremount,rw /home/admin
			rm -f /home/admin/${file}
			mount -oremount,ro /home/admin
		fi

		log "Executing post_install script."
		[ -x /usr/local/setup/post_install.sh ] && /usr/local/setup/post_install.sh

		log "Remounting AppFS partition (ro)."
		cd / && mount -o remount,ro /usr/local

                sync

		${BEROCONF} set root app-status running
		${BEROCONF} set root app-image $(cat /usr/local/FILENAME)

#                if [ "$rebootflag" == "" ] ; then
#			log "Rebooting."
#			sbin/reboot
#			exit 1
#                fi

		log "Starting AppFS services."
		for i in /usr/local/init/S??* ; do
		        # Ignore dangling symlinks (if any).
		        [ ! -f "$i" ] && continue
		        if [ "$i" = "/usr/local/init/S99upgrade-firmware" ] || [ "$i" = "/usr/local/init/S02update-conf" ]; then
                       	log "Skipping service: $i."
	                        continue
        		fi
        		log "Starting service: $i."
	        	$i start
		done

                log "Starting UserAppFS services."
                /etc/init.d/S91userapp start

		cron_daemon start
	;;
esac

log "Done."

exit 0
