6793 p2v support for ipkg-branded zones
author<gerald.jelinek@sun.com>
Tue, 10 Nov 2009 14:40:37 -0700
changeset 1483 2276b6786711
parent 1482 db83e3f4b9aa
child 1484 6a2660b61eb4
6793 p2v support for ipkg-branded zones 4513 need option to attach existing dataset 7345 zone attach should verify image is an IPS-based zone booted 8345 failed zoneadm attach leaves an zone root dataset active 8468 zoneadm install fails with "no zonepath dataset 9359 zoneadm attach should create zonepath dataset if necessary
src/brand/Makefile
src/brand/attach
src/brand/clone
src/brand/common.ksh
src/brand/config.xml
src/brand/detach
src/brand/image_install
src/brand/p2v
src/brand/pkgcreatezone
src/brand/pkgrm.conf
src/brand/pkgrm.lst
src/brand/query
src/brand/smf_disable.conf
src/brand/smf_disable.lst
src/brand/uninstall
src/pkgdefs/Makefile
src/pkgdefs/SUNWipkg-brand/prototype
src/setup.py
src/util/distro-import/128/config.xml
--- a/src/brand/Makefile	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/brand/Makefile	Tue Nov 10 14:40:37 2009 -0700
@@ -31,6 +31,7 @@
 ROOT = ../../proto/root_${MACH}
 ROOTETC = $(ROOT)/etc
 ROOTETCZONES = $(ROOT)/etc/zones
+ROOTETCBRAND = $(ROOT)/etc/brand/ipkg
 ROOTUSRLIB = $(ROOT)/usr/lib
 ROOTBRAND = $(ROOTUSRLIB)/brand
 ROOTBRANDPKG = $(ROOTBRAND)/ipkg
@@ -40,12 +41,15 @@
 ROOTDIRS = \
 	$(ROOT) \
 	$(ROOTETC) \
+	$(ROOTETCBRAND) \
 	$(ROOTETCZONES) \
 	$(ROOTUSRLIB) \
 	$(ROOTBRAND) \
 	$(ROOTBRANDPKG)
 
 ROOTFILES = \
+	$(ROOTETCBRAND)/pkgrm.conf \
+	$(ROOTETCBRAND)/smf_disable.conf \
 	$(ROOTETCZONES)/SUNWipkg.xml \
 	$(ROOTBRANDPKG)/config.xml \
 	$(ROOTBRANDPKG)/platform.xml \
@@ -54,10 +58,13 @@
 	$(ROOTBRANDPKG)/common.ksh \
 	$(ROOTBRANDPKG)/detach \
 	$(ROOTBRANDPKG)/fmri_compare \
+	$(ROOTBRANDPKG)/image_install \
+	$(ROOTBRANDPKG)/p2v \
 	$(ROOTBRANDPKG)/pkgcreatezone \
+	$(ROOTBRANDPKG)/pkgrm.lst \
 	$(ROOTBRANDPKG)/poststate \
 	$(ROOTBRANDPKG)/prestate \
-	$(ROOTBRANDPKG)/query \
+	$(ROOTBRANDPKG)/smf_disable.lst \
 	$(ROOTBRANDPKG)/support \
 	$(ROOTBRANDPKG)/uninstall
 
@@ -94,17 +101,24 @@
 # repository's working copy's versions of the commands and modules.
 PWD:sh = pwd
 link:
+	mkdir -p /etc/brand/ipkg
 	mkdir -p /usr/lib/brand/ipkg
+	ln -sf $(PWD)/pkgrm.conf /etc/brand/ipkg/pkgrm.conf
+	ln -sf $(PWD)/smf_disable.conf /etc/brand/ipkg/smf_disable.conf
+	ln -sf $(PWD)/pkgrm.lst /usr/lib/brand/ipkg/pkgrm.lst
+	ln -sf $(PWD)/smf_disable.lst /usr/lib/brand/ipkg/smf_disable.lst
+	ln -sf $(PWD)/smf_disable.conf /usr/lib/brand/ipkg/smf_disable.conf
 	ln -sf $(PWD)/config.xml /usr/lib/brand/ipkg/config.xml
 	ln -sf $(PWD)/platform.xml /usr/lib/brand/ipkg/platform.xml
 	ln -sf $(PWD)/attach /usr/lib/brand/ipkg/attach
 	ln -sf $(PWD)/clone /usr/lib/brand/ipkg/clone
 	ln -sf $(PWD)/common.ksh /usr/lib/brand/ipkg/common.ksh
 	ln -sf $(PWD)/detach /usr/lib/brand/ipkg/detach
+	ln -sf $(PWD)/image_install /usr/lib/brand/ipkg/image_install
+	ln -sf $(PWD)/p2v /usr/lib/brand/ipkg/p2v
 	ln -sf $(PWD)/pkgcreatezone /usr/lib/brand/ipkg/pkgcreatezone
 	ln -sf $(PWD)/poststate /usr/lib/brand/ipkg/poststate
 	ln -sf $(PWD)/prestate /usr/lib/brand/ipkg/prestate
-	ln -sf $(PWD)/query /usr/lib/brand/ipkg/query
 	ln -sf $(PWD)/support /usr/lib/brand/ipkg/support
 	ln -sf $(PWD)/uninstall /usr/lib/brand/ipkg/uninstall
 	ln -sf $(PWD)/SUNWipkg.xml /etc/zones/SUNWipkg.xml
@@ -112,10 +126,15 @@
 link-clean:
 	rm -rf /usr/lib/brand/ipkg
 	rm -f /etc/zones/SUNWipkg.xml
+	rm -rf /etc/brand/ipkg
 
-$(ROOT) $(ROOTETC) $(ROOTETCZONES) $(ROOTUSRLIB) $(ROOTBRAND) $(ROOTBRANDPKG):
+$(ROOT) $(ROOTETC) $(ROOTETCBRAND) $(ROOTETCZONES) $(ROOTUSRLIB) \
+	$(ROOTBRAND) $(ROOTBRANDPKG):
 	mkdir -p $@
 
+$(ROOTETCBRAND)/%: $(ROOTETCBRAND) %
+	rm -f $@; $(INSTALL) -f $(ROOTETCBRAND) -m 0644 $<
+
 $(ROOTETCZONES)/%: $(ROOTETCZONES) %
 	rm -f $@; $(INSTALL) -f $(ROOTETCZONES) -m 0444 $<
 
--- a/src/brand/attach	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/brand/attach	Tue Nov 10 14:40:37 2009 -0700
@@ -24,8 +24,12 @@
 # Use is subject to license terms.
 #
 
-m_installing=$(gettext "Installing...")
-m_usage=$(gettext  "ipkg brand attach arguments [-a archive] [-d dataset] [-n] [-r zfs-recv] [-u]\n\tThe -a archive option specifies a tar file or cpio archive.\n\tThe -d dataset option specifies an existing dataset.\n\tThe -r zfs-recv option receives the output of a 'zfs send' command\n\tof an existing zone root dataset.\n\tThe -u option indicates that the software should be updated to match\n\tthe current host.")
+. /usr/lib/brand/ipkg/common.ksh
+
+m_attach_log=$(gettext "Log File: %s")
+m_zfs=$(gettext "A ZFS file system was created for the zone.")
+m_attaching=$(gettext "Attaching...")
+m_usage=$(gettext  "attach [-a archive] [-d dataset] [-n] [-r zfs-recv] [-u]\n\tThe -a archive option specifies a tar file or cpio archive.\n\tThe -d dataset option specifies an existing dataset.\n\tThe -r zfs-recv option receives the output of a 'zfs send' command\n\tof an existing zone root dataset.\n\tThe -u option indicates that the software should be updated to match\n\tthe current host.")
 m_gzinc=$( gettext "       Global zone version: %s")
 m_zinc=$(  gettext "   Non-Global zone version: %s")
 m_insync=$(gettext "                Evaluation: Packages in %s are in sync with global zone.")
@@ -41,17 +45,10 @@
 m_sync_done=$(gettext "  Updating non-global zone: Zone updated to %s")
 m_complete=$(gettext "Attach complete.")
 
-f_option_no_ds=$(gettext "The -a, -d or -r option is required when there is no active root dataset.")
-f_option_ds=$(gettext "The -a, -d or -r option is invalid when there is already an active root dataset.")
-f_bad_archive=$(gettext "Unknown archive format.")
-f_unpack=$(gettext "Unable to install the archive.")
-f_bad_dataset=$(gettext "Non-existent or invalid zone root dataset.")
-f_nogzinc=$(gettext "Could not find 'entire' incorporation for global zone.")
-f_nozinc=$(gettext "Could not find 'entire' incorporation for attaching zone.")
+sanity_fail_global=$(gettext  "  Sanity Check: FAILED, the image is from the global zone.")
 f_downrev=$(gettext "Zone is downrev of global zone.  Specify -u to update it.")
 f_uprev=$(gettext "Zone is uprev of global zone.  Global zone will need to be updated before attach can proceed.")
 f_update=$(gettext "Could not update attaching zone")
-f_bad_publisher=$(gettext "Syntax error in publisher information.\n")
 f_gz_entire=$(gettext "Could not find 'entire' incorporation for global zone.")
 f_zone_entire=$(gettext "Could not find 'entire' incorporation for non-global zone.")
 f_fmri_compare=$(gettext "Failed to compare 'entire' FMRIs")
@@ -62,18 +59,67 @@
 f_nosuch_key=$(gettext "Failed to find key %s for global zone publisher")
 f_nosuch_cert=$(gettext "Failed to find cert %s for global zone publisher")
 
+# Clean up on interrupt
+trap_cleanup()
+{
+	msg=$(gettext "Installation cancelled due to interrupt.")
+	log "$msg"
+
+	# umount any mounted file systems
+	umnt_fs
+
+	trap_exit
+}
+
+# If the attach failed then clean up the ZFS datasets we created.
+trap_exit()
+{
+	if [[ $EXIT_CODE == $ZONE_SUBPROC_OK ]]; then
+		# unmount the zoneroot
+		umount $ZONEROOT > /dev/null 2>&1
+	else
+		if [[ "$install_media" != "-" ]]; then
+			/usr/lib/brand/ipkg/uninstall $ZONENAME $ZONEPATH -F
+		else
+			# Restore the zone properties for the pre-existing
+			# dataset.
+			if [[ -n "$ACTIVE_DS" ]]; then
+				zfs set zoned=off $ACTIVE_DS >/dev/null 2>&1
+				zfs set canmount=on $ACTIVE_DS >/dev/null 2>&1
+				zfs set mountpoint=$ZONEROOT $ACTIVE_DS \
+				    >/dev/null 2>&1
+			fi
+		fi
+	fi
+
+	exit $EXIT_CODE
+}
+
+EXIT_CODE=$ZONE_SUBPROC_USAGE
+install_media="-"
+
+trap trap_cleanup INT
+trap trap_exit EXIT
 
 #set -o xtrace
 
-. /usr/lib/brand/ipkg/common.ksh
-
-# Setup i18n output
-TEXTDOMAIN="SUNW_OST_OSCMD"
-export TEXTDOMAIN
-
 PKG="/usr/bin/pkg"
 KEYDIR=/var/pkg/ssl
 
+# If we weren't passed at least two arguments, exit now.
+(( $# < 2 )) && exit $ZONE_SUBPROC_USAGE
+
+ZONENAME="$1"
+ZONEPATH="$2"
+# XXX shared/common script currently uses lower case zonename & zonepath
+zonename="$ZONENAME"
+zonepath="$ZONEPATH"
+
+shift; shift	# remove ZONENAME and ZONEPATH from arguments array
+
+ZONEROOT="$ZONEPATH/root"
+logdir="$ZONEROOT/var/log"
+
 #
 # Resetting GZ_IMAGE to something besides slash allows for simplified
 # debugging of various global zone image configurations-- simply make
@@ -83,355 +129,178 @@
 PKG_IMAGE=$GZ_IMAGE
 export PKG_IMAGE
 
-aarg=0
-darg=0
 noexecute=0
-rarg=0
+
+unset inst_type
 
 # Other brand attach options are invalid for this brand.
-while getopts "a:d:nR:r:uz:" opt; do
+while getopts "a:d:nr:u" opt; do
 	case $opt in
-		a)	ARCHIVE="$OPTARG"
-			if [ $darg -eq 1 -o $rarg -eq 1 ]; then
-				fail_usage "$m_usage"
+		a)
+			if [[ -n "$inst_type" ]]; then
+				fatal "$incompat_options" "$m_usage"
 			fi
-			aarg=1
+		 	inst_type="archive"
+			install_media="$OPTARG"
 			;;
-		d)	DATASET="$OPTARG"
-			if [ $aarg -eq 1 -o $rarg -eq 1 ]; then
-				fail_usage "$m_usage"
+		d)
+			if [[ -n "$inst_type" ]]; then
+				fatal "$incompat_options" "$m_usage"
 			fi
-			darg=1
+		 	inst_type="directory"
+			install_media="$OPTARG"
 			;;
 		n)	noexecute=1 ;;
-		R)	zonepath="$OPTARG" ;;
-		r)	ZFSRCV="$OPTARG"
-			if [ $aarg -eq 1 -o $darg -eq 1 ]; then
-				fail_usage "$m_usage"
+		r)
+			if [[ -n "$inst_type" ]]; then
+				fatal "$incompat_options" "$m_usage"
 			fi
-			rarg=1
+		 	inst_type="stdin"
+			install_media="$OPTARG"
 			;;
 		u)	allow_update=1 ;;
-		z)	zonename="$OPTARG" ;;
-		?)	fail_usage "$m_usage" ;;
-		*)	fail_usage "$m_usage";;
+		?)	fail_usage "" ;;
+		*)	fail_usage "";;
 	esac
 done
 shift $((OPTIND-1))
 
-zoneroot=$zonepath/root
+if [[ $noexecute == 1 && -n "$inst_type" ]]; then
+	fatal "$m_usage"
+fi
+
+[[ -z "$inst_type" ]] && inst_type="directory"
 
 if [ $noexecute -eq 1 ]; then
 	#
 	# The zone doesn't have to exist when the -n option is used, so do
 	# this work early.
 	#
-	if [ $aarg -eq 1 -o $rarg -eq 1 -o $allow_update -eq 1 ]; then
-		fail_usage "$m_usage";
-	fi
 
 	# XXX There is no sw validation for IPS right now, so just pretend
 	# everything will be ok.
-	exit 0
+	EXIT_CODE=$ZONE_SUBPROC_OK
+	exit $ZONE_SUBPROC_OK
 fi
 
-get_current_gzbe
+LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp $ZONENAME.attach_log.XXXXXX)
+if [[ -z "$LOGFILE" ]]; then
+	fatal "$e_tmpfile"
+fi
+exec 2>>"$LOGFILE"
+log "$m_attach_log" "$LOGFILE"
 
 #
-# XXX we can't do the following since 'zoneadm verify' depends on the zonepath
-# already existing - maybe we can fix this in zoneadm in the future.
-#
-# First make the top-level zonepath dataset and be sure to tolerate errors
-# since this dataset could already exist from a different BE.
-#
-#pdir=`/usr/bin/dirname $zonepath`
-#zpname=`/usr/bin/basename $zonepath`
-#
-#get_zonepath_ds $pdir
-#zpds=$ZONEPATH_DS
-#
-# Note, this dataset might already exist so tolerate an error.
-#/usr/sbin/zfs create $zpds/$zpname
+# TODO - once sxce is gone, move the following block into
+# usr/lib/brand/shared/common.ksh code to share with other brands using
+# the same zfs dataset logic for attach. This currently uses get_current_gzbe
+# so we can't move it yet since beadm isn't in sxce.
 #
 
-fail_zonepath_in_rootds $zpds
+# Validate that the zonepath is not in the root dataset.
+pdir=`dirname $ZONEPATH`
+get_zonepath_ds $pdir
+fail_zonepath_in_rootds $ZONEPATH_DS
+
+EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
+
+if [[ "$install_media" == "-" ]]; then
+	#
+	# Since we're using a pre-existing dataset, the dataset currently
+	# mounted on the {zonepath}/root becomes the active dataset.  We
+	# can't depend on the usual dataset attributes to detect this since
+	# the dataset could be a detached zone or one that the user set up by
+	# hand and lacking the proper attributes.  However, since the zone is
+	# not attached yet, the 'install_media == -' means the dataset must be
+	# mounted at this point.
+	#
+	ACTIVE_DS=`mount -p | nawk -v zroot=$ZONEROOT '{
+	    if ($3 == zroot && $4 == "zfs")
+		print $1
+	    }'`
+
+	[[ -z "$ACTIVE_DS" ]] && fatal "$f_no_active_ds"
+
+	# Set up proper attributes on the ROOT dataset.
+	get_zonepath_ds $ZONEPATH
+	zfs list -H -t filesystem -o name $ZONEPATH_DS/ROOT >/dev/null 2>&1
+	(( $? != 0 )) && fatal "$f_no_active_ds"
+
+	zfs set mountpoint=legacy $ZONEPATH_DS/ROOT >/dev/null 2>&1
+	zfs set zoned=on $ZONEPATH_DS/ROOT >/dev/null 2>&1
 
-# Top-level zonepath dataset should now exist.
-get_zonepath_ds $zonepath
+	#
+	# We're typically using a pre-existing mounted dataset so setting the
+	# following propery changes will cause the {zonepath}/root dataset to
+	# be unmounted.  However, a p2v with an update-on-attach will have
+	# created the dataset with the correct properties, so setting these
+	# attributes won't unmount the dataset.  Thus, we check the mount
+	# and attempt the remount if necessary.
+	#
+	get_current_gzbe
+	zfs set $PROP_PARENT=$CURRENT_GZBE $ACTIVE_DS >/dev/null 2>&1
+	zfs set $PROP_ACTIVE=on $ACTIVE_DS >/dev/null 2>&1
+	zfs set canmount=noauto $ACTIVE_DS >/dev/null 2>&1
+	zfs inherit mountpoint $ACTIVE_DS >/dev/null 2>&1
+	zfs inherit zoned $ACTIVE_DS >/dev/null 2>&1
+
+	mounted_ds=`mount -p | nawk -v zroot=$ZONEROOT '{
+	    if ($3 == zroot && $4 == "zfs")
+		print $1
+	    }'`
+
+	if [[ -z $mounted_ds ]]; then
+		mount -F zfs $ACTIVE_DS $ZONEROOT || fatal "$f_zfs_mount"
+	fi
+else
+	#
+	# Since we're not using a pre-existing ZFS dataset layout, create
+	# the zone datasets and mount them.  Start by creating the zonepath
+	# dataset, similar to what zoneadm would do for an initial install.
+	#
+	zds=$(zfs list -H -t filesystem -o name $pdir 2>/dev/null)
+	if (( $? == 0 )); then
+		pnm=$(/usr/bin/basename $ZONEPATH)
+		# The zonepath dataset might already exist.
+		zfs list -H -t filesystem -o name $zds/$pnm >/dev/null 2>&1
+	        if (( $? != 0 )); then
+			zfs create "$zds/$pnm"
+			(( $? != 0 )) && fatal "$f_zfs_create"
+			vlog "$m_zfs"
+		fi
+	fi
+
+	create_active_ds
+fi
 
 #
-# Note that the root dataset might already exist and be populated from either
-# a SNAP clone or from an earlier attach that failed because the sw was
-# out of sync but the -u option was not provided.  The user might be
-# re-running the attach with the -u option this time.  We need to be sure
-# to handle this case gracefully.
+# The zone's datasets are now in place.
+#
+
+log "$m_attaching"
+install_image "$inst_type" "$install_media"
+
+#
+# End of TODO block to move to common code.
 #
 
 #
-# We first want to see if there is a pre-existing active root dataset, but
-# we can't call get_active_ds() since it errors out if there is no active
-# dataset.
+# Perform a final sanity check to confirm the image is not of the global zone.
+# Check for a few well-known global zone only svcs.
 #
-ACTIVE_DS=`/usr/sbin/zfs list -H -r -t filesystem \
-    -o name,$PROP_PARENT,$PROP_ACTIVE $ZONEPATH_DS/ROOT | \
-    /usr/bin/nawk -v gzbe=$CURRENT_GZBE ' {
-	if ($1 ~ /ROOT\/[^\/]+$/ && $2 == gzbe && $3 == "on") {
-		print $1
-		if (found == 1)
-			exit 1
-		found = 1
-	}
-    }'`
-
-if [ $? -ne 0 ]; then
-	fail_fatal "$f_multiple_ds"
-fi
-
-if [ ! -d $zoneroot ]; then
-	/usr/bin/mkdir -p $zoneroot
-	/usr/bin/chmod 700 $zonepath
-fi
-
-if [ -z "$ACTIVE_DS" ]; then
-	#
-	# There is no pre-existing active dataset.  In this case we need either
-	# the -a or -r option to populate a newly created dataset or the -d
-	# option to use a pre-existing dataset.
-	#
-	if [ $aarg -eq 1 -o $rarg -eq 1 ]; then
-		/usr/sbin/zfs create -o mountpoint=legacy -o zoned=on \
-		    $ZONEPATH_DS/ROOT
-
-		BENAME=zbe
-		BENUM=0
-		# Try 100 different names before giving up.
-		while [ $BENUM -lt 100 ]; do
-		        /usr/sbin/zfs create -o $PROP_ACTIVE=on \
-			    -o $PROP_PARENT=$CURRENT_GZBE \
-			    -o canmount=noauto $ZONEPATH_DS/ROOT/$BENAME
-			if [ $? = 0 ]; then
-		                break
-			fi
-		        BENUM=`expr $BENUM + 1`
-			BENAME="zbe-$BENUM"
-		done
-
-		if [ $BENUM -ge 100 ]; then
-			fail_fatal "$f_zfs_create"
-		fi
-
-		ACTIVE_DS=$ZONEPATH_DS/ROOT/$BENAME
-
-	elif [ $darg -eq 1 ]; then
-		#
-		# Verify that the dataset exists
-		#
-		/usr/sbin/zfs list -H -o name $DATASET >/dev/null 2>&1
-		if [ $? -ne 0 ]; then
-			fail_fatal "$f_bad_dataset"
-		fi
-
-		#
-		# Verify that the dataset looks like it contains a zone root.
-		#
-		oldmnt=`/usr/sbin/zfs list -H -o mountpoint $DATASET`
-
-		if [ "$oldmnt" = "legacy" ]; then
-			mntpnt=`/usr/sbin/mount -p | \
-			    /usr/bin/nawk -v fs=$DATASET \
-			    '{if ($1 == fs) print $3}'`
-
-			if [ -n "$mntpnt" ]; then
-				/usr/sbin/umount $mntpnt
-			fi
-		else
-			/usr/sbin/zfs set mountpoint=legacy $DATASET || \
-			    fail_fatal "$f_zfs_create"
-		fi
-
-		/usr/sbin/mount -F zfs $DATASET $zoneroot
-		if [ $? -ne 0 ]; then
-			/usr/sbin/zfs set mountpoint=$oldmnt $DATASET
-			if [ "$oldmnt" = "legacy" -a -n "$mntpnt" ]; then
-				/usr/sbin/mount -F zfs $DATASET $mntpnt
-			fi
-			fail_fatal "$f_zfs_mount"
-		fi
-
-		if [ ! -d $zoneroot/etc -o ! -d $zoneroot/usr ]; then
-			/usr/sbin/umount $zoneroot
-			/usr/sbin/zfs set mountpoint=$oldmnt $DATASET
-			if [ "$oldmnt" = "legacy" -a -n "$mntpnt" ]; then
-				/usr/sbin/mount -F zfs $DATASET $mntpnt
-			fi
-			fail_fatal "$f_bad_dataset"
-		fi
-
-		#
-		# The dataset seems reasonable, make it the active dataset.
-		#
-		/usr/sbin/umount $zoneroot
-
-		/usr/sbin/zfs set zoned=on $DATASET || \
-		    fail_fatal "$f_zfs_create"
-
-		/usr/sbin/zfs set canmount=noauto $DATASET || \
-		    fail_fatal "$f_zfs_create"
-
-		/usr/sbin/zfs set $PROP_ACTIVE=on $DATASET || \
-		    fail_fatal "$f_zfs_create"
-
-		/usr/sbin/zfs set $PROP_PARENT=$CURRENT_GZBE $DATASET || \
-		    fail_fatal "$f_zfs_create"
-
-		ACTIVE_DS=$DATASET
-
-	else
-		#
-		# There is no pre-existing active dataset and no
-		# -a, -d or -r option so this is an error.
-		#
-		fail_fatal "$f_option_no_ds"
-	fi
-
-elif [ $aarg -eq 1 -o $darg -eq 1 -o $rarg -eq 1 ]; then
-	#
-	# We already have an active root dataset.  In this case the -a, -d or -r
-	# option is invalid (XXX unless we want to overwrite the contents of
-	# the pre-existing dataset).
-	#
-	fail_fatal "$f_option_ds"
-fi
-
-if [ $aarg -eq 1 ]; then
-	#
-	# Given a tar or cpio archive, unpack the archive into the dataset.
-	#
-	ftype="`LC_ALL=C file $ARCHIVE | cut -d: -f 2`"
-	case "$ftype" in
-	*cpio*)		filetype="cpio"
-			stage1="cat"
-			filetypename="cpio archive"
-		;;
-	*bzip2*)	filetype="cpio"
-			stage1="bzcat"
-			filetypename="bzipped cpio archive"
-		;;
-	*gzip*)		filetype="cpio"
-			stage1="gzcat"
-			filetypename="gzipped cpio archive"
-		;;
-	*USTAR\ tar\ archive)
-			filetype="tar"
-			filetypename="tar archive"
-		;;
-	*USTAR\ tar\ archive\ extended\ format*)
-			filetype="xustar"
-			filetypename="pax (xustar) archive"
-		;;
-	*)		fail_fatal "$f_bad_archive"
-		;;
-	esac
-
-	if [ ! -d $zoneroot ]; then
-		/usr/bin/mkdir -p $zoneroot
-		/usr/bin/chmod 700 $zonepath
-	fi
-
-	/usr/sbin/mount -F zfs $ACTIVE_DS $zoneroot || fail_fatal "$f_zfs_mount"
-
-	echo $m_installing
-	echo $filetypename
-
-	#
-	# XXX What does the archive contain?  Do we just get stuff under
-	# zonepath/root or do we get zonepath?  For zfs send, we send the
-	# zonepath/root dataset, so maybe we should assume only zonepath/root
-	# here as well?
-	#
-
-	unpack_result=0
-	if [[ "$filetype" = "cpio" ]]; then
-		cpioopts="-idm"
-		(cd "$zonepath" && $stage1 "$ARCHIVE" | cpio $cpioopts)
-		unpack_result=$?
-
-	elif [[ "$filetype" = "tar" ]]; then
-		(cd "$zonepath" && tar -xf "$ARCHIVE")
-		unpack_result=$?
-
-	elif [[ "$filetype" = "xustar" ]]; then
-		(cd "$zonepath" && pax -r -f "$ARCHIVE")
-		unpack_result=$?
-	fi
-
-	/usr/sbin/umount $zoneroot
-
-	if [[ $unpack_result -ne 0 ]]; then
-		fail_fatal "$f_unpack"
-	fi
-
-elif [ $rarg -eq 1 ]; then
-	#
-	# Given 'zfs send' output, receive the snapshot into the new dataset.
-	# XXX handle piped input
-	#
-	/usr/sbin/zfs receive -F $ACTIVE_DS < $ZFSRCV || \
-	    fail_fatal "$f_zfs_create"
-
-else
-	#
-	# If neither of the -a or -r options are provided, assume
-	# detach/attach behavior with an existing SNAP clone dataset already
-	# in existence, or we're using one from an earlier detach that was
-	# specified with -d, or possibly the dataset exists from a previous
-	# attach run that did not finish successfully because the sw was not
-	# updated (due to missing -u option).
-	#
-
-	#
-	# We know we already have a valid dataset from earlier validation.
-	#
-
-	#
-	# If we are attaching a zone that was previously detached on this
-	# system, then the dataset is not zoned and is mounted at this point.
-	# Look to see if the dataset is in this state.
-	#
-	zoned=`/usr/sbin/zfs list -H -o zoned $ACTIVE_DS`
-
-	if [ "$zoned" = "off" ]; then
-		#
-		# When we detached the SNAP clone zone, we changed some of the
-		# properties and then left it mounted.  Undo that work now.
-		#
-		/usr/sbin/umount $zonepath/root >/dev/null 2>&1
-
-		/usr/sbin/zfs set zoned=on $ACTIVE_DS || \
-			fail_fatal "$f_zfs_create"
-
-		/usr/sbin/zfs set mountpoint=legacy $ACTIVE_DS || \
-			fail_incomplete "$f_zfs_create"
-
-		/usr/sbin/zfs set canmount=noauto $ACTIVE_DS || \
-			fail_fatal "$f_zfs_create"
-	fi
-fi
-
-
-/usr/sbin/mount -F zfs $ACTIVE_DS $zoneroot || fail_fatal "$f_zfs_mount"
-#
-# unmount the zoneroot and clean up our temp files if anything goes wrong
-#
-trap "/usr/sbin/umount $zoneroot > /dev/null 2>&1" EXIT
-
+[[ -f $ZONEROOT/var/svc/manifest/system/sysevent.xml ]] && \
+    fatal "$sanity_fail_global"
+[[ -f $ZONEROOT/var/svc/manifest/system/zones.xml ]] && \
+    fatal "$sanity_fail_global"
+[[ -f $ZONEROOT/var/svc/manifest/system/dumpadm.xml ]] && \
+    fatal "$sanity_fail_global"
 
 #
 # Look for the 'entire' incorporation's FMRI in the current image; due to users
 # doing weird machinations with their publishers, we strip off the publisher
 # from the FMRI if it is present.
 #
-gz_entire_fmri=$(get_entire_incorp) || fail_fatal "$f_gz_entire"
+gz_entire_fmri=$(get_entire_incorp) || fatal "$f_gz_entire"
 
 #
 # Get publisher information for global zone.
@@ -456,7 +325,7 @@
 # We're done with the global zone: switch images to the non-global
 # zone.
 #
-PKG_IMAGE="$zoneroot"
+PKG_IMAGE="$ZONEROOT"
 
 #
 # Get publisher information for non global zone.
@@ -464,13 +333,13 @@
 #
 get_preferred_publisher | IFS=" " read zone_publisher zone_publisher_url
 
-[[ -z $zone_publisher ]] && fail_usage "$f_no_pref_publisher" $zonename
-[[ -z $zone_publisher_url ]] && fail_usage "$f_no_pref_publisher" $zonename
+[[ -z $zone_publisher ]] && fail_usage "$f_no_pref_publisher" $ZONENAME
+[[ -z $zone_publisher_url ]] && fail_usage "$f_no_pref_publisher" $ZONENAME
 
 #
 # Get entire incorp for non-global zone
 #
-zone_entire_fmri=$(get_entire_incorp) || fail_fatal "$f_zone_entire"
+zone_entire_fmri=$(get_entire_incorp) || fatal "$f_zone_entire"
 
 printf "$m_gzinc\n" $gz_entire_fmri
 printf "$m_zinc\n" $zone_entire_fmri
@@ -479,16 +348,17 @@
 #
 comp=$(/usr/lib/brand/ipkg/fmri_compare $zone_entire_fmri $gz_entire_fmri)
 if [[ $? -ne 0 ]]; then
-	fail_fatal "$f_fmri_compare"
+	fatal "$f_fmri_compare"
 fi
 if [[ $comp = "=" ]]; then
-	printf "$m_insync\n" $zonename
+	printf "$m_insync\n" $ZONENAME
 	echo $m_complete
+	EXIT_CODE=$ZONE_SUBPROC_OK
 	exit $ZONE_SUBPROC_OK
 fi
 if [[ $comp = ">" ]]; then
-	printf "$m_uprev\n" $zonename
-	fail_fatal "$f_uprev"
+	printf "$m_uprev\n" $ZONENAME
+	fatal "$f_uprev"
 fi
 
 #
@@ -496,8 +366,8 @@
 #
 if [ -z $allow_update ]; then
 	# zone is downrev
-	printf "$m_dnrev\n" $zonename
-	fail_fatal "$f_downrev"
+	printf "$m_dnrev\n" $ZONENAME
+	fatal "$f_downrev"
 fi
 
 #
@@ -515,31 +385,31 @@
 	printf "$m_resetpub2\n" $gz_entire_fmri
 	printf "$m_resetpub3\n"
 
-	safe_dir $zoneroot/var
-	safe_dir $zoneroot/var/pkg
+	safe_dir var
+	safe_dir var/pkg
 
 	# Copy credentials from global zone.
 	secinfo=""
 	if [[ $gzkeyfile != "None" || $gzcertfile != "None" ]]; then
-		if [[ -e $zoneroot/$KEYDIR ]]; then
-			safe_dir $zoneroot/$KEYDIR
+		if [[ -e $ZONEROOT/$KEYDIR ]]; then
+			safe_dir $KEYDIR
 		else
-			mkdir -m 755 $zoneroot/$KEYDIR
+			mkdir -m 755 $ZONEROOT/$KEYDIR
 		fi
 	fi
 
 	if [[ $gzkeyfile != None ]]; then
 		newlocation="$KEYDIR/attach_$(basename $gzkeyfile)"
-		safe_copy $gzkeyfile $zoneroot/$newlocation
-		chmod 644 $zoneroot/$newkeylocation
-		chown -h root:root $zoneroot/$newkeylocation
+		safe_copy $gzkeyfile $ZONEROOT/$newlocation
+		chmod 644 $ZONEROOT/$newkeylocation
+		chown -h root:root $ZONEROOT/$newkeylocation
 		secinfo="$secinfo -k $newlocation"
 	fi
 	if [[ $gzcertfile != None ]]; then
 		newlocation="$KEYDIR/attach_$(basename $gzcertfile)"
-		safe_copy $gzcertfile $zoneroot/$newlocation
-		chmod 644 $zoneroot/$newkeylocation
-		chown -h root:root $zoneroot/$newkeylocation
+		safe_copy $gzcertfile $ZONEROOT/$newlocation
+		chmod 644 $ZONEROOT/$newkeylocation
+		chown -h root:root $ZONEROOT/$newkeylocation
 		secinfo="$secinfo -c $newlocation"
 	fi
 
@@ -547,7 +417,7 @@
 	# catalog to be updated.
 	$PKG set-publisher -P -O $gz_publisher_url $secinfo $gz_publisher
 	if [[ $? -ne 0 ]]; then
-		fail_fatal "$f_reset_pub"
+		fatal "$f_reset_pub"
 	fi
 	zone_publisher=$gz_publisher
 	zone_publisher_url=$gz_publisher_url
@@ -570,7 +440,7 @@
 #
 $PKG install $gz_entire_fmri
 if [ $? -ne 0 ]; then
-	fail_fatal "$f_update"
+	fatal "$f_update"
 fi
 
 printf "$m_updating2\n"
@@ -585,15 +455,16 @@
 zone_pkgs=$(LC_ALL=C $PKG list --no-refresh -H "pkg://$zone_publisher/*" | \
     awk '{print $1}' | egrep -v '^entire$')
 if [[ $? -ne 0 ]]; then
-	fail_fatal "$f_pkg_list"
+	fatal "$f_pkg_list"
 fi
 
 $PKG install $zone_pkgs
 if [ $? -ne 0 ]; then
-	fail_fatal "$f_update"
+	fatal "$f_update"
 fi
 
 printf "$m_sync_done\n" $gz_entire_fmri
 printf "$m_complete\n"
 
+EXIT_CODE=$ZONE_SUBPROC_OK
 exit $ZONE_SUBPROC_OK
--- a/src/brand/clone	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/brand/clone	Tue Nov 10 14:40:37 2009 -0700
@@ -26,6 +26,7 @@
 
 . /usr/lib/brand/ipkg/common.ksh
 
+m_usage=$(gettext "clone {sourcezone}")
 f_nosource=$(gettext "Error: unable to determine source zone dataset.")
 f_sysunconfig=$(gettext "Error: sys-unconfig failed.")
 f_nobrand=$(gettext "Error: unable to determine source zone brand.")
@@ -39,13 +40,13 @@
 	case $opt in
 		R)	zonepath="$OPTARG" ;;
 		z)	zonename="$OPTARG" ;;
-		*)	fail_usage "$0 {sourcezone}";;
+		*)	fail_usage "";;
 	esac
 done
 shift $((OPTIND-1))
 
 if [ $# -ne 1 ]; then
-	fail_usage "$0 {sourcezone}";
+	fail_usage "";
 fi
 
 sourcezone=$1
--- a/src/brand/common.ksh	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/brand/common.ksh	Tue Nov 10 14:40:37 2009 -0700
@@ -23,27 +23,41 @@
 # Use is subject to license terms.
 #
 
-ZONE_SUBPROC_OK=0
-ZONE_SUBPROC_USAGE=253
-ZONE_SUBPROC_INCOMPLETE=254
-ZONE_SUBPROC_FATAL=255
+unset LD_LIBRARY_PATH
+PATH=/usr/bin:/usr/sbin
+export PATH
+
+. /usr/lib/brand/shared/common.ksh
 
 PROP_PARENT="org.opensolaris.libbe:parentbe"
 PROP_ACTIVE="org.opensolaris.libbe:active"
 
+f_incompat_options=$(gettext "cannot specify both %s and %s options")
+f_sanity_detail=$(gettext  "Missing %s at %s")
+f_sanity_sparse=$(gettext  "Is this a sparse zone image?  The image must be whole-root.")
+sanity_ok=$(gettext     "  Sanity Check: Passed.  Looks like an OpenSolaris system.")
+sanity_fail=$(gettext   "  Sanity Check: FAILED (see log for details).")
+sanity_fail_vers=$(gettext  "  Sanity Check: the Solaris image (release %s) is not an OpenSolaris image and cannot be installed in this type of branded zone.")
+install_fail=$(gettext  "        Result: *** Installation FAILED ***")
 f_zfs_in_root=$(gettext "Installing a zone in the ROOT pool is unsupported.")
 f_zfs_create=$(gettext "Unable to create the zone's ZFS dataset.")
 f_root_create=$(gettext "Unable to create the zone's ZFS dataset mountpoint.")
-f_no_gzbe=$(gettext "Error: unable to determine global zone boot environment.")
-f_no_ds=$(gettext "Error: no zonepath dataset.")
-f_multiple_ds=$(gettext "Error: multiple active datasets.")
-f_no_active_ds=$(gettext "Error: no active dataset.")
+f_no_gzbe=$(gettext "unable to determine global zone boot environment.")
+f_no_ds=$(gettext "the zonepath must be a ZFS dataset.\nThe parent directory of the zonepath must be a ZFS dataset so that the\nzonepath ZFS dataset can be created properly.")
+f_multiple_ds=$(gettext "multiple active datasets.")
+f_no_active_ds=$(gettext "no active dataset.")
 f_zfs_mount=$(gettext "Unable to mount the zone's ZFS dataset.")
 
 f_safedir=$(gettext "Expected %s to be a directory.")
 f_cp=$(gettext "Failed to cp %s %s.")
 f_cp_unsafe=$(gettext "Failed to safely copy %s to %s.")
 
+m_brnd_usage=$(gettext "brand-specific usage: ")
+
+m_complete=$(gettext    "        Done: Installation completed in %s seconds.")
+m_postnote=$(gettext    "  Next Steps: Boot the zone, then log into the zone console (zlogin -C)")
+m_postnote2=$(gettext "              to complete the configuration process.")
+
 fail_incomplete() {
 	printf "ERROR: " 1>&2
 	printf "$@" 1>&2
@@ -51,16 +65,59 @@
 	exit $ZONE_SUBPROC_INCOMPLETE
 }
 
-fail_fatal() {
-	printf "ERROR: " 1>&2
+fail_usage() {
 	printf "$@" 1>&2
 	printf "\n" 1>&2
-	exit $ZONE_SUBPROC_FATAL
+	printf "$m_brnd_usage" 1>&2
+	printf "$m_usage\n" 1>&2
+	exit $ZONE_SUBPROC_USAGE
 }
 
-fail_usage() {
-	print "Usage: $1"
-	exit $ZONE_SUBPROC_USAGE
+sanity_check()
+{
+	typeset dir="$1"
+	shift
+	res=0
+
+	#
+	# Check for some required directories and make sure this isn't a
+	# sparse zone image from SXCE.
+	#
+	checks="etc etc/svc var var/svc"
+	for x in $checks; do
+		if [[ ! -e $dir/$x ]]; then
+			log "$f_sanity_detail" "$x" "$dir"
+			res=1
+		fi
+	done
+	if (( $res != 0 )); then
+		log "$f_sanity_sparse"
+		log "$sanity_fail"
+		fatal "$install_fail" "$ZONENAME"
+        fi
+
+	# Check for existence of pkg command.
+	if [[ ! -x $dir/usr/bin/pkg ]]; then
+		log "$f_sanity_detail" "usr/bin/pkg" "$dir"
+		log "$sanity_fail"
+		fatal "$install_fail" "$ZONENAME"
+	fi
+
+	#
+	# XXX There should be a better way to do this.
+	# Check image release.  We only work on the same minor release as the
+	# system is running.  The INST_RELEASE file doesn't exist with IPS on
+	# OpenSolaris, so its presence means we have an earlier Solaris
+	# (i.e. non-OpenSolaris) image.
+	#
+	if [[ -f "$dir/var/sadm/system/admin/INST_RELEASE" ]]; then
+		image_vers=$(nawk -F= '{if ($1 == "VERSION") print $2}' \
+		    $dir/var/sadm/system/admin/INST_RELEASE)
+		vlog "$sanity_fail_vers" "$image_vers"
+		fatal "$install_fail" "$ZONENAME"
+	fi
+	
+	vlog "$sanity_ok"
 }
 
 get_current_gzbe() {
@@ -85,19 +142,6 @@
 	fi
 }
 
-# Find the dataset mounted on the zonepath.
-get_zonepath_ds() {
-	ZONEPATH_DS=`/usr/sbin/zfs list -H -t filesystem -o name,mountpoint | \
-	    /usr/bin/nawk -v zonepath=$1 '{
-		if ($2 == zonepath)
-			print $1
-	}'`
-
-	if [ -z "$ZONEPATH_DS" ]; then
-		fail_fatal "$f_no_ds"
-	fi
-}
-
 # Find the active dataset under the zonepath dataset to mount on zonepath/root.
 # $1 CURRENT_GZBE
 # $2 ZONEPATH_DS
@@ -136,6 +180,66 @@
 }
 
 #
+# Set up ZFS dataset hierarchy for the zone root dataset.
+#
+create_active_ds() {
+	get_current_gzbe
+
+	#
+	# Find the zone's current dataset.  This should have been created by
+	# zoneadm.
+	#
+	get_zonepath_ds $zonepath
+
+	# Check that zone is not in the ROOT dataset.
+	fail_zonepath_in_rootds $ZONEPATH_DS
+
+	#
+	# From here on, errors should cause the zone to be incomplete.
+	#
+	int_code=$ZONE_SUBPROC_FATAL
+
+	#
+	# We need to tolerate errors while creating the datasets and making the
+	# mountpoint, since these could already exist from some other BE.
+	#
+
+	/usr/sbin/zfs list -H -o name $ZONEPATH_DS/ROOT >/dev/null 2>&1
+	if (( $? != 0 )); then
+		/usr/sbin/zfs create -o mountpoint=legacy \
+		    -o zoned=on $ZONEPATH_DS/ROOT
+		if (( $? != 0 )); then
+			fail_fatal "$f_zfs_create"
+		fi
+	fi
+
+	BENAME=zbe
+	BENUM=0
+	# Try 100 different names before giving up.
+	while [ $BENUM -lt 100 ]; do
+       		/usr/sbin/zfs create -o $PROP_ACTIVE=on \
+		    -o $PROP_PARENT=$CURRENT_GZBE \
+		    -o canmount=noauto $ZONEPATH_DS/ROOT/$BENAME >/dev/null 2>&1
+		if (( $? == 0 )); then
+			break
+		fi
+		BENUM=`expr $BENUM + 1`
+		BENAME="zbe-$BENUM"
+	done
+
+	if [ $BENUM -ge 100 ]; then
+		fail_fatal "$f_zfs_create"
+	fi
+
+	if [ ! -d $ZONEROOT ]; then
+		/usr/bin/mkdir $ZONEROOT
+	fi
+
+	/usr/sbin/mount -F zfs $ZONEPATH_DS/ROOT/$BENAME $ZONEROOT || \
+	    fail_incomplete "$f_zfs_mount"
+}
+
+#
 # Emits to stdout the entire incorporation for this image,
 # stripped of publisher name and other junk.
 #
@@ -172,26 +276,3 @@
 	    nawk -F': ' '/SSL Cert/ {print $2; exit 0}')
 	print $key $cert
 }
-
-# Validate that the directory is safe.
-# n.b.: this is diverged from the shared/common.ksh version.
-safe_dir()
-{
-	typeset dir="$1"
-
-	[[ -h $dir || ! -d $dir ]] && fail_fatal "$f_safedir"
-}
-
-# Make a copy even if the destination already exists.
-# n.b.: this is diverged from the shared/common.ksh version.
-safe_copy()
-{
-	typeset src="$1"
-	typeset dst="$2"
-
-	if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
-		/usr/bin/cp -p $src $dst || fail_fatal "$f_cp" "$src" "$dst"
-	else
-		fail_fatal "$f_cp_unsafe" "$src" "$dst"
-	fi
-}
--- a/src/brand/config.xml	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/brand/config.xml	Tue Nov 10 14:40:37 2009 -0700
@@ -38,20 +38,20 @@
 
 	<!-- We may not be able to do the create in pkg(1) proper. -->
 	<install>/usr/lib/brand/ipkg/pkgcreatezone -z %z -R %R</install>
-	<installopts>a:P:e:c:k:h</installopts>
+	<installopts>a:c:d:e:hk:P:p:suv</installopts>
 	<boot></boot>
 	<halt></halt>
 	<verify_cfg>/usr/lib/brand/ipkg/support verify</verify_cfg>
 	<verify_adm></verify_adm>
 	<postclone></postclone>
 	<postinstall></postinstall>
-	<attach>/usr/lib/brand/ipkg/attach -z %z -R %R</attach>
+	<attach>/usr/lib/brand/ipkg/attach %z %R</attach>
 	<detach>/usr/lib/brand/ipkg/detach -z %z -R %R</detach>
 	<clone>/usr/lib/brand/ipkg/clone -z %z -R %R</clone>
 	<uninstall>/usr/lib/brand/ipkg/uninstall %z %R</uninstall>
 	<prestatechange>/usr/lib/brand/ipkg/prestate %z %R</prestatechange>
 	<poststatechange>/usr/lib/brand/ipkg/poststate %z %R</poststatechange>
-	<query>/usr/lib/brand/ipkg/query %z %R</query>
+	<query>/usr/lib/brand/shared/query %z %R</query>
 
 	<privilege set="default" name="contract_event" />
 	<privilege set="default" name="contract_identity" />
--- a/src/brand/detach	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/brand/detach	Tue Nov 10 14:40:37 2009 -0700
@@ -20,13 +20,13 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
 . /usr/lib/brand/ipkg/common.ksh
 
-m_usage=$(gettext  "ipkg brand detach arguments [-n ].")
+m_usage=$(gettext  "detach [-n ].")
 
 f_mount=$(gettext "Error: error mounting zone root dataset.")
 
@@ -38,8 +38,8 @@
 		n)	noexecute=1 ;;
 		R)	zonepath="$OPTARG" ;;
 		z)	zonename="$OPTARG" ;;
-		?)	fail_usage "$m_usage" ;;
-		*)	fail_usage "$m_usage";;
+		?)	fail_usage "" ;;
+		*)	fail_usage "";;
 	esac
 done
 shift $((OPTIND-1))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/brand/image_install	Tue Nov 10 14:40:37 2009 -0700
@@ -0,0 +1,231 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# image_install is used when installing a zone in a 'p2v' scenario.  In
+# this case the zone install hook will branch off to this script which
+# is responsible for setting up the physical system image in the zonepath
+# and performing the various modifications necessary to enable a physical
+# system image to run inside a zone.  This script sets up the image in the
+# zonepath then calls the p2v script to modify the image to run in a zone.
+#
+
+. /usr/lib/brand/ipkg/common.ksh
+
+m_usage=$(gettext "\n        install {-a archive|-d path} {-p|-u} [-s|-v]")
+install_log=$(gettext   "    Log File: %s")
+
+p2ving=$(gettext        "Postprocessing: This may take a while...")
+p2v_prog=$(gettext      "   Postprocess: ")
+p2v_done=$(gettext      "        Result: Postprocessing complete.")
+p2v_fail=$(gettext      "        Result: Postprocessing failed.")
+m_postnote3=$(gettext "              Make any other adjustments, such as disabling SMF services\n              that are no longer needed.")
+
+media_missing=\
+$(gettext "%s: you must specify an installation source using '-a' or '-d'.")
+cfgchoice_missing=\
+$(gettext "you must specify -u (sys-unconfig) or -p (preserve identity).")
+
+# Clean up on interrupt
+trap_cleanup()
+{
+	msg=$(gettext "Installation cancelled due to interrupt.")
+	log "$msg"
+
+	trap_exit
+}
+
+# If the install failed then clean up the ZFS datasets we created.
+trap_exit()
+{
+	# umount any mounted file systems
+	[[ -n "$fstmpfile" ]] && umnt_fs
+
+	if (( $zone_is_mounted != 0 )); then
+		error "$v_unmount"
+		zoneadm -z $ZONENAME unmount
+		zone_is_mounted=0
+	fi
+
+	if (( $EXIT_CODE != $ZONE_SUBPROC_OK )); then
+		/usr/lib/brand/ipkg/uninstall $ZONENAME $ZONEPATH -F
+	fi
+
+	exit $EXIT_CODE
+}
+
+#
+# The main body of the script starts here.
+#
+# This script should never be called directly by a user but rather should
+# only be called by pkgcreatezone to install an OpenSolaris system image into
+# a zone.
+#
+
+#
+# Exit code to return if install is interrupted or exit code is otherwise
+# unspecified.
+#
+EXIT_CODE=$ZONE_SUBPROC_USAGE
+
+zone_is_mounted=0
+trap trap_cleanup INT
+trap trap_exit EXIT
+
+# If we weren't passed at least two arguments, exit now.
+(( $# < 2 )) && exit $ZONE_SUBPROC_USAGE
+
+ZONENAME="$1"
+ZONEPATH="$2"
+# XXX shared/common script currently uses lower case zonename & zonepath
+zonename="$ZONENAME"
+zonepath="$ZONEPATH"
+
+ZONEROOT="$ZONEPATH/root"
+
+shift; shift	# remove zonename and zonepath from arguments array
+
+unset inst_type
+unset msg
+unset silent_mode
+unset verbose_mode
+
+#
+# It is worth noting here that we require the end user to pick one of
+# -u (sys-unconfig) or -p (preserve config).  This is because we can't
+# really know in advance which option makes a better default.  Forcing
+# the user to pick one or the other means that they will consider their
+# choice and hopefully not be surprised or disappointed with the result.
+#
+unset unconfig_zone
+unset preserve_zone
+
+while getopts "a:d:psuv" opt
+do
+	case "$opt" in
+		a)
+			if [[ -n "$inst_type" ]]; then
+				fatal "$both_kinds" "zoneadm install"
+			fi
+		 	inst_type="archive"
+			install_media="$OPTARG"
+			;;
+		d)
+			if [[ -n "$inst_type" ]]; then
+				fatal "$both_kinds" "zoneadm install"
+			fi
+		 	inst_type="directory"
+			install_media="$OPTARG"
+			;;
+		p)	preserve_zone="-p";;
+		s)	silent_mode=1;;
+		u)	unconfig_zone="-u";;
+		v)	verbose_mode="-v";;
+		*)	exit $ZONE_SUBPROC_USAGE;;
+	esac
+done
+shift OPTIND-1
+
+# The install can't be both verbose AND silent...
+[[ -n $silent_mode && -n $verbose_mode ]] && \
+    fatal "$f_incompat_options" "-s" "-v"
+
+[[ -z $install_media ]] && fatal "$media_missing" "zoneadm install"
+
+# The install can't both preserve and unconfigure
+[[ -n $unconfig_zone && -n $preserve_zone ]] && \
+    fatal "$f_incompat_options" "-u" "-p"
+
+# Must pick one or the other.
+[[ -z $unconfig_zone && -z $preserve_zone ]] && fail_usage "$cfgchoice_missing"
+
+LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp $ZONENAME.install_log.XXXXXX)
+[[ -z "$LOGFILE" ]] && fatal "$e_tmpfile"
+exec 2>>"$LOGFILE"
+log "$install_log" "$LOGFILE"
+
+vlog "Starting pre-installation tasks."
+
+#
+# From here on out, an unspecified exit or interrupt should exit with
+# ZONE_SUBPROC_NOTCOMPLETE, meaning a user will need to do an uninstall before
+# attempting another install, as we've modified the directories we were going
+# to install to in some way.
+#
+EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
+
+# ZONEROOT was created by our caller (pkgcreatezone)
+
+vlog "Installation started for zone \"$ZONENAME\""
+install_image "$inst_type" "$install_media"
+
+#
+# Run p2v.
+#
+# Getting the output to the right places is a little tricky because what
+# we want is for p2v to output in the same way the installer does: verbose
+# messages to the log file always, and verbose messages printed to the
+# user if the user passes -v.  This rules out simple redirection.  And
+# we can't use tee or other tricks because they cause us to lose the
+# return value from the p2v script due to the way shell pipelines work.
+#
+# The simplest way to do this seems to be to hand off the management of
+# the log file to the p2v script.  So we run p2v with -l to tell it where
+# to find the log file and then reopen the log (O_APPEND) when p2v is done.
+#
+log "$p2ving"
+vlog "running: p2v $verbose_mode $unconfig_zone $ZONENAME $ZONEPATH"
+/usr/lib/brand/ipkg/p2v -l "$LOGFILE" $verbose_mode $unconfig_zone $ZONENAME \
+    $ZONEPATH
+p2v_result=$?
+exec 2>>$LOGFILE
+
+if (( $p2v_result != 0 )); then
+	log "$p2v_fail"
+	log ""
+	log "$install_fail"
+	log "$install_log" "$LOGFILE"
+	exit $ZONE_SUBPROC_FATAL
+fi
+vlog "$p2v_done"
+
+zone_is_mounted=1
+zoneadm -z $ZONENAME mount -f || fatal "$e_badmount"
+
+safe_copy $LOGFILE $ZONEPATH/lu/a/var/log/$ZONENAME.install$$.log
+
+zoneadm -z $ZONENAME unmount || fatal "$e_badunmount"
+zone_is_mounted=0
+
+trap - EXIT
+rm -f $LOGFILE
+log ""
+log "$m_complete" ${SECONDS}
+printf "$install_log\n" "$ZONEROOT/var/log/$ZONENAME.install$$.log"
+printf "$m_postnote\n"
+printf "$m_postnote2\n"
+printf "$m_postnote3\n"
+
+exit $ZONE_SUBPROC_OK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/brand/p2v	Tue Nov 10 14:40:37 2009 -0700
@@ -0,0 +1,516 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+# NOTE: this script runs in the global zone and touches the non-global
+# zone, so care should be taken to validate any modifications so that they
+# are safe.
+
+# Restrict executables to /usr/bin and /usr/sbin
+PATH=/usr/bin:/usr/sbin
+export PATH
+unset LD_LIBRARY_PATH
+
+. /usr/lib/brand/ipkg/common.ksh
+
+LOGFILE=
+EXIT_CODE=1
+
+# Clean up on failure
+trap_exit()
+{
+	if (( $zone_is_mounted != 0 )); then
+		error "$v_unmount"
+		zoneadm -z $ZONENAME unmount
+	fi
+
+	exit $EXIT_CODE
+}
+
+#
+# For an exclusive stack zone, fix up the network configuration files.
+# We need to do this even if unconfiguring the zone so sys-unconfig works
+# correctly.
+#
+fix_net()
+{
+	[[ "$STACK_TYPE" == "shared" ]] && return
+
+	NETIF_CNT=0
+	for i in $ZONEROOT/etc/hostname.* $ZONEROOT/etc/dhcp.*
+	do
+		if [[ -f "$i" ]]; then
+			NETIF_CNT=$(expr $NETIF_CNT + 1)
+			OLD_HOSTNET="$i"
+		fi
+	done
+	if (( $NETIF_CNT != 1 )); then
+		vlog "$v_nonetfix"
+		return
+	fi
+
+	NET=$(LC_ALL=C zonecfg -z $ZONENAME info net)
+	if (( $? != 0 )); then
+		error "$e_badinfo" "net"
+		return
+	fi
+
+	NETIF=$(echo $NET | nawk '{
+		for (i = 1; i < NF; i++) {
+			if ($i == "physical:") {
+				if (length(net) == 0) {
+					i++
+					net = $i
+				} else {
+					multiple=1
+				}
+			}
+		}
+	}
+	END {	if (!multiple)
+			print net
+	}')
+
+	if [[ -z "$NETIF" ]]; then
+		vlog "$v_nonetfix"
+		return
+	fi
+
+	NEWHOSTNET=${OLD_HOSTNET%*.*}
+	if [[ "$OLD_HOSTNET" != "$NEWHOSTNET.$NETIF" ]]; then
+		safe_move $OLD_HOSTNET $NEWHOSTNET.$NETIF
+	fi
+}
+
+#
+# Disable all of the shares since the zone cannot be an NFS server.
+# Note that we disable the various instances of the svc:/network/shares/group
+# SMF service in the fix_smf function. 
+#
+fix_nfs()
+{
+	zonedfs=$ZONEROOT/etc/dfs
+
+	if [[ -h $zonedfs/dfstab || ! -f $zonedfs/dfstab ]]; then
+		error "$e_badfile" "/etc/dfs/dfstab"
+		return
+	fi
+
+	tmpfile=$(mktemp -t)
+	if [[ -z "$tmpfile" ]]; then
+		error "$e_tmpfile"
+		return
+	fi
+
+	nawk '{
+		if (substr($1, 0, 1) == "#") {
+			print $0
+		} else {
+			print "#", $0
+			modified=1
+		}
+	}
+	END {
+		if (modified == 1) {
+			printf("# Modified by p2v ")
+			system("/usr/bin/date")
+			exit 0
+		}
+		exit 1
+	}' $zonedfs/dfstab >>$tmpfile
+
+	if (( $? == 0 )); then
+		if [[ ! -f $zonedfs/dfstab.pre_p2v ]]; then
+			safe_copy $zonedfs/dfstab $zonedfs/dfstab.pre_p2v
+		fi
+		safe_copy $tmpfile $zonedfs/dfstab
+	fi
+	rm -f $tmpfile
+}
+
+#
+# Comment out most of the old mounts since they are either unneeded or
+# likely incorrect within a zone.  Specific mounts can be manually 
+# reenabled if the corresponding device is added to the zone.
+#
+fix_vfstab()
+{
+	if [[ -h $ZONEROOT/etc/vfstab || ! -f $ZONEROOT/etc/vfstab ]]; then
+		error "$e_badfile" "/etc/vfstab"
+		return
+	fi
+
+	tmpfile=$(mktemp -t)
+	if [[ -z "$tmpfile" ]]; then
+		error "$e_tmpfile"
+		return
+	fi
+
+	nawk '{
+		if (substr($1, 0, 1) == "#") {
+			print $0
+		} else if ($1 == "fd" || $1 == "/proc" || $1 == "swap" ||
+		    $1 == "ctfs" || $1 == "objfs" || $1 == "sharefs" ||
+		    $4 == "nfs" || $4 == "lofs") {
+			print $0
+		} else {
+			print "#", $0
+			modified=1
+		}
+	}
+	END {
+		if (modified == 1) {
+			printf("# Modified by p2v ")
+			system("/usr/bin/date")
+			exit 0
+		}
+		exit 1
+	}' $ZONEROOT/etc/vfstab >>$tmpfile
+
+	if (( $? == 0 )); then
+		if [[ ! -f $ZONEROOT/etc/vfstab.pre_p2v ]]; then
+			safe_copy $ZONEROOT/etc/vfstab \
+			    $ZONEROOT/etc/vfstab.pre_p2v
+		fi
+		safe_copy $tmpfile $ZONEROOT/etc/vfstab
+	fi
+	rm -f $tmpfile
+}
+
+#
+# Delete or disable SMF services.
+#
+fix_smf()
+{
+	SMF_UPGRADE=/a/var/svc/profile/upgrade
+
+	#
+	# Fix network services if shared stack.
+	#
+	if [[ "$STACK_TYPE" == "shared" ]]; then
+		vlog "$v_fixnetsvcs"
+
+		NETPHYSDEF="svc:/network/physical:default"
+		NETPHYSNWAM="svc:/network/physical:nwam"
+
+		vlog "$v_enblsvc" "$NETPHYSDEF"
+		zlogin -S $ZONENAME "echo /usr/sbin/svcadm enable $NETPHYSDEF \
+		    >>$SMF_UPGRADE" </dev/null
+
+		vlog "$v_dissvc" "$NETPHYSNWAM"
+		zlogin -S $ZONENAME \
+		    "echo /usr/sbin/svcadm disable $NETPHYSNWAM \
+		    >>$SMF_UPGRADE" </dev/null
+
+		# Disable routing svcs.
+		vlog "$v_dissvc" 'svc:/network/routing/*'
+		zlogin -S $ZONENAME \
+		    "echo /usr/sbin/svcadm disable 'svc:/network/routing/*' \
+		    >>$SMF_UPGRADE" </dev/null
+	fi
+
+	#
+	# Disable well-known services that don't run in a zone.
+	#
+	vlog "$v_rminvalidsvcs"
+	for i in $(egrep -hv "^#" \
+	    /usr/lib/brand/ipkg/smf_disable.lst \
+	    /etc/brand/ipkg/smf_disable.conf)
+	do
+		# Disable the svc.
+		vlog "$v_dissvc" "$i"
+		zlogin -S $ZONENAME \
+		    "echo /usr/sbin/svcadm disable $i >>$SMF_UPGRADE" </dev/null
+	done
+
+	#
+	# Since zones can't be NFS servers, disable all of the instances of
+	# the shares svc.
+	#
+	vlog "$v_dissvc" 'svc:/network/shares/*'
+	zlogin -S $ZONENAME \
+	    "echo /usr/sbin/svcadm disable 'svc:/network/shares/*' \
+	    >>$SMF_UPGRADE" </dev/null
+}
+
+#
+# Remove well-known pkgs that do not work inside a zone.
+#
+rm_pkgs()
+{
+	for i in $(egrep -hv "^#" /usr/lib/brand/ipkg/pkgrm.lst \
+	    /etc/brand/ipkg/pkgrm.conf)
+	do
+		pkg info $i >/dev/null 2>&1
+		if (( $? != 0 )); then
+			continue
+		fi
+
+		vlog "$v_rmpkg" "$i"
+		zlogin -S $ZONENAME LC_ALL=C \
+		    /usr/bin/pkg -R /a uninstall -r $i </dev/null >&2 || \
+		    error "$e_rmpkg" $i
+	done
+}
+
+#
+# Zoneadmd writes a one-line index file into the zone when the zone boots,
+# so any information about installed zones from the original system will
+# be lost at that time.  Here we'll warn the sysadmin about any pre-existing
+# zones that they might want to clean up by hand, but we'll leave the zonepaths
+# in place in case they're on shared storage and will be migrated to
+# a new host.
+#
+warn_zones()
+{
+	zoneconfig=$ZONEROOT/etc/zones
+
+	if [[ -h $zoneconfig/index || ! -f $zoneconfig/index ]]; then
+		error "$e_badfile" "/etc/zones/index"
+		return
+	fi
+
+	NGZ=$(nawk -F: '{
+		if (substr($1, 0, 1) == "#" || $1 == "global")
+			continue
+
+		if ($2 == "installed")
+			printf("%s ", $1)
+	}' $zoneconfig/index)
+
+	# Return if there are no installed zones to warn about.
+	[[ -z "$NGZ" ]] && return
+
+	log "$v_rmzones" "$NGZ"
+
+	NGZP=$(nawk -F: '{
+		if (substr($1, 0, 1) == "#" || $1 == "global")
+			continue
+
+		if ($2 == "installed")
+			printf("%s ", $3)
+	}' $zoneconfig/index)
+
+	log "$v_rmzonepaths"
+
+	for i in $NGZP
+	do
+		log "    %s" "$i"
+	done
+}
+
+#
+# failure should unmount the zone if necessary;
+#
+zone_is_mounted=0
+trap trap_exit EXIT
+
+#
+# Parse the command line options.
+#
+OPT_U=
+OPT_V=
+OPT_L=
+while getopts "b:uvl:" opt
+do
+	case "$opt" in
+		u)	OPT_U="-u";;
+		v)	OPT_V="-v";;
+		l)	LOGFILE="$OPTARG"; OPT_L="-l \"$OPTARG\"";;
+		*)	exit 1;;
+	esac
+done
+shift OPTIND-1
+
+(( $# != 2 )) && exit 1
+
+[[ -n $LOGFILE ]] && exec 2>>$LOGFILE
+
+ZONENAME=$1
+ZONEPATH=$2
+ZONEROOT=$ZONEPATH/root
+
+e_badinfo=$(gettext "Failed to get '%s' zone resource")
+e_badfile=$(gettext "Invalid '%s' file within the zone")
+e_tmpfile=$(gettext "Unable to create temporary file")
+v_mkdirs=$(gettext "Creating mount points")
+v_nonetfix=$(gettext "Cannot update /etc/hostname.{net} file")
+v_change_var=$(gettext "Changing the pkg variant to nonglobal...")
+e_change_var=$(gettext "Changing the pkg variant to nonglobal failed")
+v_update=$(gettext "Updating the zone software to match the global zone...")
+v_updatedone=$(gettext "Zone software update complete")
+e_badupdate=$(gettext "Updating the Zone software failed")
+v_adjust=$(gettext "Updating the image to run within a zone")
+v_stacktype=$(gettext "Stack type '%s'")
+v_mounting=$(gettext "Mounting the zone")
+e_badmount=$(gettext "Zone mount failed")
+v_unmount=$(gettext "Unmounting zone")
+e_badunmount=$(gettext "Zone unmount failed")
+v_rmhollowsvcs=$(gettext "Deleting global zone-only SMF services")
+v_fixnetsvcs=$(gettext "Adjusting network SMF services")
+v_rminvalidsvcs=$(gettext "Disabling invalid SMF services")
+v_collectingsmf=$(gettext "Collecting SMF svc data")
+v_delsvc=$(gettext "Delete SMF svc '%s'")
+e_delsvc=$(gettext "deleting SMF svc '%s'")
+v_enblsvc=$(gettext "Enable SMF svc '%s'")
+e_enblsvc=$(gettext "enabling SMF svc '%s'")
+v_dissvc=$(gettext "Disable SMF svc '%s'")
+e_adminf=$(gettext "Unable to create admin file")
+v_rmpkg=$(gettext "Remove package '%s'")
+e_rmpkg=$(gettext "removing package '%s'")
+v_rmzones=$(gettext "The following zones in this image will be unusable: %s")
+v_rmzonepaths=$(gettext "These zonepaths could be removed from this image:")
+v_unconfig=$(gettext "Performing zone sys-unconfig")
+e_unconfig=$(gettext "sys-unconfig failed")
+v_exitgood=$(gettext "Postprocessing successful.")
+e_exitfail=$(gettext "Postprocessing failed.")
+
+#
+# Do some validation on the paths we'll be accessing
+#
+safe_dir etc
+safe_dir etc/dfs
+safe_dir etc/zones
+safe_dir var
+safe_dir var/log
+safe_dir var/pkg
+
+# Now do the work to update the zone.
+
+# Before booting the zone we may need to create a few mnt points, just in
+# case they don't exist for some reason.
+#
+# Whenever we reach into the zone while running in the global zone we
+# need to validate that none of the interim directories are symlinks
+# that could cause us to inadvertently modify the global zone.
+vlog "$v_mkdirs"
+if [[ ! -f $ZONEROOT/tmp && ! -d $ZONEROOT/tmp ]]; then
+	mkdir -m 1777 -p $ZONEROOT/tmp || exit $EXIT_CODE
+fi
+if [[ ! -f $ZONEROOT/var/run && ! -d $ZONEROOT/var/run ]]; then
+	mkdir -m 1755 -p $ZONEROOT/var/run || exit $EXIT_CODE
+fi
+if [[ ! -h $ZONEROOT/etc && ! -f $ZONEROOT/etc/mnttab ]]; then
+	touch $ZONEROOT/etc/mnttab || exit $EXIT_CODE
+	chmod 444 $ZONEROOT/etc/mnttab || exit $EXIT_CODE
+fi
+if [[ ! -f $ZONEROOT/proc && ! -d $ZONEROOT/proc ]]; then
+	mkdir -m 755 -p $ZONEROOT/proc || exit $EXIT_CODE
+fi
+if [[ ! -f $ZONEROOT/dev && ! -d $ZONEROOT/dev ]]; then
+	mkdir -m 755 -p $ZONEROOT/dev || exit $EXIT_CODE
+fi
+if [[ ! -h $ZONEROOT/etc && ! -h $ZONEROOT/etc/svc && ! -d $ZONEROOT/etc/svc ]]
+then
+	mkdir -m 755 -p $ZONEROOT/etc/svc/volatile || exit $EXIT_CODE
+fi
+
+# Check for zones inside of image.
+warn_zones
+
+STACK_TYPE=$(zoneadm -z $ZONENAME list -p | nawk -F: '{print $7}')
+if (( $? != 0 )); then
+	error "$e_badinfo" "stacktype"
+fi
+vlog "$v_stacktype" "$STACK_TYPE"
+
+# Note that we're doing this before update-on-attach has run.
+fix_net
+fix_nfs
+fix_vfstab
+
+#
+# Mount the zone so that we can do all of the updates needed on the zone.
+# The zone's root dataset is currently mounted so we have to first umount it.
+#
+umount $ZONEROOT || fatal "$f_umount"
+vlog "$v_mounting"
+zone_is_mounted=1
+zoneadm -z $ZONENAME mount -f || fatal "$e_badmount"
+
+#
+# Any errors in these functions are not considered fatal.  The zone can be
+# be fixed up manually afterwards and it may need some additional manual
+# cleanup in any case.
+#
+
+log "$v_adjust"
+# cleanup SMF services
+fix_smf
+# remove invalid pkgs
+rm_pkgs
+
+vlog "$v_unmount"
+zoneadm -z $ZONENAME unmount || fatal "$e_badunmount"
+zone_is_mounted=0
+
+# Mount the zone's root dataset back onto ZONEROOT.
+get_current_gzbe
+get_zonepath_ds $ZONEPATH
+get_active_ds $CURRENT_GZBE $ZONEPATH_DS
+mount -F zfs -O $ACTIVE_DS $ZONEROOT || fail_fatal "$f_mount"
+
+# Change the pkging variant from global zone to non-global zone.
+log "$v_change_var"
+pkg -R $ZONEROOT change-variant variant.opensolaris.zone=nonglobal || \
+    fatal "$e_change_var"
+
+#
+# Run update on attach.  State is currently 'incomplete' so use the private
+# force-update option.  The zone's root dataset is still mounted at this point.
+# update-on-attach will unmount the zonepath dataset when its done.
+# This also leaves the zone in the 'installed' state.  This is a known bug
+# in 'zoneadm attach'.  We change the zone state back to 'incomplete' for
+# now but this can be removed once 'zoneadm attach' is fixed.
+#
+log "$v_update"
+zoneadm -z $ZONENAME attach -U >&2 || fatal "$e_badupdate"
+zoneadm -z $ZONENAME mark incomplete || fatal "$e_badupdate"
+log "$v_updatedone"
+
+if [[ -n $OPT_U ]]; then
+	# We're sys-unconfiging the zone.
+	vlog "$v_unconfig"
+
+	vlog "$v_mounting"
+	zone_is_mounted=1
+	zoneadm -z $ZONENAME mount -f || fatal "$e_badmount"
+
+	/usr/sbin/zlogin -S $ZONENAME /usr/sbin/sys-unconfig -R /a \
+            </dev/null >/dev/null 2>&1
+        if (( $? != 0 )); then
+                error "$e_unconfig"
+		failed=1
+        fi
+
+	vlog "$v_unmount"
+	zoneadm -z $ZONENAME unmount || fatal "$e_badunmount"
+	zone_is_mounted=0
+
+	[[ -n $failed ]] && fatal "$e_exitfail"
+fi
+
+trap - EXIT
+vlog "$v_exitgood"
+exit 0
--- a/src/brand/pkgcreatezone	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/brand/pkgcreatezone	Tue Nov 10 14:40:37 2009 -0700
@@ -35,12 +35,15 @@
 
 . /usr/lib/brand/ipkg/common.ksh
 
+f_a_obs=$(gettext "-a publisher=uri option is obsolete, use -P instead.")
 f_pkg5_missing=$(gettext "pkg(5) does not seem to be present on this system.\n")
-f_no_pref_publisher=$(gettext "Unable to get global zone preferred publisher information, and none was supplied.\nYou must specify one using the -P option.\n")
+f_no_pref_publisher=$(gettext "Unable to get global zone preferred publisher information, and none was supplied.\nYou must specify one using the -P option.")
+f_key_file=$(gettext "Key file not allowed without -P")
+f_cert_file=$(gettext "Cert file not allowed without -P")
 f_img=$(gettext "failed to create image\n")
 f_pkg=$(gettext "failed to install package\n")
 f_interrupted=$(gettext "Installation cancelled due to interrupt.\n")
-f_bad_publisher=$(gettext "Syntax error in publisher information.\n")
+f_bad_publisher=$(gettext "Syntax error in publisher information.")
 f_no_entire=$(gettext "Unable to find 'entire' incorporation in the global zone image.\n")
 f_no_entire_in_pref=$(gettext "Unable to locate the incorporation '%s' in the preferred publisher '%s'.\nUse -P to supply a publisher which contains this package.\n")
 f_key_prop=$(gettext "Unable to propagate key %s to %s")
@@ -60,17 +63,14 @@
 m_smf=$(gettext	        " Postinstall: Copying SMF seed repository ...")
 m_more_brokenness=$(gettext " Postinstall: Applying workarounds.")
 m_mannote=$(gettext     "        Note: Man pages can be obtained by installing SUNWman")
-m_complete=$(gettext    "        Done: Installation completed in %s seconds.")
-m_postnote=$(gettext    "  Next Steps: Boot the zone, then log into the zone console")
-m_postnote2=$(gettext "             (zlogin -C) to complete the configuration process")
 
-m_usage=$(gettext    "$0: [-h] [-P publisher=uri] [-e extrapkg [...]]")
+m_usage=$(gettext "\n        install [-h]\n        install [-c certificate_file] [-k key_file] [-P publisher=uri]\n                [-e extrapkg [...]]\n        install {-a archive|-d path} {-p|-u} [-s|-v]")
 
 m_done=$(gettext      " done.")
 
 is_brand_labeled() {
 	brand_labeled=0
-	brand=$(/usr/sbin/zoneadm -z $zonename list -p | awk -F: '{print $6}')
+	brand=$(/usr/sbin/zoneadm -z $ZONENAME list -p | awk -F: '{print $6}')
 	if [[ $brand == "labeled" ]]; then
 		brand_labeled=1
 	fi
@@ -85,8 +85,8 @@
 trap trap_cleanup INT
 
 extra_packages=""
-zonename=""
-zonepath=""
+ZONENAME=""
+ZONEPATH=""
 pub_and_url=""
 
 # Setup i18n output
@@ -103,33 +103,83 @@
 
 certfile="None"
 keyfile="None"
-while getopts "a:P:z:R:h:e:c:k:" opt; do
+unset install_archive
+unset source_dir
+unset msg
+unset silent_mode
+unset verbose_mode
+
+while getopts "a:c:d:e:hk:P:pR:suvz:" opt; do
 	case $opt in
-		h)	fail_usage "$m_usage";;
-		R)	zonepath="$OPTARG" ;;
-		z)	zonename="$OPTARG" ;;
-		a)	pub_and_url="$OPTARG";
-			print -u2 \
-			    "WARNING: -a is deprecated.  Use -P instead." ;;
+		a)	# We're expecting a path to an archive
+			if [[ ! -f $OPTARG ]]; then
+			 	# If old style 'pub=uri' parameter then error.
+				echo $OPTARG | egrep -s =
+				if (( $? == 0 )); then
+					fail_usage "$f_a_obs"
+				fi
+			fi
+		 	install_archive="-a $OPTARG";;
+		c)	certfile="$OPTARG" ;;
+		d) 	source_dir="-d $OPTARG";;
+		e)	extra_packages="$extra_packages $OPTARG" ;;
+		h)	fail_usage "";;
+		k)	keyfile="$OPTARG" ;;
 		P)	pub_and_url="$OPTARG" ;;
-		c)	certfile="$OPTARG" ;;
-		k)	keyfile="$OPTARG" ;;
-		e)	extra_packages="$extra_packages $OPTARG" ;;
-		*)	fail_usage "$m_usage";;
+		p)	preserve_zone="-p";;
+		R)	ZONEPATH="$OPTARG" ;;
+		s)	silent_mode=1;;
+		u)	unconfig_zone="-u";;
+		v)	verbose_mode="-v";;
+		z)	ZONENAME="$OPTARG" ;;
+		*)	fail_usage "";;
 	esac
 done
 shift $((OPTIND-1))
 
-if [[ -z $zonepath || -z $zonename ]]; then
+if [[ -z $ZONEPATH || -z $ZONENAME ]]; then
 	print -u2 "Brand error: No zone path or name"
 	exit $ZONE_SUBPROC_USAGE
 fi
 
+# XXX shared/common script currently uses lower case zonename & zonepath
+zonename="$ZONENAME"
+zonepath="$ZONEPATH"
+
 is_brand_labeled
 
-zoneroot=$zonepath/root
+ZONEROOT=$ZONEPATH/root
 secinfo=""
 
+# An image install can't use both -a AND -d...
+[[ -n "$install_archive" && -n "$source_dir" ]] &&
+    fail_usage "$f_incompat_options" "-a" "-d"
+
+# The install can't be both verbose AND silent...
+[[ -n $silent_mode && -n $verbose_mode ]] && \
+    fail_usage "$f_incompat_options" "-s" "-v"
+
+# The install can't both preserve and unconfigure
+[[ -n $unconfig_zone && -n $preserve_zone ]] && \
+    fail_usage "$f_incompat_options" "-u" "-p"
+
+# IPS options aren't allowed when installing from a system image.
+if [[ -n "$install_archive" || -n "$source_dir" ]]; then
+	[[ -n $pub_and_url ]] && fail_usage "$f_incompat_options" "-a|-d" "-P"
+	[[ -n "$extra_packages" ]] && \
+	    fail_usage "$f_incompat_options" "-a|-d" "-e"
+	[[ "$certfile" != "None" ]] && \
+	    fail_usage "$f_incompat_options" "-a|-d" "-c"
+	[[ "$keyfile" != "None" ]] && \
+	    fail_usage "$f_incompat_options" "-a|-d" "-k"
+fi
+
+# p2v options aren't allowed when installing from a repo.
+if [[ -z $install_archive && -z $source_dir ]]; then
+	[[ -n $preserve_zone || -n $unconfig_zone ]] && \
+		fail_usage "$f_incompat_options" "default" "-p|-u"
+fi
+
 #
 # If the user didn't give us a publisher, and there's a preferred publisher set
 # for the system, set that as the default.
@@ -138,10 +188,10 @@
 propagate_extra=
 if [[ -z $pub_and_url ]]; then
 	if [[ $keyfile != "None" ]]; then
-		fail_usage "Key file not allowed without -P"
+		fail_usage "$f_key_file"
 	fi
 	if [[ $certfile != "None" ]]; then
-		fail_usage "Cert file not allowed without -P"
+		fail_usage "$f_cert_file"
 	fi
 
 	# We look for a preferred online origin.
@@ -226,66 +276,29 @@
 # Before installing the zone, set up ZFS dataset hierarchy for the zone root
 # dataset.
 #
-
-get_current_gzbe
-
-# Find the zone's current dataset.  This should have been created by zoneadm.
-get_zonepath_ds $zonepath
-
-# Check that zone is not in the ROOT dataset.
-fail_zonepath_in_rootds $ZONEPATH_DS
+create_active_ds
 
 #
-# From here on, errors should cause the zone to be incomplete.
-#
-int_code=$ZONE_SUBPROC_FATAL
-
-#
-# We need to tolerate errors while creating the datasets and making the
-# mountpoint, since these could already exist from some other BE.
+# If we're installing from an image, branch off to that installer.
 #
+if [[ -n $install_archive || -n $source_dir ]]; then
+	/usr/lib/brand/ipkg/image_install $ZONENAME $ZONEPATH \
+	    $install_archive $source_dir $verbose_mode $silent_mode \
+	    $unconfig_zone $preserve_zone
+	ii_result=$?
 
-/usr/sbin/zfs list -H -o name $ZONEPATH_DS/ROOT >/dev/null 2>&1
-if (( $? != 0 )); then
-	/usr/sbin/zfs create -o mountpoint=legacy -o zoned=on $ZONEPATH_DS/ROOT
-	if (( $? != 0 )); then
-		fail_fatal "$f_zfs_create"
+	if (( $ii_result != 0 )); then
+		exit $ZONE_SUBPROC_NOTCOMPLETE
 	fi
+	exit $ZONE_SUBPROC_OK
 fi
 
-BENAME=zbe
-BENUM=0
-# Try 100 different names before giving up.
-while [ $BENUM -lt 100 ]; do
-       	/usr/sbin/zfs create -o $PROP_ACTIVE=on -o $PROP_PARENT=$CURRENT_GZBE \
-	    -o canmount=noauto $ZONEPATH_DS/ROOT/$BENAME >/dev/null 2>&1
-	if (( $? == 0 )); then
-		break
-	fi
-        BENUM=`expr $BENUM + 1`
-	BENAME="zbe-$BENUM"
-done
-
-if [ $BENUM -ge 100 ]; then
-	fail_fatal "$f_zfs_create"
-fi
-
-if [ ! -d $zoneroot ]; then
-	/usr/bin/mkdir $zoneroot
-fi
-
-/usr/sbin/mount -F zfs $ZONEPATH_DS/ROOT/$BENAME $zoneroot || \
-	fail_incomplete "$f_zfs_mount"
-
-#
-# Done setting up the zone's datasets.
-#
 printf "$m_publisher\n" $publisher $publisherurl
 echo "$publishers_extra" | while IFS== read publisher publisherurl; do
 	[ -z "$publisher" ] && break
 	printf "$m_publisher\n" $publisher $publisherurl
 done
-printf "$m_image\n" $zoneroot
+printf "$m_image\n" $ZONEROOT
 
 #
 # We copy the credentials from the global zone into the new image
@@ -295,19 +308,19 @@
 	newkeylocation="$KEYDIR/$(basename $keyfile)"
 	secinfo="$secinfo -k $newkeylocation"
 	printf "$m_key_prop\n" $(basename $keyfile)
-	mkdir -p -m 755 $zoneroot/$KEYDIR || fail_fatal "$f_key_prop"
-	cp $keyfile $zoneroot/$newkeylocation || fail_fatal "$f_key_prop"
-	chmod 644 $zoneroot/$newkeylocation
-	chown -h root:root $zoneroot/$newkeylocation
+	mkdir -p -m 755 $ZONEROOT/$KEYDIR || fail_fatal "$f_key_prop"
+	cp $keyfile $ZONEROOT/$newkeylocation || fail_fatal "$f_key_prop"
+	chmod 644 $ZONEROOT/$newkeylocation
+	chown -h root:root $ZONEROOT/$newkeylocation
 fi
 if [[ $certfile != "None" ]]; then
 	newcertlocation="$KEYDIR/$(basename $certfile)"
 	secinfo="$secinfo -c $newcertlocation"
 	printf "$m_cert_prop\n" $(basename $certfile)
-	mkdir -p -m 755 $zoneroot/$KEYDIR || fail_fatal "$f_cert_prop"
-	cp $certfile $zoneroot/$newcertlocation || fail_fatal "$f_cert_prop"
-	chmod 644 $zoneroot/$newkeylocation
-	chown -h root:root $zoneroot/$newkeylocation
+	mkdir -p -m 755 $ZONEROOT/$KEYDIR || fail_fatal "$f_cert_prop"
+	cp $certfile $ZONEROOT/$newcertlocation || fail_fatal "$f_cert_prop"
+	chmod 644 $ZONEROOT/$newkeylocation
+	chown -h root:root $ZONEROOT/$newkeylocation
 fi
 
 #
@@ -318,10 +331,10 @@
 # XXX in the future, we can create the image --no-refresh, then
 # set the publisher.  But image-create --no-refresh is broken right now.
 #
-$PKG image-create -f --zone --full -p "$pub_and_url" $secinfo $zoneroot || \
+$PKG image-create -f --zone --full -p "$pub_and_url" $secinfo $ZONEROOT || \
     fail_incomplete "$f_img"
 
-PKG_IMAGE="$zoneroot"
+PKG_IMAGE="$ZONEROOT"
 export PKG_IMAGE
 
 # add extra publishers
@@ -433,35 +446,35 @@
 printf "\n$m_mannote\n"
 
 printf "$m_smf"
-ln -s ns_files.xml $zoneroot/var/svc/profile/name_service.xml
-ln -s generic_limited_net.xml $zoneroot/var/svc/profile/generic.xml
-ln -s inetd_generic.xml $zoneroot/var/svc/profile/inetd_services.xml
-ln -s platform_none.xml $zoneroot/var/svc/profile/platform.xml
+ln -s ns_files.xml $ZONEROOT/var/svc/profile/name_service.xml
+ln -s generic_limited_net.xml $ZONEROOT/var/svc/profile/generic.xml
+ln -s inetd_generic.xml $ZONEROOT/var/svc/profile/inetd_services.xml
+ln -s platform_none.xml $ZONEROOT/var/svc/profile/platform.xml
 
 # This was formerly done in i.manifest
-repfile=$zoneroot/etc/svc/repository.db
-cp $zoneroot/lib/svc/seed/nonglobal.db $repfile
+repfile=$ZONEROOT/etc/svc/repository.db
+cp $ZONEROOT/lib/svc/seed/nonglobal.db $repfile
 chmod 0600 $repfile
 chown root:sys $repfile
 
 printf "$m_done\n"
 
 # Clean up root as a role and jack if needed
-if grep "^root::::type=role;" $zoneroot/etc/user_attr >/dev/null 2>&1; then
+if grep "^root::::type=role;" $ZONEROOT/etc/user_attr >/dev/null 2>&1; then
 	printf "$m_brokenness\n"
 	#
 	# Remove "jack" user.
 	#
-	print "/^jack:/d\nw" | ed -s $zoneroot/etc/passwd
-	chmod u+w $zoneroot/etc/shadow
-	print "/^jack:/d\nw" | ed -s $zoneroot/etc/shadow
-	chmod u-w $zoneroot/etc/shadow
+	print "/^jack:/d\nw" | ed -s $ZONEROOT/etc/passwd
+	chmod u+w $ZONEROOT/etc/shadow
+	print "/^jack:/d\nw" | ed -s $ZONEROOT/etc/shadow
+	chmod u-w $ZONEROOT/etc/shadow
 
 	#
 	# Set root from a role back to... not a role.  Grr.
 	#
 	print "s/^root::::type=role;/root::::/\nw" |
-	    ed -s $zoneroot/etc/user_attr
+	    ed -s $ZONEROOT/etc/user_attr
 fi
 
 #
@@ -470,11 +483,11 @@
 # See http://defect.opensolaris.org/bz/show_bug.cgi?id=741
 #
 printf "$m_more_brokenness\n"
-/usr/sbin/sysidconfig -b $zoneroot -a /lib/svc/method/sshd
-touch $zoneroot/etc/.UNCONFIGURED
+/usr/sbin/sysidconfig -b $ZONEROOT -a /lib/svc/method/sshd
+touch $ZONEROOT/etc/.UNCONFIGURED
 
 # Umount the dataset on the root.
-/usr/sbin/umount $zoneroot
+/usr/sbin/umount $ZONEROOT
 
 printf "$m_complete\n\n" ${SECONDS}
 if [ $brand_labeled -eq 0 ]; then
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/brand/pkgrm.conf	Tue Nov 10 14:40:37 2009 -0700
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# This is a list of IPS packages which should be removed when installing
+# a zone from an image of a physical system (that is, only when installing
+# with the zoneadm -d or -a option).  Site-specific packages which must be
+# removed should be listed in this file.  During the zone installation, the
+# packages will be removed if they existed on the original physical system.
+# 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/brand/pkgrm.lst	Tue Nov 10 14:40:37 2009 -0700
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# This is a list of IPS packages which should be removed when installing
+# a zone from an image of a physical system (that is, only when installing
+# with the zoneadm -d or -a option).  Do not edit this file.  Site-specific
+# packages which must be removed should be listed in the
+# /etc/brand/native/pkgrm.conf file.  During the zone installation, the
+# packages will be removed if they existed on the original physical system.
+# 
--- a/src/brand/query	Tue Nov 10 15:49:19 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-#!/bin/ksh -p
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-. /usr/lib/brand/ipkg/common.ksh
-
-zonename=$1
-zonepath=$2
-cmd=$3
-
-if [ $3 == "datasets" ]; then
-	get_zonepath_ds $zonepath
-
-	DS=`/usr/sbin/zfs list -H -t filesystem -o name $ZONEPATH_DS/ROOT`
-	if [ ! -z "$DS" ]; then
-		echo "$DS\c"
-	else
-		fail_fatal "$f_no_ds"
-	fi
-fi
-
-exit $ZONE_SUBPROC_OK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/brand/smf_disable.conf	Tue Nov 10 14:40:37 2009 -0700
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# This is a list of SMF services which should be disabled when installing
+# a zone from an image of a physical system (that is, only when installing
+# with the zoneadm -d or -a option).  Site-specific services which must be
+# disabled should be listed in this file.  During the zone installation, the
+# services will be disabled if they existed on the original physical system.
+# 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/brand/smf_disable.lst	Tue Nov 10 14:40:37 2009 -0700
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# This is a list of SMF services which should be disabled when installing
+# a zone from an image of a physical system (that is, only when installing
+# with the zoneadm -d or -a option).  Do not edit this file.  Site-specific
+# services which must be disabled should be listed in the
+# /etc/brand/native/smf_disable.conf file.  During the zone installation, the
+# services will be disabled if they existed on the original physical system.
+# 
--- a/src/brand/uninstall	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/brand/uninstall	Tue Nov 10 14:40:37 2009 -0700
@@ -33,219 +33,7 @@
 # common shell script functions
 #
 . /usr/lib/brand/ipkg/common.ksh
-
-#
-# error messages
-#
-m_usage=$(gettext "Usage: %s: [-hFn]")
-
-m_1_zfs_promote=$(gettext "promoting '%s'.")
-m_1_zfs_destroy=$(gettext "destroying '%s'.")
-m_2_zfs_rename=$(gettext "renaming '%s' to '%s'.")
-m_3_zfs_set=$(gettext "setting property %s='%s' for '%s'.")
-m_rm_r=$(gettext "recursively deleting '%s'.")
-m_rm=$(gettext "deleting '%s'.")
-
-w_no_ds=$(gettext "Warning: no zonepath dataset found.")
-
-f_usage_err=$(gettext "Error: invalid usage")
-f_abort=$(gettext "Error: internal error detected, aborting.")
-f_1_zfs_promote=$(gettext "Error: promoting ZFS dataset '%s'.")
-f_2_zfs_rename=$(gettext "Error: renaming ZFS dataset '%s' to '%s'.")
-f_3_zfs_set=$(gettext "Error: setting ZFS propery %s='%s' for '%s'.")
-f_1_zfs_destroy=$(gettext "Error: destroying ZFS dataset.")
-f_2_zfs_get=$(gettext "Error: reading ZFS dataset property '%s' from '%s'.")
-f_user_snap=$(gettext "Error: user snapshot(s) detected.")
-f_stray_snap=$(gettext "Error: uncloned snapshot(s) detected.")
-f_stray_clone=$(gettext "Error: cloned zone datasets found outsize of zone.")
-f_rm_snap=$(gettext "Error: please delete snapshot(s) and retry uninstall.")
-f_rm_clone=$(gettext "Error: please delete clone(s) and retry uninstall.")
-f_iu_clone=$(gettext "Error: cloned zone dataset(s) in use.")
-f_dis_clone=$(gettext "Error: please stop using clone(s) and retry uninstall.")
-
-#
-# functions
-#
-print_array()
-{
-	typeset -n pa_array=$1
-
-	(( pa_i = 0 ))
-	while (( $pa_i < ${#pa_array[@]} )); do
-		printf "\t${pa_array[$pa_i]}\n"
-		(( pa_i = $pa_i + 1 ))
-	done
-}
-
-usage()
-{
-	printf "$m_usage\n" "$bname"
-	exit $ZONE_SUBPROC_USAGE
-}
-
-usage_err()
-{
-	printf "$f_usage_err\n" >&2
-	usage >&2
-}
-
-rm_zonepath()
-{
-	# cleanup stuff we know about and leave any user data alone
-
-	[[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
-		printf "$m_rm\n" "$zonepath/SUNWattached.xml"
-	$nop /bin/rm -f "$zonepath/SUNWattached.xml"
-
-	[[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
-		printf "$m_rm_r\n" "$zonepath/lu"
-	$nop /bin/rm -rf "$zonepath/lu"
-
-	[[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
-		printf "$m_rm_r\n" "$zonepath/dev"
-	$nop /bin/rm -rf "$zonepath/dev"
-
-	[[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
-		printf "$m_rm_r\n" "$zonepath/root"
-	$nop /bin/rm -rf "$zonepath/root"
-
-	[[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
-		printf "$m_rm\n" "$zonepath"
-	$nop /bin/rmdir "$zonepath" 2>/dev/null
-}
-
-zfs_destroy()
-{
-	zd_fs1="$1"
-
-	# first figure out if the target fs has an origin snapshot
-	zd_origin=`/sbin/zfs get -H -o value origin "$zd_fs1"`
-	if [[ $? != 0 ]]; then
-		printf "$f_2_zfs_get\n" origin "$zd_fs1" >&2
-		exit $ZONE_SUBPROC_FATAL
-	fi
-
-	[[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
-		printf "$m_1_zfs_destroy\n" "$zd_fs1"
-
-	#
-	# note that we specify the '-r' flag so that we destroy any
-	# descendants (filesystems and snapshot) of the specified
-	# filesystem.
-	#
-	$nop /sbin/zfs destroy -r "$zd_fs1"
-	if [[ $? != 0 ]]; then
-		printf "$f_1_zfs_destroy\n" "$zd_fs1" >&2
-		exit $ZONE_SUBPROC_FATAL
-	fi
-
-	[[ "$zd_origin" == "-" ]] && return
-
-	[[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
-		printf "$m_1_zfs_destroy\n" "$zd_origin"
-
-	$nop /sbin/zfs destroy "$zd_origin" 2>/dev/null
-	#
-	# we ignore errors while trying to destroy the origin since
-	# the origin could have been used as the source for other
-	# clones
-	#
-}
-
-zfs_promote()
-{
-	zp_fs1="$1"
-
-	[[ -z "$opt_n" ]] &&
-		printf "$m_1_zfs_promote\n" "$zp_fs1"
-
-	$nop /sbin/zfs promote "$zp_fs1"
-	if [[ $? != 0 ]]; then
-		printf "$f_1_zfs_promote\n" "$zp_fs1" >&2
-		exit $ZONE_SUBPROC_FATAL
-	fi
-}
-
-zfs_rename()
-{
-	zr_fs1="$1"
-	zr_fs2="$2"
-
-	[[ -z "$opt_n" ]] &&
-		printf "$m_2_zfs_rename\n" "$zr_fs1" "$zr_fs2"
-
-	$nop /sbin/zfs rename "$zr_fs1" "$zr_fs2"
-	if [[ $? != 0 ]]; then
-		printf "$f_2_zfs_rename\n" "$zr_fs1" "$zr_fs2" >&2
-		return 1
-	fi
-	return 0
-}
-
-zfs_set()
-{
-	zs_prop=$1
-	zs_value=$2
-	zs_fs1=$3
-
-	[[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
-		printf "$m_3_zfs_set\n" "$zs_prop" "$zs_value" "$zs_fs1"
-
-	$nop /sbin/zfs set "$zs_prop"="$zs_value" "$zs_fs1"
-	if [[ $? != 0 ]]; then
-		printf "$f_3_zfs_set\n" "$zs_prop" "$zs_value" "$zs_fs1"
-		return 1
-	fi
-	return 0
-}
-
-zfs_set_array()
-{
-	zsa_prop=$1
-	zsa_value=$2
-	typeset -n zsa_array=$3
-	zsa_ignore_errors=$4
-
-	(( zsa_i = 0 ))
-	while (( $zsa_i < ${#zsa_array[@]} )); do
-		zfs_set "$zsa_prop" "$zsa_value" "${zsa_array[$zsa_i]}"
-		[[ $? != 0 ]] && [[ -z "$zsa_ignore_errors" ]] &&
-			return 1
-		(( zsa_i = $zsa_i + 1 ))
-	done
-	return 0
-}
-
-
-(( snap_rename_zbe_i = 1 ))
-(( snap_rename_snap_i = 1 ))
-snap_rename_init()
-{
-	(( snap_rename_zbe_i = 1 ))
-	(( snap_rename_snap_i = 1 ))
-}
-
-snap_rename()
-{
-	eval sr_fs=\${$1}
-	eval sr_snap=\${$2}
-
-	if [[ "$sr_snap" == ~(Elr)(zbe-[0-9][0-9]*) ]]; then
-		sr_snap="zbe-$snap_rename_zbe_i"
-		(( snap_rename_zbe_i = $snap_rename_zbe_i + 1 ))
-	elif [[ "$sr_snap" == ~(Er)(_snap[0-9]*) ]]; then
-		sr_snap=${sr_snap##~(Er)([0-9]*)}
-		sr_snap="${sr_snap}${snap_rename_snap_i}"
-		(( snap_rename_snap_i = $snap_rename_snap_i + 1 ))
-	else
-		printf "$f_user_snap\n" >&2
-		printf "\t$sr_fs@$sr_snap\n" >&2
-		printf "$f_rm_snap\n" >&2
-		exit $ZONE_SUBPROC_FATAL
-	fi
-
-	eval $2="$sr_snap"
-}
+. /usr/lib/brand/shared/uninstall.ksh
 
 #
 # options processing
@@ -344,33 +132,8 @@
 	print "$f_no_gzbe"
 fi
 
-# find the dataset associated with $zonepath
-ZONEPATH_DS=`/sbin/zfs list -t filesystem -o name,mountpoint | \
-    /bin/nawk -v zonepath=$zonepath '{
-	if ($2 == zonepath)
-		print $1
-}'`
-
-if [ -z "$ZONEPATH_DS" ]; then
-	# there is no $zonepath dataset
-	rm_zonepath
-	exit $ZONE_SUBPROC_OK
-fi
-
-# find the dataset associated with $ZONEPATH_DS/ROOT
-ZONEPATH_RDS=`/sbin/zfs list -H -t filesystem -o name \
-	$ZONEPATH_DS/ROOT 2>/dev/null`
-
-if [ -z "$ZONEPATH_RDS" ]; then
-	# there is no $ZONEPATH_DS/ROOT dataset
-	c=`/sbin/zfs list -H -t filesystem -r $ZONEPATH_DS | wc -l`
-	if [ $c = 1 ]; then
-		# $zonepath dataset has no descendents
-		zfs_destroy "$ZONEPATH_DS"
-	fi
-	rm_zonepath
-	exit $ZONE_SUBPROC_OK
-fi
+uninstall_get_zonepath_ds
+uninstall_get_zonepath_root_ds
 
 # find all the zone BEs datasets associated with this global zone BE.
 unset fs_all
@@ -393,428 +156,6 @@
 	done
 fi
 
-# Destroy the zone BEs datasets one by one.
-(( i = 0 ))
-while (( $i < $fs_all_c )); do
-	fs=${fs_all[$i]}
-	pool=${fs%%/*}
-
-	# Fastpath.  if there are no snapshots of $fs then just delete it.
-	c=`/sbin/zfs list -H -t snapshot -o name -r $fs | grep "^$fs@" |
-	    LC_ALL=C LANG=C wc -l`
-	if (( $c == 0 )) ; then
-		zfs_destroy "$fs"
-		(( i = $i + 1 ))
-		continue
-	fi
-
-	#
-	# This zone BE has snapshots.  This can happen if a zone has
-	# multiple BEs (in which case we have snapshots named "zbe-XXX"),
-	# if this zone has been used as the source for a clone of
-	# another zone (in which case we have snapshots named
-	# "XXX_snap"), or if an administrator has been doing manual
-	# snapshotting.
-	#
-	# To be able to destroy this dataset (which we'll call the
-	# origin) we need to get rid of all it's snapshots.  The "easiest"
-	# way to do this is to:
-	#
-	# - delete any uncloned origin snapshots
-	# - find the oldest clone of the youngest origin snapshot (which
-	#   we'll call the oldest clone)
-	# - check if there are any snapshots naming conflicts between
-	#   the origin and the oldest clone.
-	# - if so, find any clones of those conflicting origin snapshots
-	# - make sure that those clones are not zoned an in-use.
-	# - if any of those clones are zoned, unzone them.
-	# - rename origin snapshots to eliminate naming conflicts
-	# - for any clones that we unzoned, rezone them.
-	# - promote the oldest clone
-	# - destroy the origin and all it's descendants
-	#
-
-	#
-	# Get a list of all the cloned datasets within the zpool
-	# containing the origin filesystem.  Filter out any filesystems
-	# that are descendants of origin because we are planning to
-	# destroy them anyway.
-	#
-	unset clones clones_origin
-	(( clones_c = 0 ))
-	pool=${fs%%/*}
-	LANG=C LC_ALL=C /sbin/zfs list -H -t filesystem -s creation \
-	    -o name,origin -r "$pool" |
-	    while IFS="	" read name origin; do
-
-		# skip non-clone filesystems
-		[[ "$origin" == "-" ]] &&
-			continue
-
-		# skip desendents of the origin we plan to destroy
-		[[ "$name" == ~()(${fs}/*) ]] &&
-			continue
-
-		# record this clone and it's origin
-		clones[$clones_c]="$name"
-		clones_origin[$clones_c]="$origin"
-		(( clones_c = $clones_c + 1 ))
-	done
-
-	#
-	# Now do a sanity check.  Search for clones of a child datasets
-	# of the dataset we want to destroy, that are not themselves
-	# children of the dataset we're going to destroy).  This should
-	# really never happen unless the global zone admin has cloned a
-	# snapshot of a zone filesystem to a location outside of that
-	# zone.  bad admin...
-	#
-	unset stray_clones
-	(( stray_clones_c = 0 ))
-	(( j = 0 ))
-	while (( $j < $clones_c )); do
-		# is the clone origin a descendant of $fs?
-		if [[ "${clones_origin[$j]}" != ~()(${fs}/*) ]]; then
-			# we don't care.
-			(( j = $j + 1 ))
-			continue
-		fi
-		stray_clones[$stray_clones_c]=${clones[$j]}
-		(( stray_clones_c = $stray_clones_c + 1 ))
-		(( j = $j + 1 ))
-	done
-	if (( stray_clones_c > 0 )); then
-		#
-		# sigh.  the admin has done something strange.
-		# tell them to clean it up and retry.
-		#
-		printf "$f_stray_clone\n" >&2
-		print_array stray_clones >&2
-		printf "$f_rm_clone\n" >&2
-		exit $ZONE_SUBPROC_FATAL
-	fi
-
-	# Find all the snapshots of the origin filesystem.
-	unset s_origin
-	(( s_origin_c = 0 ))
-	/sbin/zfs list -H -t snapshot -s creation -o name -r $fs |
-	    grep "^$fs@" | while read name; do
-		s_origin[$s_origin_c]=$name
-		(( s_origin_c = $s_origin_c + 1 ))
-	done
-
-	#
-	# Now go through the origin snapshots and find those which don't
-	# have clones.  We're going to explicity delete these snapshots
-	# before we do the promotion.
-	#
-	unset s_delete
-	(( s_delete_c = 0 ))
-	(( j = 0 ))
-	while (( $j < $s_origin_c )); do
-		(( k = 0 ))
-		while (( $k < $clones_c )); do
-			# if we have a match then break out of this loop
-			[[ "${s_origin[$j]}" == "${clones_origin[$k]}" ]] &&
-				break
-			(( k = $k + 1 ))
-		done
-		if (( $k != $clones_c )); then
-			# this snapshot has a clone, move on to the next one
-			(( j = $j + 1 ))
-			continue
-		fi
-
-		# snapshot has no clones so add it to our delete list
-		s_delete[$s_delete_c]=${s_origin[$j]}
-		(( s_delete_c = $s_delete_c + 1 ))
-		# remove it from the origin snapshot list
-		(( k = $j + 1 ))
-		while (( $k < $s_origin_c )); do
-			s_origin[(( $k - 1 ))]=${s_origin[$k]}
-			(( k = $k + 1 ))
-		done
-		(( s_origin_c = $s_origin_c - 1 ))
-	done
-
-	#
-	# Fastpath.  If there are no remaining snapshots then just
-	# delete the origin filesystem (and all it's descendents) and
-	# move onto the next zone BE.
-	#
-	if (( $s_origin_c == 0 )); then
-		zfs_destroy "$fs"
-		(( i = $i + 1 ))
-		continue
-	fi
-
-	# find the youngest snapshot of $fs
-	s_youngest=${s_origin[(( $s_origin_c - 1 ))]}
-
-	# Find the oldest clone of the youngest snapshot of $fs
-	unset s_clone
-	(( j = $clones_c - 1 ))
-	while (( $j >= 0 )); do
-		if [[ "$s_youngest" == "${clones_origin[$j]}" ]]; then
-			s_clone=${clones[$j]}
-			break
-		fi
-		(( j = $j - 1 ))
-	done
-	if [[ -z "$s_clone" ]]; then
-		# uh oh.  something has gone wrong.  bail.
-		printf "$f_stray_snap\n" >&2
-		printf "\t$s_youngest\n" >&2
-		printf "$f_rm_snap\n" >&2
-		exit $ZONE_SUBPROC_FATAL
-	fi
-
-	# create an array of clone snapshot names
-	unset s_clone_s
-	(( s_clone_s_c = 0 ))
-	/sbin/zfs list -H -t snapshot -s creation -o name -r $s_clone |
-	    grep "^$s_clone@" | while read name; do
-		s_clone_s[$s_clone_s_c]=${name##*@}
-		(( s_clone_s_c = $s_clone_s_c + 1 ))
-	done
-
-	# create an arrays of possible origin snapshot renames
-	unset s_origin_snap
-	unset s_rename
-	(( j = 0 ))
-	while (( $j < $s_origin_c )); do
-		s_origin_snap[$j]=${s_origin[$j]##*@}
-		s_rename[$j]=${s_origin[$j]##*@}
-		(( j = $j + 1 ))
-	done
-
-	#
-	# Search for snapshot name collisions between the origin and
-	# oldest clone.  If we find one, generate a new name for the
-	# origin snapshot and re-do the collision check.
-	#
-	snap_rename_init
-	(( j = 0 ))
-	while (( $j < $s_origin_c )); do
-		(( k = 0 ))
-		while (( $k < $s_clone_s_c )); do
-
-			# if there's no naming conflict continue
-			if [[ "${s_rename[$j]}" != "${s_clone_s[$k]}" ]]; then
-				(( k = $k + 1 ))
-				continue
-			fi
+destroy_zone_datasets
 
-			#
-			# The origin snapshot conflicts with a clone
-			# snapshot.  Choose a new name and then restart
-			# then check that against clone snapshot names.
-			#
-			snap_rename fs "s_rename[$j]"
-			(( k = 0 ))
-			continue;
-		done
-
-		# if we didn't rename this snapshot then continue
-		if [[ "${s_rename[$j]}" == "${s_origin_snap[$j]}" ]]; then
-			(( j = $j + 1 ))
-			continue
-		fi
-
-		#
-		# We need to rename this origin snapshot because it
-		# conflicts with a clone snapshot name.  So above we
-		# chose a name that didn't conflict with any other clone
-		# snapshot names.  But we also have to avoid naming
-		# conflicts with any other origin snapshot names.  So
-		# check for that now.
-		#
-		(( k = 0 ))
-		while (( $k < $s_origin_c )); do
-
-			# don't compare against ourself
-			if (( $j == $k )); then
-				(( k = $k + 1 ))
-				continue
-			fi
-
-			# if there's no naming conflict continue
-			if [[ "${s_rename[$j]}" != "${s_rename[$k]}" ]]; then
-				(( k = $k + 1 ))
-				continue
-			fi
-
-			#
-			# The new origin snapshot name conflicts with
-			# another origin snapshot name.  Choose a new
-			# name and then go back to check the new name
-			# for uniqueness against all the clone snapshot
-			# names.
-			#
-			snap_rename fs "s_rename[$j]"
-			continue 2;
-		done
-
-		#
-		# A new unique name has been chosen.  Move on to the
-		# next origin snapshot.
-		#
-		(( j = $j + 1 ))
-		snap_rename_init
-	done
-
-	#
-	# So now we know what snapshots need to be renamed before the
-	# promotion.  But there's an additional problem.  If any of the
-	# filesystems cloned from these snapshots have the "zoned"
-	# attribute set (which is highly likely) or if they are in use
-	# (and can't be unmounted and re-mounted) then the snapshot
-	# rename will fail.  So now we'll search for all the clones of
-	# snapshots we plan to rename and look for ones that are zoned.
-	#
-	# We'll ignore any snapshot clones that may be in use but are
-	# not zoned.  If these clones are in-use, the rename will fail
-	# and we'll abort, there's not much else we can do about it.
-	# But if they are not in use the snapshot rename will unmount
-	# and remount the clone.  This is ok because when the zoned
-	# attribute is off, we know that the clone was originally
-	# mounted from the global zone.  (So unmounting and remounting
-	# it from the global zone is ok.)
-	#
-	# But we'll abort this whole operation if we find any clones
-	# that that are zoned and in use.  (This can happen if another
-	# zone has been cloned from this one and is now booted.)  The
-	# reason we do this is because those zoned filesystems could
-	# have originally mounted from within the zone.  So if we
-	# cleared the zone attribute and did the rename, we'd be
-	# remounting the filesystem from the global zone.  This would
-	# result in the zone losing the ability to unmount the
-	# filesystem, which would be bad.
-	#
-	unset zoned_clones zoned_iu_clones
-	(( zoned_clones_c = 0 ))
-	(( zoned_iu_clones_c = 0 ))
-	(( j = 0 ))
-	# walk through all the clones
-	while (( $j < $clones_c )); do
-		# walk through all the origin snapshots
-		(( k = 0 ))
-		while (( $k < $s_origin_c )); do
-			#
-			# check if this clone originated from a snapshot that
-			# we need to rename.
-			#
-			[[ "${clones_origin[$j]}" == "${s_origin[$k]}" ]] &&
-			    [[ "${s_origin_snap[$k]}" != "${s_rename[$k]}" ]] &&
-				break
-			(( k = $k + 1 ))
-			continue
-		done
-		if (( $k == $s_origin_c )); then
-			# This isn't a clone of a snapshot we want to rename.
-			(( j = $j + 1 ))
-			continue;
-		fi
-
-		# get the zoned attr for this clone.
-		zoned=`LC_ALL=C LANG=C \
-		    /sbin/zfs get -H -o value zoned ${clones[$j]}`
-		if [[ "$zoned" != on ]]; then
-			# This clone isn't zoned so ignore it.
-			(( j = $j + 1 ))
-			continue
-		fi
-
-		# remember this clone so we can muck with it's zoned attr.
-		zoned_clones[$zoned_clones_c]=${clones[$j]}
-		(( zoned_clones_c = $zoned_clones_c + 1 ))
-
-		# check if it's in use
-		mounted=`LC_ALL=C LANG=C \
-		    /sbin/zfs get -H -o value mounted ${clones[$j]}`
-		if [[ "$mounted" != yes ]]; then
-			# Good news.  This clone isn't in use.
-			(( j = $j + 1 ))
-			continue
-		fi
-
-		# Sigh.  This clone is in use so we're destined to fail.
-		zoned_iu_clones[$zoned_iu_clones_c]=${clones[$j]}
-		(( zoned_iu_clones_c = $zoned_iu_clones_c + 1 ))
-
-		# keep looking for errors so we can report them all at once.
-		(( j = $j + 1 ))
-	done
-	if (( zoned_iu_clones_c > 0 )); then
-		#
-		# Tell the admin
-		#
-		printf "$f_iu_clone\n" >&2
-		print_array zoned_iu_clones >&2
-		printf "$f_dis_clone\n" >&2
-		exit $ZONE_SUBPROC_FATAL
-	fi
-
-	#
-	# Ok.  So we're finally done with planning and we can do some
-	# damage.  We're going to:
-	# - destroy unused snapshots
-	# - unzone clones which originate from snapshots we need to rename
-	# - rename conflicting snapshots
-	# - rezone any clones which we unzoned
-	# - promote the oldest clone of the youngest snapshot
-	# - finally destroy the origin filesystem.
-	#
-
-	# delete any unsed snapshot
-	(( j = 0 ))
-	while (( $j < $s_delete_c )); do
-		zfs_destroy "${s_delete[$j]}"
-		(( j = $j + 1 ))
-	done
-
-	# unzone clones
-	zfs_set_array zoned off zoned_clones ||
-		zfs_set_array zoned on zoned_clones 1
-
-	# rename conflicting snapshots
-	(( j = 0 ))
-	while (( $j < $s_origin_c )); do
-		if [[ "${s_origin_snap[$j]}" != "${s_rename[$j]}" ]]; then
-			zfs_rename "${s_origin[$j]}" "$fs@${s_rename[$j]}"
-			if [[ $? != 0 ]]; then
-				# re-zone the clones before aborting
-				zfs_set_array zoned on zoned_clones 1
-				exit $ZONE_SUBPROC_FATAL
-			fi
-		fi
-		(( j = $j + 1 ))
-	done
-
-	# re-zone the clones
-	zfs_set_array zoned on zoned_clones 1
-
-	# promote the youngest clone of the oldest snapshot
-	zfs_promote "$s_clone"
-
-	# destroy the origin filesystem and it's descendants
-	zfs_destroy "$fs"
-
-	(( i = $i + 1 ))
-done
-
-#
-# Check if there are any other datasets left.  There may be datasets
-# associated with other GZ BEs, so we need to leave things alone in that case.
-#
-c=`/sbin/zfs list -H -t filesystem -r $ZONEPATH_RDS | wc -l`
-if [ $c = 1 ]; then
-	zfs_destroy "$ZONEPATH_RDS"
-fi
-c=`/sbin/zfs list -H -t filesystem -r $ZONEPATH_DS | wc -l`
-if [ $c = 1 ]; then
-	zfs_destroy "$ZONEPATH_DS"
-fi
-
-rm_zonepath
 exit $ZONE_SUBPROC_OK
--- a/src/pkgdefs/Makefile	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/pkgdefs/Makefile	Tue Nov 10 14:40:37 2009 -0700
@@ -63,7 +63,13 @@
 
 PROTOS = $(SUBDIRS:%=%/prototype)
 
+#
+# The pkgproto command in the protoproto target does not generate editable
+# (e) file entries so we need to change any editable entries into simple
+# file entries for the subsequent comparison to suceed.
+#
 pkgproto: $(PROTOS)
-	nawk '$$1 ~ /[sdf]/ {print $$1, $$3}' $(PROTOS) | sort +1 -u > $@
+	nawk '$$1 ~ /[sdef]/ {print $$1, $$3}' $(PROTOS) | sed 's/^e/f/' | \
+	    sort +1 -u > $@
 
 FRC:
--- a/src/pkgdefs/SUNWipkg-brand/prototype	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/pkgdefs/SUNWipkg-brand/prototype	Tue Nov 10 14:40:37 2009 -0700
@@ -1,6 +1,10 @@
 i pkginfo
 i copyright
 d none etc 755 root sys
+d none etc/brand 755 root sys
+d none etc/brand/ipkg 755 root sys
+e none etc/brand/ipkg/pkgrm.conf 644 root bin
+e none etc/brand/ipkg/smf_disable.conf 644 root bin
 d none etc/zones 755 root sys
 f none etc/zones/SUNWipkg.xml 444 root bin
 d none usr 755 root sys
@@ -13,10 +17,13 @@
 f none usr/lib/brand/ipkg/config.xml 444 root bin
 f none usr/lib/brand/ipkg/detach 755 root bin
 f none usr/lib/brand/ipkg/fmri_compare 755 root bin
+f none usr/lib/brand/ipkg/image_install 755 root bin
+f none usr/lib/brand/ipkg/p2v 755 root bin
 f none usr/lib/brand/ipkg/pkgcreatezone 755 root bin
+f none usr/lib/brand/ipkg/pkgrm.lst 444 root bin
 f none usr/lib/brand/ipkg/platform.xml 444 root bin
 f none usr/lib/brand/ipkg/poststate 755 root bin
 f none usr/lib/brand/ipkg/prestate 755 root bin
-f none usr/lib/brand/ipkg/query 755 root bin
+f none usr/lib/brand/ipkg/smf_disable.lst 444 root bin
 f none usr/lib/brand/ipkg/support 755 root bin
 f none usr/lib/brand/ipkg/uninstall 755 root bin
--- a/src/setup.py	Tue Nov 10 15:49:19 2009 +0000
+++ b/src/setup.py	Tue Nov 10 14:40:37 2009 -0700
@@ -164,6 +164,7 @@
 resource_dir = 'usr/share/lib/pkg'
 smf_dir = 'var/svc/manifest/application'
 zones_dir = 'etc/zones'
+etcbrand_dir = 'etc/brand/ipkg'
 brand_dir = 'usr/lib/brand/ipkg'
 
 scripts_sunos = {
@@ -276,10 +277,13 @@
         'brand/detach',
         'brand/prestate',
         'brand/poststate',
-        'brand/query',
         'brand/uninstall',
         'brand/common.ksh',
         ]
+etcbrand_files = [
+        'brand/pkgrm.conf',
+        'brand/smf_disable.conf',
+        ]
 smf_files = [
         'svc/pkg-server.xml',
         'svc/pkg-update.xml',
@@ -821,6 +825,7 @@
         data_files += [
                 (zones_dir, zones_files),
                 (brand_dir, brand_files),
+                (etcbrand_dir, etcbrand_files),
                 (smf_dir, smf_files),
                 ]
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/distro-import/128/config.xml	Tue Nov 10 14:40:37 2009 -0700
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+
+<!--
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ DO NOT EDIT THIS FILE.
+-->
+
+<!DOCTYPE brand PUBLIC "-//Sun Microsystems Inc//DTD Brands//EN"
+    "file:///usr/share/lib/xml/dtd/brand.dtd.1">
+
+<brand name="labeled">
+	<modname></modname>
+
+	<initname>/sbin/init</initname>
+	<login_cmd>/usr/bin/login -z %Z -f %u</login_cmd>
+	<user_cmd>/usr/bin/getent passwd %u</user_cmd>
+
+	<!-- We may not be able to do the create in pkg(1) proper. -->
+	<install>/usr/lib/brand/ipkg/pkgcreatezone -z %z -R %R</install>
+	<installopts>a:c:d:e:hk:P:p:suv</installopts>
+	<boot></boot>
+	<halt></halt>
+	<verify_cfg>/usr/lib/brand/ipkg/support verify</verify_cfg>
+	<verify_adm></verify_adm>
+	<postclone></postclone>
+	<postinstall></postinstall>
+	<attach>/usr/lib/brand/ipkg/attach %z %R</attach>
+	<detach>/usr/lib/brand/ipkg/detach -z %z -R %R</detach>
+	<clone>/usr/lib/brand/ipkg/clone -z %z -R %R</clone>
+	<uninstall>/usr/lib/brand/ipkg/uninstall %z %R</uninstall>
+	<prestatechange>/usr/lib/brand/ipkg/prestate %z %R</prestatechange>
+	<poststatechange>/usr/lib/brand/ipkg/poststate %z %R</poststatechange>
+	<query>/usr/lib/brand/shared/query %z %R</query>
+
+	<privilege set="default" name="contract_event" />
+	<privilege set="default" name="contract_identity" />
+	<privilege set="default" name="contract_observer" />
+	<privilege set="default" name="file_chown" />
+	<privilege set="default" name="file_chown_self" />
+	<privilege set="default" name="file_dac_execute" />
+	<privilege set="default" name="file_dac_read" />
+	<privilege set="default" name="file_dac_search" />
+	<privilege set="default" name="file_dac_write" />
+	<privilege set="default" name="file_owner" />
+	<privilege set="default" name="file_setid" />
+	<privilege set="default" name="ipc_dac_read" />
+	<privilege set="default" name="ipc_dac_write" />
+	<privilege set="default" name="ipc_owner" />
+	<privilege set="default" name="net_bindmlp" />
+	<privilege set="default" name="net_icmpaccess" />
+	<privilege set="default" name="net_mac_aware" />
+	<privilege set="default" name="net_privaddr" />
+	<privilege set="default" name="net_rawaccess" ip-type="exclusive" />
+	<privilege set="default" name="proc_chroot" />
+	<privilege set="default" name="sys_audit" />
+	<privilege set="default" name="proc_audit" />
+	<privilege set="default" name="proc_lock_memory" />
+	<privilege set="default" name="proc_owner" />
+	<privilege set="default" name="proc_setid" />
+	<privilege set="default" name="proc_taskid" />
+	<privilege set="default" name="sys_acct" />
+	<privilege set="default" name="sys_admin" />
+	<privilege set="default" name="sys_ip_config" ip-type="exclusive" />
+	<privilege set="default" name="sys_mount" />
+	<privilege set="default" name="sys_nfs" />
+	<privilege set="default" name="sys_resource" />
+
+	<privilege set="prohibited" name="dtrace_kernel" />
+	<privilege set="prohibited" name="proc_zone" />
+	<privilege set="prohibited" name="sys_config" />
+	<privilege set="prohibited" name="sys_devices" />
+	<privilege set="prohibited" name="sys_ip_config" ip-type="shared" />
+	<privilege set="prohibited" name="sys_linkdir" />
+	<privilege set="prohibited" name="sys_net_config" />
+	<privilege set="prohibited" name="sys_res_config" />
+	<privilege set="prohibited" name="sys_suser_compat" />
+	<privilege set="prohibited" name="xvm_control" />
+	<privilege set="prohibited" name="virt_manage" />
+
+	<privilege set="required" name="proc_exec" />
+	<privilege set="required" name="proc_fork" />
+	<privilege set="required" name="sys_ip_config" ip-type="exclusive" />
+	<privilege set="required" name="sys_mount" />
+</brand>