#!/sbin/runscript
# Copyright 1999-2005 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-src/rc-scripts/init.d/checkfs,v 1.42.4.3 2005/02/10 01:18:46 vapier Exp $

depend() {
	need checkroot modules
}

start() {
	local retval=0

	# Start software raid.
	# You need a properly configured /etc/raidtab for raidtools usage or a
	# properly configured /etc/mdadm.conf for mdadm usage. Devices in
	# /etc/mdadm.conf are initialized first, so any duplicate devices in
	# /etc/raidtab will not get initialized.
	if [[ -z ${CDBOOT} ]] && [[ -f /proc/mdstat ]] ; then
		local mdadm_devices=
		local raidtools_devices=
		# If /etc/mdadm.conf exists, grab all the RAID devices from it
		if [[ -f /etc/mdadm.conf ]] ; then
			mdadm_devices=$(awk '/^[[:space:]]*ARRAY/ { print $2 }' /etc/mdadm.conf)
		fi
		# If /etc/raidtab exists, grab all the RAID devices from it
		if [[ -f /etc/raidtab ]] ; then
			raidtools_devices=$(awk '/^[[:space:]]*raiddev/ { print $2 }' /etc/raidtab)
		fi
		ebegin "Starting up RAID devices: "

		local rc=0
		local retval=0

		for i in ${mdadm_devices} ; do
			local raiddev=${i##*/}
			local raidstat=$(egrep "^${raiddev} : active" /proc/mdstat)

			if [[ -z ${raidstat} ]] ; then
				# First scan the /etc/fstab for the "noauto"-flag
				# for this device. If found, skip the initialization
				# for it to avoid dropping to a shell on errors.
				# If not, try raidstart...if that fails then
				# fall back to raidadd, raidrun.  If that
				# also fails, then we drop to a shell
				local retval=1
				local noauto=$(egrep "^${i}" /etc/fstab | grep -c 'noauto')

				einfon "  Trying ${raiddev}..."

				raiddev=""
				
				if [[ ${noauto} -gt 0 ]] ; then
					retval=0
					raiddev=" (skipped)"
				fi
				if [[ ${retval} -gt 0 && -x /sbin/mdadm ]] ; then
					/sbin/mdadm -As "${i}" &>/dev/null
					retval=$?
				fi

				echo "${raiddev}"
				
				if [[ ${retval} -gt 0 ]] ; then
					rc=1
					eend ${retval}
				else
					ewend ${retval}
				fi
			fi
		done

		for i in ${raidtools_devices} ; do
			local raiddev=${i##*/}
			local raidstat=$(egrep "^${raiddev} : active" /proc/mdstat)

			if [[ -z ${raidstat} ]] ; then
				# First scan the /etc/fstab for the "noauto"-flag
				# for this device. If found, skip the initialization
				# for it to avoid dropping to a shell on errors.
				# If not, try raidstart...if that fails then
				# fall back to raidadd, raidrun.  If that
				# also fails, then we drop to a shell
				local retval=1
				local noauto=$(egrep "^${i}" /etc/fstab | grep -c 'noauto')

				einfon "  Trying ${raiddev}..."

				raiddev=""

				if [[ ${noauto} -gt 0 ]] ; then
					retval=0
					raiddev=" (skipped)"
				fi
				if [[ ${retval} -gt 0 && -x /sbin/raidstart ]] ; then
					/sbin/raidstart "${i}"
					retval=$?
				fi
				if [[ ${retval} -gt 0 && -x /sbin/raid0run ]] ; then
					/sbin/raid0run "${i}"
					retval=$?
				fi
				if [[ ${retval} -gt 0 && -x /sbin/raidadd && -x /sbin/raidrun ]] ; then
					/sbin/raidadd "${i}"
					/sbin/raidrun "${i}"
					retval=$?
				fi

				echo "${raiddev}"

				if [[ ${retval} -gt 0 ]] ; then
					rc=1
					eend ${retval}
				else
					ewend ${retval}
				fi
			fi
		done

		# A non-zero return means there were problems.
		if [[ ${rc} -gt 0 ]] ; then
			echo
			eerror "An error occurred during the RAID startup"
			eerror "Dropping you to a shell; the system will reboot"
			eerror "when you leave the shell."
			echo; echo
			/sbin/sulogin ${CONSOLE}
			einfo "Unmounting filesystems"
			/bin/mount -a -o remount,ro &>/dev/null
			einfo "Rebooting"
			/sbin/reboot -f
		fi
	fi

	#
	# EVMS2 summport for /usr, /var ....
	#
	if [[ -z ${CDBOOT} ]] && [[ -f /sbin/evms_activate ]] ; then
		ebegin "Activating EVMS2"
		evms_activate
		retval=$?	
		eend ${retval}
	fi

	# LVM support for /usr, /home, /opt ....
	# This should be done *before* checking local
	# volumes, or they never get checked.

	# NOTE: Add needed modules for LVM or RAID, etc
	#       to /etc/modules.autoload if needed

	if [[ -z ${CDBOOT} && -x /sbin/vgscan ]] && \
	   [[ -d /proc/lvm || -n $(grep -o device-mapper /proc/misc) ]]
	then
		ebegin "Setting up the Logical Volume Manager"
		#still echo stderr for debugging
		/sbin/vgscan > /dev/null
		if [[ $? -eq 0 ]] && [[ -x /sbin/vgchange ]] && \
		   [[ -f /etc/lvmtab || -d /etc/lvm ]]
		then
			/sbin/vgchange -a y >/dev/null
		fi
		eend $? "Failed to setup the LVM"
	fi

	dm-crypt-start

	if [[ -f /fastboot ]] || [[ -n ${CDBOOT} ]] ; then
		rm -f /fastboot
	else
		ebegin "Checking all filesystems"
		if [[ -f /forcefsck ]] ; then
			ewarn "A full fsck has been forced"
			fsck -C -R -A -a -f
			retval=$?
			rm -f /forcefsck
		else
			fsck -C -T -R -A -a
			retval=$?
		fi
		if [[ ${retval} -eq 0 ]] ; then
			eend 0
		elif [[ ${retval} -ge 1 && ${retval} -le 3 ]] ; then
			ewend 1 "Filesystem errors corrected."
			# Everything should be ok, so return a pass
			return 0
		else
			eend 2 "Fsck could not correct all errors, manual repair needed"
			/sbin/sulogin ${CONSOLE}
		fi
	fi
}

# Note: This function is exactly duplicated in localmount.  If you change it
# here, make sure to change it there also!
dm-crypt-start() {
	local cryptfs_status=0 
	local gpg_options key loop_file mount mountline options pre_mount post_mount source swap

	if [[ -f /etc/conf.d/cryptfs ]] && [[ -x /bin/cryptsetup ]] ; then
		ebegin "Setting up dm-crypt mappings"

		while read mountline; do
			# skip comments and blank lines
			[[ ${mountline}\# == \#* ]] && continue

			# check for the start of a new mount/swap
			case ${mountline} in
				mount=*|swap=*)
					# If we have a mount queued up, then execute it
					dm-crypt-execute

					# Prepare for the next mount/swap by resetting variables
					unset gpg_options key loop_file mount options pre_mount post_mount source swap
					;;

				gpg_options=*|key=*|loop_file=*|options=*|pre_mount=*|post_mount=*|source=*)
					if [[ -z ${mount} && -z ${swap} ]] ; then
						ewarn "Ignoring setting outside mount/swap section: ${mountline}"
						continue
					fi
					;;

				*)
					ewarn "Skipping invalid line in /etc/conf.d/cryptfs: ${mountline}"
					;;
			esac

			# Queue this setting for the next call to dm-crypt-execute
			eval "${mountline}"
		done < /etc/conf.d/cryptfs

		# If we have a mount queued up, then execute it
		dm-crypt-execute

		ewend ${cryptfs_status} "Failed to setup dm-crypt devices"
	fi

	return ${cryptfs_status}
}

# Setup mappings for an individual mount/swap
#
# Note: This relies on variables localized in dm-crypt-start.  This function
# is quite different from the function by the same name in localmount...
dm-crypt-execute() {
	local dev target

	if [[ -n ${loop_file} ]] ; then
		dev="/dev/mapper/${target}"
		ebegin "  Setting up loop device ${source}"
		/sbin/losetup ${source} ${loop_file} 
	fi

	if [[ -n ${mount} ]] ; then
		target=${mount}
		: ${options:='-c aes -h sha1'}
		[[ -n ${key} ]] && : ${gpg_options:='-q -d'}
	elif [[ -n ${swap} ]] ; then
		target=${swap}
		: ${options:='-c aes -h sha1 -d /dev/urandom'}
		: ${pre_mount:='mkswap ${dev}'}
	else
		return
	fi

	if /bin/cryptsetup status ${target} | egrep -q '\<active:'; then
		einfo "dm-crypt mapping ${target} is already configured"
		return
	fi

	ebegin "dm-crypt map ${target}"
	if [[ -z ${key} ]] ; then
		/bin/cryptsetup ${options} create ${target} ${source} >/dev/console </dev/console
		eend $? "failure running cryptsetup"
	else
		if [[ -x /usr/bin/gpg ]] ; then
			retval=1
			while [[ $retval -gt 0 ]] ; do
				keystring=$(gpg ${gpg_options} ${key} 2>/dev/null </dev/console)
				if [[ -z ${keystring} ]] ; then
					retval=5
				else
					/bin/cryptsetup ${options} create ${target} ${source} << EOF
${keystring}
EOF
					retval=$?
				fi
			done
			eend $retval
		else
			einfo "You have to install app-crypt/gpg first"
		fi
	fi
	if [[ $? != 0 ]] ; then
		cryptfs_status=1
	else
		if [[ -n ${pre_mount} ]] ; then
			dev="/dev/mapper/${target}"
			ebegin "  Running pre_mount commands for ${target}"
			eval "${pre_mount}" > /dev/null
			ewend $? || cryptfs_status=1
		fi
	fi
}

# vim:ts=4
