#! /bin/bash
### BEGIN INIT INFO
# Provides:             voyage-sync
# Required-Start:       $local_fs
# Required-Stop:        $local_fs
# X-Stop-After:     	$network
# Should-Start:
# Should-Stop:          
# Default-Start:        S
# Default-Stop:         0 6
# Short-Description:    Voyage tmpfs and sync
# Description:          Voyage tmpfs and sync
### END INIT INFO
#
# skeleton  example file to build /etc/init.d/ scripts.
#       This file should be used to construct scripts for /etc/init.d.
#
#       Written by Miquel van Smoorenburg <miquels@cistron.nl>.
#       Modified for Debian
#       by Ian Murdock <imurdock@gnu.ai.mit.edu>.
#
# Version:  @(#)skeleton  1.9  26-Feb-2001  miquels@cistron.nl
#

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
#DAEMON=/usr/sbin/voyage-sync
NAME=voyage-sync
DESC=voyage-sync

#TMPFS_ROOT=/lib/init/rw
TMPFS_ROOT=/tmp
SYNC_DIRS="var/log var/tmp"
SAVED_DATE_FILE=/var/log/voyage.saved-date

NEED_REBOOT=no

# using the following commands to install
#	
#	update-rc.d voyage-sync start 36 S . stop 99 0 6 .

if [ -f /etc/default/voyage-util ] ; then 
	. /etc/default/voyage-util; 
fi

SYNC_DIRS="$SYNC_DIRS $VOYAGE_SYNC_DIRS"
UNIONFS=${VOYAGE_UNIONFS:=tmpfs}

reconfig_resolvconf() {
	PKG=$(dpkg-query --show|grep resolvconf)
	if  [ ! -z "$PKG" ] && [ ! -L /etc/resolv.conf ] ; then
		MSG="  Reconfiguring resolvconf." ; voyage_log
		DEBIAN_FRONTEND=noninteractive dpkg-reconfigure resolvconf
	fi
}

voyage_log() {
	echo "`date +\"%b %e %T\"` $HOSTNAME $NAME: $MSG" >> /var/log/syslog
	echo "$NAME: $MSG"
}

copy_ro_to_rw() {
	if [ -d /ro ] ; then
		if [ -d $TMPFS_ROOT ] ; then
			MSG="  Copying /ro to $TMPFS_ROOT" ; voyage_log

			DIRMODE=$(stat -c "%a" $TMPFS_ROOT)
			tar -C /ro -cf - . | tar -C $TMPFS_ROOT -xf -
			chmod $DIRMODE $TMPFS_ROOT
		fi
	fi
}

mount_dirs()
{
	# $1 : aufs|unionfs|tmpfs
	# $2 : source directory
	# $3 : target directory
	case $1 in
		'aufs')
			PERM=$(stat --format=%U:%G $2)
			chmod --reference=$2 $3
			chown --reference=$2 $3
			mount -t aufs -o dirs=$3:$2=ro none $2> /dev/null 2>&1
			#echo "chown $PERM $2"
			chown $PERM $2
			;;
		'unionfs')
			PERM=$(stat --format=%U:%G $2)
			chmod --reference=$2 $3
			chown --reference=$2 $3
			mount -t unionfs -o dirs=$3:$2=ro none $2> /dev/null 2>&1
			#echo "chown $PERM $2"
			chown $PERM $2
			;;
		'tmpfs')
			PERM=$(stat --format=%U:%G $2)
			chmod --reference=$2 $3
			chown --reference=$2 $3
			if [ "$(ls -A $2)" ] ; then cp -rp $2/. $3/; fi
			MSG="  tmpfs: mount back $3 to $2" ; voyage_log
			mount --bind $3 $2 
			#echo "chown $PERM $2"
			chown $PERM $2
			;;
		*)
	    	;;
	esac
}

save_system_time() {
	date > $SAVED_DATE_FILE
	MSG="Saved system time: `cat $SAVED_DATE_FILE`" ; voyage_log
}

restore_system_time() {
	if [ -f $SAVED_DATE_FILE ] ; then
		CURRENT_DATE=`date`
		if [ "${CURRENT_DATE:24:4}" -lt "2011" ] ; then
			# Only if no RTC present, or no battery 
			MSG="Restore system time to: `cat $SAVED_DATE_FILE`" ; voyage_log
			date -s "`cat $SAVED_DATE_FILE`"
		fi
	fi
}

case $1 in
	'start')
		if [ "$VOYAGE_SAVE_DATE_TIME" = "YES" ] ; then 
			restore_system_time
		fi 
		MSG="Start tmpfs..." ; voyage_log
		# check SYNC_DIRS if recovery after a power failure is activated
		if [ "$VOYAGE_SYNC_RECOVER" = "YES" ] ; then
			MSG="  Checking if recovery from a power failure is needed..." ; voyage_log
			VOYAGE_SYNC_RECOVER_DIRS=${VOYAGE_SYNC_RECOVER_DIRS:-$SYNC_DIRS}
			for SYNC_DIR in $VOYAGE_SYNC_RECOVER_DIRS ; do
				if [ -d /.sync/$SYNC_DIR ] ; then
					MSG="  Recover'ing /.sync/$SYNC_DIR to `dirname /$SYNC_DIR`" ; voyage_log
					rsync -a -q --delete-after /.sync/$SYNC_DIR `dirname /$SYNC_DIR`
					MSG="  `dirname /$SYNC_DIR` recovered" ; voyage_log
					NEED_REBOOT=yes
				fi
			done
			# and now remove /.sync
			rm -rf /.sync
			# check if reboot is needed
			if [ "$NEED_REBOOT" = yes ] ; then
				MSG="Will now restart after recovery from a power failure" ; voyage_log
				sync
				# wait for logging to console
				sleep 1
				reboot -f
			fi
		fi

		reconfig_resolvconf
		copy_ro_to_rw
	
		MSG="  Setting up tmpfs for changed files..." ; voyage_log
		for SYNC_DIR in $SYNC_DIRS $VOYAGE_RW_DIRS; do
			if [ ! -d /$SYNC_DIR ] ; then continue; fi
			[ ! -d $TMPFS_ROOT/$SYNC_DIR ] && mkdir -p $TMPFS_ROOT/$SYNC_DIR
			
			mount_dirs $UNIONFS /$SYNC_DIR $TMPFS_ROOT/$SYNC_DIR
			
			#chmod --reference=/$SYNC_DIR $TMPFS_ROOT/$SYNC_DIR
			#chown --reference=/$SYNC_DIR $TMPFS_ROOT/$SYNC_DIR			
			#mount -t aufs -o dirs=$TMPFS_ROOT/$SYNC_DIR:$SYNC_DIR=ro none /$SYNC_DIR> /dev/null 2>&1
		done
		MSG="Start tmpfs completed" ; voyage_log
		;;
	'sync')
        if [ "$VOYAGE_SAVE_DATE_TIME" = "YES" ] ; then 
			save_system_time
        fi
		MSG="Synchronizing tmpfs changed files..." ; voyage_log
		for SYNC_DIR in $SYNC_DIRS ; do
			if [ ! -d /$SYNC_DIR ] ; then continue; fi
			if [ ! -d /.sync/$SYNC_DIR ] ; then
				mkdir -p /.sync/$SYNC_DIR
				PERM=$(stat --format=%U:%G /$SYNC_DIR)
				chown $PERM /.sync/$SYNC_DIR
			fi
		
			MSG="  Sync'ing /$SYNC_DIR to `dirname /.sync/$SYNC_DIR`" ; voyage_log
			if [ "$(ls -A /$SYNC_DIR)" ]; then
				rsync -a -q --delete-after /$SYNC_DIR/. /.sync/$SYNC_DIR &
			fi
		done
		MSG="Wait until all sync complete." ; voyage_log
		wait
		sync
		MSG="Synchronization tmpfs completed" ; voyage_log
		;;
	'stop')
		if [ $(cat /proc/cmdline|grep "boot=live"|wc -l) -gt 0 ] ; then
			exit 0
		fi

		MSG="Stop tmpfs..." ; voyage_log
		[ -f /usr/local/sbin/remountrw ] && /usr/local/sbin/remountrw

		# call "voyage-sync sync"
		$0 sync

		# then kill suspicous process in sync & RW dir and unmount
		for SYNC_DIR in $SYNC_DIRS $VOYAGE_RW_DIRS; do
			if [ ! -d /$SYNC_DIR ] ; then continue; fi
			if [ "$(ls -A /$SYNC_DIR)" ]; then
			for P in `lsof -F p /$SYNC_DIR`
			do
				MSG="  Killing process: $(ps --no-heading --format=comm -p ${P:1})" ; voyage_log
				kill ${P:1}
			done
			fi
			sleep 1

			MSG="  Unmount'ing /$SYNC_DIR" ; voyage_log
			umount /$SYNC_DIR		
			
			MSG="  Sync'ing /.sync/$SYNC_DIR to `dirname /$SYNC_DIR`" ; voyage_log
			rsync -a -q --delete-after /.sync/$SYNC_DIR `dirname /$SYNC_DIR` &
		done
		# wait until all sync complete.
		MSG="Wait until all sync complete." ; voyage_log
		wait
		
		# at last remove /.sync
		rm -rf /.sync
		sync
		MSG="Stop tmpfs completed" ; voyage_log
		;;
  	force-reload|restart)
    	;;

	*)
		echo "Usage: /etc/init.d/voyage-sync {start|stop|sync}" >&2
	;;
esac

