#!/bin/sh -efu

. shell-error

## Volume manager specific functions

fstype() {
	[ "$#" -eq 1 -a -n "$1" ] || return 1
	blkid -o value -s TYPE "$1"|grep -v swap
}

volumes() {
	blkid -o device | grep -v loop | grep -v ram | grep -v /dev/sr[0-9]
}

## Functions

usage() {
	echo "Usage: $PROG [--help|--list-only|<outdir>]" >&2
	exit 1
}

workdir=
exit_handler() {
	local rc=$?
	trap - EXIT
	if cut -d' ' -f2 /proc/mounts | grep -Fxqs "$workdir"; then
		umount -l "$workdir"
	fi
	[ ! -d "$workdir" ] || rm -rf -- "$workdir"
	exit $rc
}

suggest_manual() {
	echo "warning: $1 might need recovery or \`noload' mount option" >&2
}

listonly=
outdir=
i=0
fstab_list() {
	local v fs fslist success opts
	grep -wqs forensic /proc/cmdline && opts=",loop" || opts=
	for v in `volumes`; do
		fslist="`fstype "$v"`" && [ -n "$fslist" ] || continue

		success=
		for fs in $fslist; do
			case "$fs" in	# MDRAID, LVM2, LUKS
			*_member|crypto_*) continue;;
			esac

			modprobe -b $fs ||:
			mount -t "$fs" -o "ro$opts" "$v" "$workdir" \
				>/dev/null 2>&1 && success=1 || {
					[ -z "$opts" ] ||
						case "$fs" in
						ext3|ext4)
							suggest_manual "$v";;
						esac
				}
			case "$fs" in
			btrfs)
				subvols="$(btrfs subvolume list "$workdir" | cut -f9 -d' ')";;
			*)
				subvols=;;
			esac
		done

		[ -n "$success" ] || continue

		if [ ! -f "$workdir/etc/fstab" ] && [ -z "$subvols" ]; then
			umount -l "$workdir"
			continue
		fi

		for subvol in '' $subvols; do
			[ -f "$workdir/$subvol/etc/fstab" ] || continue
			i="$(($i+1))"
			[ -z "$listonly" ] &&
				cp -- "$workdir/$subvol/etc/fstab" "$outdir/fstab.$i" ||
				echo "File /etc/fstab found on volume '$v'"
			umount -l "$workdir"
		done
	done
}

[ "$#" -eq 1 ] || usage

if [ "$1" = "--list-only" ]; then
	listonly=1
elif [ "$1" = "--help" ]; then
	usage
else
	outdir="`readlink -ev "$1"`"
fi

trap exit_handler HUP PIPE INT QUIT TERM EXIT
workdir="`mktemp -dt "$PROG.XXXXXXXXXX"`"
fstab_list

[ "$i" -gt 0 ] && rc=0 || rc=1
exit $rc
