#!/bin/sh

# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# ident	"@(#)luset_zone_fs.sh	1.1	07/03/02 SMI"
#
# This is a helper function for lucreate and lucopy.  It iterates through the
# zones in an ABE and sets up the file system entries according to the ICF
# file.
#
# Parameters: <ABE-root-path> <ABE-ICF>

PATH=/usr/bin:/usr/sbin:/sbin
export PATH

LUBIN=${LUBIN:=/usr/lib/lu}
. $LUBIN/lulib

if [ $# -ne 2 ]; then
	$LUPRINTF -Eel2 "`gettext 'usage: luset_zone_fs <path> <icf>'`"
	exit 1
fi

BE_ROOT="$1"
BE_ICF="$2"

if [ ! -d "$BE_ROOT" ]; then
	$LUPRINTF -Eelp2 "`gettext '<%s> is not a directory'`" "$BE_ROOT"
	exit 1
fi

case "$BE_ROOT" in
/*)	;;
*)	$LUPRINTF -Eelp2 "`gettext '<%s> is not an absolute path'`" "$BE_ROOT"
	exit 1;;
esac

if [ ! -f "$BE_ICF" ]; then
	$LUPRINTF -Eelp2 "`gettext '<%s> is not a file'`" "$BE_ICF"
	exit 1
fi

lulib_zone_check "$BE_ROOT"

SAVEIFS="$IFS"

icflist=/tmp/luset_zone_fs-icf.$$
zonelist=/tmp/luset_zone_fs-zone.$$
cmdlist=/tmp/luset_zone_fs-cmds.$$
rm -f $icflist $zonelist $cmdlist

# Process two lists in vfstab format.  Print out the entries in the
# first list that differ significantly (mount point, device, or type)
# from the second.
not_in_second()
{
	(
		cat $2
		echo FIRST
		cat $1
	) | nawk '
	BEGIN {
		infirst=idx=0
	}
	/^FIRST$/		{
		infirst=1;
		next;
	}
	infirst == 0	{
		blockdev[idx] = $1
		rawdev[idx] = $2
		mntpnt[idx] = $3
		fstype[idx] = $4
		opts[idx] = $7
		idx++;
		next;
	}
	{
		for (i = 0; i < idx; i++) {
			if (mntpnt[i] == $3)
				break;
		}
		if (i >= idx || blockdev[i] != $1 || rawdev[i] != $2 ||
		    fstype[i] != $4) {
			# ICF does not store options, so just keep "best" ones
			if (i < idx && opts[i] != "-")
				$7 = opts[i]
			print $0
		}
	}'
}

# Iterate through the configured zones in the ABE.  For each one, find
# out what file systems the zone currently has, what ones are in the
# ICF file, and reconcile.

lulib_list_zones -c "$BE_ROOT" |
while IFS=: read zoneid zonename status zonepath uuid more; do
	IFS="$SAVEIFS"
	if [ $zonename != global ]; then
		lulib_get_zone_icffs "$BE_ICF" $zonename > $icflist
		lulib_get_zone_fs "$BE_ROOT" $zonename > $zonelist

		(
		# Each file system not listed in the ICF file gets deleted.
		not_in_second $zonelist $icflist |
		while read blockdev rawdev mntpnt fstype fsckpass atboot opts
		do
			echo "remove fs dir=$mntpnt"
		done

		# Each file system not already listed in the zone gets added.
		not_in_second $icflist $zonelist |
		while read blockdev rawdev mntpnt fstype fsckpass atboot opts
		do
			echo "add fs"
			echo "set dir=$mntpnt"
			echo "set special=$blockdev"
			if [ "$rawdev" != - ]; then
				echo "set raw=$rawdev"
			fi
			echo "set type=$fstype"
			if [ "$opts" != - ]; then
				echo "add options [$opts]"
			fi
			echo "end"
		done
		) > $cmdlist

		if [ -s $cmdlist ]; then
			zonecfg -R "$BE_ROOT" -z $zonename < $cmdlist || exit 1
		fi
	fi
done

rm -f $icflist $zonelist $cmdlist

exit 0
