changeset 8759:8436cd998603

PSARC 2008/766 native zones p2v 6667924 physical to virtual utility for native zones
author <gerald.jelinek@sun.com>
date Wed, 11 Feb 2009 09:33:05 -0700
parents fdbd8b79f478
children d018ee496d5a
files usr/src/Targetdirs usr/src/cmd/zoneadm/zoneadm.c usr/src/head/libzonecfg.h usr/src/lib/brand/Makefile.brand usr/src/lib/brand/lx/zone/lx_install.ksh usr/src/lib/brand/native/zone/Makefile usr/src/lib/brand/native/zone/common.ksh usr/src/lib/brand/native/zone/config.xml usr/src/lib/brand/native/zone/image_install.ksh usr/src/lib/brand/native/zone/p2v.ksh usr/src/lib/brand/native/zone/pkgrm.conf usr/src/lib/brand/native/zone/pkgrm.lst usr/src/lib/brand/native/zone/smf_disable.conf usr/src/lib/brand/native/zone/smf_disable.lst usr/src/lib/brand/native/zone/sw_support.c usr/src/lib/libzonecfg/common/libzonecfg.c usr/src/lib/libzonecfg/common/mapfile-vers usr/src/pkgdefs/SUNWzoner/prototype_com usr/src/pkgdefs/SUNWzoneu/prototype_com
diffstat 19 files changed, 2120 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/Targetdirs	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/Targetdirs	Wed Feb 11 09:33:05 2009 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -78,6 +78,8 @@
 	/devices \
 	/devices/pseudo \
 	/etc \
+	/etc/brand  \
+	/etc/brand/native  \
 	/etc/certs	\
 	/etc/cron.d \
 	/etc/crypto \
@@ -259,6 +261,7 @@
 	/usr/lib/abi \
 	/usr/lib/brand \
 	/usr/lib/brand/native \
+	/usr/lib/brand/shared \
 	/usr/lib/brand/sn1 \
 	/usr/lib/class \
 	/usr/lib/class/FSS \
--- a/usr/src/cmd/zoneadm/zoneadm.c	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/cmd/zoneadm/zoneadm.c	Wed Feb 11 09:33:05 2009 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -102,7 +102,6 @@
 
 static zone_entry_t *zents;
 static size_t nzents;
-static boolean_t is_native_zone = B_TRUE;
 
 #define	LOOPBACK_IF	"lo0"
 #define	SOCKET_AF(af)	(((af) == AF_UNSPEC) ? AF_INET : (af))
@@ -1087,10 +1086,6 @@
 			return (Z_ERR);
 		}
 		if ((res = stat(rootpath, &stbuf)) == 0) {
-			struct dirent	*dp;
-			DIR		*dirp;
-			boolean_t	empty = B_TRUE;
-
 			if (zonecfg_detached(rpath)) {
 				(void) fprintf(stderr,
 				    gettext("Cannot %s detached "
@@ -1119,32 +1114,6 @@
 				    "0755.\n"), rootpath);
 				return (Z_ERR);
 			}
-
-			if ((dirp = opendir(rootpath)) == NULL) {
-				(void) fprintf(stderr, gettext("Could not "
-				    "open rootpath %s\n"), rootpath);
-				return (Z_ERR);
-			}
-
-			/* Verify that the dir is empty. */
-			while ((dp = readdir(dirp)) != NULL) {
-				if (strcmp(dp->d_name, ".") == 0 ||
-				    strcmp(dp->d_name, "..") == 0)
-					continue;
-
-				empty = B_FALSE;
-				break;
-			}
-			(void) closedir(dirp);
-
-			if (!empty) {
-				(void) fprintf(stderr, gettext("Rootpath %s "
-				    "exists and contains data; remove or move "
-				    "aside prior to %s.\n"), rootpath,
-				    cmd_to_str(cmd_num));
-				return (Z_ERR);
-			}
-
 		}
 	}
 
@@ -1713,6 +1682,17 @@
 			}
 			break;
 		case CMD_ATTACH:
+			if (state == ZONE_STATE_INSTALLED) {
+				zerror(gettext("is already %s."),
+				    zone_state_str(ZONE_STATE_INSTALLED));
+				return (Z_ERR);
+			} else if (state == ZONE_STATE_INCOMPLETE && !force) {
+				zerror(gettext("zone is %s; %s required."),
+				    zone_state_str(ZONE_STATE_INCOMPLETE),
+				    cmd_to_str(CMD_UNINSTALL));
+				return (Z_ERR);
+			}
+			break;
 		case CMD_CLONE:
 		case CMD_INSTALL:
 			if (state == ZONE_STATE_INSTALLED) {
@@ -1735,15 +1715,11 @@
 			if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
 			    force)
 				min_state = ZONE_STATE_INCOMPLETE;
+			else if (cmd_num == CMD_MARK)
+				min_state = ZONE_STATE_CONFIGURED;
 			else
 				min_state = ZONE_STATE_INSTALLED;
 
-			if (force && cmd_num == CMD_BOOT && is_native_zone) {
-				zerror(gettext("Only branded zones may be "
-				    "force-booted."));
-				return (Z_ERR);
-			}
-
 			if (state < min_state) {
 				zerror(gettext("must be %s before %s."),
 				    zone_state_str(min_state),
@@ -4625,6 +4601,10 @@
 	int manifest_pos;
 	brand_handle_t bh = NULL;
 	int status;
+	int last_index = 0;
+	int offset;
+	char *up;
+	boolean_t forced_update = B_FALSE;
 
 	if (zonecfg_in_alt_root()) {
 		zerror(gettext("cannot attach zone in alternate root"));
@@ -4634,7 +4614,7 @@
 	/* Check the argv string for args we handle internally */
 	optind = 0;
 	opterr = 0;
-	while ((arg = getopt(argc, argv, "?Fn:")) != EOF) {
+	while ((arg = getopt(argc, argv, "?Fn:U")) != EOF) {
 		switch (arg) {
 		case '?':
 			if (optopt == '?') {
@@ -4651,10 +4631,25 @@
 			manifest_path = optarg;
 			manifest_pos = optind - 1;
 			break;
+		case 'U':
+			/*
+			 * Undocumented 'force update' option for p2v update on
+			 * attach when zone is in the incomplete state.  Change
+			 * the option back to 'u' and set forced_update flag.
+			 */
+			if (optind == last_index)
+				offset = optind;
+			else
+				offset = optind - 1;
+			if ((up = index(argv[offset], 'U')) != NULL)
+				*up = 'u';
+			forced_update = B_TRUE;
+			break;
 		default:
 			/* Ignore unknown options - may be brand specific. */
 			break;
 		}
+		last_index = optind;
 	}
 
 	if (brand_help) {
@@ -4676,7 +4671,7 @@
 	if (execute) {
 		if (!brand_help) {
 			if (sanity_check(target_zone, CMD_ATTACH, B_FALSE,
-			    B_TRUE, B_FALSE) != Z_OK)
+			    B_TRUE, forced_update) != Z_OK)
 				return (Z_ERR);
 			if (verify_details(CMD_ATTACH, argv) != Z_OK)
 				return (Z_ERR);
@@ -4749,14 +4744,14 @@
 		 */
 		if (cmdbuf[0] != '\0') {
 			/* Run the attach hook */
-			status = do_subproc_interactive(cmdbuf);
+			status = do_subproc(cmdbuf);
 			if ((status = subproc_status(gettext("brand-specific "
 			    "attach"), status, B_FALSE)) != ZONE_SUBPROC_OK) {
 				if (status == ZONE_SUBPROC_USAGE && !brand_help)
 					sub_usage(SHELP_ATTACH, CMD_ATTACH);
 
 				if (execute && !brand_help) {
-					assert(lockfd >= 0);
+					assert(zonecfg_lock_file_held(&lockfd));
 					zonecfg_release_lock_file(target_zone,
 					    lockfd);
 					lockfd = -1;
@@ -4799,7 +4794,7 @@
 		zperror(gettext("could not reset state"), B_TRUE);
 	}
 
-	assert(lockfd >= 0);
+	assert(zonecfg_lock_file_held(&lockfd));
 	zonecfg_release_lock_file(target_zone, lockfd);
 	lockfd = -1;
 
@@ -5118,10 +5113,38 @@
 mark_func(int argc, char *argv[])
 {
 	int err, lockfd;
-
-	if (argc != 1 || strcmp(argv[0], "incomplete") != 0)
+	int arg;
+	boolean_t force = B_FALSE;
+	int state;
+
+	optind = 0;
+	opterr = 0;
+	while ((arg = getopt(argc, argv, "F")) != EOF) {
+		switch (arg) {
+		case 'F':
+			force = B_TRUE;
+			break;
+		default:
+			return (Z_USAGE);
+		}
+	}
+
+	if (argc != (optind + 1))
 		return (Z_USAGE);
-	if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_FALSE, B_FALSE)
+
+	if (strcmp(argv[optind], "configured") == 0)
+		state = ZONE_STATE_CONFIGURED;
+	else if (strcmp(argv[optind], "incomplete") == 0)
+		state = ZONE_STATE_INCOMPLETE;
+	else if (strcmp(argv[optind], "installed") == 0)
+		state = ZONE_STATE_INSTALLED;
+	else
+		return (Z_USAGE);
+
+	if (state != ZONE_STATE_INCOMPLETE && !force)
+		return (Z_USAGE);
+
+	if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_TRUE, B_FALSE)
 	    != Z_OK)
 		return (Z_ERR);
 
@@ -5137,7 +5160,7 @@
 		return (Z_ERR);
 	}
 
-	err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
+	err = zone_set_state(target_zone, state);
 	if (err != Z_OK) {
 		errno = err;
 		zperror2(target_zone, gettext("could not set state"));
@@ -5592,7 +5615,6 @@
 			zerror(gettext("missing or invalid brand"));
 			exit(Z_ERR);
 		}
-		is_native_zone = (strcmp(target_brand, NATIVE_BRAND_NAME) == 0);
 	}
 
 	err = parse_and_run(argc - optind, &argv[optind]);
--- a/usr/src/head/libzonecfg.h	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/head/libzonecfg.h	Wed Feb 11 09:33:05 2009 -0700
@@ -558,6 +558,7 @@
 extern void zonecfg_init_lock_file(const char *, char **);
 extern void zonecfg_release_lock_file(const char *, int);
 extern int zonecfg_grab_lock_file(const char *, int *);
+extern boolean_t zonecfg_lock_file_held(int *);
 extern int zonecfg_ping_zoneadmd(const char *);
 extern int zonecfg_call_zoneadmd(const char *, zone_cmd_arg_t *, char *,
     boolean_t);
--- a/usr/src/lib/brand/Makefile.brand	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/brand/Makefile.brand	Wed Feb 11 09:33:05 2009 -0700
@@ -19,10 +19,9 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
 
 include $(SRC)/Makefile.master
 
@@ -30,10 +29,12 @@
 ROOTTEMPLATEDIR=	$(ROOT)/etc/zones
 ROOTBRANDDIR=	$(ROOTDIR)/$(BRAND)
 ROOTBRANDDIR64=	$(ROOTDIR)/$(BRAND)/$(MACH64)
+ROOTSHAREDDIR=	$(ROOTDIR)/shared
 
 ROOTPROGS=	$(PROGS:%=$(ROOTBRANDDIR)/%)
 ROOTTXTS=	$(TXTS:%=$(ROOTBRANDDIR)/%)
 ROOTXMLDOCS=	$(XMLDOCS:%=$(ROOTBRANDDIR)/%)
+ROOTSHARED=	$(SHARED:%=$(ROOTSHAREDDIR)/%)
 
 ROOTTEMPLATES=	$(TEMPLATES:%=$(ROOTTEMPLATEDIR)/%)
 
@@ -45,6 +46,10 @@
 $(ROOTXMLDOCS) :=	OWNER = root
 $(ROOTXMLDOCS) :=	GROUP = bin
 
+$(ROOTSHARED) :=	FILEMODE = 444
+$(ROOTSHARED) :=	OWNER = root
+$(ROOTSHARED) :=	GROUP = bin
+
 $(ROOTTEMPLATEDIR) :=	FILEMODE = 755
 $(ROOTTEMPLATEDIR) :=	OWNER = root
 $(ROOTTEMPLATEDIR) :=	GROUP = sys
@@ -61,7 +66,7 @@
 $(ROOTPROGS) :=	OWNER = root
 $(ROOTPROGS) :=	GROUP = bin
 
-$(ROOTBRANDDIR)/% $(ROOTBRANDDIR64)/% $(ROOTTEMPLATEDIR)/%: %
+$(ROOTBRANDDIR)/% $(ROOTBRANDDIR64)/% $(ROOTTEMPLATEDIR)/% $(ROOTSHAREDDIR)/%: %
 	$(INS.file)
 
 .SUFFIXES:	.ksh
--- a/usr/src/lib/brand/lx/zone/lx_install.ksh	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/brand/lx/zone/lx_install.ksh	Wed Feb 11 09:33:05 2009 -0700
@@ -85,6 +85,8 @@
 no_log=$(gettext "Could not create log directory '%s'")
 no_logfile=$(gettext "Could not create log file '%s'")
 
+root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.")
+
 install_zone=$(gettext "Installing zone '%s' at root directory '%s'")
 install_from=$(gettext "from archive '%s'")
 
@@ -457,6 +459,15 @@
 	fi
 fi
 
+#
+# Check for a non-empty root.
+# 
+cnt=`ls $install_root | wc -l`
+if [ $cnt -ne 0 ]; then
+	screenlog "$root_full" "$install_root"
+	exit $int_code
+fi
+
 if [[ ! -d "$logdir" ]]
 then
 	if ! mkdir -p "$logdir" 2>/dev/null; then
--- a/usr/src/lib/brand/native/zone/Makefile	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/brand/native/zone/Makefile	Wed Feb 11 09:33:05 2009 -0700
@@ -20,18 +20,28 @@
 #
 
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
+
+ETCBRANDDIR=	$(ROOT)/etc/brand/native
+ETCUSER=	$(USERFILES:%=$(ETCBRANDDIR)/%)
+$(ETCUSER) :=	FILEMODE = 644
+$(ETCUSER) :=	OWNER = root
+$(ETCUSER) :=	GROUP = sys
+
+$(ETCBRANDDIR)/%: %
+	$(INS.file)
 
 PROG=		sw_support
 BRAND=		native
-PROGS=		attach_update $(PROG)
-XMLDOCS=	config.xml platform.xml
+PROGS=		attach_update image_install p2v $(PROG)
+XMLDOCS=	config.xml platform.xml smf_disable.lst pkgrm.lst
+USERFILES=	smf_disable.conf pkgrm.conf
+SHARED=		common.ksh
 TEMPLATES=	SUNWdefault.xml SUNWblank.xml
-CLOBBERFILES=	$(ROOTPROGS) $(ROOTXMLDOCS) $(ROOTTEMPLATES)
+CLOBBERFILES=	$(ROOTPROGS) $(ROOTXMLDOCS) $(ROOTTEMPLATES) $(ROOTSHARED) \
+	$(ETCUSER)
 
 all:	$(PROGS)
 
@@ -52,7 +62,8 @@
 
 lint: lint_PROG
 
-install: $(PROGS) $(ROOTPROGS) $(ROOTXMLDOCS) $(ROOTTEMPLATES)
+install: $(PROGS) $(ROOTPROGS) $(ROOTXMLDOCS) $(ROOTTEMPLATES) $(ROOTSHARED) \
+	$(ETCUSER)
 
 clean:
 	-$(RM) $(PROGS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/common.ksh	Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,516 @@
+#
+# 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.
+#
+
+#
+# Send the error message to the screen and to the logfile.
+#
+error()
+{
+        typeset fmt="$1"
+        shift
+
+        printf "${MSG_PREFIX}ERROR: ${fmt}\n" "$@"
+        [[ -n $LOGFILE ]] && printf "[$(date)] ERROR: ${fmt}\n" "$@" >&2
+}
+
+fatal()
+{
+        typeset fmt="$1"
+        shift
+
+	error "$fmt" "$@"
+	exit $EXIT_CODE
+}
+
+#
+# Send the provided printf()-style arguments to the screen and to the logfile.
+#
+log()
+{
+        typeset fmt="$1"
+        shift
+
+        printf "${MSG_PREFIX}${fmt}\n" "$@"
+        [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
+}
+
+#
+# Print provided text to the screen if the shell variable "OPT_V" is set.
+# The text is always sent to the logfile.
+#
+vlog()
+{
+        typeset fmt="$1"
+        shift
+
+        [[ -n $OPT_V ]] && printf "${MSG_PREFIX}${fmt}\n" "$@"
+        [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
+}
+
+# Validate that the directory is safe.
+safe_dir()
+{
+	typeset dir="$1"
+
+	if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then
+		fatal "$e_baddir" "$dir"
+	fi
+}
+
+# Only make a copy if we haven't already done so.
+safe_backup()
+{
+	typeset src="$1"
+	typeset dst="$2"
+
+	if [[ ! -h $src && ! -h $dst && ! -d $dst && ! -f $dst ]]; then
+		/usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
+	fi
+}
+
+# Make a copy even if the destination already exists.
+safe_copy()
+{
+	typeset src="$1"
+	typeset dst="$2"
+
+	if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
+		/usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
+	fi
+}
+
+# Move a file
+safe_move()
+{
+	typeset src="$1"
+	typeset dst="$2"
+
+	if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
+		/usr/bin/mv $src $dst || fatal "$e_badfile" "$src"
+	fi
+}
+
+#
+# Read zonecfg ipd and fs entries and save the relevant data, one entry per
+# line.
+# This assumes the properties from the zonecfg output, e.g.:
+#	inherit-pkg-dir:
+#		dir: /usr
+#	fs:
+#		dir: /opt
+#		special: /opt
+#		raw not specified
+#		type: lofs
+#		options: [noexec,ro,noatime]
+#
+# and it assumes the order of the fs properties as above.  This also saves the
+# inherit-pkg-dir patterns into the ipd.{cpio|pax} temporary files for
+# filtering while extracting the image into the zonepath.  We have to save the
+# IPD patterns in the appropriate format for filtering with the different
+# archivers and we don't know what format we'll get until after the flash
+# archive is unpacked.
+#
+get_fs_info()
+{
+	zonecfg -z $zonename info inherit-pkg-dir | \
+	    nawk -v ipdcpiof=$ipdcpiofile -v ipdpaxf=$ipdpaxfile '{
+		if ($1 == "dir:") {
+			dir=$2;
+			printf("%s lofs %s ro\n", dir, dir);
+
+			if (substr(dir, 1, 1) == "/") {
+				printf("%s\n", substr(dir, 2)) >> ipdcpiof
+				printf("%s/*\n", substr(dir, 2)) >> ipdcpiof
+			} else {
+				printf("%s\n", dir) >> ipdcpiof
+				printf("%s/*\n", dir) >> ipdcpiof
+			}
+
+			if (substr(dir, 1, 1) == "/") {
+				printf("%s ", substr(dir, 2)) >> ipdpaxf
+			} else {
+				printf("%s ", dir) >> ipdpaxf
+			}
+		}
+	}' >> $fstmpfile
+
+	zonecfg -z $zonename info fs | nawk '{
+		if ($1 == "options:") {
+			# Remove brackets.
+			options=substr($2, 2, length($2) - 2);
+			printf("%s %s %s %s\n", dir, type, special, options);
+		} else if ($1 == "dir:") {
+			dir=$2;
+		} else if ($1 == "special:") {
+			special=$2;
+		} else if ($1 == "type:") {
+			type=$2
+		}
+	}' >> $fstmpfile
+}
+
+#
+# Mount zonecfg fs entries into the zonepath.
+#
+mnt_fs()
+{
+	if [ ! -s $fstmpfile ]; then
+		return;
+	fi
+
+	# Sort the fs entries so we can handle nested mounts.
+	sort $fstmpfile | nawk -v zonepath=$zonepath '{
+		if (NF == 4)
+			options="-o " $4;
+		else
+			options=""
+
+		# Create the mount point.  Ignore errors since we might have
+		# a nested mount with a pre-existing mount point.
+		cmd="/usr/bin/mkdir -p " zonepath "/root" $1 " >/dev/null 2>&1"
+		system(cmd);
+
+		cmd="/usr/sbin/mount -F " $2 " " options " " $3 " " \
+		    zonepath "/root" $1;
+		if (system(cmd) != 0) {
+			printf("command failed: %s\n", cmd);
+			exit 1;
+		}
+	}' >>$LOGFILE
+}
+
+#
+# Unmount zonecfg fs entries from the zonepath.
+#
+umnt_fs()
+{
+	if [ ! -s $fstmpfile ]; then
+		return;
+	fi
+
+	# Reverse sort the fs entries so we can handle nested unmounts.
+	sort -r $fstmpfile | nawk -v zonepath=$zonepath '{
+		cmd="/usr/sbin/umount " zonepath "/root" $1
+		if (system(cmd) != 0) {
+			printf("command failed: %s\n", cmd);
+		}
+	}' >>$LOGFILE
+}
+
+#
+# Determine flar compression style from identification file.
+#
+get_compression()
+{
+	typeset ident=$1
+	typeset line=$(grep "^files_compressed_method=" $ident)
+
+	print ${line##*=}
+}
+
+#
+# Determine flar archive style from identification file.
+#
+get_archiver()
+{
+        typeset ident=$1
+        typeset line=$(grep "^files_archived_method=" $ident)
+
+        print ${line##*=}
+}
+
+#
+# Unpack flar into current directory (which should be zoneroot).  The flash
+# archive is standard input.  See flash_archive(4) man page.
+# 
+# We can't use "flar split" since it will only unpack into a directory called
+# "archive".  We need to unpack in place in order to properly handle nested
+# fs mounts within the zone root.  This function does the unpacking into the
+# current directory.
+#
+# This code is derived from the gen_split() function in /usr/sbin/flar so
+# we keep the same style as the original.
+#
+install_flar()
+{
+	typeset result
+        typeset archiver_command
+        typeset archiver_arguments
+
+	vlog "cd $ZONEROOT && do_flar < \"$install_archive\""
+
+	# Read cookie
+	read -r input_line
+	if (( $? != 0 )); then
+		log "$not_readable" "$install_media"
+		return 1
+	fi
+	# The cookie has format FlAsH-aRcHiVe-m.n where m and n are integers.
+	if [[ ${input_line%%-[0-9]*.[0-9]*} != "FlAsH-aRcHiVe" ]]; then
+		log "$not_flar"
+		return 1
+	fi
+
+	while [ true ]
+	do
+		# We should always be at the start of a section here
+		read -r input_line
+		if [[ ${input_line%%=*} != "section_begin" ]]; then
+			log "$bad_flar"
+			return 1
+		fi
+		section_name=${input_line##*=}
+
+		# If we're at the archive, we're done skipping sections.
+		if [[ "$section_name" == "archive" ]]; then
+			break
+		fi
+		
+		#
+		# Save identification section to a file so we can determine
+		# how to unpack the archive.
+		#
+		if [[ "$section_name" == "identification" ]]; then
+			/usr/bin/rm -f identification
+			while read -r input_line
+			do
+				if [[ ${input_line%%=*} == \
+				    "section_begin" ]]; then
+					/usr/bin/rm -f identification
+					log "$bad_flar"
+					return 1
+				fi
+
+				if [[ $input_line == \
+				    "section_end=$section_name" ]]; then
+					break;
+				fi
+				echo $input_line >> identification
+			done
+
+			continue
+		fi
+
+		#
+		# Otherwise skip past this section; read lines until detecting
+		# section_end.  According to flash_archive(4) we can have
+		# an arbitrary number of sections but the archive section
+		# must be last.
+		#
+		success=0
+		while read -r input_line
+		do
+			if [[ $input_line == "section_end=$section_name" ]];
+			then
+				success=1
+				break
+			fi
+			# Fail if we miss the end of the section
+			if [[ ${input_line%%=*} == "section_begin" ]]; then
+				/usr/bin/rm -f identification
+				log "$bad_flar"
+				return 1
+			fi
+		done
+		if (( $success == 0 )); then
+			#
+			# If we get here we read to the end of the file before
+			# seeing the end of the section we were reading.
+			#
+			/usr/bin/rm -f identification
+			log "$bad_flar"
+			return 1
+		fi
+	done
+
+	# Get the information needed to unpack the archive.
+	archiver=$(get_archiver identification)
+	if [[ $archiver == "pax" ]]; then
+		# pax archiver specified
+		archiver_command="/usr/bin/pax"
+		if [[ -s $ipdpaxfile ]]; then
+			archiver_arguments="-r -p e -c \
+			    $(/usr/bin/cat $ipdpaxfile)"
+		else
+			archiver_arguments="-r -p e"
+		fi
+	elif [[ $archiver == "cpio" || -z $archiver ]]; then
+		# cpio archived specified OR no archiver specified - use default
+		archiver_command="/usr/bin/cpio"
+		archiver_arguments="-icdumfE $ipdcpiofile"
+	else
+		# unknown archiver specified
+		log "$unknown_archiver" $archiver
+		return 1
+	fi
+
+	if [[ ! -x $archiver_command ]]; then
+		/usr/bin/rm -f identification
+		log "$cmd_not_exec" $archiver_command
+		return 1
+	fi 
+
+	compression=$(get_compression identification)
+
+	# We're done with the identification file
+	/usr/bin/rm -f identification
+
+	# Extract archive
+	if [[ $compression == "compress" ]]; then
+		/usr/bin/zcat | ppriv -e -s A=all,-sys_devices \
+		    $archiver_command $archiver_arguments 2>/dev/null
+	else
+		ppriv -e -s A=all,-sys_devices \
+		    $archiver_command $archiver_arguments 2>/dev/null
+	fi
+	result=$?
+
+	(( $result != 0 )) && return 1
+
+	return 0 
+}
+
+#
+# Unpack cpio archive into zoneroot.
+#
+install_cpio()
+{
+	stage1=$1
+	archive=$2
+
+	cpioopts="-idmfE $ipdcpiofile"
+
+	vlog "cd \"$ZONEROOT\" && $stage1 \"$archive\" | "
+	vlog "ppriv -e -s A=all,-sys_devices cpio $cpioopts"
+
+	( cd "$ZONEROOT" && $stage1 "$archive" | \
+	     ppriv -e -s A=all,-sys_devices cpio $cpioopts )
+}
+
+#
+# Unpack pax archive into zoneroot.
+#
+install_pax()
+{
+	archive=$1
+
+	if [[ -s $ipdpaxfile ]]; then
+		filtopt="-c $(/usr/bin/cat $ipdpaxfile)"
+	fi
+
+	vlog "cd \"$ZONEROOT\" && "
+	vlog "ppriv -e -s A=all,-sys_devices pax -r -f \"$archive\" $filtopt"
+
+	( cd "$ZONEROOT" && ppriv -e -s A=all,-sys_devices \
+	    pax -r -f "$archive" $filtopt )
+}
+
+#
+# Unpack UFS dump into zoneroot.
+#
+install_ufsdump()
+{
+	archive=$1
+
+	vlog "cd \"$ZONEROOT\" && "
+	vlog "ppriv -e -s A=all,-sys_devices ufsrestore rf \"$archive\""
+
+	#
+	# ufsrestore goes interactive if you ^C it.  To prevent that,
+	# we make sure its stdin is not a terminal.
+	# Note that there is no way to filter inherit-pkg-dirs for a full
+	# restore so there will be warnings in the log file.
+	#
+	( cd "$ZONEROOT" && ppriv -e -s A=all,-sys_devices \
+	    ufsrestore rf "$archive" < /dev/null )
+}
+
+#
+# Copy directory hierarchy into zoneroot.
+#
+install_dir()
+{
+	source_dir=$1
+
+	cpioopts="-pdm"
+
+	first=1
+	filt=$(for i in $(cat $ipdpaxfile)
+		do
+			echo $i | egrep -s "/" && continue
+			if [[ $first == 1 ]]; then
+				printf "^%s" $i
+				first=0
+			else
+				printf "|^%s" $i
+			fi
+		done)
+
+	list=$(cd "$source_dir" && ls -d * | egrep -v "$filt")
+	flist=$(for i in $list
+	do
+		printf "%s " "$i"
+	done)
+	findopts="-xdev ( -type d -o -type f -o -type l ) -print"
+
+	vlog "cd \"$source_dir\" && find $flist $findopts | "
+	vlog "ppriv -e -s A=all,-sys_devices cpio $cpioopts \"$ZONEROOT\""
+
+	( cd "$source_dir" && find $flist $findopts | \
+	    ppriv -e -s A=all,-sys_devices cpio $cpioopts "$ZONEROOT" )
+}
+
+# Setup i18n output
+TEXTDOMAIN="SUNW_OST_OSCMD"
+export TEXTDOMAIN
+
+e_baddir=$(gettext "Invalid '%s' directory within the zone")
+e_badfile=$(gettext "Invalid '%s' file within the zone")
+
+#
+# Exit values used by the script, as #defined in <sys/zone.h>
+#
+#	ZONE_SUBPROC_OK
+#	===============
+#	Installation was successful
+#
+#	ZONE_SUBPROC_USAGE
+#	==================
+#	Improper arguments were passed, so print a usage message before exiting
+#
+#	ZONE_SUBPROC_NOTCOMPLETE
+#	========================
+#	Installation did not complete, but another installation attempt can be
+#	made without an uninstall
+#
+#	ZONE_SUBPROC_FATAL
+#	==================
+#	Installation failed and an uninstall will be required before another
+#	install can be attempted
+#
+ZONE_SUBPROC_OK=0
+ZONE_SUBPROC_USAGE=253
+ZONE_SUBPROC_NOTCOMPLETE=254
+ZONE_SUBPROC_FATAL=255
+
--- a/usr/src/lib/brand/native/zone/config.xml	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/brand/native/zone/config.xml	Wed Feb 11 09:33:05 2009 -0700
@@ -20,7 +20,7 @@
 
  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.
 
  DO NOT EDIT THIS FILE.
@@ -37,6 +37,7 @@
 	<user_cmd>/usr/bin/getent passwd %u</user_cmd>
 
 	<install>/usr/lib/brand/native/sw_support install %z %R</install>
+	<installopts>a:b:d:psuv</installopts>
 	<verify_cfg></verify_cfg>
 	<verify_adm></verify_adm>
 	<postclone>/usr/lib/brand/native/sw_support postclone %z %R</postclone>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/image_install.ksh	Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,517 @@
+#!/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.
+#
+
+. /usr/lib/brand/shared/common.ksh
+
+# Restrict executables to /bin, /usr/bin and /usr/sfw/bin
+PATH=/bin:/usr/bin:/usr/sbin:/usr/sfw/bin
+export PATH
+
+cmd_not_found=$(gettext "Required command '%s' cannot be found!")
+cmd_not_exec=$(gettext "Required command '%s' not executable!")
+zone_initfail=$(gettext "Attempt to initialize zone '%s' FAILED.")
+path_abs=$(gettext "Pathname specified to -a '%s' must be absolute.")
+
+e_tmpfile=$(gettext "Unable to create temporary file")
+
+both_modes=$(gettext "%s: cannot select both silent and verbose modes")
+
+both_choices=$(gettext "%s: cannot select both preserve and unconfigure options")
+
+both_kinds=$(gettext "%s: cannot specify both archive and directory")
+
+not_found=$(gettext "%s: error: file or directory not found.")
+
+wrong_dir_type=$(gettext "error: must be a directory")
+
+not_readable=$(gettext "Cannot read file '%s'")
+
+no_install=$(gettext "Could not create install directory '%s'")
+no_log=$(gettext "Could not create log directory '%s'")
+
+media_taste=$(gettext   "    Media Type: %s")
+bad_archive=$(gettext "ERROR: must be a flash archive, a cpio archive (can also
+be gzipped or bzipped), a pax XUSTAR archive, or a level 0 ufsdump archive.")
+
+product_vers=$(gettext  "       Product: %s")
+install_vers=$(gettext  "     Installer: %s")
+install_zone=$(gettext  "          Zone: %s")
+install_path=$(gettext  "          Path: %s")
+install_from=$(gettext  "        Source: %s")
+installing=$(gettext    "    Installing: This may take several minutes...")
+no_installing=$(gettext "    Installing: Using pre-existing data in zonepath")
+install_prog=$(gettext  "    Installing: %s")
+
+install_fail=$(gettext  "        Result: *** Installation FAILED ***")
+install_log=$(gettext   "      Log File: %s")
+
+install_abort=$(gettext "        Result: Installation aborted.")
+install_good=$(gettext  "        Result: Installation completed successfully.")
+
+not_native_image=$(gettext  "  Sanity Check: %s doesn't look like a native image.")
+sanity_ok=$(gettext     "  Sanity Check: Passed.  Looks like a native system.")
+sanity_fail_detail=$(gettext  "  Sanity Check: Missing %s at %s")
+sanity_fail_vers=$(gettext  "  Sanity Check: image release version %s does not match system release version %s, the zone is not usable on this system.")
+sanity_fail=$(gettext   "  Sanity Check: FAILED (see log for details).")
+
+
+p2ving=$(gettext        "Postprocessing: This may take a while...")
+p2v_prog=$(gettext      "   Postprocess: ")
+p2v_done=$(gettext      "        Result: Postprocessing complete.")
+p2v_fail=$(gettext      "        Result: Postprocessing failed.")
+
+root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.")
+
+media_missing=\
+$(gettext "%s: you must specify an installation source using '-a' or '-d'.")
+
+cfgchoice_missing=\
+$(gettext "%s: you must specify -u (sys-unconfig) or -p (preserve identity).")
+
+mount_failed=$(gettext "ERROR: zonecfg(1M) 'fs' mount failed")
+
+not_flar=$(gettext "Input is not a flash archive")
+bad_flar=$(gettext "Flash archive is a corrupt")
+unknown_archiver=$(gettext "Archiver %s is not supported")
+
+e_baddir=$(gettext "Invalid '%s' directory within the zone")
+
+# Clean up on interrupt
+trap_cleanup()
+{
+	msg=$(gettext "Installation cancelled due to interrupt.")
+	log "$msg"
+
+	# umount IPDs
+	umnt_fs
+
+	exit $EXIT_CODE
+}
+
+sanity_check()
+{
+	typeset dir="$1"
+	shift
+	ret=0
+
+	# These checks must work with a sparse zone.
+	checks="etc etc/svc usr sbin lib var var/svc"
+	for x in $checks; do
+		if [[ ! -e $dir/$x ]]; then
+			vlog "$sanity_fail_detail" "$x" "$dir"
+			ret=1
+		fi
+	done
+
+	#
+	# Check image release against system release.  We only work on the
+	# same minor release as the system is running.
+	#
+	sys_vers=0
+	image_vers=-1
+	if [[ -f /var/sadm/system/admin/INST_RELEASE ]]; then
+		sys_vers=$(nawk -F= '{if ($1 == "VERSION") print $2}' \
+		    /var/sadm/system/admin/INST_RELEASE)
+	fi
+
+	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)
+	fi
+
+	if (( $sys_vers != $image_vers )); then
+		vlog "$sanity_fail_vers" "$image_vers" "$sys_vers"
+		ret=1
+	fi
+	
+	return $ret
+}
+
+#
+# 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 zoneadm to install a native system image into a zone.
+#
+
+#
+# Exit code to return if install is interrupted or exit code is otherwise
+# unspecified.
+#
+EXIT_CODE=$ZONE_SUBPROC_USAGE
+
+trap trap_cleanup INT
+
+# If we weren't passed at least two arguments, exit now.
+(( $# < 2 )) && exit $ZONE_SUBPROC_USAGE
+
+zonename="$1"
+zonepath="$2"
+
+ZONEROOT="$zonepath/root"
+logdir="$ZONEROOT/var/log"
+
+shift; shift	# remove zonename and zonepath from arguments array
+
+unset backout
+unset install_archive
+unset source_dir
+unset msg
+unset silent_mode
+unset OPT_V
+
+#
+# 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:b:d:psuv" opt
+do
+	case "$opt" in
+		a) 	install_archive="$OPTARG" ; install_media="$OPTARG";;
+		b)	if [[ -n "$backout" ]]; then
+				backout="$backout -b $OPTARG"
+			else
+				backout="-b $OPTARG"
+			fi
+			;;
+		d) 	source_dir="$OPTARG" ; install_media="$OPTARG";;
+		p)	preserve_zone="-p";;
+		s)	silent_mode=1;;
+		u)	unconfig_zone="-u";;
+		v)	OPT_V="-v";;
+		*)	exit $ZONE_SUBPROC_USAGE;;
+	esac
+done
+shift OPTIND-1
+
+# The install can't be both verbose AND silent...
+if [[ -n $silent_mode && -n $OPT_V ]]; then
+	fatal "$both_modes" "zoneadm install"
+fi
+
+if [[ -z $install_media ]]; then
+	fatal "$media_missing" "zoneadm install"
+fi
+
+if [[ -n $install_archive && -n $source_dir ]]; then
+	fatal "$both_kinds" "zoneadm install"
+fi
+
+# The install can't both preserve and unconfigure
+if [[ -n $unconfig_zone && -n $preserve_zone ]]; then
+	fatal "$both_choices" "zoneadm install"
+fi
+
+# Must pick one or the other.
+if [[ -z $unconfig_zone && -z $preserve_zone ]]; then
+	fatal "$cfgchoice_missing" "zoneadm install"
+fi
+
+#
+# Handle "-d -" option to use whatever is already installed into the zonepath.
+#
+if [ "$source_dir" != "-" ]; then
+	#
+	# Validate $install_media (things common to archive/dir)
+	#
+	if [[ "$(echo $install_media | cut -c 1)" != "/" ]]; then
+		fatal "$path_abs" "$install_media"
+	fi
+
+	if [[ ! -e "$install_media" ]]; then
+		log "$not_found" "$install_media"
+		fatal "$install_abort" "$zonename"
+	fi
+
+	if [[ ! -r "$install_media" ]]; then
+		log "$not_readable" "$install_media"
+		fatal "$install_abort" "$zonename"
+	fi
+
+	if [[ -n $install_archive ]]; then
+		if [[ ! -f "$install_archive" ]]; then
+			log "$media_taste" "$bad_archive"
+			fatal "$install_abort" "$zonename"
+		fi
+	fi
+
+	if [[ -n $source_dir ]]; then
+		if [[ ! -d "$source_dir" ]]; then
+			log "$media_taste" "$wrong_dir_type"
+			fatal "$install_abort" "$zonename"
+		fi
+	fi
+fi
+
+LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp $zonename.install_log.XXXXXX)
+if [[ -z "$LOGFILE" ]]; then
+	fatal "$e_tmpfile"
+fi
+zone_logfile="${logdir}/$zonename.install$$.log"
+exec 2>>"$LOGFILE"
+log "$install_log" "$LOGFILE"
+
+vlog "Starting pre-installation tasks."
+
+if [[ -z $install_archive && -n $source_dir ]]; then
+	#
+	# Minimal check to make sure that the user is passing
+	# us something that at least seems to be a native image.
+	#
+	if [[ "$source_dir" == "-" ]]; then
+		filetype="existing"
+		filetypename="existing"
+	else
+		sanity_check $source_dir
+		if (( $? != 0 )); then
+			fatal "$not_native_image" "$source_dir"
+		fi
+
+		filetype="directory"
+		filetypename="directory"
+	fi
+else
+	ftype="$(LC_ALL=C file $install_archive | cut -d: -f 2)"
+	case "$ftype" in
+	*cpio*)		filetype="cpio"
+			filetypename="cpio archive"
+		;;
+	*bzip2*)	filetype="bzip2"
+			filetypename="bzipped cpio archive"
+		;;
+	*gzip*)		filetype="gzip"
+			filetypename="gzipped cpio archive"
+		;;
+	*ufsdump*)	filetype="ufsdump"
+			filetypename="ufsdump archive"
+		;;
+	*Flash\ Archive*)	filetype="flar"
+			filetypename="flash archive"
+		;;
+	*USTAR\ tar\ archive\ extended\ format*)	filetype="xustar"
+			filetypename="pax (xustar) archive"
+		;;
+	*)		log "$media_taste" "$bad_archive"
+			fatal "$install_abort" "$zonename"
+		;;
+	esac
+fi
+
+#
+# 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
+
+if [[ ! -d "$ZONEROOT" ]]
+then
+	if ! mkdir -p "$ZONEROOT" 2>/dev/null; then
+		fatal "$no_install" "$ZONEROOT"
+	fi
+fi
+
+#
+# Check for a non-empty root if no '-d -' option. 
+#
+if [[ "$filetype" != "existing" ]]; then
+	cnt=$(ls $ZONEROOT | wc -l)
+	if (( $cnt != 0 )); then
+		fatal "$root_full" "$ZONEROOT"
+	fi
+fi
+
+vlog "Installation started for zone \"$zonename\""
+
+log "$install_from" "$install_media"
+vlog "$media_taste" "$filetypename"
+
+fstmpfile=$(/usr/bin/mktemp -t -p /var/tmp)
+if [[ -z "$fstmpfile" ]]; then
+	fatal "$e_tmpfile"
+fi
+
+# Make sure we always have the files holding the directories to filter
+# out when extracting from a CPIO or PAX archive.  We'll add the IPDs to these
+# files in get_fs_info().
+ipdcpiofile=$(/usr/bin/mktemp -t -p /var/tmp ipd.cpio.XXXXXX)
+if [[ -z "$ipdcpiofile" ]]; then
+	rm -f $fstmpfile
+	fatal "$e_tmpfile"
+fi
+
+# In addition to the IPDs, also filter out these directories.
+echo 'dev/*' >>$ipdcpiofile
+echo 'devices/*' >>$ipdcpiofile
+echo 'devices' >>$ipdcpiofile
+echo 'proc/*' >>$ipdcpiofile
+echo 'tmp/*' >>$ipdcpiofile
+echo 'var/run/*' >>$ipdcpiofile
+echo 'system/contract/*' >>$ipdcpiofile
+echo 'system/object/*' >>$ipdcpiofile
+
+ipdpaxfile=$(/usr/bin/mktemp -t -p /var/tmp ipd.pax.XXXXXX)
+if [[ -z "$ipdpaxfile" ]]; then
+	rm -f $fstmpfile $ipdcpiofile
+	fatal "$e_tmpfile"
+fi
+
+printf "%s " "dev devices proc tmp var/run system/contract system/object" \
+    >>$ipdpaxfile
+
+# Set up any fs mounts so the archive will install into the correct locations.
+get_fs_info
+mnt_fs
+if (( $? != 0 )); then
+	umnt_fs >/dev/null 2>&1
+	rm -f $fstmpfile $ipdcpiofile $ipdpaxfile
+	fatal "$mount_failed"
+fi
+
+if [[ "$filetype" == "existing" ]]; then
+	log "$no_installing"
+else
+	log "$installing"
+fi
+
+unpack_result=0
+stage1="cat"
+if [[ "$filetype" == "gzip" ]]; then
+	stage1="gzcat"
+	filetype="cpio"
+fi
+
+if [[ "$filetype" == "bzip2" ]]; then
+	stage1="bzcat"
+	filetype="cpio"
+fi
+
+if [[ "$filetype" == "cpio" ]]; then
+	install_cpio "$stage1" "$install_archive"
+	unpack_result=$?
+
+elif [[ "$filetype" == "flar" ]]; then
+	( cd "$ZONEROOT" && install_flar < "$install_archive" )
+	unpack_result=$?
+
+elif [[ "$filetype" == "xustar" ]]; then
+	install_pax "$install_archive"
+	unpack_result=$?
+
+elif [[ "$filetype" == "ufsdump" ]]; then
+	install_ufsdump "$install_archive"
+	unpack_result=$?
+
+elif [[ "$filetype" == "directory" ]]; then
+	install_dir "$source_dir"
+	unpack_result=$?
+fi
+
+# Clean up any fs mounts used during unpacking.
+umnt_fs
+rm -f $fstmpfile $ipdcpiofile $ipdpaxfile
+
+#
+# Do a sanity check to see if various things we think should be present
+# are present.  If not, the user might have supplied a cpio archive which was
+# not created properly.
+#
+if (( $unpack_result == 0 )); then
+	sanity_check $ZONEROOT
+	if (( $? != 0 )); then
+		log "$sanity_fail"
+		log ""
+		log "$install_log" "$LOGFILE"
+		fatal "$install_fail" "$zonename"
+	else
+		vlog "$sanity_ok"
+	fi
+fi
+	
+chmod 700 $zonepath
+
+log "$p2ving"
+vlog "running: p2v $OPT_V $unconfig_zone $backout $zonename $zonepath"
+
+#
+# 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.
+#
+/usr/lib/brand/native/p2v -l "$LOGFILE" -m "$p2v_prog" \
+     $OPT_V $unconfig_zone $backout $zonename $zonepath
+p2v_result=$?
+exec 2>>$LOGFILE
+
+if (( $p2v_result == 0 )); then
+	vlog "$p2v_done"
+else
+	log "$p2v_fail"
+	log ""
+	log "$install_fail"
+	log "$install_log" "$LOGFILE"
+	exit $ZONE_SUBPROC_FATAL
+fi
+
+EXIT_CODE=$ZONE_SUBPROC_OK
+
+log ""
+log "$install_good" "$zonename"
+
+if [[ -h $ZONEROOT/var || ! -d $ZONEROOT/var || -h $ZONEROOT/var/log ]]; then
+	log "$e_baddir" "/var/log"
+	exit $ZONE_SUBPROC_FATAL
+fi
+
+# Just in case the log directory isn't present...
+if [[ ! -d "$logdir" ]]; then
+	if ! mkdir -p "$logdir" 2>/dev/null; then
+		log "$no_log" "$logdir"
+	fi
+fi
+
+if [[ ! -h $zone_logfile && ! -d $zone_logfile ]]; then
+	cp $LOGFILE $zone_logfile
+fi
+log "$install_log" "$zone_logfile"
+rm -f $LOGFILE
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/p2v.ksh	Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,680 @@
+#!/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.
+
+. /usr/lib/brand/shared/common.ksh
+
+LOGFILE=
+MSG_PREFIX="p2v: "
+EXIT_CODE=1
+
+usage()
+{
+	echo "$0 [-s] [-m msgprefix] [-u] [-v] [-b patchid]* zonename" >&2
+	exit $EXIT_CODE
+}
+
+# Clean up on interrupt
+trap_cleanup()
+{
+	msg=$(gettext "Postprocessing cancelled due to interrupt.")
+	error "$msg"
+
+	if (( $zone_is_running != 0 )); then
+		error "$e_shutdown" "$ZONENAME"
+		/usr/sbin/zoneadm -z $ZONENAME halt
+	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=$(/usr/bin/ls $ZONEROOT/etc/hostname.* 2>/dev/null | \
+	    /usr/bin/wc -l)
+	if (( $NETIF_CNT != 1 )); then
+		vlog "$v_nonetfix"
+		return
+	fi
+
+	NET=$(LC_ALL=C /usr/sbin/zonecfg -z $ZONENAME info net)
+	if (( $? != 0 )); then
+		error "$e_badinfo" "net"
+		return
+	fi
+
+	NETIF=$(echo $NET | /usr/bin/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
+
+	OLD_HOSTNET=$(/usr/bin/ls $ZONEROOT/etc/hostname.*)
+	if [[ "$OLD_HOSTNET" != "$ZONEROOT/etc/hostname.$NETIF" ]]; then
+		safe_move $OLD_HOSTNET $ZONEROOT/etc/hostname.$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=$(/usr/bin/mktemp -t -p /var/tmp)
+	if [[ -z "$tmpfile" ]]; then
+		error "$e_tmpfile"
+		return
+	fi
+
+	/usr/bin/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
+	/usr/bin/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=$(/usr/bin/mktemp -t -p /var/tmp)
+	if [[ -z "$tmpfile" ]]; then
+		error "$e_tmpfile"
+		return
+	fi
+
+	/usr/bin/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
+	/usr/bin/rm -f $tmpfile
+}
+
+#
+# Delete or disable SMF services.
+# Zone is booted to milestone=none when this function is called.
+#
+fix_smf()
+{
+	#
+	# Delete services that are delivered in hollow pkgs.
+	#
+	# Start by getting the svc manifests that are delivered by hollow
+	# pkgs then use 'svccfg inventory' to get the names of the svcs
+	# delivered by those manifests.  The svc names are saved into a
+	# temporary file.  We then login to the zone and delete them from SMF
+	# so that the various dependencies also get cleaned up properly.
+	#
+
+	smftmpfile=$(/usr/bin/mktemp -t -p /var/tmp smf.XXXXXX)
+	if [[ -z "$smftmpfile" ]]; then
+		error "$e_tmpfile"
+		return
+	fi
+
+	for i in /var/sadm/pkg/*
+	do
+		pkg=$(/usr/bin/basename $i)
+		[[ ! -f /var/sadm/pkg/$pkg/save/pspool/$pkg/pkgmap ]] && \
+		    continue
+
+		manifests=$(/usr/bin/nawk '{if ($2 == "f" &&
+		    substr($4, 1, 17) == "var/svc/manifest/") print $4}' \
+		    /var/sadm/pkg/$pkg/save/pspool/$pkg/pkgmap)
+
+		if [[ -n "$manifests" ]]; then
+			/usr/bin/egrep -s "SUNW_PKG_HOLLOW=true" \
+			    /var/sadm/pkg/$pkg/pkginfo || continue
+
+			for j in $manifests
+			do
+				svcs=$(SVCCFG_NOVALIDATE=1 /usr/sbin/svccfg \
+				    inventory /$j)
+				for k in $svcs
+				do
+					case $k in
+					*:default)
+						# ignore default instance
+						;;
+					*)
+						echo $k >> $smftmpfile
+						;;
+					esac
+				done
+			done
+		fi
+	done
+
+	# 
+	# Zone was already booted to milestone=none, wait until SMF door exists.
+	#
+	for i in 0 1 2 3 4 5 6 7 8 9
+	do
+		[[ -r $ZONEROOT/etc/svc/volatile/repository_door ]] && break
+		sleep 5
+	done
+
+	if [[ $i -eq 9 && ! -r $ZONEROOT/etc/svc/volatile/repository_door ]];
+	then
+		error "$e_nosmf"
+		/usr/bin/rm -f $smftmpfile
+		return
+	fi
+
+	insttmpfile=$(/usr/bin/mktemp -t -p /var/tmp instsmf.XXXXXX)
+	if [[ -z "$insttmpfile" ]]; then
+		error "$e_tmpfile"
+		/usr/bin/rm -f $smftmpfile
+		return
+	fi
+
+	# Get a list of the svcs that exist in the zone.
+	/usr/sbin/zlogin -S $ZONENAME /usr/bin/svcs -aH | \
+	    /usr/bin/nawk '{print $3}' >>$insttmpfile
+
+	[[ -n $LOGFILE ]] && \
+	    printf "[$(date)] ${MSG_PREFIX}${v_svcsinzone}\n" >&2
+	[[ -n $LOGFILE ]] && cat $insttmpfile >&2
+
+	vlog "$v_rmhollowsvcs"
+	for i in $(cat $smftmpfile)
+	do
+		# Skip svcs not installed in the zone.
+		/usr/bin/egrep -s "$i:" $insttmpfile || continue
+
+		# Delete the svc.
+		vlog "$v_delsvc" "$i"
+		/usr/sbin/zlogin -S $ZONENAME /usr/sbin/svccfg delete $i >&2 \
+		    || error "$e_delsvc" $i
+	done
+
+	/usr/bin/rm -f $smftmpfile
+
+	#
+	# Fix network services if shared stack.
+	#
+	if [[ "$STACK_TYPE" == "shared" ]]; then
+		vlog "$v_fixnetsvcs"
+
+		NETPHYSDEF="svc:/network/physical:default"
+		NETPHYSNWAM="svc:/network/physical:nwam"
+
+		/usr/bin/egrep -s "$NETPHYSDEF" $insttmpfile
+		if (( $? == 0 )); then
+			vlog "$v_enblsvc" "$NETPHYSDEF"
+			/usr/sbin/zlogin -S $ZONENAME \
+			    /usr/sbin/svcadm enable $NETPHYSDEF || \
+			    error "$e_dissvc" "$NETPHYSDEF"
+		fi
+
+		/usr/bin/egrep -s "$NETPHYSNWAM" $insttmpfile
+		if (( $? == 0 )); then
+			vlog "$v_dissvc" "$NETPHYSNWAM"
+			/usr/sbin/zlogin -S $ZONENAME \
+			    /usr/sbin/svcadm disable $NETPHYSNWAM || \
+			    error "$e_enblsvc" "$NETPHYSNWAM"
+		fi
+
+		for i in $(/usr/bin/egrep network/routing $insttmpfile)
+		do
+			# Disable the svc.
+			vlog "$v_dissvc" "$i"
+			/usr/sbin/zlogin -S $ZONENAME \
+			    /usr/sbin/svcadm disable $i || \
+			    error "$e_dissvc" $i
+		done
+	fi
+
+	#
+	# Disable well-known services that don't run in a zone.
+	#
+	vlog "$v_rminvalidsvcs"
+	for i in $(/usr/bin/egrep -hv "^#" \
+	    /usr/lib/brand/native/smf_disable.lst \
+	    /etc/brand/native/smf_disable.conf)
+	do
+		# Skip svcs not installed in the zone.
+		/usr/bin/egrep -s "$i:" $insttmpfile || continue
+
+		# Disable the svc.
+		vlog "$v_dissvc" "$i"
+		/usr/sbin/zlogin -S $ZONENAME /usr/sbin/svcadm disable $i || \
+		    error "$e_dissvc" $i
+	done
+
+	#
+	# Since zones can't be NFS servers, disable all of the instances of
+	# the shares svc.
+	#
+	for i in $(/usr/bin/egrep network/shares/group $insttmpfile)
+	do
+		vlog "$v_dissvc" "$i"
+		/usr/sbin/zlogin -S $ZONENAME /usr/sbin/svcadm disable $i || \
+		    error "$e_dissvc" $i
+	done
+
+	/usr/bin/rm -f $insttmpfile
+}
+
+#
+# Remove well-known pkgs that do not work inside a zone.
+#
+rm_pkgs()
+{
+	/usr/bin/cat <<-EOF > $ZONEROOT/tmp/admin || fatal "$e_adminf"
+	mail=
+	instance=overwrite
+	partial=nocheck
+	runlevel=nocheck
+	idepend=nocheck
+	rdepend=nocheck
+	space=nocheck
+	setuid=nocheck
+	conflict=nocheck
+	action=nocheck
+	basedir=default
+	EOF
+
+	for i in $(/usr/bin/egrep -hv "^#" /usr/lib/brand/native/pkgrm.lst \
+	    /etc/brand/native/pkgrm.conf)
+	do
+		[[ ! -d $ZONEROOT/var/sadm/pkg/$i ]] && continue
+
+		vlog "$v_rmpkg" "$i"
+		/usr/sbin/zlogin -S $ZONENAME \
+		    /usr/sbin/pkgrm -na /tmp/admin $i >&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=$(/usr/bin/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=$(/usr/bin/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
+}
+
+unset LD_LIBRARY_PATH
+PATH=/usr/sbin:/usr/bin
+export PATH
+
+#
+# ^C Should cleanup; if the zone is running, it should try to halt it.
+#
+zone_is_running=0
+trap trap_cleanup INT
+
+#
+# Parse the command line options.
+#
+unset backout
+OPT_U=
+OPT_V=
+OPT_M=
+OPT_L=
+while getopts "b:uvm:l:" opt
+do
+	case "$opt" in
+		b)	if [[ -n "$backout" ]]; then
+				backout="$backout -b $OPTARG"
+			else
+				backout="-b $OPTARG"
+			fi
+			;;
+		u)	OPT_U="-u";;
+		v)	OPT_V="-v";;
+		m)	MSG_PREFIX="$OPTARG"; OPT_M="-m \"$OPTARG\"";;
+		l)	LOGFILE="$OPTARG"; OPT_L="-l \"$OPTARG\"";;
+		*)	usage;;
+	esac
+done
+shift OPTIND-1
+
+(( $# < 1 )) && usage
+
+(( $# > 2 )) && usage
+
+[[ -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_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_booting=$(gettext "Booting zone to single user mode")
+e_badboot=$(gettext "Zone boot failed")
+e_nosmf=$(gettext "ERROR: SMF repository unavailable.")
+e_nosingleuser=$(gettext "ERROR: zone did not finish booting to single-user.")
+v_svcsinzone=$(gettext "The following SMF services are installed:")
+v_rmhollowsvcs=$(gettext "Deleting SMF services from hollow packages")
+v_fixnetsvcs=$(gettext "Adjusting network SMF services")
+v_rminvalidsvcs=$(gettext "Disabling invalid SMF services")
+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_dissvc=$(gettext "disabling 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_halting=$(gettext "Halting zone")
+e_shutdown=$(gettext "Shutting down zone %s...")
+e_badhalt=$(gettext "Zone halt 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
+
+# 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
+	/usr/bin/touch $ZONEROOT/etc/mnttab || exit $EXIT_CODE
+	/usr/bin/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
+
+#
+# Run update on attach.  State is currently 'incomplete' so use the private
+# force-update option.
+#
+log "$v_update"
+/usr/sbin/zoneadm -z $ZONENAME attach -U $backout >&2
+res=$?
+if (( $? != 0 )); then
+	fatal "$e_badupdate"
+else
+	log "$v_updatedone"
+fi
+
+log "$v_adjust"
+
+#
+# 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.
+#
+
+STACK_TYPE=$(/usr/sbin/zoneadm -z $ZONENAME list -p | \
+    /usr/bin/nawk -F: '{print $7}')
+if (( $? != 0 )); then
+	error "$e_badinfo" "stacktype"
+fi
+vlog "$v_stacktype" "$STACK_TYPE"
+
+fix_net
+fix_nfs
+fix_vfstab
+
+vlog "$v_booting"
+
+#
+# Boot the zone so that we can do all of the SMF updates needed on the zone's
+# repository.
+#
+
+zone_is_running=1
+
+# The 'update on attach' left the zone installed.
+/usr/sbin/zoneadm -z $ZONENAME boot -f -- -m milestone=none
+if (( $? != 0 )); then
+	error "$e_badboot"
+	fatal "$e_exitfail"
+fi
+
+# cleanup SMF services
+fix_smf
+
+# remove invalid pkgs
+rm_pkgs
+
+vlog "$v_halting"
+/usr/sbin/zoneadm -z $ZONENAME halt
+if (( $? != 0 )); then
+	error "$e_badhalt"
+	failed=1
+fi
+zone_is_running=0
+
+if [[ -z $failed && -n $OPT_U ]]; then
+	#
+	# We're sys-unconfiging the zone.  This will halt the zone, however
+	# there are problems with sys-unconfig and it usually hangs when the
+	# zone is booted to milestone=none.  This is why we previously halted
+	# the zone.  We now boot to milestone=single-user.  Again, the
+	# sys-unconfig can hang if the zone is still in the process of
+	# booting when we try to run sys-unconfig.  Wait until the boot is
+	# done, which we do by checking for sulogin, or waiting 30 seconds,
+	# whichever comes first.
+	#
+
+	vlog "$v_unconfig"
+
+	zone_is_running=1
+	/usr/sbin/zoneadm -z $ZONENAME boot -- -m milestone=single-user
+	if (( $? != 0 )); then
+		error "$e_badboot"
+		fatal "$e_exitfail"
+	fi
+
+        for i in 0 1 2 3 4 5 6 7 8 9
+        do
+                sleep 10
+		/usr/sbin/zlogin $ZONENAME \
+		    /usr/bin/svcs -H svc:/milestone/single-user:default 2>&1 |
+		    /usr/bin/nawk '{
+			if ($1 == "online")
+				exit 0
+			else
+				exit 1
+		    }' && break
+        done
+
+	if (( $i == 9 )); then
+		vlog "$e_nosingleuser"
+        fi
+
+	echo "yes" | /usr/sbin/zlogin -S $ZONENAME \
+	    /usr/sbin/sys-unconfig >/dev/null 2>&1
+	if (( $? != 0 )); then
+		error "$e_unconfig"
+		failed=1
+	fi
+fi
+
+
+if [[ -n $failed ]]; then
+	fatal "$e_exitfail"
+fi
+
+vlog "$v_exitgood"
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/pkgrm.conf	Wed Feb 11 09:33:05 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 SVr4 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/usr/src/lib/brand/native/zone/pkgrm.lst	Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,31 @@
+#
+# 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 SVr4 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.
+# 
+VRTSvxvm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/native/zone/smf_disable.conf	Wed Feb 11 09:33:05 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/usr/src/lib/brand/native/zone/smf_disable.lst	Wed Feb 11 09:33:05 2009 -0700
@@ -0,0 +1,32 @@
+#
+# 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.
+# 
+svc:/network/smb/server
+svc:/system/virtualbox/vboxservice
--- a/usr/src/lib/brand/native/zone/sw_support.c	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/brand/native/zone/sw_support.c	Wed Feb 11 09:33:05 2009 -0700
@@ -20,12 +20,10 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * sw_support does install, detach and attach processing for svr4 pkgs.
  */
@@ -3646,23 +3644,62 @@
 	return (res);
 }
 
+static boolean_t
+add_opts(char *buf, int bsize, char opt, char *arg)
+{
+	char argbuf[MAXPATHLEN];
+
+	if (snprintf(argbuf, sizeof (argbuf), " -%c '%s'", opt, arg)
+	    > sizeof (argbuf) || strlcat(buf, argbuf, bsize) >= bsize) {
+		(void) fprintf(stderr, gettext("Command line too long"));
+		return (B_TRUE);
+	}
+
+	return (B_FALSE);
+}
+
+static boolean_t
+add_opt(char *buf, int bsize, char opt)
+{
+	char argbuf[4];
+
+	(void) snprintf(argbuf, sizeof (argbuf), " -%c", opt);
+	if (strlcat(buf, argbuf, bsize) >= bsize) {
+		(void) fprintf(stderr, gettext("Command line too long"));
+		return (B_TRUE);
+	}
+
+	return (B_FALSE);
+}
+
 static void
 install_usage()
 {
-	(void) fprintf(stderr, gettext("usage:\t%s brand options: none\n"),
+	(void) fprintf(stderr, gettext("usage:\t%s brand options:\n"
+	    "\tWith no options the zone is freshly installed:\n"
+	    "\t\tinstall\n"
+	    "\tAlternatively, the zone may be installed using an existing\n"
+	    "\tsystem image from an archive or a directory:\n"
+	    "\t\tinstall -a archive (-u | -p) [-v | -s] [-b patchid]*\n"
+	    "\t\tinstall -d directory (-u | -p) [-v | -s] [-b patchid]*\n"),
 	    MY_BRAND_NAME);
 }
 
 static int
 install_func(int argc, char *argv[])
 {
-	char cmdbuf[MAXPATHLEN];
+	char cmdbuf[NCARGS];
+	char argbuf[NCARGS];
 	int arg;
 	int status;
+	boolean_t image_install = B_FALSE;
+	char image_install_arg = '\0';
+
+	argbuf[0] = '\0';
 
 	opterr = 0;
 	optind = 0;
-	while ((arg = getopt(argc, argv, "?x:")) != EOF) {
+	while ((arg = getopt(argc, argv, "?a:b:d:psuvx:")) != EOF) {
 		switch (arg) {
 		case '?':
 			if (optopt != '?') {
@@ -3672,6 +3709,50 @@
 			}
 			install_usage();
 			return (optopt == '?' ? Z_OK : ZONE_SUBPROC_USAGE);
+
+		case 'a':
+			if (image_install) {
+				install_usage();
+				return (ZONE_SUBPROC_USAGE);
+			}
+			image_install = B_TRUE;
+			if (add_opts(argbuf, sizeof (argbuf), arg, optarg))
+				return (Z_ERR);
+			break;
+		case 'b':
+			image_install_arg = optopt;
+			if (add_opts(argbuf, sizeof (argbuf), arg, optarg))
+				return (Z_ERR);
+			break;
+		case 'd':
+			if (image_install) {
+				install_usage();
+				return (ZONE_SUBPROC_USAGE);
+			}
+			image_install = B_TRUE;
+			if (add_opts(argbuf, sizeof (argbuf), arg, optarg))
+				return (Z_ERR);
+			break;
+		case 'p':
+			image_install_arg = optopt;
+			if (add_opt(argbuf, sizeof (argbuf), arg))
+				return (Z_ERR);
+			break;
+		case 's':
+			image_install_arg = optopt;
+			if (add_opt(argbuf, sizeof (argbuf), arg))
+				return (Z_ERR);
+			break;
+		case 'u':
+			image_install_arg = optopt;
+			if (add_opt(argbuf, sizeof (argbuf), arg))
+				return (Z_ERR);
+			break;
+		case 'v':
+			image_install_arg = optopt;
+			if (add_opt(argbuf, sizeof (argbuf), arg))
+				return (Z_ERR);
+			break;
 		case 'x':
 			if (strcmp(optarg, "nodataset") != 0) {
 				(void) fprintf(stderr, gettext("%s brand: "
@@ -3693,9 +3774,70 @@
 		return (ZONE_SUBPROC_USAGE);
 	}
 
-	if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/lu/lucreatezone -z %s",
-	    zonename) >= sizeof (cmdbuf))
-		return (Z_ERR);
+	/*
+	 * Either install the zone using a system image or using the
+	 * traditional lu support.
+	 */
+	if (image_install) {
+		if (snprintf(cmdbuf, sizeof (cmdbuf),
+		    "/usr/lib/brand/native/image_install %s %s %s", zonename,
+		    zonepath, argbuf) >= sizeof (cmdbuf))
+			return (Z_ERR);
+
+	} else {
+		struct stat	stbuf;
+		char		rootpath[MAXPATHLEN]; /* zone root path */
+
+		if (snprintf(rootpath, sizeof (rootpath), "%s/root", zonepath)
+		    >= sizeof (rootpath)) {
+			(void) fprintf(stderr,
+			    gettext("Zonepath %s is too long.\n"), zonepath);
+			return (Z_ERR);
+		}
+
+		if (stat(rootpath, &stbuf) == 0) {
+			struct dirent	*dp;
+			DIR		*dirp;
+			boolean_t	empty = B_TRUE;
+
+			if ((dirp = opendir(rootpath)) == NULL) {
+				(void) fprintf(stderr, gettext("Could not "
+				    "open rootpath %s\n"), rootpath);
+				return (Z_ERR);
+			}
+
+			/* Verify that the dir is empty. */
+			while ((dp = readdir(dirp)) != NULL) {
+				if (strcmp(dp->d_name, ".") == 0 ||
+				    strcmp(dp->d_name, "..") == 0)
+					continue;
+
+				empty = B_FALSE;
+				break;
+			}
+			(void) closedir(dirp);
+
+			if (!empty) {
+				(void) fprintf(stderr, gettext("Zonepath root "
+				    "%s exists and contains data; remove or "
+				    "move aside prior to install.\n"),
+				    rootpath);
+				return (Z_ERR);
+			}
+		}
+
+		if (image_install_arg != '\0') {
+			(void) fprintf(stderr, gettext("%s brand: option: %c "
+			    "is only valid with -a or -d\n"), MY_BRAND_NAME,
+			    image_install_arg);
+			return (ZONE_SUBPROC_USAGE);
+		}
+
+		if (snprintf(cmdbuf, sizeof (cmdbuf),
+		    "/usr/lib/lu/lucreatezone -z %s", zonename) >=
+		    sizeof (cmdbuf))
+			return (Z_ERR);
+	}
 
 	/*
 	 * According to the Application Packaging Developer's Guide, a
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c	Wed Feb 11 09:33:05 2009 -0700
@@ -7161,6 +7161,14 @@
 	return (Z_OK);
 }
 
+boolean_t
+zonecfg_lock_file_held(int *lockfd)
+{
+	if (*lockfd >= 0 || zone_lock_cnt > 0)
+		return (B_TRUE);
+	return (B_FALSE);
+}
+
 static boolean_t
 get_doorname(const char *zone_name, char *buffer)
 {
--- a/usr/src/lib/libzonecfg/common/mapfile-vers	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/lib/libzonecfg/common/mapfile-vers	Wed Feb 11 09:33:05 2009 -0700
@@ -146,6 +146,7 @@
 	zonecfg_init_lock_file;
 	zonecfg_is_rctl;
 	zonecfg_is_scratch;
+	zonecfg_lock_file_held;
 	zonecfg_lock_scratch;
 	zonecfg_lookup_attr;
 	zonecfg_lookup_dev;
--- a/usr/src/pkgdefs/SUNWzoner/prototype_com	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/pkgdefs/SUNWzoner/prototype_com	Wed Feb 11 09:33:05 2009 -0700
@@ -19,11 +19,9 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 # This required package information file contains a list of package contents.
 # The 'pkgmk' command uses this file to identify the contents of a package
 # and their location on the development machine when building the package.
@@ -49,6 +47,10 @@
 # SUNWzoner
 #
 d none etc 755 root sys
+d none etc/brand 755 root sys
+d none etc/brand/native 755 root sys
+e none etc/brand/native/pkgrm.conf 644 root sys
+e none etc/brand/native/smf_disable.conf 644 root sys
 d none etc/zones 755 root sys
 e preserve etc/zones/index 644 root sys
 f none etc/zones/SUNWdefault.xml 444 root bin
--- a/usr/src/pkgdefs/SUNWzoneu/prototype_com	Wed Feb 11 09:51:50 2009 -0600
+++ b/usr/src/pkgdefs/SUNWzoneu/prototype_com	Wed Feb 11 09:33:05 2009 -0700
@@ -19,11 +19,9 @@
 # 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.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 # This required package information file contains a list of package contents.
 # The 'pkgmk' command uses this file to identify the contents of a package
 # and their location on the development machine when building the package.
@@ -54,8 +52,14 @@
 d none usr/lib/brand/native 755 root sys
 f none usr/lib/brand/native/attach_update 755 root bin
 f none usr/lib/brand/native/config.xml 444 root bin
+f none usr/lib/brand/native/image_install 755 root bin
+f none usr/lib/brand/native/p2v 755 root bin
+f none usr/lib/brand/native/pkgrm.lst 444 root bin
 f none usr/lib/brand/native/platform.xml 444 root bin
+f none usr/lib/brand/native/smf_disable.lst 444 root bin
 f none usr/lib/brand/native/sw_support 755 root bin
+d none usr/lib/brand/shared 755 root sys
+f none usr/lib/brand/shared/common.ksh 444 root bin
 f none usr/lib/libbrand.so.1 755 root bin
 f none usr/lib/libzonecfg.so.1 755 root bin
 d none usr/lib/zones 755 root bin