#
# overlayfs specific common functions.
#
. ./common/module

# Export overlayfs xattrs and constant value
export OVL_XATTR_OPAQUE="trusted.overlay.opaque"
export OVL_XATTR_REDIRECT="trusted.overlay.redirect"
export OVL_XATTR_IMPURE="trusted.overlay.impure"
export OVL_XATTR_ORIGIN="trusted.overlay.origin"
export OVL_XATTR_NLINK="trusted.overlay.nlink"
export OVL_XATTR_UPPER="trusted.overlay.upper"

# helper function to do the actual overlayfs mount operation
_overlay_mount_dirs()
{
	local lowerdir=$1
	local upperdir=$2
	local workdir=$3
	shift 3

	$MOUNT_PROG -t overlay -o lowerdir=$lowerdir -o upperdir=$upperdir \
		    -o workdir=$workdir `_common_dev_mount_options $*`
}

# Mount with same options/mnt/dev of scratch mount, but optionally
# with different lower/upper/work dirs
_overlay_scratch_mount_dirs()
{
	local lowerdir=$1
	local upperdir=$2
	local workdir=$3
	shift 3

	_overlay_mount_dirs $lowerdir $upperdir $workdir \
				$* $OVL_BASE_SCRATCH_MNT $SCRATCH_MNT
}

_overlay_mkdirs()
{
	local dir=$1

	mkdir -p $dir/$OVL_UPPER
	mkdir -p $dir/$OVL_LOWER
	mkdir -p $dir/$OVL_WORK
	mkdir -p $dir/$OVL_MNT
}

# Given a base fs dir, set up overlay directories and mount on the given mnt.
# The dir is used as the mount device so it can be seen from df or mount
_overlay_mount()
{
	local dir=$1
	local mnt=$2
	shift 2

	_supports_filetype $dir || _notrun "upper fs needs to support d_type"

	_overlay_mkdirs $dir

	_overlay_mount_dirs $dir/$OVL_LOWER $dir/$OVL_UPPER $dir/$OVL_WORK \
				$* $dir $mnt
}

_overlay_base_mount()
{
	local devname=$1
	local mntname=$2
	local dev=$3
	local mnt=$4
	shift 4

	if [ -z "$dev" -o -z "$mnt" ] || \
		_check_mounted_on $devname $dev $mntname $mnt; then
		# no base fs or already mounted
		return 0
	elif [ $? -ne 1 ]; then
		# base fs mounted but not on mount point
		return 1
	fi

	_mount $* $dev $mnt
}

_overlay_base_test_mount()
{
	_overlay_base_mount OVL_BASE_TEST_DEV OVL_BASE_TEST_DIR \
			"$OVL_BASE_TEST_DEV" "$OVL_BASE_TEST_DIR" \
			$TEST_FS_MOUNT_OPTS $SELINUX_MOUNT_OPTIONS
}

_overlay_test_mount()
{
	_overlay_base_test_mount && \
		_overlay_mount $OVL_BASE_TEST_DIR $TEST_DIR $*
}

_overlay_base_scratch_mount()
{
	_overlay_base_mount OVL_BASE_SCRATCH_DEV OVL_BASE_SCRATCH_MNT \
			"$OVL_BASE_SCRATCH_DEV" "$OVL_BASE_SCRATCH_MNT" \
			$OVL_BASE_MOUNT_OPTIONS $SELINUX_MOUNT_OPTIONS
}

_overlay_scratch_mount()
{
	_overlay_base_scratch_mount && \
		_overlay_mount $OVL_BASE_SCRATCH_MNT $SCRATCH_MNT $*
}

_overlay_base_unmount()
{
	local dev=$1
	local mnt=$2

	[ -n "$dev" -a -n "$mnt" ] || return 0

	$UMOUNT_PROG $mnt
}

_overlay_test_unmount()
{
	$UMOUNT_PROG $TEST_DIR
	_overlay_base_unmount "$OVL_BASE_TEST_DEV" "$OVL_BASE_TEST_DIR"
}

_overlay_scratch_unmount()
{
	$UMOUNT_PROG $SCRATCH_MNT
	_overlay_base_unmount "$OVL_BASE_SCRATCH_DEV" "$OVL_BASE_SCRATCH_MNT"
}

# Check that a specific overlayfs feature is supported
__check_scratch_overlay_feature()
{
	local feature=$1

	# overalyfs features (e.g. redirect_dir, index) are
	# configurable from Kconfig (the build default), by module
	# parameter (the system default) and per mount by mount
	# option ${feature}=[on|off].
	#
	# If the module parameter does not exist then there is no
	# point in checking the mount option.
	local default=`_get_fs_module_param ${feature}`
	[ "$default" = Y ] || [ "$default" = N ] || \
		_notrun "feature '${feature}' not supported by ${FSTYP}"

	# Check options to be sure. For example, Overlayfs will fallback to
	# index=off if underlying fs does not support file handles.
	# Overlayfs only displays mount option if it differs from the default.
	# Overlayfs may enable the feature, but fallback to read-only mount.
	((( [ "$default" = N ] && _fs_options $SCRATCH_DEV | grep -q "${feature}=on" ) || \
	  ( [ "$default" = Y ] && ! _fs_options $SCRATCH_DEV | grep -q "${feature}=off" )) && \
	    touch $SCRATCH_MNT/foo 2>/dev/null ) || \
	        _notrun "${FSTYP} feature '${feature}' cannot be enabled on ${SCRATCH_DEV}"
}

# Require a set of overlayfs features
_require_scratch_overlay_features()
{
	local features=( $* )
	local opts="rw"

	for feature in ${features[*]}; do
		opts+=",${feature}=on"
	done

	_scratch_mkfs > /dev/null 2>&1
	_try_scratch_mount -o $opts || \
		_notrun "overlay options '$opts' cannot be enabled on ${SCRATCH_DEV}"

	for feature in ${features[*]}; do
		__check_scratch_overlay_feature ${feature}
	done

	_scratch_unmount
}

# Helper function to check underlying dirs of overlay filesystem
_overlay_fsck_dirs()
{
	local lowerdir=$1
	local upperdir=$2
	local workdir=$3
	shift 3

	[[ ! -x "$FSCK_OVERLAY_PROG" ]] && return 0

	$FSCK_OVERLAY_PROG -o lowerdir=$lowerdir -o upperdir=$upperdir \
			   -o workdir=$workdir $*
}

_overlay_check_dirs()
{
	local lowerdir=$1
	local upperdir=$2
	local workdir=$3
	shift 3
	local err=0

	_overlay_fsck_dirs $lowerdir $upperdir $workdir \
			   $FSCK_OPTIONS $* >>$tmp.fsck 2>&1
	if [ $? -ne 0 ]; then
		_log_err "_overlay_check_fs: overlayfs on $lowerdir,$upperdir,$workdir is inconsistent"

		echo "*** fsck.overlay output ***"	>>$seqres.full
		cat $tmp.fsck				>>$seqres.full
		echo "*** end fsck.overlay output"	>>$seqres.full

		echo "*** mount output ***"		>>$seqres.full
		_mount					>>$seqres.full
		echo "*** end mount output"		>>$seqres.full

		err=1
	fi
	rm -f $tmp.fsck

	return $err
}

# Check the same mnt/dev of _check_overlay_scratch_fs but non-default
# underlying scratch dirs of overlayfs, it needs lower/upper/work dirs
# provided as arguments, and it's useful for non-default setups such
# as multiple lower layers
_overlay_check_scratch_dirs()
{
	local lowerdir=$1
	local upperdir=$2
	local workdir=$3
	shift 3

	# Need to umount overlay for scratch dir check
	local ovl_mounted=`_is_dir_mountpoint $SCRATCH_MNT`
	[ -z "$ovl_mounted" ] || $UMOUNT_PROG $SCRATCH_MNT

	# Check dirs with extra overlay options
	_overlay_check_dirs $lowerdir $upperdir $workdir $*
	local ret=$?

	if [ $ret -eq 0 -a -n "$ovl_mounted" ]; then
		# overlay was mounted, remount with extra mount options
		_overlay_scratch_mount_dirs $lowerdir $upperdir \
					    $workdir $*
		ret=$?
	fi

	return $ret
}

_overlay_check_fs()
{
	# The first arguments is overlay mount point use for checking
	# overlay filesystem is mounted or not, the remaining arquments
	# use for mounting overlay base filesystem if it was not mounted.
	# We shift one to aligns arguments for _overlay_base_mount.
	local ovl_mnt=$1
	shift 1

	local base_dev=$3
	local base_mnt=$4

	[ "$FSTYP" = overlay ] || return 0

	# Base fs needs to be mounted to check overlay dirs
	local base_fstype=""
	local ovl_mounted=""

	[ -z "$base_dev" ] || \
		base_fstype=`_fs_type $base_dev`

	# If base_dev is set but base_fstype is empty, base fs is not
	# mounted, we need to mount base fs. Otherwise, we need to
	# check and umount overlayfs if it was mounted.
	if [ -n "$base_dev" -a -z "$base_fstype" ]; then
		_overlay_base_mount $*
	else
		# Check and umount overlay for dir check
		ovl_mounted=`_is_dir_mountpoint $ovl_mnt`
		[ -z "$ovl_mounted" ] || $UMOUNT_PROG $ovl_mnt
	fi

	_overlay_check_dirs $base_mnt/$OVL_LOWER $base_mnt/$OVL_UPPER \
			    $base_mnt/$OVL_WORK
	local ret=$?

	if [ -n "$base_dev" -a -z "$base_fstype" ]; then
		_overlay_base_unmount "$base_dev" "$base_mnt"
	elif [ $ret -eq 0 -a -n "$ovl_mounted" ]; then
		# overlay was mounted, remount besides extra mount options
		_overlay_mount $base_mnt $ovl_mnt
		ret=$?
	fi

	if [ $ret != 0 ]; then
		status=1
		if [ "$iam" != "check" ]; then
			exit 1
		fi
		return 1
	fi

	return 0
}

_check_overlay_test_fs()
{
	_overlay_check_fs "$TEST_DIR" \
		OVL_BASE_TEST_DEV OVL_BASE_TEST_DIR \
		"$OVL_BASE_TEST_DEV" "$OVL_BASE_TEST_DIR" \
		$TEST_FS_MOUNT_OPTS $SELINUX_MOUNT_OPTIONS
}

_check_overlay_scratch_fs()
{
	_overlay_check_fs "$SCRATCH_MNT" \
		OVL_BASE_SCRATCH_DEV OVL_BASE_SCRATCH_MNT \
		"$OVL_BASE_SCRATCH_DEV" "$OVL_BASE_SCRATCH_MNT" \
		$OVL_BASE_MOUNT_OPTIONS $SELINUX_MOUNT_OPTIONS
}
