#! /bin/sh
#
# Preserve the random seed between reboots. See urandom(4).
#

# Quietly do nothing if /dev/urandom does not exist
[ -c /dev/urandom ] || exit 0

URANDOM_SEED="/var/lib/random-seed"

# shellcheck source=/dev/null
[ -r "/etc/default/urandom" ] && . "/etc/default/urandom"

if pool_bits=$(cat /proc/sys/kernel/random/poolsize 2> /dev/null); then
	pool_size=$((pool_bits/8))
else
	pool_size=512
fi

check_file_size() {
	[ -f "$URANDOM_SEED" ] || return 1
	# Try to read two blocks but exactly one will be read if the file has
	# the correct size.
	size=$(dd if="$URANDOM_SEED" bs="$pool_size" count=2 2> /dev/null | wc -c)
	test "$size" -eq "$pool_size"
}

init_rng() {
	if check_file_size; then
		printf 'Initializing random number generator: '
		dd if="$URANDOM_SEED" bs="$pool_size" of=/dev/urandom count=1 2> /dev/null
		status=$?
		if [ "$status" -eq 0 ]; then
			echo "OK"
		else
			echo "FAIL"
		fi
		return "$status"
	fi
}

save_random_seed() {
	printf 'Saving random seed: '
	if touch "$URANDOM_SEED" 2> /dev/null; then
		old_umask=$(umask)
		umask 077
		dd if=/dev/urandom of="$URANDOM_SEED" bs="$pool_size" count=1 2> /dev/null
		status=$?
		umask "$old_umask"
		if [ "$status" -eq 0 ]; then
			echo "OK"
		else
			echo "FAIL"
		fi
	else
		status=$?
		echo "SKIP (read-only file system detected)"
	fi
	return "$status"
}

case "$1" in
	start|restart|reload)
		# Carry a random seed from start-up to start-up
		# Load and then save the whole entropy pool
		init_rng && save_random_seed;;
	stop)
		# Carry a random seed from shut-down to start-up
		# Save the whole entropy pool
		save_random_seed;;
	*)
		echo "Usage: $0 {start|stop|restart|reload}"
		exit 1
esac
