#!/bin/sh
#
# This file checks the integrity of root image,
#

PATH=/bin:/usr/bin:/sbin:/usr/sbin

# Important files (or subdirs) which could be corrupted by
# unsynced power-off.
#
# XXXX
# Anything else we need to put here.

SYS_CONFIG_FILES="
/etc/config
/etc/hosts
/etc/passwd
"

#
# check_sysconf_files()
#
# Check whether there is any corrupted system config file in the primary partition.
#
#
check_sys_files()
{
	RET=0
	for i in $SYS_CONFIG_FILES; do
		if [ -d $i ]; then
			# is subdirs
			# Check all files under the subdirs.
			for j in `find $i -print`; do
				if [ -d $j ]; then 
					# Skip dirs.
					continue;
				fi
				# check if the file is clobbered. 
				grep "[[:alnum:]]" < $j >/dev/null 2>&1
				if [ $? -ne 0 ]; then
					# It is corrupted on primary.
					# Check if it belongs to any rpms.
					rpm -qf $j 2>/dev/null 1>&2
					if [ $? -ne 0 ]; then
						continue
					fi

					# Check the secondary
					grep "[[:alnum:]]" < /mnt/$j >/dev/null 2>&1
					if [ $? -ne 0 ]; then 
			echo "--- File $j is corrupted on both partitions."
						RET=1
					else
			echo "Recover file $j on primary partition."
						cp -a /mnt/$j $j	
					fi
				fi	
			done
		else	
			grep "[[:alnum:]]" < $i > /dev/null 2>&1
			if [ $? -ne 0 ]; then
				# It is corrupted on primary.
				# Check if it belongs to any rpms.
				rpm -qf $j 2>/dev/null 1>&2
				if [ $? -ne 0 ]; then
					continue
				fi

				# Check the secondary.
				grep "[[:alnum:]]" < /mnt/$i >/dev/null 2>&1
				if [ $? -ne 0 ]; then
			echo "--- File $i is corrupted on both partition"
					RET=1
				else
			echo "Recover file $i on primary partition."
					cp -a /mnt/$i $i	
				fi
			fi
		fi
	done
	return $RET
}

check_mount()
{
	status=0
	loop=0

	if [ "$2" = "" ]; then

		for dev in `bootenv OSRootPartition 2> /dev/null | tr ';' ' '`; do
			if [ $loop -eq 0 ]; then
				if [ "$dev" == "$1" ]; then
					state_value="clean;shutdown"
				else
					state_value="shutdown;clean"
				fi
			fi
			loop=`expr $loop + 1`
		done

		bootenv OSPartitionState "$state_value"
		status=1
	fi

	return $status
}
		

#
# set_recovery()
#
# Set up bootenv variables so the corrupted secondary image can be recovered. 
# Also restore OSRootPartition in case system is reboot again, before firmware
# is reloaded.
#
set_recovery()
{
	# Restore OSRootPartition.
	OSROOT=`bootenv OSRootPartition 2>/dev/null`
	set -- `echo $OSROOT | tr ';' ' '`
	case $# in
		2 ) bootenv OSRootPartition "$1;$2"
		;;
		3 ) bootenv OSRootPartition "$1;$2;$3"    
		;;
		* )
		echo "OSRootPartition is not set correctly!" 
		return 1 ;;
	esac
	
	# Set up AutoCommit token.
	bootenv Upgrade "/dev/$1"

	softupgrade=`bootenv SoftUpgrade 2>/dev/null`
	if [ "$softupgrade" = "" ]; then
		bootenv SoftUpgrade "commit"	
	fi

	return 0
}

#
# bad_system()
#
#  Both partitions are corrupted. Need manual recovery.
#  Mark both partition to be bad and reboot. 
# 
bad_system()
{
	bootenv BadRootDev "$1;$2"

	echo "--- System is going down for reboot now!"

#	reboot -f
}

#
# check_integrity()
#
# BadRootDev can be set for a partition due to interrupted firmwareDownload, 
# firmwareCommit or xfs_force_shutdown on that partition. 
# 
# If BadRootDev is set for both partition, we could not have come here because
# the code would have exited to the shell in linuxrc. The secondary partition
# may be in BadRootDev though.
#
# In this routine, we are doing 1) whether we have mounted the /mnt filesystem
# successfully or not. 2) Whether there are corrupted system config files or not. And 3)
# we set up bootenv variables to recover the secondary partition if it is in 
# BadRootDev.
#
check_integrity()
{
	dev_p=`cat /proc/mounts | grep " / " | grep -v rootfs |sed 's? .*??g;s?^.*dev/??g'`
	dev_s=`cat /proc/mounts |grep "/mnt" | sed 's? .*??g;s?^.*dev/??g'`
        dev_p=`echo $dev_p`     # skip space
        dev_s=`echo $dev_s`     # skip space

	# check mount point 
	check_mount $dev_p $dev_s
	if [ $? -ne 0 ]; then
		echo "--- Can not mount the secondary partition. "
		echo "--- System is going down for reboot for recovery."
		reboot -f
	fi	

	# Check if config files are corrupted.
	check_sys_files
	if [ $? -ne 0 ]; then
		echo "---" 
		echo "--- Please fix above files."
		echo "---" 
		bad_system $dev_p $dev_s
	fi

	badroot=`bootenv BadRootDev 2>/dev/null`

	# If there are two partitions in BadRootDev, we couldn't not come here.
	# Thus, if BadRootDev is set, it must be the secondary partition.
	#
	if [ $? -eq 0 ]; then
		echo "--- It appears that partition /dev/$dev_s is inconsistent."
		echo "--- Its content will be restored to be the same as that of /dev/$dev_p."
		echo "--- Please check the version and re-load firmware if necessary after the system is booted up".
		#
		# When SoftUpgrade token is set by software upgrade 
		# don't do recovery.
		#
			set_recovery $dev_p $dev_s
	fi
}

#
# main
#

check_integrity
