#!/bin/sh
# Sub-tests that require a mounted partition.
set -e
partition="$1"

. /usr/share/os-prober/common.sh

do_unmount() {
	if [ "$mounted" ]; then
		if ! umount "$tmpmnt"; then
			warn "failed to umount $tmpmnt"
		fi
	fi
	rmdir "$tmpmnt" || true
}

if [ "x$1" = xbtrfs ]; then
       types=btrfs
       if [ -z "$2" -o -z "$3" ]; then
               debug "missing btrfs parameters, exiting"
               exit 1
       fi
       UUID="$2"
       BTRFSDEV="$3"
else
       partition="$1"
       types="$(fs_type "$partition")"
fi

if [ "$types" = NOT-DETECTED ]; then
	debug "$1 type not recognised; skipping"
	exit 0
elif [ "$types" = swap ]; then
	debug "$1 is a swap partition; skipping"
	exit 0
elif [ "$types" = crypto_LUKS ]; then
	debug "$1 is a LUKS partition; skipping"
	exit 0
elif [ "$types" = LVM2_member ]; then
	debug "$1 is an LVM member; skipping"
	exit 0
elif [ "$types" = ntfs ]; then
	if type ntfs-3g >/dev/null 2>&1; then
		types='ntfs-3g ntfs'
	fi
elif [ -z "$types" ]; then
	if type cryptsetup >/dev/null 2>&1 && \
	   cryptsetup luksDump "$partition" >/dev/null 2>&1; then
		debug "$1 is a LUKS partition; skipping"
		exit 0
	fi

	# Simply skip such partition is better than trying to detect
	# it by blinded test mounts with all kinds of kernel file system,
	# that would lead to unwanted consequence like kernel oops and
	# risk to corrupt your system and data.
	debug "$1 is a partition without file system; skipping"
	exit 0
fi

tmpmnt="$(mktemp -d /tmp/os-probes-50mounted-tests.XXXXXX)"

mounted=

if [ "$types" = btrfs ]; then
	partition="$BTRFSDEV"
elif type grub2-mount >/dev/null 2>&1 && \
   type grub2-probe >/dev/null 2>&1 && \
   grub2-mount "$partition" "$tmpmnt" 2>/dev/null; then
	mounted=1
	type="$(grub2-probe -d "$partition" -t fs)" || true
	if [ "$type" ]; then
		debug "mounted using GRUB $type filesystem driver"
	else
		debug "mounted using GRUB, but unknown filesystem?"
		type=fuseblk
	fi
fi

if [ "$mounted" ]; then
	for test in /usr/lib/os-probes/mounted/*; do
		debug "running subtest $test"
		if [ -f "$test" ] && [ -x "$test" ]; then
			if "$test" "$partition" "$tmpmnt" "$type"; then
				debug "os found by subtest $test"
				do_unmount
				exit 0
			fi
		fi
	done
fi

if [ "$types" != "btrfs" ]; then
	do_unmount
	exit 1
fi

probe_subvol ()
{
	local subvol=$1
	local partition=$2
	local UUID=$3
	local tmpmnt=$4

	local mounted=
	mpoint="$(grep btrfs /proc/self/mountinfo | grep "$partition " | grep "/$subvol " | cut -d ' ' -f 5)"
	ret=1

	if [ -n "$subvol" ]; then
		opts="-o subvol=$subvol"
	fi

	if [ -n "$mpoint" ]; then
		if [ "x$mpoint" = "x/" ]; then
			return 1
  		fi
	else
		# again, do not mount btrfs ro
		if mount -t btrfs $opts -U "$UUID" "$tmpmnt" 2>/dev/null; then
			debug "btrfs volume $UUID mounted with $opt"
			mpoint="$tmpmnt"
			mounted=1
		else
			warn "cannot mount btrfs volume $UUID with $opt"
			return 1
		fi
	fi
	test="/usr/lib/os-probes/mounted/90linux-distro"
	if [ -f "$test" ] && [ -x "$test" ]; then
		debug "running subtest $test"
		if "$test" "$partition" "$mpoint" btrfs "UUID=$UUID" "subvol=$subvol"; then
			debug "os found by subtest $test on subvol $subvol"
			ret=0
		fi
	fi
	if [ "$mounted" ]; then
		if ! umount "$tmpmnt"; then
			warn "failed to umount $tmpmnt"
		fi
	fi
	return $ret
}

# all btrfs processing here.  Handle both unmounted and
# mounted subvolumes.
if [ "$types" = btrfs ]; then
	debug "begin btrfs processing for $UUID"
	# note that the btrfs volume must not be mounted ro
	if mount -t btrfs -U "$UUID" "$tmpmnt"  2>/dev/null; then
		debug "btrfs volume $UUID mounted"
	else
		warn "cannot mount btrfs volume $UUID, exiting"
		rmdir "$tmpmnt" || true
		exit 1
	fi

	if type btrfs >/dev/null 2>&1; then
		# besides regular subvols, get ro and snapshot so thet can be excluded
		subvols=$(btrfs subvolume list -a "$tmpmnt" | cut -d ' ' -f 9 | sed -e s!^\<FS_TREE\>/!!)
		rosubvols=$(btrfs subvolume list -r -a "$tmpmnt" | cut -d ' ' -f 9 | sed -e s!^\<FS_TREE\>/!!)
		sssubvols=$(btrfs subvolume list -s -a "$tmpmnt" | cut -d ' ' -f 14 | sed -e s!^\<FS_TREE\>/!!)
		defaultvol=$(btrfs subvolume get-default "$tmpmnt" | cut -d ' ' -f 9)
	else
		subvols=""
		rosubvols=""
		sssubvols=""
		defaultvol=""
	fi

        if ! umount "$tmpmnt"; then
            warn "failed to umount btrfs volume on $tmpmnt"
            rmdir "$tmpmnt" || true
            exit 1
        fi

	found=
	# Always probe subvol or root set as default
	if probe_subvol "$defaultvol" "$partition" "$UUID" "$tmpmnt"; then
		found=1
	fi

	# Probe any other OS on subvol
	for subvol in $subvols; do
		if echo "$rosubvols" | grep -q -x "$subvol" ||
		   echo "$sssubvols" | grep -q -x "$subvol" ||
		   echo "$defaultvol" | grep -q -x "$subvol"; then
			continue
		fi
		debug "begin btrfs processing for $UUID subvol=$subvol"
		if probe_subvol "$subvol" "$partition" "$UUID" "$tmpmnt"; then
			found=1
		fi
	done
	rmdir "$tmpmnt" || true
	if [ "$found" ]; then
		exit 0
	fi
fi

# No tests found anything.
exit 1
