#!/bin/sh
#
# chkconfig:	2345 02 98
# description:	cryptofs is used to mount encrypted filesystems (including \
#		swap files/partitions)
# processname:	cryptofs
# config:	/etc/cryptofstab

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

# See how we were called.
case "$1" in
  start)
	LOOPNO=0
	cat /etc/cryptofstab |\
	sed 's/#.*//' |\
	while read DEVICE MNTPNT FSTYPE CRYPT OPTS FSCK; do
	    # Mount at startup?
	    [ -z "$DEVICE" ] && continue
	    echo "$OPTS" | grep -qw "noauto" && continue
	    cat /etc/cryptomtab 2>&1 | awk '{ print $2 }' |\
	    grep -qw "$DEVICE" && continue
            # Find next suitable loop device
            while
		losetup "/dev/loop$LOOPNO" >/dev/null 2>&1; [ "$?" = "0" ]
	    do
		LOOPNO="$(( $LOOPNO + 1 ))"
	    done
	    if [ "$FSTYPE" = "swap" ]; then
		PRI="$( echo "$OPTS" | sed '
		    s/.*pri=\(-\?[0-9]\+\)/\1/
		    t
		    d
		')"
		echo "$OPTS" | grep -qw "new" && NEWSWAP=1
		echo "$OPTS" | grep -qw "randompass" && RANDPASS=1 && NEWSWAP=1
		while true; do
		    show "Setting up %s encryption on %s (%s)" "$CRYPT" "$DEVICE" "$FSTYPE"
		    started
		    if [ -n "$RANDPASS" ]; then
			dd if=/dev/urandom bs=16 count=1 2>/dev/null |\
			losetup "/dev/loop$LOOPNO" "$DEVICE" \
			    -e "$CRYPT" -p 0
		    else
		    	losetup "/dev/loop$LOOPNO" "$DEVICE" \
				-e "$CRYPT" <&2
		    fi
		    if [ -n "$NEWSWAP" ]; then
			show "Creating swap filesystem on %s" $DEVICE
			mkswap "/dev/loop$LOOPNO" > /dev/null 2>&1
			ok
		    fi	
		    if
			show "Activating swap on $DEVICE"
			swapon "/dev/loop$LOOPNO" \
			    $( [ -n "$PRI" ] && echo "-p $PRI" ) > /dev/null 2>&1
			[ "$?" = 0 ] && ok || fail
		    then
		    	echo "/dev/loop$LOOPNO $DEVICE swap" >> /etc/cryptomtab 
		    	break
		    else
			losetup -d "/dev/loop$LOOPNO"
			nls -n "swapon for %s failed! Try again? [yes]: " "$DEVICE"
			read ODP <&2
			is_no "$ODP" && [ -n "$ODP" ] && break
		    fi
		done
	    else
		# not a swap fs
		while true; do
		    	show "Setting up %s encryption on %s (%s)" "$CRYPT" "$DEVICE" "$FSTYPE"
			started
			losetup "/dev/loop$LOOPNO" "$DEVICE" \
				-e "$CRYPT" <&2
			# fake mount - check if password was correct
			if
				show "Mounting %s as %s (ro)" "$DEVICE" "$MNTPNT"
				mount "/dev/loop$LOOPNO" \
					"$MNTPNT" \
					-t "$FSTYPE" \
					-n \
					-o "ro,$OPTS" >/dev/null 2>&1
			then
				ok
				if is_yes "$FSCK"; then
					show "Checking filesystem"; started
					initlog -c "fsck -C -T -a /dev/loop$LOOPNO"
					if [ "$?" -gt 1 ]; then
						nls "*** An error occured during the file system check."
						nls "*** This filesystem will NOT be mounted."
						umount "/dev/loop$LOOPNO" -n
						losetup -d "/dev/loop$LOOPNO"
						break
					fi
				fi
				
				umount "/dev/loop$LOOPNO"
				run_cmd "Remounting filesystem in rw mode" \
					mount "/dev/loop$LOOPNO" \
						"$MNTPNT" \
						-t "$FSTYPE" \
						-o "$OPTS"
				awk "\$1==\"/dev/loop$LOOPNO\" {
					\$1 = \"$DEVICE\"
					\$4 = \$4 \",loop=/dev/loop$LOOPNO\"
					\$4 = \$4 \",encryption=$CRYPT\"
				}
				{ print }" /etc/mtab > /etc/mtab~
				mv -f /etc/mtab~ /etc/mtab
				echo "/dev/loop$LOOPNO $DEVICE $FSTYPE" >> /etc/cryptomtab
				break
			else
				fail
				losetup -d "/dev/loop$LOOPNO"
				nls -n "mount for %s failed! Try again? [yes]: " "$DEVICE"
				read ODP <&2
				is_no "$ODP" && [ -n "$ODP" ] && break
			fi
		done
	    fi
	done 2<&1
	[ -s /etc/cryptomtab ] &&\
	touch /var/lock/subsys/cryptofs ||\
	rm -f /var/lock/subsys/cryptofs
	exit 0
	;;
  stop)
  	: > /etc/cryptomtab~
	show "Disabling encrypted swap"
	cat /etc/cryptomtab |\
	while read LOOP DEVICE TYPE; do
		if [ "$TYPE" = "swap" ]; then
			swapoff "$LOOP"
			losetup -d "$LOOP"
		fi
	done
	ok
	show "Unmounting encrypted filesystems"
	cat /etc/cryptomtab |\
	while read LOOP DEVICE TYPE; do
		if [ "$TYPE" != "swap" ]; then
			umount "$DEVICE" ||\
			echo "$LOOP $DEVICE $TYPE" >> /etc/cryptomtab~
		fi
	done
	mv -f /etc/cryptomtab~ /etc/cryptomtab
	[ -s /etc/cryptomtab ] && fail || ok
	[ -s /etc/cryptomtab ] &&\
	touch /var/lock/subsys/cryptofs ||\
	rm -f /var/lock/subsys/cryptofs
	exit 0
	;;
  status)
  	LOOPNO=0
	while
	    losetup "/dev/loop$LOOPNO" 2>/dev/null
	do
	    LOOPNO="$(( $LOOPNO + 1 ))"
	done
	exit 0
	;;
  *)
	msg_Usage "$0 {start|stop|status}"
	exit 1
esac

