#!/bin/sh

# This script does the following:
# dm-crypt:  creates /etc/crypttab entries

. /lib/partman/lib/base.sh

crypttab_add_entry () {
	local realdev realdevdir cryptdev cryptdevdir keytype keyfile opts
	local method mnt target source
	realdev=$1
	realdevdir=$2
	cryptdev=$3
	cryptdevdir=$4
	keytype=$(cat $realdevdir/keytype)

	# Set basic options
	if [ $keytype = passphrase ]; then
		opts="luks"
	else
		for opt in cipher ivalgorithm keyhash keysize; do
			eval local $opt
			if [ -r "$realdevdir/$opt" ]; then
				eval $opt=$(cat $realdevdir/$opt)
			else
				return 1
			fi
		done
		opts="cipher=$cipher-$ivalgorithm,size=$keysize"
		if [ $keytype != random ] && [ -n "$keyhash" ]; then
			opts="$opts,hash=$keyhash"
		fi
	fi

	# Set key source
	if [ $keytype = random ]; then
		keyfile="/dev/urandom"
	elif [ $keytype = passphrase ]; then
		keyfile="none"
	elif [ -f $realdevdir/keyfile ]; then
		keyfile=$(cat $realdevdir/keyfile)
	else
		return 1
	fi

	# Check for special mounts
	method=$(cat $cryptdevdir/method)
	mnt=""
	if [ -f $cryptdevdir/mountpoint ]; then
		mnt=$(cat $cryptdevdir/mountpoint)
	fi
	if [ $method = swap ]; then
		opts="$opts,swap"
	elif [ "$mnt" = /tmp ] && [ $keytype = random ]; then
		opts="$opts,tmp"
	fi

        # Allow TRIM operations, and ensure systemd closes the
        # device at the end of the shutdown process, to avoid races
        opts="$opts,discard,x-initrd.attach"

	# Check mapping name
	target=$(basename $cryptdev)

	# Check source device
	source=$realdev

	# Use UUID for LUKS devices
	if cryptsetup isLuks "$source"; then
		local uuid=$(cryptsetup luksUUID "$source")
		source="UUID=$uuid"
	fi

	# Add entry to crypttab
	echo "$target $source $keyfile $opts" >> /target/etc/crypttab
}

for dev in $DEVICES/*; do
	[ -d "$dev" ] || continue
	cd $dev
	# skip unless encrypted
	[ -f crypt_realdev ] || continue

	partitions=
	open_dialog PARTITIONS
	while { read_line num id size type fs path name; [ "$id" ]; }; do
		[ "$fs" != free ] || continue
		partitions="$partitions $id,$path"
	done
	close_dialog

	for part in $partitions; do
		id=${part%,*}
		path=${part#*,}

		r=$(cat crypt_realdev)
		set -- $(IFS=: && echo $r)
		realdev=$1
		realdevnum=$2
		realdevdir=$3
		cryptdevdir=$dev/$id

		[ -f $realdevdir/cipher ] || continue
		[ -f $realdevdir/crypto_type ] || continue
		[ -f $realdevdir/keytype ] || continue
		[ -f $id/method ] || continue

		# skip unless swap, to be mounted or lvm on dm-crypt
		method=$(cat $id/method)
		type=$(cat $realdevdir/crypto_type)
		if [ "$method" != swap ] && [ "$method" != lvm ] && \
		   [ ! -f $id/mountpoint ]; then
			continue
		fi
		if [ "$method" = lvm ] && [ "$type" != dm-crypt ]; then
			continue
		fi

		realdev=$(mapdevfs $realdev)
		cryptdev=$(mapdevfs $path)

		case $type in
		dm-crypt)
			crypttab_add_entry $realdev $realdevdir $cryptdev $cryptdevdir
			;;
		esac
	done
done
