#! /bin/sh
### BEGIN INIT INFO
# Provides:          geli
# Required-Start:    kldutils
# Required-Stop:
# X-Start-Before:    checkroot
# X-Stop-After:      umountfs
# Default-Start:     S
# Default-Stop:      0 6
# Short-Description: Start/stop GELI subsystem.
# Description:
### END INIT INFO

# Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.

PATH=/sbin:/bin

. /lib/lsb/init-functions
. /lib/init/vars.sh

if test -e /etc/default/geli ; then
	. /etc/default/geli
fi

SYSCTL_N="sysctl -n"

# ltr str src dst
#	Change every $src in $str to $dst.
ltr()
{
	local _str _src _dst
	_str=$1
	_src=$2
	_dst=$3
	echo "${_str}" | sed -e "s,${_src},${_dst},g"
}

# Creates a list of providers for GELI encryption.
geli_make_list()
{
	local devices devices2
	local provider mountpoint type options rest

	# Create list of GELI providers from fstab.
	while read provider mountpoint type options rest ; do
		case ":${options}" in
		:*noauto*)
			noauto=yes
			;;
		*)
			noauto=no
			;;
		esac

		case ":${provider}" in
		:#*)
			continue
			;;
		*.eli)
			# Skip swap devices.
			if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then
				continue
			fi
			devices="${devices} ${provider}"
			;;
		esac
	done < /etc/fstab

	# Append providers from geli_devices.
	devices="${devices} ${geli_devices}"

	for provider in ${devices}; do
		provider=${provider%.eli}
		provider=${provider#/dev/}
		devices2="${devices2} ${provider}"
	done

	echo ${devices2}
}

geli_start()
{
	log_begin_msg "Starting GELI subsystem:"

	devices=`geli_make_list`
	if [ -z "${devices}" ]; then
		log_progress_msg "not configured; see /etc/default/geli"
		log_end_msg 255 # (warning)
		exit 0
	fi

	log_progress_msg "geom_eli"
	kldload geom_eli 2> /dev/null

	if [ -z "${geli_tries}" ]; then
		if [ -n "${geli_attach_attempts}" ]; then
			# Compatibility with rc.d/gbde.
			geli_tries=${geli_attach_attempts}
		else
			geli_tries=`${SYSCTL_N} kern.geom.eli.tries`
		fi
	fi

	for provider in ${devices}; do
		provider_=`ltr ${provider} '/' '_'`

		eval "flags=\${geli_${provider_}_flags}"
		if [ -z "${flags}" ]; then
			flags=${geli_default_flags}
		fi
		if [ -e "/dev/${provider}" -a ! -e "/dev/${provider}.eli" ]; then
			log_progress_msg "${provider}"
			count=1
			while [ ${count} -le ${geli_tries} ]; do
				geli attach ${flags} ${provider}
				RET=$?
				if [ -e "/dev/${provider}.eli" ]; then
					break
				fi
				count=$((count+1))
			done
			if ! [ "$RET" = 0 ]; then
				log_end_msg $RET
				exit $RET
			fi
		fi
	done

	# end
	log_end_msg 0
}

geli_stop()
{
	log_begin_msg "Stopping GELI subsystem:"

	devices=`geli_make_list`

	for provider in ${devices}; do
		if [ -e "/dev/${provider}.eli" ]; then
			log_progress_msg "${provider}"

			umount "/dev/${provider}.eli" 2>/dev/null
			geli detach "${provider}"
		fi
	done

	# end
	log_end_msg 0
}

case "$1" in
  start|"")
	geli_start
	;;
  restart|reload|force-reload)
	echo "Error: argument '$1' not supported" >&2
	exit 3
	;;
  stop)
	geli_stop
	;;
  *)
	echo "Usage: $0 [start|stop]" >&2
	exit 3
	;;
esac

:
