#!/sbin/runscript
# Copyright 1999-2004 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 2004/10/03 00:37:54 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}" -a -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 -a -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 -a -x /sbin/raidstart ]
				then
					/sbin/raidstart "${i}"
					retval=$?
				fi
				if [ "${retval}" -gt 0 -a -x /sbin/raid0run ]
				then
					/sbin/raid0run "${i}"
					retval=$?
				fi
				if [ "${retval}" -gt 0 -a -x /sbin/raidadd -a -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}" -a -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}" -a -x /sbin/vgscan ] && \
	   [ -d /proc/lvm -o "$(grep device-mapper /proc/misc 2>/dev/null)" ]
	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 -o -d /etc/lvm ]
		then
			/sbin/vgchange -a y >/dev/null
		fi
		eend $? "Failed to setup the LVM"
	fi

	dm-crypt-start

	if [ -f /fastboot -o -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 -a "${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 mountline mount swap options pre_mount post_mount source

	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 mount swap options pre_mount post_mount source
					;;

				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 ${mount} ]]; then
		target=${mount}
		: ${options:='-c aes -h sha1'}
	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}"
	/bin/cryptsetup ${options} create ${target} ${source} >/dev/console </dev/console
	eend $? "failure running cryptsetup"
	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
