#! /bin/bash
#
# docomomo
#
# chkconfig: 2345 03 97
# description: mounts file systems from images in USB memory
#
# Copyright (C) 2006 zunda <zunda at freeshell.org>
# 
# Permission is granted for copying, modification, distribution,
# and distribution of modified versions of this work under the
# terms of GPL version 2 or later.
#
# Read the GPL.txt fle or gpl-3.0.txt file for more details.
#

RETVAL=0

# Source function library.
. /etc/init.d/functions

# Functions
# loads kernel modules to mount USB storage
load_module() {
	echo $"Loading kernel modules for USB storage ..."
	modprobe scsi_mod
	modprobe usb-storage
	echo $"Waiting 8 seconds for drive initialization ..."
	sleep 8
	modprobe uhci-hcd
	modprobe fat
	modprobe vfat
}

# detects where the USB storage is
usb_disk() {
	dmesg | grep -i 'Attached SCSI removable disk' | sed 's/.*\(sd[a-z]\).*/\1/;2Q'
}

usb_uuid() {
	for argv in $(cat /proc/cmdline); do
		case $argv in
			docomomo_uuid=*)
				echo ${argv#docomomo_uuid=}
				break
				;;
		esac
	done
}

usb_dev() {
	for argv in $(cat /proc/cmdline); do
		case $argv in
			docomomo_dev=*)
				echo ${argv#docomomo_dev=}
				break
				;;
		esac
	done
}

# identification of local machine
machine_id() {
	/sbin/lspci -n | /usr/bin/md5sum - | /bin/cut -d\  -f1
}

etc_size=1M	# ext2 image size reserved for changes in /etc
etc_erase='mtab blkid lvm sysconfig/hwconf sysconfig/xinit-session'
etc_patch=/mnt/usb/boot/etc/`machine_id`.patch

# See how we were called.
case "$1" in

  start)
	# check kernel modules
	[ -z `usb_disk` ] && load_module
	# mount file systems
	uuid=`usb_uuid`
	grep -q /mnt/usb /proc/mounts ||\
	if [ -z "$uuid" ]; then
		dev=`usb_dev`
		if [ -z "$dev" ]; then
			dev=/dev/`usb_disk`1
		fi
		echo $"Mounting USB flash drive at $dev"
		mount $dev /mnt/usb
	else
		echo $"Mounting USB flash drive $uuid"
		mount -U $uuid /mnt/usb
	fi;
	grep -q /mnt/usb /proc/mounts ||\
	{
		echo $"Failed mounting USB flash drive. Going to runlevel 1 in 10 sec"
		( sleep 10; telinit 1 ) &
		exit 1
	}

	echo $"Mounting /usr and /.etc.prinstine"
	grep -q /usr /proc/mounts ||\
	mount -t squashfs -o loop /mnt/usb/boot/usr.sqs /usr &&\
	mount -t unionfs -o dirs=/mnt/unionfs/usr=rw:/usr=ro unionfs /usr ||\
	exit 1

	grep -q /.etc.prinstine /proc/mounts ||\
	mount -t squashfs -o loop /mnt/usb/boot/etc-orig.sqs /.etc.prinstine ||\
	exit 1

	if [ -e $etc_patch ]; then
		echo $"Restoring modified files in /etc"
		cd /etc && patch -p2 -N < $etc_patch
	fi

	echo $"Mounting /home"
	grep -q /home /proc/mounts ||\
	mount -t ext2 -o loop /mnt/usb/boot/home.ext /home ||\
	{
		fsck -t ext2 /mnt/usb/boot/home.ext
		mount -t ext2 -o loop /mnt/usb/boot/home.ext /home
	} || exit 1

	RETVAL=0
	touch /var/lock/subsys/docomomo
	;;

  stop)
	RETVAL=0
	# Store configurations
	echo $"Storing modified files in /etc"
	diff -urN --exclude=mtab --exclude=blkid /.etc.prinstine /etc > $etc_patch

	# umount file systems
	echo -n $"Stopping processes still using /usr or /home"
	/sbin/fuser -k -c -v /usr /home && sleep 1 && \
	/sbin/fuser -k -c -v /usr /home && sleep 2 && \
	/sbin/fuser -k -c -v /usr /home

	echo $"Umounting /home, /usr, and /.etc.prinstine"
	grep -q /home /proc/mounts && umount /home || RETVAL=1
	grep -q 'unionfs /usr' /proc/mounts && umount /usr && umount /usr || RETVAL=1
	grep -q /.etc.prinstine /proc/mounts && umount /.etc.prinstine || RETVAL=1

	echo $"Umounting the USB memory"
	grep -q /mnt/usb /proc/mounts && umount /mnt/usb || RETVAL=1
	[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/docomomo
	;;

  status)
	if [ -e /var/lock/subsys/docomomo ]; then
		echo 'Modified files in /etc:'
		diff -urN --exclude=mtab --exclude=blkid /.etc.prinstine /etc
		echo "This should also be in $etc_patch"
	fi
	RETVAL=0

	;;
  *)
	echo $"Usage: $0 {start|stop|status}"
	exit 1
	;;
esac

exit $RETVAL 
