OpenGrok

Cross Reference: zoneadm.c
xref: /onnv/onnv-gate/usr/src/cmd/zoneadm/zoneadm.c
Home | History | Annotate | Line # | Download | only in zoneadm
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     24  */
     25 
     26 /*
     27  * zoneadm is a command interpreter for zone administration.  It is all in
     28  * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
     29  * main() calls parse_and_run() which calls cmd_match(), then invokes the
     30  * appropriate command's handler function.  The rest of the program is the
     31  * handler functions and their helper functions.
     32  *
     33  * Some of the helper functions are used largely to simplify I18N: reducing
     34  * the need for translation notes.  This is particularly true of many of
     35  * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
     36  * than zerror(gettext("foo failed")) with a translation note indicating
     37  * that "foo" need not be translated.
     38  */
     39 
     40 #include <stdio.h>
     41 #include <errno.h>
     42 #include <unistd.h>
     43 #include <signal.h>
     44 #include <stdarg.h>
     45 #include <ctype.h>
     46 #include <stdlib.h>
     47 #include <string.h>
     48 #include <wait.h>
     49 #include <zone.h>
     50 #include <priv.h>
     51 #include <locale.h>
     52 #include <libintl.h>
     53 #include <libzonecfg.h>
     54 #include <bsm/adt.h>
     55 #include <sys/brand.h>
     56 #include <sys/param.h>
     57 #include <sys/types.h>
     58 #include <sys/stat.h>
     59 #include <sys/statvfs.h>
     60 #include <assert.h>
     61 #include <sys/sockio.h>
     62 #include <sys/mntent.h>
     63 #include <limits.h>
     64 #include <dirent.h>
     65 #include <uuid/uuid.h>
     66 #include <fcntl.h>
     67 #include <door.h>
     68 #include <macros.h>
     69 #include <libgen.h>
     70 #include <fnmatch.h>
     71 #include <sys/modctl.h>
     72 #include <libbrand.h>
     73 #include <libscf.h>
     74 #include <procfs.h>
     75 #include <strings.h>
     76 #include <pool.h>
     77 #include <sys/pool.h>
     78 #include <sys/priocntl.h>
     79 #include <sys/fsspriocntl.h>
     80 #include <libdladm.h>
     81 #include <libdllink.h>
     82 #include <pwd.h>
     83 #include <auth_list.h>
     84 #include <auth_attr.h>
     85 #include <secdb.h>
     86 
     87 #include "zoneadm.h"
     88 
     89 #define	MAXARGS	8
     90 #define	SOURCE_ZONE (CMD_MAX + 1)
     91 
     92 /* Reflects kernel zone entries */
     93 typedef struct zone_entry {
     94 	zoneid_t	zid;
     95 	char		zname[ZONENAME_MAX];
     96 	char		*zstate_str;
     97 	zone_state_t	zstate_num;
     98 	char		zbrand[MAXNAMELEN];
     99 	char		zroot[MAXPATHLEN];
    100 	char		zuuid[UUID_PRINTABLE_STRING_LENGTH];
    101 	zone_iptype_t	ziptype;
    102 } zone_entry_t;
    103 
    104 #define	CLUSTER_BRAND_NAME	"cluster"
    105 
    106 static zone_entry_t *zents;
    107 static size_t nzents;
    108 
    109 #define	LOOPBACK_IF	"lo0"
    110 #define	SOCKET_AF(af)	(((af) == AF_UNSPEC) ? AF_INET : (af))
    111 
    112 struct net_if {
    113 	char	*name;
    114 	int	af;
    115 };
    116 
    117 /* 0755 is the default directory mode. */
    118 #define	DEFAULT_DIR_MODE \
    119 	(S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
    120 
    121 struct cmd {
    122 	uint_t	cmd_num;				/* command number */
    123 	char	*cmd_name;				/* command name */
    124 	char	*short_usage;				/* short form help */
    125 	int	(*handler)(int argc, char *argv[]);	/* function to call */
    126 
    127 };
    128 
    129 #define	SHELP_HELP	"help"
    130 #define	SHELP_BOOT	"boot [-- boot_arguments]"
    131 #define	SHELP_HALT	"halt"
    132 #define	SHELP_READY	"ready"
    133 #define	SHELP_REBOOT	"reboot [-- boot_arguments]"
    134 #define	SHELP_LIST	"list [-cipv]"
    135 #define	SHELP_VERIFY	"verify"
    136 #define	SHELP_INSTALL	"install [brand-specific args]"
    137 #define	SHELP_UNINSTALL	"uninstall [-F] [brand-specific args]"
    138 #define	SHELP_CLONE	"clone [-m method] [-s <ZFS snapshot>] "\
    139 	"[brand-specific args] zonename"
    140 #define	SHELP_MOVE	"move zonepath"
    141 #define	SHELP_DETACH	"detach [-n] [brand-specific args]"
    142 #define	SHELP_ATTACH	"attach [-F] [-n <path>] [brand-specific args]"
    143 #define	SHELP_MARK	"mark incomplete"
    144 
    145 #define	EXEC_PREFIX	"exec "
    146 #define	EXEC_LEN	(strlen(EXEC_PREFIX))
    147 #define	RMCOMMAND	"/usr/bin/rm -rf"
    148 
    149 static int cleanup_zonepath(char *, boolean_t);
    150 
    151 
    152 static int help_func(int argc, char *argv[]);
    153 static int ready_func(int argc, char *argv[]);
    154 static int boot_func(int argc, char *argv[]);
    155 static int halt_func(int argc, char *argv[]);
    156 static int reboot_func(int argc, char *argv[]);
    157 static int list_func(int argc, char *argv[]);
    158 static int verify_func(int argc, char *argv[]);
    159 static int install_func(int argc, char *argv[]);
    160 static int uninstall_func(int argc, char *argv[]);
    161 static int mount_func(int argc, char *argv[]);
    162 static int unmount_func(int argc, char *argv[]);
    163 static int clone_func(int argc, char *argv[]);
    164 static int move_func(int argc, char *argv[]);
    165 static int detach_func(int argc, char *argv[]);
    166 static int attach_func(int argc, char *argv[]);
    167 static int mark_func(int argc, char *argv[]);
    168 static int apply_func(int argc, char *argv[]);
    169 static int sysboot_func(int argc, char *argv[]);
    170 static int sanity_check(char *zone, int cmd_num, boolean_t running,
    171     boolean_t unsafe_when_running, boolean_t force);
    172 static int cmd_match(char *cmd);
    173 static int verify_details(int, char *argv[]);
    174 static int verify_brand(zone_dochandle_t, int, char *argv[]);
    175 static int invoke_brand_handler(int, char *argv[]);
    176 
    177 static struct cmd cmdtab[] = {
    178 	{ CMD_HELP,		"help",		SHELP_HELP,	help_func },
    179 	{ CMD_BOOT,		"boot",		SHELP_BOOT,	boot_func },
    180 	{ CMD_HALT,		"halt",		SHELP_HALT,	halt_func },
    181 	{ CMD_READY,		"ready",	SHELP_READY,	ready_func },
    182 	{ CMD_REBOOT,		"reboot",	SHELP_REBOOT,	reboot_func },
    183 	{ CMD_LIST,		"list",		SHELP_LIST,	list_func },
    184 	{ CMD_VERIFY,		"verify",	SHELP_VERIFY,	verify_func },
    185 	{ CMD_INSTALL,		"install",	SHELP_INSTALL,	install_func },
    186 	{ CMD_UNINSTALL,	"uninstall",	SHELP_UNINSTALL,
    187 	    uninstall_func },
    188 	/* mount and unmount are private commands for admin/install */
    189 	{ CMD_MOUNT,		"mount",	NULL,		mount_func },
    190 	{ CMD_UNMOUNT,		"unmount",	NULL,		unmount_func },
    191 	{ CMD_CLONE,		"clone",	SHELP_CLONE,	clone_func },
    192 	{ CMD_MOVE,		"move",		SHELP_MOVE,	move_func },
    193 	{ CMD_DETACH,		"detach",	SHELP_DETACH,	detach_func },
    194 	{ CMD_ATTACH,		"attach",	SHELP_ATTACH,	attach_func },
    195 	{ CMD_MARK,		"mark",		SHELP_MARK,	mark_func },
    196 	{ CMD_APPLY,		"apply",	NULL,		apply_func },
    197 	{ CMD_SYSBOOT,		"sysboot",	NULL,		sysboot_func }
    198 };
    199 
    200 /* global variables */
    201 
    202 /* set early in main(), never modified thereafter, used all over the place */
    203 static char *execname;
    204 static char target_brand[MAXNAMELEN];
    205 static char default_brand[MAXPATHLEN];
    206 static char *locale;
    207 char *target_zone;
    208 static char *target_uuid;
    209 char *username;
    210 
    211 char *
    212 cmd_to_str(int cmd_num)
    213 {
    214 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
    215 	return (cmdtab[cmd_num].cmd_name);
    216 }
    217 
    218 /* This is a separate function because of gettext() wrapping. */
    219 static char *
    220 long_help(int cmd_num)
    221 {
    222 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
    223 	switch (cmd_num) {
    224 	case CMD_HELP:
    225 		return (gettext("Print usage message."));
    226 	case CMD_BOOT:
    227 		return (gettext("Activates (boots) specified zone.  See "
    228 		    "zoneadm(1m) for valid boot\n\targuments."));
    229 	case CMD_HALT:
    230 		return (gettext("Halts specified zone, bypassing shutdown "
    231 		    "scripts and removing runtime\n\tresources of the zone."));
    232 	case CMD_READY:
    233 		return (gettext("Prepares a zone for running applications but "
    234 		    "does not start any user\n\tprocesses in the zone."));
    235 	case CMD_REBOOT:
    236 		return (gettext("Restarts the zone (equivalent to a halt / "
    237 		    "boot sequence).\n\tFails if the zone is not active.  "
    238 		    "See zoneadm(1m) for valid boot\n\targuments."));
    239 	case CMD_LIST:
    240 		return (gettext("Lists the current zones, or a "
    241 		    "specific zone if indicated.  By default,\n\tall "
    242 		    "running zones are listed, though this can be "
    243 		    "expanded to all\n\tinstalled zones with the -i "
    244 		    "option or all configured zones with the\n\t-c "
    245 		    "option.  When used with the general -z <zone> and/or -u "
    246 		    "<uuid-match>\n\toptions, lists only the specified "
    247 		    "matching zone, but lists it\n\tregardless of its state, "
    248 		    "and the -i and -c options are disallowed.  The\n\t-v "
    249 		    "option can be used to display verbose information: zone "
    250 		    "name, id,\n\tcurrent state, root directory and options.  "
    251 		    "The -p option can be used\n\tto request machine-parsable "
    252 		    "output.  The -v and -p options are mutually\n\texclusive."
    253 		    "  If neither -v nor -p is used, just the zone name is "
    254 		    "listed."));
    255 	case CMD_VERIFY:
    256 		return (gettext("Check to make sure the configuration "
    257 		    "can safely be instantiated\n\ton the machine: "
    258 		    "physical network interfaces exist, etc."));
    259 	case CMD_INSTALL:
    260 		return (gettext("Install the configuration on to the system.  "
    261 		    "All arguments are passed to the brand installation "
    262 		    "function;\n\tsee brands(5) for more information."));
    263 	case CMD_UNINSTALL:
    264 		return (gettext("Uninstall the configuration from the system.  "
    265 		    "The -F flag can be used\n\tto force the action.  All "
    266 		    "other arguments are passed to the brand\n\tuninstall "
    267 		    "function; see brands(5) for more information."));
    268 	case CMD_CLONE:
    269 		return (gettext("Clone the installation of another zone.  "
    270 		    "The -m option can be used to\n\tspecify 'copy' which "
    271 		    "forces a copy of the source zone.  The -s option\n\t"
    272 		    "can be used to specify the name of a ZFS snapshot "
    273 		    "that was taken from\n\ta previous clone command.  The "
    274 		    "snapshot will be used as the source\n\tinstead of "
    275 		    "creating a new ZFS snapshot.  All other arguments are "
    276 		    "passed\n\tto the brand clone function; see "
    277 		    "brands(5) for more information."));
    278 	case CMD_MOVE:
    279 		return (gettext("Move the zone to a new zonepath."));
    280 	case CMD_DETACH:
    281 		return (gettext("Detach the zone from the system. The zone "
    282 		    "state is changed to\n\t'configured' (but the files under "
    283 		    "the zonepath are untouched).\n\tThe zone can subsequently "
    284 		    "be attached, or can be moved to another\n\tsystem and "
    285 		    "attached there.  The -n option can be used to specify\n\t"
    286 		    "'no-execute' mode.  When -n is used, the information "
    287 		    "needed to attach\n\tthe zone is sent to standard output "
    288 		    "but the zone is not actually\n\tdetached.  All other "
    289 		    "arguments are passed to the brand detach function;\n\tsee "
    290 		    "brands(5) for more information."));
    291 	case CMD_ATTACH:
    292 		return (gettext("Attach the zone to the system.  The zone "
    293 		    "state must be 'configured'\n\tprior to attach; upon "
    294 		    "successful completion, the zone state will be\n\t"
    295 		    "'installed'.  The system software on the current "
    296 		    "system must be\n\tcompatible with the software on the "
    297 		    "zone's original system.\n\tSpecify -F "
    298 		    "to force the attach and skip software compatibility "
    299 		    "tests.\n\tThe -n option can be used to specify "
    300 		    "'no-execute' mode.  When -n is\n\tused, the information "
    301 		    "needed to attach the zone is read from the\n\tspecified "
    302 		    "path and the configuration is only validated.  The path "
    303 		    "can\n\tbe '-' to specify standard input.  The -F and -n "
    304 		    "options are mutually\n\texclusive.  All other arguments "
    305 		    "are passed to the brand attach\n\tfunction; see "
    306 		    "brands(5) for more information."));
    307 	case CMD_MARK:
    308 		return (gettext("Set the state of the zone.  This can be used "
    309 		    "to force the zone\n\tstate to 'incomplete' "
    310 		    "administratively if some activity has rendered\n\tthe "
    311 		    "zone permanently unusable.  The only valid state that "
    312 		    "may be\n\tspecified is 'incomplete'."));
    313 	default:
    314 		return ("");
    315 	}
    316 	/* NOTREACHED */
    317 	return (NULL);
    318 }
    319 
    320 /*
    321  * Called with explicit B_TRUE when help is explicitly requested, B_FALSE for
    322  * unexpected errors.
    323  */
    324 
    325 static int
    326 usage(boolean_t explicit)
    327 {
    328 	int i;
    329 	FILE *fd = explicit ? stdout : stderr;
    330 
    331 	(void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname);
    332 	(void) fprintf(fd, "\t%s [-z <zone>] [-u <uuid-match>] list\n",
    333 	    execname);
    334 	(void) fprintf(fd, "\t%s {-z <zone>|-u <uuid-match>} <%s>\n", execname,
    335 	    gettext("subcommand"));
    336 	(void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands"));
    337 	for (i = CMD_MIN; i <= CMD_MAX; i++) {
    338 		if (cmdtab[i].short_usage == NULL)
    339 			continue;
    340 		(void) fprintf(fd, "%s\n", cmdtab[i].short_usage);
    341 		if (explicit)
    342 			(void) fprintf(fd, "\t%s\n\n", long_help(i));
    343 	}
    344 	if (!explicit)
    345 		(void) fputs("\n", fd);
    346 	return (Z_USAGE);
    347 }
    348 
    349 static void
    350 sub_usage(char *short_usage, int cmd_num)
    351 {
    352 	(void) fprintf(stderr, "%s:\t%s\n", gettext("usage"), short_usage);
    353 	(void) fprintf(stderr, "\t%s\n", long_help(cmd_num));
    354 }
    355 
    356 /*
    357  * zperror() is like perror(3c) except that this also prints the executable
    358  * name at the start of the message, and takes a boolean indicating whether
    359  * to call libc'c strerror() or that from libzonecfg.
    360  */
    361 
    362 void
    363 zperror(const char *str, boolean_t zonecfg_error)
    364 {
    365 	(void) fprintf(stderr, "%s: %s: %s\n", execname, str,
    366 	    zonecfg_error ? zonecfg_strerror(errno) : strerror(errno));
    367 }
    368 
    369 /*
    370  * zperror2() is very similar to zperror() above, except it also prints a
    371  * supplied zone name after the executable.
    372  *
    373  * All current consumers of this function want libzonecfg's strerror() rather
    374  * than libc's; if this ever changes, this function can be made more generic
    375  * like zperror() above.
    376  */
    377 
    378 void
    379 zperror2(const char *zone, const char *str)
    380 {
    381 	(void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str,
    382 	    zonecfg_strerror(errno));
    383 }
    384 
    385 /* PRINTFLIKE1 */
    386 void
    387 zerror(const char *fmt, ...)
    388 {
    389 	va_list alist;
    390 
    391 	va_start(alist, fmt);
    392 	(void) fprintf(stderr, "%s: ", execname);
    393 	if (target_zone != NULL)
    394 		(void) fprintf(stderr, "zone '%s': ", target_zone);
    395 	(void) vfprintf(stderr, fmt, alist);
    396 	(void) fprintf(stderr, "\n");
    397 	va_end(alist);
    398 }
    399 
    400 static void *
    401 safe_calloc(size_t nelem, size_t elsize)
    402 {
    403 	void *r = calloc(nelem, elsize);
    404 
    405 	if (r == NULL) {
    406 		zerror(gettext("failed to allocate %lu bytes: %s"),
    407 		    (ulong_t)nelem * elsize, strerror(errno));
    408 		exit(Z_ERR);
    409 	}
    410 	return (r);
    411 }
    412 
    413 static void
    414 zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable)
    415 {
    416 	static boolean_t firsttime = B_TRUE;
    417 	char *ip_type_str;
    418 
    419 	/* Skip a zone that shutdown while we were collecting data. */
    420 	if (zent->zname[0] == '\0')
    421 		return;
    422 
    423 	if (zent->ziptype == ZS_EXCLUSIVE)
    424 		ip_type_str = "excl";
    425 	else
    426 		ip_type_str = "shared";
    427 
    428 	assert(!(verbose && parsable));
    429 	if (firsttime && verbose) {
    430 		firsttime = B_FALSE;
    431 		(void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
    432 		    ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
    433 		    "IP");
    434 	}
    435 	if (!verbose) {
    436 		char *cp, *clim;
    437 
    438 		if (!parsable) {
    439 			(void) printf("%s\n", zent->zname);
    440 			return;
    441 		}
    442 		if (zent->zid == ZONE_ID_UNDEFINED)
    443 			(void) printf("-");
    444 		else
    445 			(void) printf("%lu", zent->zid);
    446 		(void) printf(":%s:%s:", zent->zname, zent->zstate_str);
    447 		cp = zent->zroot;
    448 		while ((clim = strchr(cp, ':')) != NULL) {
    449 			(void) printf("%.*s\\:", clim - cp, cp);
    450 			cp = clim + 1;
    451 		}
    452 		(void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
    453 		    ip_type_str);
    454 		return;
    455 	}
    456 	if (zent->zstate_str != NULL) {
    457 		if (zent->zid == ZONE_ID_UNDEFINED)
    458 			(void) printf("%*s", ZONEID_WIDTH, "-");
    459 		else
    460 			(void) printf("%*lu", ZONEID_WIDTH, zent->zid);
    461 		(void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
    462 		    zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
    463 	}
    464 }
    465 
    466 static int
    467 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
    468 {
    469 	char root[MAXPATHLEN], *cp;
    470 	int err;
    471 	uuid_t uuid;
    472 	zone_dochandle_t handle;
    473 
    474 	(void) strlcpy(zent->zname, zone_name, sizeof (zent->zname));
    475 	(void) strlcpy(zent->zroot, "???", sizeof (zent->zroot));
    476 	(void) strlcpy(zent->zbrand, "???", sizeof (zent->zbrand));
    477 	zent->zstate_str = "???";
    478 
    479 	zent->zid = zid;
    480 
    481 	if (zonecfg_get_uuid(zone_name, uuid) == Z_OK &&
    482 	    !uuid_is_null(uuid))
    483 		uuid_unparse(uuid, zent->zuuid);
    484 	else
    485 		zent->zuuid[0] = '\0';
    486 
    487 	/*
    488 	 * For labeled zones which query the zone path of lower-level
    489 	 * zones, the path needs to be adjusted to drop the final
    490 	 * "/root" component. This adjusted path is then useful
    491 	 * for reading down any exported directories from the
    492 	 * lower-level zone.
    493 	 */
    494 	if (is_system_labeled() && zent->zid != ZONE_ID_UNDEFINED) {
    495 		if (zone_getattr(zent->zid, ZONE_ATTR_ROOT, zent->zroot,
    496 		    sizeof (zent->zroot)) == -1) {
    497 			zperror2(zent->zname,
    498 			    gettext("could not get zone path."));
    499 			return (Z_ERR);
    500 		}
    501 		cp = zent->zroot + strlen(zent->zroot) - 5;
    502 		if (cp > zent->zroot && strcmp(cp, "/root") == 0)
    503 			*cp = 0;
    504 	} else {
    505 		if ((err = zone_get_zonepath(zent->zname, root,
    506 		    sizeof (root))) != Z_OK) {
    507 			errno = err;
    508 			zperror2(zent->zname,
    509 			    gettext("could not get zone path."));
    510 			return (Z_ERR);
    511 		}
    512 		(void) strlcpy(zent->zroot, root, sizeof (zent->zroot));
    513 	}
    514 
    515 	if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) {
    516 		errno = err;
    517 		zperror2(zent->zname, gettext("could not get state"));
    518 		return (Z_ERR);
    519 	}
    520 	zent->zstate_str = zone_state_str(zent->zstate_num);
    521 
    522 	/*
    523 	 * A zone's brand is only available in the .xml file describing it,
    524 	 * which is only visible to the global zone.  This causes
    525 	 * zone_get_brand() to fail when called from within a non-global
    526 	 * zone.  Fortunately we only do this on labeled systems, where we
    527 	 * know all zones are native.
    528 	 */
    529 	if (getzoneid() != GLOBAL_ZONEID) {
    530 		assert(is_system_labeled() != 0);
    531 		(void) strlcpy(zent->zbrand, default_brand,
    532 		    sizeof (zent->zbrand));
    533 	} else if (zone_get_brand(zent->zname, zent->zbrand,
    534 	    sizeof (zent->zbrand)) != Z_OK) {
    535 		zperror2(zent->zname, gettext("could not get brand name"));
    536 		return (Z_ERR);
    537 	}
    538 
    539 	/*
    540 	 * Get ip type of the zone.
    541 	 * Note for global zone, ZS_SHARED is set always.
    542 	 */
    543 	if (zid == GLOBAL_ZONEID) {
    544 		zent->ziptype = ZS_SHARED;
    545 		return (Z_OK);
    546 	}
    547 
    548 	/*
    549 	 * There is a race condition where the zone could boot while
    550 	 * we're walking the index file.  In this case the zone state
    551 	 * could be seen as running from the call above, but the zoneid
    552 	 * would be undefined.
    553 	 *
    554 	 * There is also a race condition where the zone could shutdown after
    555 	 * we got its running state above.  This is also not an error and
    556 	 * we fall back to getting the ziptype from the zone configuration.
    557 	 */
    558 	if (zent->zstate_num == ZONE_STATE_RUNNING &&
    559 	    zid != ZONE_ID_UNDEFINED) {
    560 		ushort_t flags;
    561 
    562 		if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
    563 		    sizeof (flags)) >= 0) {
    564 			if (flags & ZF_NET_EXCL)
    565 				zent->ziptype = ZS_EXCLUSIVE;
    566 			else
    567 				zent->ziptype = ZS_SHARED;
    568 			return (Z_OK);
    569 		}
    570 	}
    571 
    572 	if ((handle = zonecfg_init_handle()) == NULL) {
    573 		zperror2(zent->zname, gettext("could not init handle"));
    574 		return (Z_ERR);
    575 	}
    576 	if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) {
    577 		zperror2(zent->zname, gettext("could not get handle"));
    578 		zonecfg_fini_handle(handle);
    579 		return (Z_ERR);
    580 	}
    581 
    582 	if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) {
    583 		zperror2(zent->zname, gettext("could not get ip-type"));
    584 		zonecfg_fini_handle(handle);
    585 		return (Z_ERR);
    586 	}
    587 	zonecfg_fini_handle(handle);
    588 
    589 	return (Z_OK);
    590 }
    591 
    592 /*
    593  * fetch_zents() calls zone_list(2) to find out how many zones are running
    594  * (which is stored in the global nzents), then calls zone_list(2) again
    595  * to fetch the list of running zones (stored in the global zents).  This
    596  * function may be called multiple times, so if zents is already set, we
    597  * return immediately to save work.
    598  *
    599  * Note that the data about running zones can change while this function
    600  * is running, so its possible that the list of zones will have empty slots
    601  * at the end.
    602  */
    603 
    604 static int
    605 fetch_zents(void)
    606 {
    607 	zoneid_t *zids = NULL;
    608 	uint_t nzents_saved;
    609 	int i, retv;
    610 	FILE *fp;
    611 	boolean_t inaltroot;
    612 	zone_entry_t *zentp;
    613 	const char *altroot;
    614 
    615 	if (nzents > 0)
    616 		return (Z_OK);
    617 
    618 	if (zone_list(NULL, &nzents) != 0) {
    619 		zperror(gettext("failed to get zoneid list"), B_FALSE);
    620 		return (Z_ERR);
    621 	}
    622 
    623 again:
    624 	if (nzents == 0)
    625 		return (Z_OK);
    626 
    627 	zids = safe_calloc(nzents, sizeof (zoneid_t));
    628 	nzents_saved = nzents;
    629 
    630 	if (zone_list(zids, &nzents) != 0) {
    631 		zperror(gettext("failed to get zone list"), B_FALSE);
    632 		free(zids);
    633 		return (Z_ERR);
    634 	}
    635 	if (nzents != nzents_saved) {
    636 		/* list changed, try again */
    637 		free(zids);
    638 		goto again;
    639 	}
    640 
    641 	zents = safe_calloc(nzents, sizeof (zone_entry_t));
    642 
    643 	inaltroot = zonecfg_in_alt_root();
    644 	if (inaltroot) {
    645 		fp = zonecfg_open_scratch("", B_FALSE);
    646 		altroot = zonecfg_get_root();
    647 	} else {
    648 		fp = NULL;
    649 	}
    650 	zentp = zents;
    651 	retv = Z_OK;
    652 	for (i = 0; i < nzents; i++) {
    653 		char name[ZONENAME_MAX];
    654 		char altname[ZONENAME_MAX];
    655 		char rev_altroot[MAXPATHLEN];
    656 
    657 		if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) {
    658 			/*
    659 			 * There is a race condition where the zone may have
    660 			 * shutdown since we retrieved the number of running
    661 			 * zones above.  This is not an error, there will be
    662 			 * an empty slot at the end of the list.
    663 			 */
    664 			continue;
    665 		}
    666 		if (zonecfg_is_scratch(name)) {
    667 			/* Ignore scratch zones by default */
    668 			if (!inaltroot)
    669 				continue;
    670 			if (fp == NULL ||
    671 			    zonecfg_reverse_scratch(fp, name, altname,
    672 			    sizeof (altname), rev_altroot,
    673 			    sizeof (rev_altroot)) == -1) {
    674 				zerror(gettext("could not resolve scratch "
    675 				    "zone %s"), name);
    676 				retv = Z_ERR;
    677 				continue;
    678 			}
    679 			/* Ignore zones in other alternate roots */
    680 			if (strcmp(rev_altroot, altroot) != 0)
    681 				continue;
    682 			(void) strcpy(name, altname);
    683 		} else {
    684 			/* Ignore non-scratch when in an alternate root */
    685 			if (inaltroot && strcmp(name, GLOBAL_ZONENAME) != 0)
    686 				continue;
    687 		}
    688 		if (lookup_zone_info(name, zids[i], zentp) != Z_OK) {
    689 			/*
    690 			 * There is a race condition where the zone may have
    691 			 * shutdown since we retrieved the number of running
    692 			 * zones above.  This is not an error, there will be
    693 			 * an empty slot at the end of the list.
    694 			 */
    695 			continue;
    696 		}
    697 		zentp++;
    698 	}
    699 	nzents = zentp - zents;
    700 	if (fp != NULL)
    701 		zonecfg_close_scratch(fp);
    702 
    703 	free(zids);
    704 	return (retv);
    705 }
    706 
    707 static int
    708 zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable)
    709 {
    710 	int i;
    711 	zone_entry_t zent;
    712 	FILE *cookie;
    713 	char *name;
    714 
    715 	/*
    716 	 * First get the list of running zones from the kernel and print them.
    717 	 * If that is all we need, then return.
    718 	 */
    719 	if ((i = fetch_zents()) != Z_OK) {
    720 		/*
    721 		 * No need for error messages; fetch_zents() has already taken
    722 		 * care of this.
    723 		 */
    724 		return (i);
    725 	}
    726 	for (i = 0; i < nzents; i++)
    727 		zone_print(&zents[i], verbose, parsable);
    728 	if (min_state >= ZONE_STATE_RUNNING)
    729 		return (Z_OK);
    730 	/*
    731 	 * Next, get the full list of zones from the configuration, skipping
    732 	 * any we have already printed.
    733 	 */
    734 	cookie = setzoneent();
    735 	while ((name = getzoneent(cookie)) != NULL) {
    736 		for (i = 0; i < nzents; i++) {
    737 			if (strcmp(zents[i].zname, name) == 0)
    738 				break;
    739 		}
    740 		if (i < nzents) {
    741 			free(name);
    742 			continue;
    743 		}
    744 		if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
    745 			free(name);
    746 			continue;
    747 		}
    748 		free(name);
    749 		if (zent.zstate_num >= min_state)
    750 			zone_print(&zent, verbose, parsable);
    751 	}
    752 	endzoneent(cookie);
    753 	return (Z_OK);
    754 }
    755 
    756 /*
    757  * Retrieve a zone entry by name.  Returns NULL if no such zone exists.
    758  */
    759 static zone_entry_t *
    760 lookup_running_zone(const char *str)
    761 {
    762 	int i;
    763 
    764 	if (fetch_zents() != Z_OK)
    765 		return (NULL);
    766 
    767 	for (i = 0; i < nzents; i++) {
    768 		if (strcmp(str, zents[i].zname) == 0)
    769 			return (&zents[i]);
    770 	}
    771 	return (NULL);
    772 }
    773 
    774 /*
    775  * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if
    776  * B_FALSE, it should be off.  Return B_TRUE if the mode is bad (incorrect).
    777  */
    778 static boolean_t
    779 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file)
    780 {
    781 	char *str;
    782 
    783 	assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR ||
    784 	    bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP ||
    785 	    bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH);
    786 	/*
    787 	 * TRANSLATION_NOTE
    788 	 * The strings below will be used as part of a larger message,
    789 	 * either:
    790 	 * (file name) must be (owner|group|world) (read|writ|execut)able
    791 	 * or
    792 	 * (file name) must not be (owner|group|world) (read|writ|execut)able
    793 	 */
    794 	switch (bit) {
    795 	case S_IRUSR:
    796 		str = gettext("owner readable");
    797 		break;
    798 	case S_IWUSR:
    799 		str = gettext("owner writable");
    800 		break;
    801 	case S_IXUSR:
    802 		str = gettext("owner executable");
    803 		break;
    804 	case S_IRGRP:
    805 		str = gettext("group readable");
    806 		break;
    807 	case S_IWGRP:
    808 		str = gettext("group writable");
    809 		break;
    810 	case S_IXGRP:
    811 		str = gettext("group executable");
    812 		break;
    813 	case S_IROTH:
    814 		str = gettext("world readable");
    815 		break;
    816 	case S_IWOTH:
    817 		str = gettext("world writable");
    818 		break;
    819 	case S_IXOTH:
    820 		str = gettext("world executable");
    821 		break;
    822 	}
    823 	if ((mode & bit) == (on ? 0 : bit)) {
    824 		/*
    825 		 * TRANSLATION_NOTE
    826 		 * The first parameter below is a file name; the second
    827 		 * is one of the "(owner|group|world) (read|writ|execut)able"
    828 		 * strings from above.
    829 		 */
    830 		/*
    831 		 * The code below could be simplified but not in a way
    832 		 * that would easily translate to non-English locales.
    833 		 */
    834 		if (on) {
    835 			(void) fprintf(stderr, gettext("%s must be %s.\n"),
    836 			    file, str);
    837 		} else {
    838 			(void) fprintf(stderr, gettext("%s must not be %s.\n"),
    839 			    file, str);
    840 		}
    841 		return (B_TRUE);
    842 	}
    843 	return (B_FALSE);
    844 }
    845 
    846 /*
    847  * We want to make sure that no zone has its zone path as a child node
    848  * (in the directory sense) of any other.  We do that by comparing this
    849  * zone's path to the path of all other (non-global) zones.  The comparison
    850  * in each case is simple: add '/' to the end of the path, then do a
    851  * strncmp() of the two paths, using the length of the shorter one.
    852  */
    853 
    854 static int
    855 crosscheck_zonepaths(char *path)
    856 {
    857 	char rpath[MAXPATHLEN];		/* resolved path */
    858 	char path_copy[MAXPATHLEN];	/* copy of original path */
    859 	char rpath_copy[MAXPATHLEN];	/* copy of original rpath */
    860 	struct zoneent *ze;
    861 	int res, err;
    862 	FILE *cookie;
    863 
    864 	cookie = setzoneent();
    865 	while ((ze = getzoneent_private(cookie)) != NULL) {
    866 		/* Skip zones which are not installed. */
    867 		if (ze->zone_state < ZONE_STATE_INSTALLED) {
    868 			free(ze);
    869 			continue;
    870 		}
    871 		/* Skip the global zone and the current target zone. */
    872 		if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0 ||
    873 		    strcmp(ze->zone_name, target_zone) == 0) {
    874 			free(ze);
    875 			continue;
    876 		}
    877 		if (strlen(ze->zone_path) == 0) {
    878 			/* old index file without path, fall back */
    879 			if ((err = zone_get_zonepath(ze->zone_name,
    880 			    ze->zone_path, sizeof (ze->zone_path))) != Z_OK) {
    881 				errno = err;
    882 				zperror2(ze->zone_name,
    883 				    gettext("could not get zone path"));
    884 				free(ze);
    885 				continue;
    886 			}
    887 		}
    888 		(void) snprintf(path_copy, sizeof (path_copy), "%s%s",
    889 		    zonecfg_get_root(), ze->zone_path);
    890 		res = resolvepath(path_copy, rpath, sizeof (rpath));
    891 		if (res == -1) {
    892 			if (errno != ENOENT) {
    893 				zperror(path_copy, B_FALSE);
    894 				free(ze);
    895 				return (Z_ERR);
    896 			}
    897 			(void) printf(gettext("WARNING: zone %s is installed, "
    898 			    "but its %s %s does not exist.\n"), ze->zone_name,
    899 			    "zonepath", path_copy);
    900 			free(ze);
    901 			continue;
    902 		}
    903 		rpath[res] = '\0';
    904 		(void) snprintf(path_copy, sizeof (path_copy), "%s/", path);
    905 		(void) snprintf(rpath_copy, sizeof (rpath_copy), "%s/", rpath);
    906 		if (strncmp(path_copy, rpath_copy,
    907 		    min(strlen(path_copy), strlen(rpath_copy))) == 0) {
    908 			/*
    909 			 * TRANSLATION_NOTE
    910 			 * zonepath is a literal that should not be translated.
    911 			 */
    912 			(void) fprintf(stderr, gettext("%s zonepath (%s) and "
    913 			    "%s zonepath (%s) overlap.\n"),
    914 			    target_zone, path, ze->zone_name, rpath);
    915 			free(ze);
    916 			return (Z_ERR);
    917 		}
    918 		free(ze);
    919 	}
    920 	endzoneent(cookie);
    921 	return (Z_OK);
    922 }
    923 
    924 static int
    925 validate_zonepath(char *path, int cmd_num)
    926 {
    927 	int res;			/* result of last library/system call */
    928 	boolean_t err = B_FALSE;	/* have we run into an error? */
    929 	struct stat stbuf;
    930 	struct statvfs64 vfsbuf;
    931 	char rpath[MAXPATHLEN];		/* resolved path */
    932 	char ppath[MAXPATHLEN];		/* parent path */
    933 	char rppath[MAXPATHLEN];	/* resolved parent path */
    934 	char rootpath[MAXPATHLEN];	/* root path */
    935 	zone_state_t state;
    936 
    937 	if (path[0] != '/') {
    938 		(void) fprintf(stderr,
    939 		    gettext("%s is not an absolute path.\n"), path);
    940 		return (Z_ERR);
    941 	}
    942 	if ((res = resolvepath(path, rpath, sizeof (rpath))) == -1) {
    943 		if ((errno != ENOENT) ||
    944 		    (cmd_num != CMD_VERIFY && cmd_num != CMD_INSTALL &&
    945 		    cmd_num != CMD_CLONE && cmd_num != CMD_MOVE)) {
    946 			zperror(path, B_FALSE);
    947 			return (Z_ERR);
    948 		}
    949 		if (cmd_num == CMD_VERIFY) {
    950 			/*
    951 			 * TRANSLATION_NOTE
    952 			 * zoneadm is a literal that should not be translated.
    953 			 */
    954 			(void) fprintf(stderr, gettext("WARNING: %s does not "
    955 			    "exist, so it could not be verified.\nWhen "
    956 			    "'zoneadm %s' is run, '%s' will try to create\n%s, "
    957 			    "and '%s' will be tried again,\nbut the '%s' may "
    958 			    "fail if:\nthe parent directory of %s is group- or "
    959 			    "other-writable\nor\n%s overlaps with any other "
    960 			    "installed zones.\n"), path,
    961 			    cmd_to_str(CMD_INSTALL), cmd_to_str(CMD_INSTALL),
    962 			    path, cmd_to_str(CMD_VERIFY),
    963 			    cmd_to_str(CMD_VERIFY), path, path);
    964 			return (Z_OK);
    965 		}
    966 		/*
    967 		 * The zonepath is supposed to be mode 700 but its
    968 		 * parent(s) 755.  So use 755 on the mkdirp() then
    969 		 * chmod() the zonepath itself to 700.
    970 		 */
    971 		if (mkdirp(path, DEFAULT_DIR_MODE) < 0) {
    972 			zperror(path, B_FALSE);
    973 			return (Z_ERR);
    974 		}
    975 		/*
    976 		 * If the chmod() fails, report the error, but might
    977 		 * as well continue the verify procedure.
    978 		 */
    979 		if (chmod(path, S_IRWXU) != 0)
    980 			zperror(path, B_FALSE);
    981 		/*
    982 		 * Since the mkdir() succeeded, we should not have to
    983 		 * worry about a subsequent ENOENT, thus this should
    984 		 * only recurse once.
    985 		 */
    986 		return (validate_zonepath(path, cmd_num));
    987 	}
    988 	rpath[res] = '\0';
    989 	if (strcmp(path, rpath) != 0) {
    990 		errno = Z_RESOLVED_PATH;
    991 		zperror(path, B_TRUE);
    992 		return (Z_ERR);
    993 	}
    994 	if ((res = stat(rpath, &stbuf)) != 0) {
    995 		zperror(rpath, B_FALSE);
    996 		return (Z_ERR);
    997 	}
    998 	if (!S_ISDIR(stbuf.st_mode)) {
    999 		(void) fprintf(stderr, gettext("%s is not a directory.\n"),
   1000 		    rpath);
   1001 		return (Z_ERR);
   1002 	}
   1003 	if (strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) {
   1004 		(void) printf(gettext("WARNING: %s is on a temporary "
   1005 		    "file system.\n"), rpath);
   1006 	}
   1007 	if (crosscheck_zonepaths(rpath) != Z_OK)
   1008 		return (Z_ERR);
   1009 	/*
   1010 	 * Try to collect and report as many minor errors as possible
   1011 	 * before returning, so the user can learn everything that needs
   1012 	 * to be fixed up front.
   1013 	 */
   1014 	if (stbuf.st_uid != 0) {
   1015 		(void) fprintf(stderr, gettext("%s is not owned by root.\n"),
   1016 		    rpath);
   1017 		err = B_TRUE;
   1018 	}
   1019 	err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath);
   1020 	err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath);
   1021 	err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rpath);
   1022 	err |= bad_mode_bit(stbuf.st_mode, S_IRGRP, B_FALSE, rpath);
   1023 	err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rpath);
   1024 	err |= bad_mode_bit(stbuf.st_mode, S_IXGRP, B_FALSE, rpath);
   1025 	err |= bad_mode_bit(stbuf.st_mode, S_IROTH, B_FALSE, rpath);
   1026 	err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath);
   1027 	err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath);
   1028 
   1029 	(void) snprintf(ppath, sizeof (ppath), "%s/..", path);
   1030 	if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) {
   1031 		zperror(ppath, B_FALSE);
   1032 		return (Z_ERR);
   1033 	}
   1034 	rppath[res] = '\0';
   1035 	if ((res = stat(rppath, &stbuf)) != 0) {
   1036 		zperror(rppath, B_FALSE);
   1037 		return (Z_ERR);
   1038 	}
   1039 	/* theoretically impossible */
   1040 	if (!S_ISDIR(stbuf.st_mode)) {
   1041 		(void) fprintf(stderr, gettext("%s is not a directory.\n"),
   1042 		    rppath);
   1043 		return (Z_ERR);
   1044 	}
   1045 	if (stbuf.st_uid != 0) {
   1046 		(void) fprintf(stderr, gettext("%s is not owned by root.\n"),
   1047 		    rppath);
   1048 		err = B_TRUE;
   1049 	}
   1050 	err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rppath);
   1051 	err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rppath);
   1052 	err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rppath);
   1053 	err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rppath);
   1054 	err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rppath);
   1055 	if (strcmp(rpath, rppath) == 0) {
   1056 		(void) fprintf(stderr, gettext("%s is its own parent.\n"),
   1057 		    rppath);
   1058 		err = B_TRUE;
   1059 	}
   1060 
   1061 	if (statvfs64(rpath, &vfsbuf) != 0) {
   1062 		zperror(rpath, B_FALSE);
   1063 		return (Z_ERR);
   1064 	}
   1065 	if (strcmp(vfsbuf.f_basetype, MNTTYPE_NFS) == 0) {
   1066 		/*
   1067 		 * TRANSLATION_NOTE
   1068 		 * Zonepath and NFS are literals that should not be translated.
   1069 		 */
   1070 		(void) fprintf(stderr, gettext("Zonepath %s is on an NFS "
   1071 		    "mounted file system.\n"
   1072 		    "\tA local file system must be used.\n"), rpath);
   1073 		return (Z_ERR);
   1074 	}
   1075 	if (vfsbuf.f_flag & ST_NOSUID) {
   1076 		/*
   1077 		 * TRANSLATION_NOTE
   1078 		 * Zonepath and nosuid are literals that should not be
   1079 		 * translated.
   1080 		 */
   1081 		(void) fprintf(stderr, gettext("Zonepath %s is on a nosuid "
   1082 		    "file system.\n"), rpath);
   1083 		return (Z_ERR);
   1084 	}
   1085 
   1086 	if ((res = zone_get_state(target_zone, &state)) != Z_OK) {
   1087 		errno = res;
   1088 		zperror2(target_zone, gettext("could not get state"));
   1089 		return (Z_ERR);
   1090 	}
   1091 	/*
   1092 	 * The existence of the root path is only bad in the configured state,
   1093 	 * as it is *supposed* to be there at the installed and later states.
   1094 	 * However, the root path is expected to be there if the zone is
   1095 	 * detached.
   1096 	 * State/command mismatches are caught earlier in verify_details().
   1097 	 */
   1098 	if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) {
   1099 		if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >=
   1100 		    sizeof (rootpath)) {
   1101 			/*
   1102 			 * TRANSLATION_NOTE
   1103 			 * Zonepath is a literal that should not be translated.
   1104 			 */
   1105 			(void) fprintf(stderr,
   1106 			    gettext("Zonepath %s is too long.\n"), rpath);
   1107 			return (Z_ERR);
   1108 		}
   1109 		if ((res = stat(rootpath, &stbuf)) == 0) {
   1110 			if (zonecfg_detached(rpath)) {
   1111 				(void) fprintf(stderr,
   1112 				    gettext("Cannot %s detached "
   1113 				    "zone.\nUse attach or remove %s "
   1114 				    "directory.\n"), cmd_to_str(cmd_num),
   1115 				    rpath);
   1116 				return (Z_ERR);
   1117 			}
   1118 
   1119 			/* Not detached, check if it really looks ok. */
   1120 
   1121 			if (!S_ISDIR(stbuf.st_mode)) {
   1122 				(void) fprintf(stderr, gettext("%s is not a "
   1123 				    "directory.\n"), rootpath);
   1124 				return (Z_ERR);
   1125 			}
   1126 
   1127 			if (stbuf.st_uid != 0) {
   1128 				(void) fprintf(stderr, gettext("%s is not "
   1129 				    "owned by root.\n"), rootpath);
   1130 				return (Z_ERR);
   1131 			}
   1132 
   1133 			if ((stbuf.st_mode & 0777) != 0755) {
   1134 				(void) fprintf(stderr, gettext("%s mode is not "
   1135 				    "0755.\n"), rootpath);
   1136 				return (Z_ERR);
   1137 			}
   1138 		}
   1139 	}
   1140 
   1141 	return (err ? Z_ERR : Z_OK);
   1142 }
   1143 
   1144 static int
   1145 invoke_brand_handler(int cmd_num, char *argv[])
   1146 {
   1147 	zone_dochandle_t handle;
   1148 	int err;
   1149 
   1150 	if ((handle = zonecfg_init_handle()) == NULL) {
   1151 		zperror(cmd_to_str(cmd_num), B_TRUE);
   1152 		return (Z_ERR);
   1153 	}
   1154 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
   1155 		errno = err;
   1156 		zperror(cmd_to_str(cmd_num), B_TRUE);
   1157 		zonecfg_fini_handle(handle);
   1158 		return (Z_ERR);
   1159 	}
   1160 	if (verify_brand(handle, cmd_num, argv) != Z_OK) {
   1161 		zonecfg_fini_handle(handle);
   1162 		return (Z_ERR);
   1163 	}
   1164 	zonecfg_fini_handle(handle);
   1165 	return (Z_OK);
   1166 }
   1167 
   1168 static int
   1169 ready_func(int argc, char *argv[])
   1170 {
   1171 	zone_cmd_arg_t zarg;
   1172 	int arg;
   1173 
   1174 	if (zonecfg_in_alt_root()) {
   1175 		zerror(gettext("cannot ready zone in alternate root"));
   1176 		return (Z_ERR);
   1177 	}
   1178 
   1179 	optind = 0;
   1180 	if ((arg = getopt(argc, argv, "?")) != EOF) {
   1181 		switch (arg) {
   1182 		case '?':
   1183 			sub_usage(SHELP_READY, CMD_READY);
   1184 			return (optopt == '?' ? Z_OK : Z_USAGE);
   1185 		default:
   1186 			sub_usage(SHELP_READY, CMD_READY);
   1187 			return (Z_USAGE);
   1188 		}
   1189 	}
   1190 	if (argc > optind) {
   1191 		sub_usage(SHELP_READY, CMD_READY);
   1192 		return (Z_USAGE);
   1193 	}
   1194 	if (sanity_check(target_zone, CMD_READY, B_FALSE, B_FALSE, B_FALSE)
   1195 	    != Z_OK)
   1196 		return (Z_ERR);
   1197 	if (verify_details(CMD_READY, argv) != Z_OK)
   1198 		return (Z_ERR);
   1199 
   1200 	zarg.cmd = Z_READY;
   1201 	if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
   1202 		zerror(gettext("call to %s failed"), "zoneadmd");
   1203 		return (Z_ERR);
   1204 	}
   1205 	return (Z_OK);
   1206 }
   1207 
   1208 static int
   1209 boot_func(int argc, char *argv[])
   1210 {
   1211 	zone_cmd_arg_t zarg;
   1212 	boolean_t force = B_FALSE;
   1213 	int arg;
   1214 
   1215 	if (zonecfg_in_alt_root()) {
   1216 		zerror(gettext("cannot boot zone in alternate root"));
   1217 		return (Z_ERR);
   1218 	}
   1219 
   1220 	zarg.bootbuf[0] = '\0';
   1221 
   1222 	/*
   1223 	 * The following getopt processes arguments to zone boot; that
   1224 	 * is to say, the [here] portion of the argument string:
   1225 	 *
   1226 	 *	zoneadm -z myzone boot [here] -- -v -m verbose
   1227 	 *
   1228 	 * Where [here] can either be nothing, -? (in which case we bail
   1229 	 * and print usage), -f (a private option to indicate that the
   1230 	 * boot operation should be 'forced'), or -s.  Support for -s is
   1231 	 * vestigal and obsolete, but is retained because it was a
   1232 	 * documented interface and there are known consumers including
   1233 	 * admin/install; the proper way to specify boot arguments like -s
   1234 	 * is:
   1235 	 *
   1236 	 *	zoneadm -z myzone boot -- -s -v -m verbose.
   1237 	 */
   1238 	optind = 0;
   1239 	while ((arg = getopt(argc, argv, "?fs")) != EOF) {
   1240 		switch (arg) {
   1241 		case '?':
   1242 			sub_usage(SHELP_BOOT, CMD_BOOT);
   1243 			return (optopt == '?' ? Z_OK : Z_USAGE);
   1244 		case 's':
   1245 			(void) strlcpy(zarg.bootbuf, "-s",
   1246 			    sizeof (zarg.bootbuf));
   1247 			break;
   1248 		case 'f':
   1249 			force = B_TRUE;
   1250 			break;
   1251 		default:
   1252 			sub_usage(SHELP_BOOT, CMD_BOOT);
   1253 			return (Z_USAGE);
   1254 		}
   1255 	}
   1256 
   1257 	for (; optind < argc; optind++) {
   1258 		if (strlcat(zarg.bootbuf, argv[optind],
   1259 		    sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
   1260 			zerror(gettext("Boot argument list too long"));
   1261 			return (Z_ERR);
   1262 		}
   1263 		if (optind < argc - 1)
   1264 			if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
   1265 			    sizeof (zarg.bootbuf)) {
   1266 				zerror(gettext("Boot argument list too long"));
   1267 				return (Z_ERR);
   1268 			}
   1269 	}
   1270 	if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE, force)
   1271 	    != Z_OK)
   1272 		return (Z_ERR);
   1273 	if (verify_details(CMD_BOOT, argv) != Z_OK)
   1274 		return (Z_ERR);
   1275 	zarg.cmd = force ? Z_FORCEBOOT : Z_BOOT;
   1276 	if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
   1277 		zerror(gettext("call to %s failed"), "zoneadmd");
   1278 		return (Z_ERR);
   1279 	}
   1280 
   1281 	return (Z_OK);
   1282 }
   1283 
   1284 static void
   1285 fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr)
   1286 {
   1287 	ssize_t result;
   1288 	uuid_t uuid;
   1289 	FILE *fp;
   1290 	ushort_t flags;
   1291 
   1292 	(void) memset(zeptr, 0, sizeof (*zeptr));
   1293 
   1294 	zeptr->zid = zid;
   1295 
   1296 	/*
   1297 	 * Since we're looking up our own (non-global) zone name,
   1298 	 * we can be assured that it will succeed.
   1299 	 */
   1300 	result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname));
   1301 	assert(result >= 0);
   1302 	if (zonecfg_is_scratch(zeptr->zname) &&
   1303 	    (fp = zonecfg_open_scratch("", B_FALSE)) != NULL) {
   1304 		(void) zonecfg_reverse_scratch(fp, zeptr->zname, zeptr->zname,
   1305 		    sizeof (zeptr->zname), NULL, 0);
   1306 		zonecfg_close_scratch(fp);
   1307 	}
   1308 
   1309 	if (is_system_labeled()) {
   1310 		(void) zone_getattr(zid, ZONE_ATTR_ROOT, zeptr->zroot,
   1311 		    sizeof (zeptr->zroot));
   1312 		(void) strlcpy(zeptr->zbrand, NATIVE_BRAND_NAME,
   1313 		    sizeof (zeptr->zbrand));
   1314 	} else {
   1315 		(void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot));
   1316 		(void) zone_getattr(zid, ZONE_ATTR_BRAND, zeptr->zbrand,
   1317 		    sizeof (zeptr->zbrand));
   1318 	}
   1319 
   1320 	zeptr->zstate_str = "running";
   1321 	if (zonecfg_get_uuid(zeptr->zname, uuid) == Z_OK &&
   1322 	    !uuid_is_null(uuid))
   1323 		uuid_unparse(uuid, zeptr->zuuid);
   1324 
   1325 	if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, sizeof (flags)) < 0) {
   1326 		zperror2(zeptr->zname, gettext("could not get zone flags"));
   1327 		exit(Z_ERR);
   1328 	}
   1329 	if (flags & ZF_NET_EXCL)
   1330 		zeptr->ziptype = ZS_EXCLUSIVE;
   1331 	else
   1332 		zeptr->ziptype = ZS_SHARED;
   1333 }
   1334 
   1335 static int
   1336 list_func(int argc, char *argv[])
   1337 {
   1338 	zone_entry_t *zentp, zent;
   1339 	int arg, retv;
   1340 	boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE;
   1341 	zone_state_t min_state = ZONE_STATE_RUNNING;
   1342 	zoneid_t zone_id = getzoneid();
   1343 
   1344 	if (target_zone == NULL) {
   1345 		/* all zones: default view to running but allow override */
   1346 		optind = 0;
   1347 		while ((arg = getopt(argc, argv, "?cipv")) != EOF) {
   1348 			switch (arg) {
   1349 			case '?':
   1350 				sub_usage(SHELP_LIST, CMD_LIST);
   1351 				return (optopt == '?' ? Z_OK : Z_USAGE);
   1352 				/*
   1353 				 * The 'i' and 'c' options are not mutually
   1354 				 * exclusive so if 'c' is given, then min_state
   1355 				 * is set to 0 (ZONE_STATE_CONFIGURED) which is
   1356 				 * the lowest possible state.  If 'i' is given,
   1357 				 * then min_state is set to be the lowest state
   1358 				 * so far.
   1359 				 */
   1360 			case 'c':
   1361 				min_state = ZONE_STATE_CONFIGURED;
   1362 				break;
   1363 			case 'i':
   1364 				min_state = min(ZONE_STATE_INSTALLED,
   1365 				    min_state);
   1366 
   1367 				break;
   1368 			case 'p':
   1369 				parsable = B_TRUE;
   1370 				break;
   1371 			case 'v':
   1372 				verbose = B_TRUE;
   1373 				break;
   1374 			default:
   1375 				sub_usage(SHELP_LIST, CMD_LIST);
   1376 				return (Z_USAGE);
   1377 			}
   1378 		}
   1379 		if (parsable && verbose) {
   1380 			zerror(gettext("%s -p and -v are mutually exclusive."),
   1381 			    cmd_to_str(CMD_LIST));
   1382 			return (Z_ERR);
   1383 		}
   1384 		if (zone_id == GLOBAL_ZONEID || is_system_labeled()) {
   1385 			retv = zone_print_list(min_state, verbose, parsable);
   1386 		} else {
   1387 			fake_up_local_zone(zone_id, &zent);
   1388 			retv = Z_OK;
   1389 			zone_print(&zent, verbose, parsable);
   1390 		}
   1391 		return (retv);
   1392 	}
   1393 
   1394 	/*
   1395 	 * Specific target zone: disallow -i/-c suboptions.
   1396 	 */
   1397 	optind = 0;
   1398 	while ((arg = getopt(argc, argv, "?pv")) != EOF) {
   1399 		switch (arg) {
   1400 		case '?':
   1401 			sub_usage(SHELP_LIST, CMD_LIST);
   1402 			return (optopt == '?' ? Z_OK : Z_USAGE);
   1403 		case 'p':
   1404 			parsable = B_TRUE;
   1405 			break;
   1406 		case 'v':
   1407 			verbose = B_TRUE;
   1408 			break;
   1409 		default:
   1410 			sub_usage(SHELP_LIST, CMD_LIST);
   1411 			return (Z_USAGE);
   1412 		}
   1413 	}
   1414 	if (parsable && verbose) {
   1415 		zerror(gettext("%s -p and -v are mutually exclusive."),
   1416 		    cmd_to_str(CMD_LIST));
   1417 		return (Z_ERR);
   1418 	}
   1419 	if (argc > optind) {
   1420 		sub_usage(SHELP_LIST, CMD_LIST);
   1421 		return (Z_USAGE);
   1422 	}
   1423 	if (zone_id != GLOBAL_ZONEID && !is_system_labeled()) {
   1424 		fake_up_local_zone(zone_id, &zent);
   1425 		/*
   1426 		 * main() will issue a Z_NO_ZONE error if it cannot get an
   1427 		 * id for target_zone, which in a non-global zone should
   1428 		 * happen for any zone name except `zonename`.  Thus we
   1429 		 * assert() that here but don't otherwise check.
   1430 		 */
   1431 		assert(strcmp(zent.zname, target_zone) == 0);
   1432 		zone_print(&zent, verbose, parsable);
   1433 		output = B_TRUE;
   1434 	} else if ((zentp = lookup_running_zone(target_zone)) != NULL) {
   1435 		zone_print(zentp, verbose, parsable);
   1436 		output = B_TRUE;
   1437 	} else if (lookup_zone_info(target_zone, ZONE_ID_UNDEFINED,
   1438 	    &zent) == Z_OK) {
   1439 		zone_print(&zent, verbose, parsable);
   1440 		output = B_TRUE;
   1441 	}
   1442 
   1443 	/*
   1444 	 * Invoke brand-specific handler. Note that we do this
   1445 	 * only if we're in the global zone, and target_zone is specified
   1446 	 * and it is not the global zone.
   1447 	 */
   1448 	if (zone_id == GLOBAL_ZONEID && target_zone != NULL &&
   1449 	    strcmp(target_zone, GLOBAL_ZONENAME) != 0)
   1450 		if (invoke_brand_handler(CMD_LIST, argv) != Z_OK)
   1451 			return (Z_ERR);
   1452 
   1453 	return (output ? Z_OK : Z_ERR);
   1454 }
   1455 
   1456 int
   1457 do_subproc(char *cmdbuf)
   1458 {
   1459 	void (*saveint)(int);
   1460 	void (*saveterm)(int);
   1461 	void (*savequit)(int);
   1462 	void (*savehup)(int);
   1463 	int pid, child, status;
   1464 
   1465 	if ((child = vfork()) == 0) {
   1466 		(void) execl("/bin/sh", "sh", "-c", cmdbuf, (char *)NULL);
   1467 	}
   1468 
   1469 	if (child == -1)
   1470 		return (-1);
   1471 
   1472 	saveint = sigset(SIGINT, SIG_IGN);
   1473 	saveterm = sigset(SIGTERM, SIG_IGN);
   1474 	savequit = sigset(SIGQUIT, SIG_IGN);
   1475 	savehup = sigset(SIGHUP, SIG_IGN);
   1476 
   1477 	while ((pid = waitpid(child, &status, 0)) != child && pid != -1)
   1478 		;
   1479 
   1480 	(void) sigset(SIGINT, saveint);
   1481 	(void) sigset(SIGTERM, saveterm);
   1482 	(void) sigset(SIGQUIT, savequit);
   1483 	(void) sigset(SIGHUP, savehup);
   1484 
   1485 	return (pid == -1 ? -1 : status);
   1486 }
   1487 
   1488 int
   1489 subproc_status(const char *cmd, int status, boolean_t verbose_failure)
   1490 {
   1491 	if (WIFEXITED(status)) {
   1492 		int exit_code = WEXITSTATUS(status);
   1493 
   1494 		if ((verbose_failure) && (exit_code != ZONE_SUBPROC_OK))
   1495 			zerror(gettext("'%s' failed with exit code %d."), cmd,
   1496 			    exit_code);
   1497 
   1498 		return (exit_code);
   1499 	} else if (WIFSIGNALED(status)) {
   1500 		int signal = WTERMSIG(status);
   1501 		char sigstr[SIG2STR_MAX];
   1502 
   1503 		if (sig2str(signal, sigstr) == 0) {
   1504 			zerror(gettext("'%s' terminated by signal SIG%s."), cmd,
   1505 			    sigstr);
   1506 		} else {
   1507 			zerror(gettext("'%s' terminated by an unknown signal."),
   1508 			    cmd);
   1509 		}
   1510 	} else {
   1511 		zerror(gettext("'%s' failed for unknown reasons."), cmd);
   1512 	}
   1513 
   1514 	/*
   1515 	 * Assume a subprocess that died due to a signal or an unknown error
   1516 	 * should be considered an exit code of ZONE_SUBPROC_FATAL, as the
   1517 	 * user will likely need to do some manual cleanup.
   1518 	 */
   1519 	return (ZONE_SUBPROC_FATAL);
   1520 }
   1521 
   1522 static int
   1523 auth_check(char *user, char *zone, int cmd_num)
   1524 {
   1525 	char authname[MAXAUTHS];
   1526 
   1527 	switch (cmd_num) {
   1528 	case CMD_LIST:
   1529 	case CMD_HELP:
   1530 		return (Z_OK);
   1531 	case SOURCE_ZONE:
   1532 		(void) strlcpy(authname, ZONE_CLONEFROM_AUTH, MAXAUTHS);
   1533 		break;
   1534 	case CMD_BOOT:
   1535 	case CMD_HALT:
   1536 	case CMD_READY:
   1537 	case CMD_REBOOT:
   1538 	case CMD_SYSBOOT:
   1539 	case CMD_VERIFY:
   1540 	case CMD_INSTALL:
   1541 	case CMD_UNINSTALL:
   1542 	case CMD_MOUNT:
   1543 	case CMD_UNMOUNT:
   1544 	case CMD_CLONE:
   1545 	case CMD_MOVE:
   1546 	case CMD_DETACH:
   1547 	case CMD_ATTACH:
   1548 	case CMD_MARK:
   1549 	case CMD_APPLY:
   1550 	default:
   1551 		(void) strlcpy(authname, ZONE_MANAGE_AUTH, MAXAUTHS);
   1552 		break;
   1553 	}
   1554 	(void) strlcat(authname, KV_OBJECT, MAXAUTHS);
   1555 	(void) strlcat(authname, zone, MAXAUTHS);
   1556 	if (chkauthattr(authname, user) == 0) {
   1557 		return (Z_ERR);
   1558 	} else {
   1559 		/*
   1560 		 * Some subcommands, e.g. install, run subcommands,
   1561 		 * e.g. sysidcfg, that require a real uid of root,
   1562 		 *  so switch to root, here.
   1563 		 */
   1564 		if (setuid(0) == -1) {
   1565 			zperror(gettext("insufficient privilege"), B_TRUE);
   1566 			return (Z_ERR);
   1567 		}
   1568 		return (Z_OK);
   1569 	}
   1570 }
   1571 
   1572 /*
   1573  * Various sanity checks; make sure:
   1574  * 1. We're in the global zone.
   1575  * 2. The calling user has sufficient privilege.
   1576  * 3. The target zone is neither the global zone nor anything starting with
   1577  *    "SUNW".
   1578  * 4a. If we're looking for a 'not running' (i.e., configured or installed)
   1579  *     zone, the name service knows about it.
   1580  * 4b. For some operations which expect a zone not to be running, that it is
   1581  *     not already running (or ready).
   1582  */
   1583 static int
   1584 sanity_check(char *zone, int cmd_num, boolean_t running,
   1585     boolean_t unsafe_when_running, boolean_t force)
   1586 {
   1587 	zone_entry_t *zent;
   1588 	priv_set_t *privset;
   1589 	zone_state_t state, min_state;
   1590 	char kernzone[ZONENAME_MAX];
   1591 	FILE *fp;
   1592 
   1593 	if (getzoneid() != GLOBAL_ZONEID) {
   1594 		switch (cmd_num) {
   1595 		case CMD_HALT:
   1596 			zerror(gettext("use %s to %s this zone."), "halt(1M)",
   1597 			    cmd_to_str(cmd_num));
   1598 			break;
   1599 		case CMD_REBOOT:
   1600 			zerror(gettext("use %s to %s this zone."),
   1601 			    "reboot(1M)", cmd_to_str(cmd_num));
   1602 			break;
   1603 		default:
   1604 			zerror(gettext("must be in the global zone to %s a "
   1605 			    "zone."), cmd_to_str(cmd_num));
   1606 			break;
   1607 		}
   1608 		return (Z_ERR);
   1609 	}
   1610 
   1611 	if ((privset = priv_allocset()) == NULL) {
   1612 		zerror(gettext("%s failed"), "priv_allocset");
   1613 		return (Z_ERR);
   1614 	}
   1615 
   1616 	if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
   1617 		zerror(gettext("%s failed"), "getppriv");
   1618 		priv_freeset(privset);
   1619 		return (Z_ERR);
   1620 	}
   1621 
   1622 	if (priv_isfullset(privset) == B_FALSE) {
   1623 		zerror(gettext("only a privileged user may %s a zone."),
   1624 		    cmd_to_str(cmd_num));
   1625 		priv_freeset(privset);
   1626 		return (Z_ERR);
   1627 	}
   1628 	priv_freeset(privset);
   1629 
   1630 	if (zone == NULL) {
   1631 		zerror(gettext("no zone specified"));
   1632 		return (Z_ERR);
   1633 	}
   1634 
   1635 	if (auth_check(username, zone, cmd_num) == Z_ERR) {
   1636 		zerror(gettext("User %s is not authorized to %s this zone."),
   1637 		    username, cmd_to_str(cmd_num));
   1638 		return (Z_ERR);
   1639 	}
   1640 
   1641 	if (strcmp(zone, GLOBAL_ZONENAME) == 0) {
   1642 		zerror(gettext("%s operation is invalid for the global zone."),
   1643 		    cmd_to_str(cmd_num));
   1644 		return (Z_ERR);
   1645 	}
   1646 
   1647 	if (strncmp(zone, "SUNW", 4) == 0) {
   1648 		zerror(gettext("%s operation is invalid for zones starting "
   1649 		    "with SUNW."), cmd_to_str(cmd_num));
   1650 		return (Z_ERR);
   1651 	}
   1652 
   1653 	if (!zonecfg_in_alt_root()) {
   1654 		zent = lookup_running_zone(zone);
   1655 	} else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) {
   1656 		zent = NULL;
   1657 	} else {
   1658 		if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(),
   1659 		    kernzone, sizeof (kernzone)) == 0)
   1660 			zent = lookup_running_zone(kernzone);
   1661 		else
   1662 			zent = NULL;
   1663 		zonecfg_close_scratch(fp);
   1664 	}
   1665 
   1666 	/*
   1667 	 * Look up from the kernel for 'running' zones.
   1668 	 */
   1669 	if (running && !force) {
   1670 		if (zent == NULL) {
   1671 			zerror(gettext("not running"));
   1672 			return (Z_ERR);
   1673 		}
   1674 	} else {
   1675 		int err;
   1676 
   1677 		if (unsafe_when_running && zent != NULL) {
   1678 			/* check whether the zone is ready or running */
   1679 			if ((err = zone_get_state(zent->zname,
   1680 			    &zent->zstate_num)) != Z_OK) {
   1681 				errno = err;
   1682 				zperror2(zent->zname,
   1683 				    gettext("could not get state"));
   1684 				/* can't tell, so hedge */
   1685 				zent->zstate_str = "ready/running";
   1686 			} else {
   1687 				zent->zstate_str =
   1688 				    zone_state_str(zent->zstate_num);
   1689 			}
   1690 			zerror(gettext("%s operation is invalid for %s zones."),
   1691 			    cmd_to_str(cmd_num), zent->zstate_str);
   1692 			return (Z_ERR);
   1693 		}
   1694 		if ((err = zone_get_state(zone, &state)) != Z_OK) {
   1695 			errno = err;
   1696 			zperror2(zone, gettext("could not get state"));
   1697 			return (Z_ERR);
   1698 		}
   1699 		switch (cmd_num) {
   1700 		case CMD_UNINSTALL:
   1701 			if (state == ZONE_STATE_CONFIGURED) {
   1702 				zerror(gettext("is already in state '%s'."),
   1703 				    zone_state_str(ZONE_STATE_CONFIGURED));
   1704 				return (Z_ERR);
   1705 			}
   1706 			break;
   1707 		case CMD_ATTACH:
   1708 			if (state == ZONE_STATE_INSTALLED) {
   1709 				zerror(gettext("is already %s."),
   1710 				    zone_state_str(ZONE_STATE_INSTALLED));
   1711 				return (Z_ERR);
   1712 			} else if (state == ZONE_STATE_INCOMPLETE && !force) {
   1713 				zerror(gettext("zone is %s; %s required."),
   1714 				    zone_state_str(ZONE_STATE_INCOMPLETE),
   1715 				    cmd_to_str(CMD_UNINSTALL));
   1716 				return (Z_ERR);
   1717 			}
   1718 			break;
   1719 		case CMD_CLONE:
   1720 		case CMD_INSTALL:
   1721 			if (state == ZONE_STATE_INSTALLED) {
   1722 				zerror(gettext("is already %s."),
   1723 				    zone_state_str(ZONE_STATE_INSTALLED));
   1724 				return (Z_ERR);
   1725 			} else if (state == ZONE_STATE_INCOMPLETE) {
   1726 				zerror(gettext("zone is %s; %s required."),
   1727 				    zone_state_str(ZONE_STATE_INCOMPLETE),
   1728 				    cmd_to_str(CMD_UNINSTALL));
   1729 				return (Z_ERR);
   1730 			}
   1731 			break;
   1732 		case CMD_DETACH:
   1733 		case CMD_MOVE:
   1734 		case CMD_READY:
   1735 		case CMD_BOOT:
   1736 		case CMD_MOUNT:
   1737 		case CMD_MARK:
   1738 			if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
   1739 			    force)
   1740 				min_state = ZONE_STATE_INCOMPLETE;
   1741 			else if (cmd_num == CMD_MARK)
   1742 				min_state = ZONE_STATE_CONFIGURED;
   1743 			else
   1744 				min_state = ZONE_STATE_INSTALLED;
   1745 
   1746 			if (state < min_state) {
   1747 				zerror(gettext("must be %s before %s."),
   1748 				    zone_state_str(min_state),
   1749 				    cmd_to_str(cmd_num));
   1750 				return (Z_ERR);
   1751 			}
   1752 			break;
   1753 		case CMD_VERIFY:
   1754 			if (state == ZONE_STATE_INCOMPLETE) {
   1755 				zerror(gettext("zone is %s; %s required."),
   1756 				    zone_state_str(ZONE_STATE_INCOMPLETE),
   1757 				    cmd_to_str(CMD_UNINSTALL));
   1758 				return (Z_ERR);
   1759 			}
   1760 			break;
   1761 		case CMD_UNMOUNT:
   1762 			if (state != ZONE_STATE_MOUNTED) {
   1763 				zerror(gettext("must be %s before %s."),
   1764 				    zone_state_str(ZONE_STATE_MOUNTED),
   1765 				    cmd_to_str(cmd_num));
   1766 				return (Z_ERR);
   1767 			}
   1768 			break;
   1769 		case CMD_SYSBOOT:
   1770 			if (state != ZONE_STATE_INSTALLED) {
   1771 				zerror(gettext("%s operation is invalid for %s "
   1772 				    "zones."), cmd_to_str(cmd_num),
   1773 				    zone_state_str(state));
   1774 				return (Z_ERR);
   1775 			}
   1776 			break;
   1777 		}
   1778 	}
   1779 	return (Z_OK);
   1780 }
   1781 
   1782 static int
   1783 halt_func(int argc, char *argv[])
   1784 {
   1785 	zone_cmd_arg_t zarg;
   1786 	int arg;
   1787 
   1788 	if (zonecfg_in_alt_root()) {
   1789 		zerror(gettext("cannot halt zone in alternate root"));
   1790 		return (Z_ERR);
   1791 	}
   1792 
   1793 	optind = 0;
   1794 	if ((arg = getopt(argc, argv, "?")) != EOF) {
   1795 		switch (arg) {
   1796 		case '?':
   1797 			sub_usage(SHELP_HALT, CMD_HALT);
   1798 			return (optopt == '?' ? Z_OK : Z_USAGE);
   1799 		default:
   1800 			sub_usage(SHELP_HALT, CMD_HALT);
   1801 			return (Z_USAGE);
   1802 		}
   1803 	}
   1804 	if (argc > optind) {
   1805 		sub_usage(SHELP_HALT, CMD_HALT);
   1806 		return (Z_USAGE);
   1807 	}
   1808 	/*
   1809 	 * zoneadmd should be the one to decide whether or not to proceed,
   1810 	 * so even though it seems that the fourth parameter below should
   1811 	 * perhaps be B_TRUE, it really shouldn't be.
   1812 	 */
   1813 	if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE, B_FALSE)
   1814 	    != Z_OK)
   1815 		return (Z_ERR);
   1816 
   1817 	/*
   1818 	 * Invoke brand-specific handler.
   1819 	 */
   1820 	if (invoke_brand_handler(CMD_HALT, argv) != Z_OK)
   1821 		return (Z_ERR);
   1822 
   1823 	zarg.cmd = Z_HALT;
   1824 	return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale,
   1825 	    B_TRUE) == 0) ?  Z_OK : Z_ERR);
   1826 }
   1827 
   1828 static int
   1829 reboot_func(int argc, char *argv[])
   1830 {
   1831 	zone_cmd_arg_t zarg;
   1832 	int arg;
   1833 
   1834 	if (zonecfg_in_alt_root()) {
   1835 		zerror(gettext("cannot reboot zone in alternate root"));
   1836 		return (Z_ERR);
   1837 	}
   1838 
   1839 	optind = 0;
   1840 	if ((arg = getopt(argc, argv, "?")) != EOF) {
   1841 		switch (arg) {
   1842 		case '?':
   1843 			sub_usage(SHELP_REBOOT, CMD_REBOOT);
   1844 			return (optopt == '?' ? Z_OK : Z_USAGE);
   1845 		default:
   1846 			sub_usage(SHELP_REBOOT, CMD_REBOOT);
   1847 			return (Z_USAGE);
   1848 		}
   1849 	}
   1850 
   1851 	zarg.bootbuf[0] = '\0';
   1852 	for (; optind < argc; optind++) {
   1853 		if (strlcat(zarg.bootbuf, argv[optind],
   1854 		    sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
   1855 			zerror(gettext("Boot argument list too long"));
   1856 			return (Z_ERR);
   1857 		}
   1858 		if (optind < argc - 1)
   1859 			if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
   1860 			    sizeof (zarg.bootbuf)) {
   1861 				zerror(gettext("Boot argument list too long"));
   1862 				return (Z_ERR);
   1863 			}
   1864 	}
   1865 
   1866 
   1867 	/*
   1868 	 * zoneadmd should be the one to decide whether or not to proceed,
   1869 	 * so even though it seems that the fourth parameter below should
   1870 	 * perhaps be B_TRUE, it really shouldn't be.
   1871 	 */
   1872 	if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE, B_FALSE)
   1873 	    != Z_OK)
   1874 		return (Z_ERR);
   1875 	if (verify_details(CMD_REBOOT, argv) != Z_OK)
   1876 		return (Z_ERR);
   1877 
   1878 	zarg.cmd = Z_REBOOT;
   1879 	return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) == 0)
   1880 	    ? Z_OK : Z_ERR);
   1881 }
   1882 
   1883 static int
   1884 get_hook(brand_handle_t bh, char *cmd, size_t len, int (*bp)(brand_handle_t,
   1885     const char *, const char *, char *, size_t), char *zonename, char *zonepath)
   1886 {
   1887 	if (strlcpy(cmd, EXEC_PREFIX, len) >= len)
   1888 		return (Z_ERR);
   1889 
   1890 	if (bp(bh, zonename, zonepath, cmd + EXEC_LEN, len - EXEC_LEN) != 0)
   1891 		return (Z_ERR);
   1892 
   1893 	if (strlen(cmd) <= EXEC_LEN)
   1894 		cmd[0] = '\0';
   1895 
   1896 	return (Z_OK);
   1897 }
   1898 
   1899 static int
   1900 verify_brand(zone_dochandle_t handle, int cmd_num, char *argv[])
   1901 {
   1902 	char cmdbuf[MAXPATHLEN];
   1903 	int err;
   1904 	char zonepath[MAXPATHLEN];
   1905 	brand_handle_t bh = NULL;
   1906 	int status, i;
   1907 
   1908 	/*
   1909 	 * Fetch the verify command from the brand configuration.
   1910 	 * "exec" the command so that the returned status is that of
   1911 	 * the command and not the shell.
   1912 	 */
   1913 	if (handle == NULL) {
   1914 		(void) strlcpy(zonepath, "-", sizeof (zonepath));
   1915 	} else if ((err = zonecfg_get_zonepath(handle, zonepath,
   1916 	    sizeof (zonepath))) != Z_OK) {
   1917 		errno = err;
   1918 		zperror(cmd_to_str(cmd_num), B_TRUE);
   1919 		return (Z_ERR);
   1920 	}
   1921 	if ((bh = brand_open(target_brand)) == NULL) {
   1922 		zerror(gettext("missing or invalid brand"));
   1923 		return (Z_ERR);
   1924 	}
   1925 
   1926 	/*
   1927 	 * If the brand has its own verification routine, execute it now.
   1928 	 * The verification routine validates the intended zoneadm
   1929 	 * operation for the specific brand. The zoneadm subcommand and
   1930 	 * all its arguments are passed to the routine.
   1931 	 */
   1932 	err = get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_verify_adm,
   1933 	    target_zone, zonepath);
   1934 	brand_close(bh);
   1935 	if (err != Z_OK)
   1936 		return (Z_BRAND_ERROR);
   1937 	if (cmdbuf[0] == '\0')
   1938 		return (Z_OK);
   1939 
   1940 	if (strlcat(cmdbuf, cmd_to_str(cmd_num),
   1941 	    sizeof (cmdbuf)) >= sizeof (cmdbuf))
   1942 		return (Z_ERR);
   1943 
   1944 	/* Build the argv string */
   1945 	i = 0;
   1946 	while (argv[i] != NULL) {
   1947 		if ((strlcat(cmdbuf, " ",
   1948 		    sizeof (cmdbuf)) >= sizeof (cmdbuf)) ||
   1949 		    (strlcat(cmdbuf, argv[i++],
   1950 		    sizeof (cmdbuf)) >= sizeof (cmdbuf)))
   1951 			return (Z_ERR);
   1952 	}
   1953 
   1954 	status = do_subproc(cmdbuf);
   1955 	err = subproc_status(gettext("brand-specific verification"),
   1956 	    status, B_FALSE);
   1957 
   1958 	return ((err == ZONE_SUBPROC_OK) ? Z_OK : Z_BRAND_ERROR);
   1959 }
   1960 
   1961 static int
   1962 verify_rctls(zone_dochandle_t handle)
   1963 {
   1964 	struct zone_rctltab rctltab;
   1965 	size_t rbs = rctlblk_size();
   1966 	rctlblk_t *rctlblk;
   1967 	int error = Z_INVAL;
   1968 
   1969 	if ((rctlblk = malloc(rbs)) == NULL) {
   1970 		zerror(gettext("failed to allocate %lu bytes: %s"), rbs,
   1971 		    strerror(errno));
   1972 		return (Z_NOMEM);
   1973 	}
   1974 
   1975 	if (zonecfg_setrctlent(handle) != Z_OK) {
   1976 		zerror(gettext("zonecfg_setrctlent failed"));
   1977 		free(rctlblk);
   1978 		return (error);
   1979 	}
   1980 
   1981 	rctltab.zone_rctl_valptr = NULL;
   1982 	while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
   1983 		struct zone_rctlvaltab *rctlval;
   1984 		const char *name = rctltab.zone_rctl_name;
   1985 
   1986 		if (!zonecfg_is_rctl(name)) {
   1987 			zerror(gettext("WARNING: Ignoring unrecognized rctl "
   1988 			    "'%s'."),  name);
   1989 			zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
   1990 			rctltab.zone_rctl_valptr = NULL;
   1991 			continue;
   1992 		}
   1993 
   1994 		for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL;
   1995 		    rctlval = rctlval->zone_rctlval_next) {
   1996 			if (zonecfg_construct_rctlblk(rctlval, rctlblk)
   1997 			    != Z_OK) {
   1998 				zerror(gettext("invalid rctl value: "
   1999 				    "(priv=%s,limit=%s,action%s)"),
   2000 				    rctlval->zone_rctlval_priv,
   2001 				    rctlval->zone_rctlval_limit,
   2002 				    rctlval->zone_rctlval_action);
   2003 				goto out;
   2004 			}
   2005 			if (!zonecfg_valid_rctl(name, rctlblk)) {
   2006 				zerror(gettext("(priv=%s,limit=%s,action=%s) "
   2007 				    "is not a valid value for rctl '%s'"),
   2008 				    rctlval->zone_rctlval_priv,
   2009 				    rctlval->zone_rctlval_limit,
   2010 				    rctlval->zone_rctlval_action,
   2011 				    name);
   2012 				goto out;
   2013 			}
   2014 		}
   2015 		zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
   2016 	}
   2017 	rctltab.zone_rctl_valptr = NULL;
   2018 	error = Z_OK;
   2019 out:
   2020 	zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
   2021 	(void) zonecfg_endrctlent(handle);
   2022 	free(rctlblk);
   2023 	return (error);
   2024 }
   2025 
   2026 static int
   2027 verify_pool(zone_dochandle_t handle)
   2028 {
   2029 	char poolname[MAXPATHLEN];
   2030 	pool_conf_t *poolconf;
   2031 	pool_t *pool;
   2032 	int status;
   2033 	int error;
   2034 
   2035 	/*
   2036 	 * This ends up being very similar to the check done in zoneadmd.
   2037 	 */
   2038 	error = zonecfg_get_pool(handle, poolname, sizeof (poolname));
   2039 	if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) {
   2040 		/*
   2041 		 * No pool specified.
   2042 		 */
   2043 		return (0);
   2044 	}
   2045 	if (error != Z_OK) {
   2046 		zperror(gettext("Unable to retrieve pool name from "
   2047 		    "configuration"), B_TRUE);
   2048 		return (error);
   2049 	}
   2050 	/*
   2051 	 * Don't do anything if pools aren't enabled.
   2052 	 */
   2053 	if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) {
   2054 		zerror(gettext("WARNING: pools facility not active; "
   2055 		    "zone will not be bound to pool '%s'."), poolname);
   2056 		return (Z_OK);
   2057 	}
   2058 	/*
   2059 	 * Try to provide a sane error message if the requested pool doesn't
   2060 	 * exist.  It isn't clear that pools-related failures should
   2061 	 * necessarily translate to a failure to verify the zone configuration,
   2062 	 * hence they are not considered errors.
   2063 	 */
   2064 	if ((poolconf = pool_conf_alloc()) == NULL) {
   2065 		zerror(gettext("WARNING: pool_conf_alloc failed; "
   2066 		    "using default pool"));
   2067 		return (Z_OK);
   2068 	}
   2069 	if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) !=
   2070 	    PO_SUCCESS) {
   2071 		zerror(gettext("WARNING: pool_conf_open failed; "
   2072 		    "using default pool"));
   2073 		pool_conf_free(poolconf);
   2074 		return (Z_OK);
   2075 	}
   2076 	pool = pool_get_pool(poolconf, poolname);
   2077 	(void) pool_conf_close(poolconf);
   2078 	pool_conf_free(poolconf);
   2079 	if (pool == NULL) {
   2080 		zerror(gettext("WARNING: pool '%s' not found. "
   2081 		    "using default pool"), poolname);
   2082 	}
   2083 
   2084 	return (Z_OK);
   2085 }
   2086 
   2087 /*
   2088  * Verify that the special device/file system exists and is valid.
   2089  */
   2090 static int
   2091 verify_fs_special(struct zone_fstab *fstab)
   2092 {
   2093 	struct stat64 st;
   2094 
   2095 	/*
   2096 	 * This validation is really intended for standard zone administration.
   2097 	 * If we are in a mini-root or some other upgrade situation where
   2098 	 * we are using the scratch zone, just by-pass this.
   2099 	 */
   2100 	if (zonecfg_in_alt_root())
   2101 		return (Z_OK);
   2102 
   2103 	if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0)
   2104 		return (verify_fs_zfs(fstab));
   2105 
   2106 	if (stat64(fstab->zone_fs_special, &st) != 0) {
   2107 		(void) fprintf(stderr, gettext("could not verify fs "
   2108 		    "%s: could not access %s: %s\n"), fstab->zone_fs_dir,
   2109 		    fstab->zone_fs_special, strerror(errno));
   2110 		return (Z_ERR);
   2111 	}
   2112 
   2113 	if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
   2114 		/*
   2115 		 * TRANSLATION_NOTE
   2116 		 * fs and NFS are literals that should
   2117 		 * not be translated.
   2118 		 */
   2119 		(void) fprintf(stderr, gettext("cannot verify "
   2120 		    "fs %s: NFS mounted file system.\n"
   2121 		    "\tA local file system must be used.\n"),
   2122 		    fstab->zone_fs_special);
   2123 		return (Z_ERR);
   2124 	}
   2125 
   2126 	return (Z_OK);
   2127 }
   2128 
   2129 static int
   2130 isregfile(const char *path)
   2131 {
   2132 	struct stat64 st;
   2133 
   2134 	if (stat64(path, &st) == -1)
   2135 		return (-1);
   2136 
   2137 	return (S_ISREG(st.st_mode));
   2138 }
   2139 
   2140 static int
   2141 verify_filesystems(zone_dochandle_t handle)
   2142 {
   2143 	int return_code = Z_OK;
   2144 	struct zone_fstab fstab;
   2145 	char cmdbuf[MAXPATHLEN];
   2146 	struct stat st;
   2147 
   2148 	/*
   2149 	 * Since the actual mount point is not known until the dependent mounts
   2150 	 * are performed, we don't attempt any path validation here: that will
   2151 	 * happen later when zoneadmd actually does the mounts.
   2152 	 */
   2153 	if (zonecfg_setfsent(handle) != Z_OK) {
   2154 		(void) fprintf(stderr, gettext("could not verify file systems: "
   2155 		    "unable to enumerate mounts\n"));
   2156 		return (Z_ERR);
   2157 	}
   2158 	while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
   2159 		if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) {
   2160 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
   2161 			    "type %s is not allowed.\n"), fstab.zone_fs_dir,
   2162 			    fstab.zone_fs_type);
   2163 			return_code = Z_ERR;
   2164 			goto next_fs;
   2165 		}
   2166 		/*
   2167 		 * Verify /usr/lib/fs/<fstype>/mount exists.
   2168 		 */
   2169 		if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount",
   2170 		    fstab.zone_fs_type) > sizeof (cmdbuf)) {
   2171 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
   2172 			    "type %s is too long.\n"), fstab.zone_fs_dir,
   2173 			    fstab.zone_fs_type);
   2174 			return_code = Z_ERR;
   2175 			goto next_fs;
   2176 		}
   2177 		if (stat(cmdbuf, &st) != 0) {
   2178 			(void) fprintf(stderr, gettext("could not verify fs "
   2179 			    "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
   2180 			    cmdbuf, strerror(errno));
   2181 			return_code = Z_ERR;
   2182 			goto next_fs;
   2183 		}
   2184 		if (!S_ISREG(st.st_mode)) {
   2185 			(void) fprintf(stderr, gettext("could not verify fs "
   2186 			    "%s: %s is not a regular file\n"),
   2187 			    fstab.zone_fs_dir, cmdbuf);
   2188 			return_code = Z_ERR;
   2189 			goto next_fs;
   2190 		}
   2191 		/*
   2192 		 * If zone_fs_raw is set, verify that there's an fsck
   2193 		 * binary for it.  If zone_fs_raw is not set, and it's
   2194 		 * not a regular file (lofi mount), and there's an fsck
   2195 		 * binary for it, complain.
   2196 		 */
   2197 		if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck",
   2198 		    fstab.zone_fs_type) > sizeof (cmdbuf)) {
   2199 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
   2200 			    "type %s is too long.\n"), fstab.zone_fs_dir,
   2201 			    fstab.zone_fs_type);
   2202 			return_code = Z_ERR;
   2203 			goto next_fs;
   2204 		}
   2205 		if (fstab.zone_fs_raw[0] != '\0' &&
   2206 		    (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) {
   2207 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
   2208 			    "'raw' device specified but "
   2209 			    "no fsck executable exists for %s\n"),
   2210 			    fstab.zone_fs_dir, fstab.zone_fs_type);
   2211 			return_code = Z_ERR;
   2212 			goto next_fs;
   2213 		} else if (fstab.zone_fs_raw[0] == '\0' &&
   2214 		    stat(cmdbuf, &st) == 0 &&
   2215 		    isregfile(fstab.zone_fs_special) != 1) {
   2216 			(void) fprintf(stderr, gettext("could not verify fs "
   2217 			    "%s: must specify 'raw' device for %s "
   2218 			    "file systems\n"),
   2219 			    fstab.zone_fs_dir, fstab.zone_fs_type);
   2220 			return_code = Z_ERR;
   2221 			goto next_fs;
   2222 		}
   2223 
   2224 		/* Verify fs_special. */
   2225 		if ((return_code = verify_fs_special(&fstab)) != Z_OK)
   2226 			goto next_fs;
   2227 
   2228 		/* Verify fs_raw. */
   2229 		if (fstab.zone_fs_raw[0] != '\0' &&
   2230 		    stat(fstab.zone_fs_raw, &st) != 0) {
   2231 			/*
   2232 			 * TRANSLATION_NOTE
   2233 			 * fs is a literal that should not be translated.
   2234 			 */
   2235 			(void) fprintf(stderr, gettext("could not verify fs "
   2236 			    "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
   2237 			    fstab.zone_fs_raw, strerror(errno));
   2238 			return_code = Z_ERR;
   2239 			goto next_fs;
   2240 		}
   2241 next_fs:
   2242 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
   2243 	}
   2244 	(void) zonecfg_endfsent(handle);
   2245 
   2246 	return (return_code);
   2247 }
   2248 
   2249 static int
   2250 verify_limitpriv(zone_dochandle_t handle)
   2251 {
   2252 	char *privname = NULL;
   2253 	int err;
   2254 	priv_set_t *privs;
   2255 
   2256 	if ((privs = priv_allocset()) == NULL) {
   2257 		zperror(gettext("failed to allocate privilege set"), B_FALSE);
   2258 		return (Z_NOMEM);
   2259 	}
   2260 	err = zonecfg_get_privset(handle, privs, &privname);
   2261 	switch (err) {
   2262 	case Z_OK:
   2263 		break;
   2264 	case Z_PRIV_PROHIBITED:
   2265 		(void) fprintf(stderr, gettext("privilege \"%s\" is not "
   2266 		    "permitted within the zone's privilege set\n"), privname);
   2267 		break;
   2268 	case Z_PRIV_REQUIRED:
   2269 		(void) fprintf(stderr, gettext("required privilege \"%s\" is "
   2270 		    "missing from the zone's privilege set\n"), privname);
   2271 		break;
   2272 	case Z_PRIV_UNKNOWN:
   2273 		(void) fprintf(stderr, gettext("unknown privilege \"%s\" "
   2274 		    "specified in the zone's privilege set\n"), privname);
   2275 		break;
   2276 	default:
   2277 		zperror(
   2278 		    gettext("failed to determine the zone's privilege set"),
   2279 		    B_TRUE);
   2280 		break;
   2281 	}
   2282 	free(privname);
   2283 	priv_freeset(privs);
   2284 	return (err);
   2285 }
   2286 
   2287 static void
   2288 free_local_netifs(int if_cnt, struct net_if **if_list)
   2289 {
   2290 	int		i;
   2291 
   2292 	for (i = 0; i < if_cnt; i++) {
   2293 		free(if_list[i]->name);
   2294 		free(if_list[i]);
   2295 	}
   2296 	free(if_list);
   2297 }
   2298 
   2299 /*
   2300  * Get a list of the network interfaces, along with their address families,
   2301  * that are plumbed in the global zone.  See if_tcp(7p) for a description
   2302  * of the ioctls used here.
   2303  */
   2304 static int
   2305 get_local_netifs(int *if_cnt, struct net_if ***if_list)
   2306 {
   2307 	int		s;
   2308 	int		i;
   2309 	int		res = Z_OK;
   2310 	int		space_needed;
   2311 	int		cnt = 0;
   2312 	struct		lifnum if_num;
   2313 	struct		lifconf if_conf;
   2314 	struct		lifreq *if_reqp;
   2315 	char		*if_buf;
   2316 	struct net_if	**local_ifs = NULL;
   2317 
   2318 	*if_cnt = 0;
   2319 	*if_list = NULL;
   2320 
   2321 	if ((s = socket(SOCKET_AF(AF_INET), SOCK_DGRAM, 0)) < 0)
   2322 		return (Z_ERR);
   2323 
   2324 	/*
   2325 	 * Come back here in the unlikely event that the number of interfaces
   2326 	 * increases between the time we get the count and the time we do the
   2327 	 * SIOCGLIFCONF ioctl.
   2328 	 */
   2329 retry:
   2330 	/* Get the number of interfaces. */
   2331 	if_num.lifn_family = AF_UNSPEC;
   2332 	if_num.lifn_flags = LIFC_NOXMIT;
   2333 	if (ioctl(s, SIOCGLIFNUM, &if_num) < 0) {
   2334 		(void) close(s);
   2335 		return (Z_ERR);
   2336 	}
   2337 
   2338 	/* Get the interface configuration list. */
   2339 	space_needed = if_num.lifn_count * sizeof (struct lifreq);
   2340 	if ((if_buf = malloc(space_needed)) == NULL) {
   2341 		(void) close(s);
   2342 		return (Z_ERR);
   2343 	}
   2344 	if_conf.lifc_family = AF_UNSPEC;
   2345 	if_conf.lifc_flags = LIFC_NOXMIT;
   2346 	if_conf.lifc_len = space_needed;
   2347 	if_conf.lifc_buf = if_buf;
   2348 	if (ioctl(s, SIOCGLIFCONF, &if_conf) < 0) {
   2349 		free(if_buf);
   2350 		/*
   2351 		 * SIOCGLIFCONF returns EINVAL if the buffer we passed in is
   2352 		 * too small.  In this case go back and get the new if cnt.
   2353 		 */
   2354 		if (errno == EINVAL)
   2355 			goto retry;
   2356 
   2357 		(void) close(s);
   2358 		return (Z_ERR);
   2359 	}
   2360 	(void) close(s);
   2361 
   2362 	/* Get the name and address family for each interface. */
   2363 	if_reqp = if_conf.lifc_req;
   2364 	for (i = 0; i < (if_conf.lifc_len / sizeof (struct lifreq)); i++) {
   2365 		struct net_if	**p;
   2366 		struct lifreq	req;
   2367 
   2368 		if (strcmp(LOOPBACK_IF, if_reqp->lifr_name) == 0) {
   2369 			if_reqp++;
   2370 			continue;
   2371 		}
   2372 
   2373 		if ((s = socket(SOCKET_AF(if_reqp->lifr_addr.ss_family),
   2374 		    SOCK_DGRAM, 0)) == -1) {
   2375 			res = Z_ERR;
   2376 			break;
   2377 		}
   2378 
   2379 		(void) strncpy(req.lifr_name, if_reqp->lifr_name,
   2380 		    sizeof (req.lifr_name));
   2381 		if (ioctl(s, SIOCGLIFADDR, &req) < 0) {
   2382 			(void) close(s);
   2383 			if_reqp++;
   2384 			continue;
   2385 		}
   2386 
   2387 		if ((p = (struct net_if **)realloc(local_ifs,
   2388 		    sizeof (struct net_if *) * (cnt + 1))) == NULL) {
   2389 			res = Z_ERR;
   2390 			break;
   2391 		}
   2392 		local_ifs = p;
   2393 
   2394 		if ((local_ifs[cnt] = malloc(sizeof (struct net_if))) == NULL) {
   2395 			res = Z_ERR;
   2396 			break;
   2397 		}
   2398 
   2399 		if ((local_ifs[cnt]->name = strdup(if_reqp->lifr_name))
   2400 		    == NULL) {
   2401 			free(local_ifs[cnt]);
   2402 			res = Z_ERR;
   2403 			break;
   2404 		}
   2405 		local_ifs[cnt]->af = req.lifr_addr.ss_family;
   2406 		cnt++;
   2407 
   2408 		(void) close(s);
   2409 		if_reqp++;
   2410 	}
   2411 
   2412 	free(if_buf);
   2413 
   2414 	if (res != Z_OK) {
   2415 		free_local_netifs(cnt, local_ifs);
   2416 	} else {
   2417 		*if_cnt = cnt;
   2418 		*if_list = local_ifs;
   2419 	}
   2420 
   2421 	return (res);
   2422 }
   2423 
   2424 static char *
   2425 af2str(int af)
   2426 {
   2427 	switch (af) {
   2428 	case AF_INET:
   2429 		return ("IPv4");
   2430 	case AF_INET6:
   2431 		return ("IPv6");
   2432 	default:
   2433 		return ("Unknown");
   2434 	}
   2435 }
   2436 
   2437 /*
   2438  * Cross check the network interface name and address family with the
   2439  * interfaces that are set up in the global zone so that we can print the
   2440  * appropriate error message.
   2441  */
   2442 static void
   2443 print_net_err(char *phys, char *addr, int af, char *msg)
   2444 {
   2445 	int		i;
   2446 	int		local_if_cnt = 0;
   2447 	struct net_if	**local_ifs = NULL;
   2448 	boolean_t	found_if = B_FALSE;
   2449 	boolean_t	found_af = B_FALSE;
   2450 
   2451 	if (get_local_netifs(&local_if_cnt, &local_ifs) != Z_OK) {
   2452 		(void) fprintf(stderr,
   2453 		    gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
   2454 		    "net", "address", addr, "physical", phys, msg);
   2455 		return;
   2456 	}
   2457 
   2458 	for (i = 0; i < local_if_cnt; i++) {
   2459 		if (strcmp(phys, local_ifs[i]->name) == 0) {
   2460 			found_if = B_TRUE;
   2461 			if (af == local_ifs[i]->af) {
   2462 				found_af = B_TRUE;
   2463 				break;
   2464 			}
   2465 		}
   2466 	}
   2467 
   2468 	free_local_netifs(local_if_cnt, local_ifs);
   2469 
   2470 	if (!found_if) {
   2471 		(void) fprintf(stderr,
   2472 		    gettext("could not verify %s %s=%s\n\t"
   2473 		    "network interface %s is not plumbed in the global zone\n"),
   2474 		    "net", "physical", phys, phys);
   2475 		return;
   2476 	}
   2477 
   2478 	/*
   2479 	 * Print this error if we were unable to find the address family
   2480 	 * for this interface.  If the af variable is not initialized to
   2481 	 * to something meaningful by the caller (not AF_UNSPEC) then we
   2482 	 * also skip this message since it wouldn't be informative.
   2483 	 */
   2484 	if (!found_af && af != AF_UNSPEC) {
   2485 		(void) fprintf(stderr,
   2486 		    gettext("could not verify %s %s=%s %s=%s\n\tthe %s address "
   2487 		    "family is not configured on this network interface in "
   2488 		    "the\n\tglobal zone\n"),
   2489 		    "net", "address", addr, "physical", phys, af2str(af));
   2490 		return;
   2491 	}
   2492 
   2493 	(void) fprintf(stderr,
   2494 	    gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
   2495 	    "net", "address", addr, "physical", phys, msg);
   2496 }
   2497 
   2498 static int
   2499 verify_handle(int cmd_num, zone_dochandle_t handle, char *argv[])
   2500 {
   2501 	struct zone_nwiftab nwiftab;
   2502 	int return_code = Z_OK;
   2503 	int err;
   2504 	boolean_t in_alt_root;
   2505 	zone_iptype_t iptype;
   2506 	dladm_handle_t dh;
   2507 	dladm_status_t status;
   2508 	datalink_id_t linkid;
   2509 	char errmsg[DLADM_STRSIZE];
   2510 
   2511 	in_alt_root = zonecfg_in_alt_root();
   2512 	if (in_alt_root)
   2513 		goto no_net;
   2514 
   2515 	if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK) {
   2516 		errno = err;
   2517 		zperror(cmd_to_str(cmd_num), B_TRUE);
   2518 		zonecfg_fini_handle(handle);
   2519 		return (Z_ERR);
   2520 	}
   2521 	if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
   2522 		errno = err;
   2523 		zperror(cmd_to_str(cmd_num), B_TRUE);
   2524 		zonecfg_fini_handle(handle);
   2525 		return (Z_ERR);
   2526 	}
   2527 	while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
   2528 		struct lifreq lifr;
   2529 		sa_family_t af = AF_UNSPEC;
   2530 		char dl_owner_zname[ZONENAME_MAX];
   2531 		zoneid_t dl_owner_zid;
   2532 		zoneid_t target_zid;
   2533 		int res;
   2534 
   2535 		/* skip any loopback interfaces */
   2536 		if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0)
   2537 			continue;
   2538 		switch (iptype) {
   2539 		case ZS_SHARED:
   2540 			if ((res = zonecfg_valid_net_address(
   2541 			    nwiftab.zone_nwif_address, &lifr)) != Z_OK) {
   2542 				print_net_err(nwiftab.zone_nwif_physical,
   2543 				    nwiftab.zone_nwif_address, af,
   2544 				    zonecfg_strerror(res));
   2545 				return_code = Z_ERR;
   2546 				continue;
   2547 			}
   2548 			af = lifr.lifr_addr.ss_family;
   2549 			if (!zonecfg_ifname_exists(af,
   2550 			    nwiftab.zone_nwif_physical)) {
   2551 				/*
   2552 				 * The interface failed to come up. We continue
   2553 				 * on anyway for the sake of consistency: a
   2554 				 * zone is not shut down if the interface fails
   2555 				 * any time after boot, nor does the global zone
   2556 				 * fail to boot if an interface fails.
   2557 				 */
   2558 				(void) fprintf(stderr,
   2559 				    gettext("WARNING: skipping network "
   2560 				    "interface '%s' which may not be "
   2561 				    "present/plumbed in the global "
   2562 				    "zone.\n"),
   2563 				    nwiftab.zone_nwif_physical);
   2564 			}
   2565 			break;
   2566 		case ZS_EXCLUSIVE:
   2567 			/* Warning if it exists for either IPv4 or IPv6 */
   2568 
   2569 			if (zonecfg_ifname_exists(AF_INET,
   2570 			    nwiftab.zone_nwif_physical) ||
   2571 			    zonecfg_ifname_exists(AF_INET6,
   2572 			    nwiftab.zone_nwif_physical)) {
   2573 				(void) fprintf(stderr,
   2574 				    gettext("WARNING: skipping network "
   2575 				    "interface '%s' which is used in the "
   2576 				    "global zone.\n"),
   2577 				    nwiftab.zone_nwif_physical);
   2578 				break;
   2579 			}
   2580 
   2581 			/*
   2582 			 * Verify that the datalink exists and that it isn't
   2583 			 * already assigned to a zone.
   2584 			 */
   2585 			if ((status = dladm_open(&dh)) == DLADM_STATUS_OK) {
   2586 				status = dladm_name2info(dh,
   2587 				    nwiftab.zone_nwif_physical, &linkid, NULL,
   2588 				    NULL, NULL);
   2589 				dladm_close(dh);
   2590 			}
   2591 			if (status != DLADM_STATUS_OK) {
   2592 				(void) fprintf(stderr,
   2593 				    gettext("WARNING: skipping network "
   2594 				    "interface '%s': %s\n"),
   2595 				    nwiftab.zone_nwif_physical,
   2596 				    dladm_status2str(status, errmsg));
   2597 				break;
   2598 			}
   2599 			dl_owner_zid = ALL_ZONES;
   2600 			if (zone_check_datalink(&dl_owner_zid, linkid) != 0)
   2601 				break;
   2602 
   2603 			/*
   2604 			 * If the zone being verified is
   2605 			 * running and owns the interface
   2606 			 */
   2607 			target_zid = getzoneidbyname(target_zone);
   2608 			if (target_zid == dl_owner_zid)
   2609 				break;
   2610 
   2611 			/* Zone id match failed, use name to check */
   2612 			if (getzonenamebyid(dl_owner_zid, dl_owner_zname,
   2613 			    ZONENAME_MAX) < 0) {
   2614 				/* No name, show ID instead */
   2615 				(void) snprintf(dl_owner_zname, ZONENAME_MAX,
   2616 				    "<%d>", dl_owner_zid);
   2617 			} else if (strcmp(dl_owner_zname, target_zone) == 0)
   2618 				break;
   2619 
   2620 			/*
   2621 			 * Note here we only report a warning that
   2622 			 * the interface is already in use by another
   2623 			 * running zone, and the verify process just
   2624 			 * goes on, if the interface is still in use
   2625 			 * when this zone really boots up, zoneadmd
   2626 			 * will find it. If the name of the zone which
   2627 			 * owns this interface cannot be determined,
   2628 			 * then it is not possible to determine if there
   2629 			 * is a conflict so just report it as a warning.
   2630 			 */
   2631 			(void) fprintf(stderr,
   2632 			    gettext("WARNING: skipping network interface "
   2633 			    "'%s' which is used by the non-global zone "
   2634 			    "'%s'.\n"), nwiftab.zone_nwif_physical,
   2635 			    dl_owner_zname);
   2636 			break;
   2637 		}
   2638 	}
   2639 	(void) zonecfg_endnwifent(handle);
   2640 no_net:
   2641 
   2642 	/* verify that lofs has not been excluded from the kernel */
   2643 	if (!(cmd_num == CMD_DETACH || cmd_num == CMD_ATTACH ||
   2644 	    cmd_num == CMD_MOVE || cmd_num == CMD_CLONE) &&
   2645 	    modctl(MODLOAD, 1, "fs/lofs", NULL) != 0) {
   2646 		if (errno == ENXIO)
   2647 			(void) fprintf(stderr, gettext("could not verify "
   2648 			    "lofs(7FS): possibly excluded in /etc/system\n"));
   2649 		else
   2650 			(void) fprintf(stderr, gettext("could not verify "
   2651 			    "lofs(7FS): %s\n"), strerror(errno));
   2652 		return_code = Z_ERR;
   2653 	}
   2654 
   2655 	if (verify_filesystems(handle) != Z_OK)
   2656 		return_code = Z_ERR;
   2657 	if (!in_alt_root && verify_rctls(handle) != Z_OK)
   2658 		return_code = Z_ERR;
   2659 	if (!in_alt_root && verify_pool(handle) != Z_OK)
   2660 		return_code = Z_ERR;
   2661 	if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK)
   2662 		return_code = Z_ERR;
   2663 	if (!in_alt_root && verify_datasets(handle) != Z_OK)
   2664 		return_code = Z_ERR;
   2665 
   2666 	/*
   2667 	 * As the "mount" command is used for patching/upgrading of zones
   2668 	 * or other maintenance processes, the zone's privilege set is not
   2669 	 * checked in this case.  Instead, the default, safe set of
   2670 	 * privileges will be used when this zone is created in the
   2671 	 * kernel.
   2672 	 */
   2673 	if (!in_alt_root && cmd_num != CMD_MOUNT &&
   2674 	    verify_limitpriv(handle) != Z_OK)
   2675 		return_code = Z_ERR;
   2676 
   2677 	return (return_code);
   2678 }
   2679 
   2680 static int
   2681 verify_details(int cmd_num, char *argv[])
   2682 {
   2683 	zone_dochandle_t handle;
   2684 	char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
   2685 	int return_code = Z_OK;
   2686 	int err;
   2687 
   2688 	if ((handle = zonecfg_init_handle()) == NULL) {
   2689 		zperror(cmd_to_str(cmd_num), B_TRUE);
   2690 		return (Z_ERR);
   2691 	}
   2692 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
   2693 		errno = err;
   2694 		zperror(cmd_to_str(cmd_num), B_TRUE);
   2695 		zonecfg_fini_handle(handle);
   2696 		return (Z_ERR);
   2697 	}
   2698 	if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
   2699 	    Z_OK) {
   2700 		errno = err;
   2701 		zperror(cmd_to_str(cmd_num), B_TRUE);
   2702 		zonecfg_fini_handle(handle);
   2703 		return (Z_ERR);
   2704 	}
   2705 	/*
   2706 	 * zonecfg_get_zonepath() gets its data from the XML repository.
   2707 	 * Verify this against the index file, which is checked first by
   2708 	 * zone_get_zonepath().  If they don't match, bail out.
   2709 	 */
   2710 	if ((err = zone_get_zonepath(target_zone, checkpath,
   2711 	    sizeof (checkpath))) != Z_OK) {
   2712 		errno = err;
   2713 		zperror2(target_zone, gettext("could not get zone path"));
   2714 		zonecfg_fini_handle(handle);
   2715 		return (Z_ERR);
   2716 	}
   2717 	if (strcmp(zonepath, checkpath) != 0) {
   2718 		/*
   2719 		 * TRANSLATION_NOTE
   2720 		 * XML and zonepath are literals that should not be translated.
   2721 		 */
   2722 		(void) fprintf(stderr, gettext("The XML repository has "
   2723 		    "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
   2724 		    "These must match, so fix the incorrect entry.\n"),
   2725 		    zonepath, checkpath);
   2726 		zonecfg_fini_handle(handle);
   2727 		return (Z_ERR);
   2728 	}
   2729 	if (cmd_num != CMD_ATTACH &&
   2730 	    validate_zonepath(zonepath, cmd_num) != Z_OK) {
   2731 		(void) fprintf(stderr, gettext("could not verify zonepath %s "
   2732 		    "because of the above errors.\n"), zonepath);
   2733 		return_code = Z_ERR;
   2734 	}
   2735 
   2736 	if (verify_handle(cmd_num, handle, argv) != Z_OK)
   2737 		return_code = Z_ERR;
   2738 
   2739 	zonecfg_fini_handle(handle);
   2740 	if (return_code == Z_ERR)
   2741 		(void) fprintf(stderr,
   2742 		    gettext("%s: zone %s failed to verify\n"),
   2743 		    execname, target_zone);
   2744 	return (return_code);
   2745 }
   2746 
   2747 static int
   2748 verify_func(int argc, char *argv[])
   2749 {
   2750 	int arg;
   2751 
   2752 	optind = 0;
   2753 	if ((arg = getopt(argc, argv, "?")) != EOF) {
   2754 		switch (arg) {
   2755 		case '?':
   2756 			sub_usage(SHELP_VERIFY, CMD_VERIFY);
   2757 			return (optopt == '?' ? Z_OK : Z_USAGE);
   2758 		default:
   2759 			sub_usage(SHELP_VERIFY, CMD_VERIFY);
   2760 			return (Z_USAGE);
   2761 		}
   2762 	}
   2763 	if (argc > optind) {
   2764 		sub_usage(SHELP_VERIFY, CMD_VERIFY);
   2765 		return (Z_USAGE);
   2766 	}
   2767 	if (sanity_check(target_zone, CMD_VERIFY, B_FALSE, B_FALSE, B_FALSE)
   2768 	    != Z_OK)
   2769 		return (Z_ERR);
   2770 	return (verify_details(CMD_VERIFY, argv));
   2771 }
   2772 
   2773 static int
   2774 addoptions(char *buf, char *argv[], size_t len)
   2775 {
   2776 	int i = 0;
   2777 
   2778 	if (buf[0] == '\0')
   2779 		return (Z_OK);
   2780 
   2781 	while (argv[i] != NULL) {
   2782 		if (strlcat(buf, " ", len) >= len ||
   2783 		    strlcat(buf, argv[i++], len) >= len) {
   2784 			zerror("Command line too long");
   2785 			return (Z_ERR);
   2786 		}
   2787 	}
   2788 
   2789 	return (Z_OK);
   2790 }
   2791 
   2792 static int
   2793 addopt(char *buf, int opt, char *optarg, size_t bufsize)
   2794 {
   2795 	char optstring[4];
   2796 
   2797 	if (opt > 0)
   2798 		(void) sprintf(optstring, " -%c", opt);
   2799 	else
   2800 		(void) strcpy(optstring, " ");
   2801 
   2802 	if ((strlcat(buf, optstring, bufsize) > bufsize))
   2803 		return (Z_ERR);
   2804 
   2805 	if ((optarg != NULL) && (strlcat(buf, optarg, bufsize) > bufsize))
   2806 		return (Z_ERR);
   2807 
   2808 	return (Z_OK);
   2809 }
   2810 
   2811 /* ARGSUSED */
   2812 static int
   2813 install_func(int argc, char *argv[])
   2814 {
   2815 	char cmdbuf[MAXPATHLEN];
   2816 	char postcmdbuf[MAXPATHLEN];
   2817 	int lockfd;
   2818 	int arg, err, subproc_err;
   2819 	char zonepath[MAXPATHLEN];
   2820 	brand_handle_t bh = NULL;
   2821 	int status;
   2822 	boolean_t do_postinstall = B_FALSE;
   2823 	boolean_t brand_help = B_FALSE;
   2824 	char opts[128];
   2825 
   2826 	if (target_zone == NULL) {
   2827 		sub_usage(SHELP_INSTALL, CMD_INSTALL);
   2828 		return (Z_USAGE);
   2829 	}
   2830 
   2831 	if (zonecfg_in_alt_root()) {
   2832 		zerror(gettext("cannot install zone in alternate root"));
   2833 		return (Z_ERR);
   2834 	}
   2835 
   2836 	if ((err = zone_get_zonepath(target_zone, zonepath,
   2837 	    sizeof (zonepath))) != Z_OK) {
   2838 		errno = err;
   2839 		zperror2(target_zone, gettext("could not get zone path"));
   2840 		return (Z_ERR);
   2841 	}
   2842 
   2843 	/* Fetch the install command from the brand configuration.  */
   2844 	if ((bh = brand_open(target_brand)) == NULL) {
   2845 		zerror(gettext("missing or invalid brand"));
   2846 		return (Z_ERR);
   2847 	}
   2848 
   2849 	if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_install,
   2850 	    target_zone, zonepath) != Z_OK) {
   2851 		zerror("invalid brand configuration: missing install resource");
   2852 		brand_close(bh);
   2853 		return (Z_ERR);
   2854 	}
   2855 
   2856 	if (get_hook(bh, postcmdbuf, sizeof (postcmdbuf), brand_get_postinstall,
   2857 	    target_zone, zonepath) != Z_OK) {
   2858 		zerror("invalid brand configuration: missing postinstall "
   2859 		    "resource");
   2860 		brand_close(bh);
   2861 		return (Z_ERR);
   2862 	}
   2863 
   2864 	if (postcmdbuf[0] != '\0')
   2865 		do_postinstall = B_TRUE;
   2866 
   2867 	(void) strcpy(opts, "?x:");
   2868 	/*
   2869 	 * Fetch the list of recognized command-line options from
   2870 	 * the brand configuration file.
   2871 	 */
   2872 	if (brand_get_installopts(bh, opts + strlen(opts),
   2873 	    sizeof (opts) - strlen(opts)) != 0) {
   2874 		zerror("invalid brand configuration: missing "
   2875 		    "install options resource");
   2876 		brand_close(bh);
   2877 		return (Z_ERR);
   2878 	}
   2879 
   2880 	brand_close(bh);
   2881 
   2882 	if (cmdbuf[0] == '\0') {
   2883 		zerror("Missing brand install command");
   2884 		return (Z_ERR);
   2885 	}
   2886 
   2887 	/* Check the argv string for args we handle internally */
   2888 	optind = 0;
   2889 	opterr = 0;
   2890 	while ((arg = getopt(argc, argv, opts)) != EOF) {
   2891 		switch (arg) {
   2892 		case '?':
   2893 			if (optopt == '?') {
   2894 				sub_usage(SHELP_INSTALL, CMD_INSTALL);
   2895 				brand_help = B_TRUE;
   2896 			}
   2897 			/* Ignore unknown options - may be brand specific. */
   2898 			break;
   2899 		default:
   2900 			/* Ignore unknown options - may be brand specific. */
   2901 			break;
   2902 		}
   2903 
   2904 		/*
   2905 		 * Append the option to the command line passed to the
   2906 		 * brand-specific install and postinstall routines.
   2907 		 */
   2908 		if (addopt(cmdbuf, optopt, optarg, sizeof (cmdbuf)) != Z_OK) {
   2909 			zerror("Install command line too long");
   2910 			return (Z_ERR);
   2911 		}
   2912 		if (addopt(postcmdbuf, optopt, optarg, sizeof (postcmdbuf))
   2913 		    != Z_OK) {
   2914 			zerror("Post-Install command line too long");
   2915 			return (Z_ERR);
   2916 		}
   2917 	}
   2918 
   2919 	for (; optind < argc; optind++) {
   2920 		if (addopt(cmdbuf, 0, argv[optind], sizeof (cmdbuf)) != Z_OK) {
   2921 			zerror("Install command line too long");
   2922 			return (Z_ERR);
   2923 		}
   2924 
   2925 		if (addopt(postcmdbuf, 0, argv[optind], sizeof (postcmdbuf))
   2926 		    != Z_OK) {
   2927 			zerror("Post-Install command line too long");
   2928 			return (Z_ERR);
   2929 		}
   2930 	}
   2931 
   2932 	if (!brand_help) {
   2933 		if (sanity_check(target_zone, CMD_INSTALL, B_FALSE, B_TRUE,
   2934 		    B_FALSE) != Z_OK)
   2935 			return (Z_ERR);
   2936 		if (verify_details(CMD_INSTALL, argv) != Z_OK)
   2937 			return (Z_ERR);
   2938 
   2939 		if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
   2940 			zerror(gettext("another %s may have an operation in "
   2941 			    "progress."), "zoneadm");
   2942 			return (Z_ERR);
   2943 		}
   2944 		err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
   2945 		if (err != Z_OK) {
   2946 			errno = err;
   2947 			zperror2(target_zone, gettext("could not set state"));
   2948 			goto done;
   2949 		}
   2950 
   2951 		create_zfs_zonepath(zonepath);
   2952 	}
   2953 
   2954 	status = do_subproc(cmdbuf);
   2955 	if ((subproc_err =
   2956 	    subproc_status(gettext("brand-specific installation"), status,
   2957 	    B_FALSE)) != ZONE_SUBPROC_OK) {
   2958 		if (subproc_err == ZONE_SUBPROC_USAGE && !brand_help) {
   2959 			sub_usage(SHELP_INSTALL, CMD_INSTALL);
   2960 			zonecfg_release_lock_file(target_zone, lockfd);
   2961 			return (Z_ERR);
   2962 		}
   2963 		errno = subproc_err;
   2964 		err = Z_ERR;
   2965 		goto done;
   2966 	}
   2967 
   2968 	if (brand_help)
   2969 		return (Z_OK);
   2970 
   2971 	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
   2972 		errno = err;
   2973 		zperror2(target_zone, gettext("could not set state"));
   2974 		goto done;
   2975 	}
   2976 
   2977 	if (do_postinstall) {
   2978 		status = do_subproc(postcmdbuf);
   2979 
   2980 		if ((subproc_err =
   2981 		    subproc_status(gettext("brand-specific post-install"),
   2982 		    status, B_FALSE)) != ZONE_SUBPROC_OK) {
   2983 			errno = subproc_err;
   2984 			err = Z_ERR;
   2985 			(void) zone_set_state(target_zone,
   2986 			    ZONE_STATE_INCOMPLETE);
   2987 		}
   2988 	}
   2989 
   2990 done:
   2991 	/*
   2992 	 * If the install script exited with ZONE_SUBPROC_NOTCOMPLETE, try to
   2993 	 * clean up the zone and leave the zone in the CONFIGURED state so that
   2994 	 * another install can be attempted without requiring an uninstall
   2995 	 * first.
   2996 	 */
   2997 	if (subproc_err == ZONE_SUBPROC_NOTCOMPLETE) {
   2998 		int temp_err;
   2999 
   3000 		if ((temp_err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) {
   3001 			errno = err = temp_err;
   3002 			zperror2(target_zone,
   3003 			    gettext("cleaning up zonepath failed"));
   3004 		} else if ((temp_err = zone_set_state(target_zone,
   3005 		    ZONE_STATE_CONFIGURED)) != Z_OK) {
   3006 			errno = err = temp_err;
   3007 			zperror2(target_zone, gettext("could not set state"));
   3008 		}
   3009 	}
   3010 
   3011 	if (!brand_help)
   3012 		zonecfg_release_lock_file(target_zone, lockfd);
   3013 	return ((err == Z_OK) ? Z_OK : Z_ERR);
   3014 }
   3015 
   3016 static void
   3017 warn_dev_match(zone_dochandle_t s_handle, char *source_zone,
   3018 	zone_dochandle_t t_handle, char *target_zone)
   3019 {
   3020 	int err;
   3021 	struct zone_devtab s_devtab;
   3022 	struct zone_devtab t_devtab;
   3023 
   3024 	if ((err = zonecfg_setdevent(t_handle)) != Z_OK) {
   3025 		errno = err;
   3026 		zperror2(target_zone, gettext("could not enumerate devices"));
   3027 		return;
   3028 	}
   3029 
   3030 	while (zonecfg_getdevent(t_handle, &t_devtab) == Z_OK) {
   3031 		if ((err = zonecfg_setdevent(s_handle)) != Z_OK) {
   3032 			errno = err;
   3033 			zperror2(source_zone,
   3034 			    gettext("could not enumerate devices"));
   3035 			(void) zonecfg_enddevent(t_handle);
   3036 			return;
   3037 		}
   3038 
   3039 		while (zonecfg_getdevent(s_handle, &s_devtab) == Z_OK) {
   3040 			/*
   3041 			 * Use fnmatch to catch the case where wildcards
   3042 			 * were used in one zone and the other has an
   3043 			 * explicit entry (e.g. /dev/dsk/c0t0d0s6 vs.
   3044 			 * /dev/\*dsk/c0t0d0s6).
   3045 			 */
   3046 			if (fnmatch(t_devtab.zone_dev_match,
   3047 			    s_devtab.zone_dev_match, FNM_PATHNAME) == 0 ||
   3048 			    fnmatch(s_devtab.zone_dev_match,
   3049 			    t_devtab.zone_dev_match, FNM_PATHNAME) == 0) {
   3050 				(void) fprintf(stderr,
   3051 				    gettext("WARNING: device '%s' "
   3052 				    "is configured in both zones.\n"),
   3053 				    t_devtab.zone_dev_match);
   3054 				break;
   3055 			}
   3056 		}
   3057 		(void) zonecfg_enddevent(s_handle);
   3058 	}
   3059 
   3060 	(void) zonecfg_enddevent(t_handle);
   3061 }
   3062 
   3063 /*
   3064  * Check if the specified mount option (opt) is contained within the
   3065  * options string.
   3066  */
   3067 static boolean_t
   3068 opt_match(char *opt, char *options)
   3069 {
   3070 	char *p;
   3071 	char *lastp;
   3072 
   3073 	if ((p = strtok_r(options, ",", &lastp)) != NULL) {
   3074 		if (strcmp(p, opt) == 0)
   3075 			return (B_TRUE);
   3076 		while ((p = strtok_r(NULL, ",", &lastp)) != NULL) {
   3077 			if (strcmp(p, opt) == 0)
   3078 				return (B_TRUE);
   3079 		}
   3080 	}
   3081 
   3082 	return (B_FALSE);
   3083 }
   3084 
   3085 #define	RW_LOFS	"WARNING: read-write lofs file system on '%s' is configured " \
   3086 	"in both zones.\n"
   3087 
   3088 static void
   3089 print_fs_warnings(struct zone_fstab *s_fstab, struct zone_fstab *t_fstab)
   3090 {
   3091 	/*
   3092 	 * It is ok to have shared lofs mounted fs but we want to warn if
   3093 	 * either is rw since this will effect the other zone.
   3094 	 */
   3095 	if (strcmp(t_fstab->zone_fs_type, "lofs") == 0) {
   3096 		zone_fsopt_t *optp;
   3097 
   3098 		/* The default is rw so no options means rw */
   3099 		if (t_fstab->zone_fs_options == NULL ||
   3100 		    s_fstab->zone_fs_options == NULL) {
   3101 			(void) fprintf(stderr, gettext(RW_LOFS),
   3102 			    t_fstab->zone_fs_special);
   3103 			return;
   3104 		}
   3105 
   3106 		for (optp = s_fstab->zone_fs_options; optp != NULL;
   3107 		    optp = optp->zone_fsopt_next) {
   3108 			if (opt_match("rw", optp->zone_fsopt_opt)) {
   3109 				(void) fprintf(stderr, gettext(RW_LOFS),
   3110 				    s_fstab->zone_fs_special);
   3111 				return;
   3112 			}
   3113 		}
   3114 
   3115 		for (optp = t_fstab->zone_fs_options; optp != NULL;
   3116 		    optp = optp->zone_fsopt_next) {
   3117 			if (opt_match("rw", optp->zone_fsopt_opt)) {
   3118 				(void) fprintf(stderr, gettext(RW_LOFS),
   3119 				    t_fstab->zone_fs_special);
   3120 				return;
   3121 			}
   3122 		}
   3123 
   3124 		return;
   3125 	}
   3126 
   3127 	/*
   3128 	 * TRANSLATION_NOTE
   3129 	 * The first variable is the file system type and the second is
   3130 	 * the file system special device.  For example,
   3131 	 * WARNING: ufs file system on '/dev/dsk/c0t0d0s0' ...
   3132 	 */
   3133 	(void) fprintf(stderr, gettext("WARNING: %s file system on '%s' "
   3134 	    "is configured in both zones.\n"), t_fstab->zone_fs_type,
   3135 	    t_fstab->zone_fs_special);
   3136 }
   3137 
   3138 static void
   3139 warn_fs_match(zone_dochandle_t s_handle, char *source_zone,
   3140 	zone_dochandle_t t_handle, char *target_zone)
   3141 {
   3142 	int err;
   3143 	struct zone_fstab s_fstab;
   3144 	struct zone_fstab t_fstab;
   3145 
   3146 	if ((err = zonecfg_setfsent(t_handle)) != Z_OK) {
   3147 		errno = err;
   3148 		zperror2(target_zone,
   3149 		    gettext("could not enumerate file systems"));
   3150 		return;
   3151 	}
   3152 
   3153 	while (zonecfg_getfsent(t_handle, &t_fstab) == Z_OK) {
   3154 		if ((err = zonecfg_setfsent(s_handle)) != Z_OK) {
   3155 			errno = err;
   3156 			zperror2(source_zone,
   3157 			    gettext("could not enumerate file systems"));
   3158 			(void) zonecfg_endfsent(t_handle);
   3159 			return;
   3160 		}
   3161 
   3162 		while (zonecfg_getfsent(s_handle, &s_fstab) == Z_OK) {
   3163 			if (strcmp(t_fstab.zone_fs_special,
   3164 			    s_fstab.zone_fs_special) == 0) {
   3165 				print_fs_warnings(&s_fstab, &t_fstab);
   3166 				break;
   3167 			}
   3168 		}
   3169 		(void) zonecfg_endfsent(s_handle);
   3170 	}
   3171 
   3172 	(void) zonecfg_endfsent(t_handle);
   3173 }
   3174 
   3175 /*
   3176  * We don't catch the case where you used the same IP address but
   3177  * it is not an exact string match.  For example, 192.9.0.128 vs. 192.09.0.128.
   3178  * However, we're not going to worry about that but we will check for
   3179  * a possible netmask on one of the addresses (e.g. 10.0.0.1 and 10.0.0.1/24)
   3180  * and handle that case as a match.
   3181  */
   3182 static void
   3183 warn_ip_match(zone_dochandle_t s_handle, char *source_zone,
   3184 	zone_dochandle_t t_handle, char *target_zone)
   3185 {
   3186 	int err;
   3187 	struct zone_nwiftab s_nwiftab;
   3188 	struct zone_nwiftab t_nwiftab;
   3189 
   3190 	if ((err = zonecfg_setnwifent(t_handle)) != Z_OK) {
   3191 		errno = err;
   3192 		zperror2(target_zone,
   3193 		    gettext("could not enumerate network interfaces"));
   3194 		return;
   3195 	}
   3196 
   3197 	while (zonecfg_getnwifent(t_handle, &t_nwiftab) == Z_OK) {
   3198 		char *p;
   3199 
   3200 		/* remove an (optional) netmask from the address */
   3201 		if ((p = strchr(t_nwiftab.zone_nwif_address, '/')) != NULL)
   3202 			*p = '\0';
   3203 
   3204 		if ((err = zonecfg_setnwifent(s_handle)) != Z_OK) {
   3205 			errno = err;
   3206 			zperror2(source_zone,
   3207 			    gettext("could not enumerate network interfaces"));
   3208 			(void) zonecfg_endnwifent(t_handle);
   3209 			return;
   3210 		}
   3211 
   3212 		while (zonecfg_getnwifent(s_handle, &s_nwiftab) == Z_OK) {
   3213 			/* remove an (optional) netmask from the address */
   3214 			if ((p = strchr(s_nwiftab.zone_nwif_address, '/'))
   3215 			    != NULL)
   3216 				*p = '\0';
   3217 
   3218 			/* For exclusive-IP zones, address is not specified. */
   3219 			if (strlen(s_nwiftab.zone_nwif_address) == 0)
   3220 				continue;
   3221 
   3222 			if (strcmp(t_nwiftab.zone_nwif_address,
   3223 			    s_nwiftab.zone_nwif_address) == 0) {
   3224 				(void) fprintf(stderr,
   3225 				    gettext("WARNING: network address '%s' "
   3226 				    "is configured in both zones.\n"),
   3227 				    t_nwiftab.zone_nwif_address);
   3228 				break;
   3229 			}
   3230 		}
   3231 		(void) zonecfg_endnwifent(s_handle);
   3232 	}
   3233 
   3234 	(void) zonecfg_endnwifent(t_handle);
   3235 }
   3236 
   3237 static void
   3238 warn_dataset_match(zone_dochandle_t s_handle, char *source,
   3239 	zone_dochandle_t t_handle, char *target)
   3240 {
   3241 	int err;
   3242 	struct zone_dstab s_dstab;
   3243 	struct zone_dstab t_dstab;
   3244 
   3245 	if ((err = zonecfg_setdsent(t_handle)) != Z_OK) {
   3246 		errno = err;
   3247 		zperror2(target, gettext("could not enumerate datasets"));
   3248 		return;
   3249 	}
   3250 
   3251 	while (zonecfg_getdsent(t_handle, &t_dstab) == Z_OK) {
   3252 		if ((err = zonecfg_setdsent(s_handle)) != Z_OK) {
   3253 			errno = err;
   3254 			zperror2(source,
   3255 			    gettext("could not enumerate datasets"));
   3256 			(void) zonecfg_enddsent(t_handle);
   3257 			return;
   3258 		}
   3259 
   3260 		while (zonecfg_getdsent(s_handle, &s_dstab) == Z_OK) {
   3261 			if (strcmp(t_dstab.zone_dataset_name,
   3262 			    s_dstab.zone_dataset_name) == 0) {
   3263 				target_zone = source;
   3264 				zerror(gettext("WARNING: dataset '%s' "
   3265 				    "is configured in both zones.\n"),
   3266 				    t_dstab.zone_dataset_name);
   3267 				break;
   3268 			}
   3269 		}
   3270 		(void) zonecfg_enddsent(s_handle);
   3271 	}
   3272 
   3273 	(void) zonecfg_enddsent(t_handle);
   3274 }
   3275 
   3276 /*
   3277  * Check that the clone and its source have the same brand type.
   3278  */
   3279 static int
   3280 valid_brand_clone(char *source_zone, char *target_zone)
   3281 {
   3282 	brand_handle_t bh;
   3283 	char source_brand[MAXNAMELEN];
   3284 
   3285 	if ((zone_get_brand(source_zone, source_brand,
   3286 	    sizeof (source_brand))) != Z_OK) {
   3287 		(void) fprintf(stderr, "%s: zone '%s': %s\n",
   3288 		    execname, source_zone, gettext("missing or invalid brand"));
   3289 		return (Z_ERR);
   3290 	}
   3291 
   3292 	if (strcmp(source_brand, target_brand) != 0) {
   3293 		(void) fprintf(stderr,
   3294 		    gettext("%s: Zones '%s' and '%s' have different brand "
   3295 		    "types.\n"), execname, source_zone, target_zone);
   3296 		return (Z_ERR);
   3297 	}
   3298 
   3299 	if ((bh = brand_open(target_brand)) == NULL) {
   3300 		zerror(gettext("missing or invalid brand"));
   3301 		return (Z_ERR);
   3302 	}
   3303 	brand_close(bh);
   3304 	return (Z_OK);
   3305 }
   3306 
   3307 static int
   3308 validate_clone(char *source_zone, char *target_zone)
   3309 {
   3310 	int err = Z_OK;
   3311 	zone_dochandle_t s_handle;
   3312 	zone_dochandle_t t_handle;
   3313 
   3314 	if ((t_handle = zonecfg_init_handle()) == NULL) {
   3315 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
   3316 		return (Z_ERR);
   3317 	}
   3318 	if ((err = zonecfg_get_handle(target_zone, t_handle)) != Z_OK) {
   3319 		errno = err;
   3320 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
   3321 		zonecfg_fini_handle(t_handle);
   3322 		return (Z_ERR);
   3323 	}
   3324 
   3325 	if ((s_handle = zonecfg_init_handle()) == NULL) {
   3326 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
   3327 		zonecfg_fini_handle(t_handle);
   3328 		return (Z_ERR);
   3329 	}
   3330 	if ((err = zonecfg_get_handle(source_zone, s_handle)) != Z_OK) {
   3331 		errno = err;
   3332 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
   3333 		goto done;
   3334 	}
   3335 
   3336 	/* verify new zone has same brand type */
   3337 	err = valid_brand_clone(source_zone, target_zone);
   3338 	if (err != Z_OK)
   3339 		goto done;
   3340 
   3341 	/* warn about imported fs's which are the same */
   3342 	warn_fs_match(s_handle, source_zone, t_handle, target_zone);
   3343 
   3344 	/* warn about imported IP addresses which are the same */
   3345 	warn_ip_match(s_handle, source_zone, t_handle, target_zone);
   3346 
   3347 	/* warn about imported devices which are the same */
   3348 	warn_dev_match(s_handle, source_zone, t_handle, target_zone);
   3349 
   3350 	/* warn about imported datasets which are the same */
   3351 	warn_dataset_match(s_handle, source_zone, t_handle, target_zone);
   3352 
   3353 done:
   3354 	zonecfg_fini_handle(t_handle);
   3355 	zonecfg_fini_handle(s_handle);
   3356 
   3357 	return ((err == Z_OK) ? Z_OK : Z_ERR);
   3358 }
   3359 
   3360 static int
   3361 copy_zone(char *src, char *dst)
   3362 {
   3363 	boolean_t out_null = B_FALSE;
   3364 	int status;
   3365 	char *outfile;
   3366 	char cmdbuf[MAXPATHLEN * 2 + 128];
   3367 
   3368 	if ((outfile = tempnam("/var/log", "zone")) == NULL) {
   3369 		outfile = "/dev/null";
   3370 		out_null = B_TRUE;
   3371 	}
   3372 
   3373 	/*
   3374 	 * Use find to get the list of files to copy.  We need to skip
   3375 	 * files of type "socket" since cpio can't handle those but that
   3376 	 * should be ok since the app will recreate the socket when it runs.
   3377 	 * We also need to filter out anything under the .zfs subdir.  Since
   3378 	 * find is running depth-first, we need the extra egrep to filter .zfs.
   3379 	 */
   3380 	(void) snprintf(cmdbuf, sizeof (cmdbuf),
   3381 	    "cd %s && /usr/bin/find . -type s -prune -o -depth -print | "
   3382 	    "/usr/bin/egrep -v '^\\./\\.zfs$|^\\./\\.zfs/' | "
   3383 	    "/usr/bin/cpio -pdmuP@ %s > %s 2>&1",
   3384 	    src, dst, outfile);
   3385 
   3386 	status = do_subproc(cmdbuf);
   3387 
   3388 	if (subproc_status("copy", status, B_TRUE) != ZONE_SUBPROC_OK) {
   3389 		if (!out_null)
   3390 			(void) fprintf(stderr, gettext("\nThe copy failed.\n"
   3391 			    "More information can be found in %s\n"), outfile);
   3392 		return (Z_ERR);
   3393 	}
   3394 
   3395 	if (!out_null)
   3396 		(void) unlink(outfile);
   3397 
   3398 	return (Z_OK);
   3399 }
   3400 
   3401 /* ARGSUSED */
   3402 int
   3403 zfm_print(const struct mnttab *p, void *r) {
   3404 	zerror("  %s\n", p->mnt_mountp);
   3405 	return (0);
   3406 }
   3407 
   3408 int
   3409 clone_copy(char *source_zonepath, char *zonepath)
   3410 {
   3411 	int err;
   3412 
   3413 	/* Don't clone the zone if anything is still mounted there */
   3414 	if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) {
   3415 		zerror(gettext("These file systems are mounted on "
   3416 		    "subdirectories of %s.\n"), source_zonepath);
   3417 		(void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL);
   3418 		return (Z_ERR);
   3419 	}
   3420 
   3421 	/*
   3422 	 * Attempt to create a ZFS fs for the zonepath.  As usual, we don't
   3423 	 * care if this works or not since we always have the default behavior
   3424 	 * of a simple directory for the zonepath.
   3425 	 */
   3426 	create_zfs_zonepath(zonepath);
   3427 
   3428 	(void) printf(gettext("Copying %s..."), source_zonepath);
   3429 	(void) fflush(stdout);
   3430 
   3431 	err = copy_zone(source_zonepath, zonepath);
   3432 
   3433 	(void) printf("\n");
   3434 
   3435 	return (err);
   3436 }
   3437 
   3438 static int
   3439 clone_func(int argc, char *argv[])
   3440 {
   3441 	char *source_zone = NULL;
   3442 	int lockfd;
   3443 	int err, arg;
   3444 	char zonepath[MAXPATHLEN];
   3445 	char source_zonepath[MAXPATHLEN];
   3446 	zone_state_t state;
   3447 	zone_entry_t *zent;
   3448 	char *method = NULL;
   3449 	char *snapshot = NULL;
   3450 	char cmdbuf[MAXPATHLEN];
   3451 	char postcmdbuf[MAXPATHLEN];
   3452 	char presnapbuf[MAXPATHLEN];
   3453 	char postsnapbuf[MAXPATHLEN];
   3454 	char validsnapbuf[MAXPATHLEN];
   3455 	brand_handle_t bh = NULL;
   3456 	int status;
   3457 	boolean_t brand_help = B_FALSE;
   3458 
   3459 	if (zonecfg_in_alt_root()) {
   3460 		zerror(gettext("cannot clone zone in alternate root"));
   3461 		return (Z_ERR);
   3462 	}
   3463 
   3464 	/* Check the argv string for args we handle internally */
   3465 	optind = 0;
   3466 	opterr = 0;
   3467 	while ((arg = getopt(argc, argv, "?m:s:")) != EOF) {
   3468 		switch (arg) {
   3469 		case '?':
   3470 			if (optopt == '?') {
   3471 				sub_usage(SHELP_CLONE, CMD_CLONE);
   3472 				brand_help = B_TRUE;
   3473 			}
   3474 			/* Ignore unknown options - may be brand specific. */
   3475 			break;
   3476 		case 'm':
   3477 			method = optarg;
   3478 			break;
   3479 		case 's':
   3480 			snapshot = optarg;
   3481 			break;
   3482 		default:
   3483 			/* Ignore unknown options - may be brand specific. */
   3484 			break;
   3485 		}
   3486 	}
   3487 
   3488 	if (argc != (optind + 1)) {
   3489 		sub_usage(SHELP_CLONE, CMD_CLONE);
   3490 		return (Z_USAGE);
   3491 	}
   3492 
   3493 	source_zone = argv[optind];
   3494 
   3495 	if (!brand_help) {
   3496 		if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE,
   3497 		    B_FALSE) != Z_OK)
   3498 			return (Z_ERR);
   3499 		if (verify_details(CMD_CLONE, argv) != Z_OK)
   3500 			return (Z_ERR);
   3501 
   3502 		/*
   3503 		 * We also need to do some extra validation on the source zone.
   3504 		 */
   3505 		if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) {
   3506 			zerror(gettext("%s operation is invalid for the "
   3507 			    "global zone."), cmd_to_str(CMD_CLONE));
   3508 			return (Z_ERR);
   3509 		}
   3510 
   3511 		if (strncmp(source_zone, "SUNW", 4) == 0) {
   3512 			zerror(gettext("%s operation is invalid for zones "
   3513 			    "starting with SUNW."), cmd_to_str(CMD_CLONE));
   3514 			return (Z_ERR);
   3515 		}
   3516 
   3517 		if (auth_check(username, source_zone, SOURCE_ZONE) == Z_ERR) {
   3518 			zerror(gettext("%s operation is invalid because "
   3519 			    "user is not authorized to read source zone."),
   3520 			    cmd_to_str(CMD_CLONE));
   3521 			return (Z_ERR);
   3522 		}
   3523 
   3524 		zent = lookup_running_zone(source_zone);
   3525 		if (zent != NULL) {
   3526 			/* check whether the zone is ready or running */
   3527 			if ((err = zone_get_state(zent->zname,
   3528 			    &zent->zstate_num)) != Z_OK) {
   3529 				errno = err;
   3530 				zperror2(zent->zname, gettext("could not get "
   3531 				    "state"));
   3532 				/* can't tell, so hedge */
   3533 				zent->zstate_str = "ready/running";
   3534 			} else {
   3535 				zent->zstate_str =
   3536 				    zone_state_str(zent->zstate_num);
   3537 			}
   3538 			zerror(gettext("%s operation is invalid for %s zones."),
   3539 			    cmd_to_str(CMD_CLONE), zent->zstate_str);
   3540 			return (Z_ERR);
   3541 		}
   3542 
   3543 		if ((err = zone_get_state(source_zone, &state)) != Z_OK) {
   3544 			errno = err;
   3545 			zperror2(source_zone, gettext("could not get state"));
   3546 			return (Z_ERR);
   3547 		}
   3548 		if (state != ZONE_STATE_INSTALLED) {
   3549 			(void) fprintf(stderr,
   3550 			    gettext("%s: zone %s is %s; %s is required.\n"),
   3551 			    execname, source_zone, zone_state_str(state),
   3552 			    zone_state_str(ZONE_STATE_INSTALLED));
   3553 			return (Z_ERR);
   3554 		}
   3555 
   3556 		/*
   3557 		 * The source zone checks out ok, continue with the clone.
   3558 		 */
   3559 
   3560 		if (validate_clone(source_zone, target_zone) != Z_OK)
   3561 			return (Z_ERR);
   3562 
   3563 		if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
   3564 			zerror(gettext("another %s may have an operation in "
   3565 			    "progress."), "zoneadm");
   3566 			return (Z_ERR);
   3567 		}
   3568 	}
   3569 
   3570 	if ((err = zone_get_zonepath(source_zone, source_zonepath,
   3571 	    sizeof (source_zonepath))) != Z_OK) {
   3572 		errno = err;
   3573 		zperror2(source_zone, gettext("could not get zone path"));
   3574 		goto done;
   3575 	}
   3576 
   3577 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
   3578 	    != Z_OK) {
   3579 		errno = err;
   3580 		zperror2(target_zone, gettext("could not get zone path"));
   3581 		goto done;
   3582 	}
   3583 
   3584 	/*
   3585 	 * Fetch the clone and postclone hooks from the brand configuration.
   3586 	 */
   3587 	if ((bh = brand_open(target_brand)) == NULL) {
   3588 		zerror(gettext("missing or invalid brand"));
   3589 		err = Z_ERR;
   3590 		goto done;
   3591 	}
   3592 
   3593 	if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_clone, target_zone,
   3594 	    zonepath) != Z_OK) {
   3595 		zerror("invalid brand configuration: missing clone resource");
   3596 		brand_close(bh);
   3597 		err = Z_ERR;
   3598 		goto done;
   3599 	}
   3600 
   3601 	if (get_hook(bh, postcmdbuf, sizeof (postcmdbuf), brand_get_postclone,
   3602 	    target_zone, zonepath) != Z_OK) {
   3603 		zerror("invalid brand configuration: missing postclone "
   3604 		    "resource");
   3605 		brand_close(bh);
   3606 		err = Z_ERR;
   3607 		goto done;
   3608 	}
   3609 
   3610 	if (get_hook(bh, presnapbuf, sizeof (presnapbuf), brand_get_presnap,
   3611 	    source_zone, source_zonepath) != Z_OK) {
   3612 		zerror("invalid brand configuration: missing presnap "
   3613 		    "resource");
   3614 		brand_close(bh);
   3615 		err = Z_ERR;
   3616 		goto done;
   3617 	}
   3618 
   3619 	if (get_hook(bh, postsnapbuf, sizeof (postsnapbuf), brand_get_postsnap,
   3620 	    source_zone, source_zonepath) != Z_OK) {
   3621 		zerror("invalid brand configuration: missing postsnap "
   3622 		    "resource");
   3623 		brand_close(bh);
   3624 		err = Z_ERR;
   3625 		goto done;
   3626 	}
   3627 
   3628 	if (get_hook(bh, validsnapbuf, sizeof (validsnapbuf),
   3629 	    brand_get_validatesnap, target_zone, zonepath) != Z_OK) {
   3630 		zerror("invalid brand configuration: missing validatesnap "
   3631 		    "resource");
   3632 		brand_close(bh);
   3633 		err = Z_ERR;
   3634 		goto done;
   3635 	}
   3636 	brand_close(bh);
   3637 
   3638 	/* Append all options to clone hook. */
   3639 	if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK) {
   3640 		err = Z_ERR;
   3641 		goto done;
   3642 	}
   3643 
   3644 	/* Append all options to postclone hook. */
   3645 	if (addoptions(postcmdbuf, argv, sizeof (postcmdbuf)) != Z_OK) {
   3646 		err = Z_ERR;
   3647 		goto done;
   3648 	}
   3649 
   3650 	if (!brand_help) {
   3651 		if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE))
   3652 		    != Z_OK) {
   3653 			errno = err;
   3654 			zperror2(target_zone, gettext("could not set state"));
   3655 			goto done;
   3656 		}
   3657 	}
   3658 
   3659 	/*
   3660 	 * The clone hook is optional.  If it exists, use the hook for
   3661 	 * cloning, otherwise use the built-in clone support
   3662 	 */
   3663 	if (cmdbuf[0] != '\0') {
   3664 		/* Run the clone hook */
   3665 		status = do_subproc(cmdbuf);
   3666 		if ((status = subproc_status(gettext("brand-specific clone"),
   3667 		    status, B_FALSE)) != ZONE_SUBPROC_OK) {
   3668 			if (status == ZONE_SUBPROC_USAGE && !brand_help)
   3669 				sub_usage(SHELP_CLONE, CMD_CLONE);
   3670 			err = Z_ERR;
   3671 			goto done;
   3672 		}
   3673 
   3674 		if (brand_help)
   3675 			return (Z_OK);
   3676 
   3677 	} else {
   3678 		/* If just help, we're done since there is no brand help. */
   3679 		if (brand_help)
   3680 			return (Z_OK);
   3681 
   3682 		/* Run the built-in clone support. */
   3683 
   3684 		/* The only explicit built-in method is "copy". */
   3685 		if (method != NULL && strcmp(method, "copy") != 0) {
   3686 			sub_usage(SHELP_CLONE, CMD_CLONE);
   3687 			err = Z_USAGE;
   3688 			goto done;
   3689 		}
   3690 
   3691 		if (snapshot != NULL) {
   3692 			err = clone_snapshot_zfs(snapshot, zonepath,
   3693 			    validsnapbuf);
   3694 		} else {
   3695 			/*
   3696 			 * We always copy the clone unless the source is ZFS
   3697 			 * and a ZFS clone worked.  We fallback to copying if
   3698 			 * the ZFS clone fails for some reason.
   3699 			 */
   3700 			err = Z_ERR;
   3701 			if (method == NULL && is_zonepath_zfs(source_zonepath))
   3702 				err = clone_zfs(source_zonepath, zonepath,
   3703 				    presnapbuf, postsnapbuf);
   3704 
   3705 			if (err != Z_OK)
   3706 				err = clone_copy(source_zonepath, zonepath);
   3707 		}
   3708 	}
   3709 
   3710 	if (err == Z_OK && postcmdbuf[0] != '\0') {
   3711 		status = do_subproc(postcmdbuf);
   3712 		if ((err = subproc_status("postclone", status, B_FALSE))
   3713 		    != ZONE_SUBPROC_OK) {
   3714 			zerror(gettext("post-clone configuration failed."));
   3715 			err = Z_ERR;
   3716 		}
   3717 	}
   3718 
   3719 done:
   3720 	/*
   3721 	 * If everything went well, we mark the zone as installed.
   3722 	 */
   3723 	if (err == Z_OK) {
   3724 		err = zone_set_state(target_zone, ZONE_STATE_INSTALLED);
   3725 		if (err != Z_OK) {
   3726 			errno = err;
   3727 			zperror2(target_zone, gettext("could not set state"));
   3728 		}
   3729 	}
   3730 	if (!brand_help)
   3731 		zonecfg_release_lock_file(target_zone, lockfd);
   3732 	return ((err == Z_OK) ? Z_OK : Z_ERR);
   3733 }
   3734 
   3735 /*
   3736  * Used when removing a zonepath after uninstalling or cleaning up after
   3737  * the move subcommand.  This handles a zonepath that has non-standard
   3738  * contents so that we will only cleanup the stuff we know about and leave
   3739  * any user data alone.
   3740  *
   3741  * If the "all" parameter is true then we should remove the whole zonepath
   3742  * even if it has non-standard files/directories in it.  This can be used when
   3743  * we need to cleanup after moving the zonepath across file systems.
   3744  *
   3745  * We "exec" the RMCOMMAND so that the returned status is that of RMCOMMAND
   3746  * and not the shell.
   3747  */
   3748 static int
   3749 cleanup_zonepath(char *zonepath, boolean_t all)
   3750 {
   3751 	int		status;
   3752 	int		i;
   3753 	boolean_t	non_std = B_FALSE;
   3754 	struct dirent	*dp;
   3755 	DIR		*dirp;
   3756 			/*
   3757 			 * The SUNWattached.xml file is expected since it might
   3758 			 * exist if the zone was force-attached after a
   3759 			 * migration.
   3760 			 */
   3761 	char		*std_entries[] = {"dev", "lu", "root",
   3762 			    "SUNWattached.xml", NULL};
   3763 			/* (MAXPATHLEN * 3) is for the 3 std_entries dirs */
   3764 	char		cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 3) + 64];
   3765 
   3766 	/*
   3767 	 * We shouldn't need these checks but lets be paranoid since we
   3768 	 * could blow away the whole system here if we got the wrong zonepath.
   3769 	 */
   3770 	if (*zonepath == NULL || strcmp(zonepath, "/") == 0) {
   3771 		(void) fprintf(stderr, "invalid zonepath '%s'\n", zonepath);
   3772 		return (Z_INVAL);
   3773 	}
   3774 
   3775 	/*
   3776 	 * If the dirpath is already gone (maybe it was manually removed) then
   3777 	 * we just return Z_OK so that the cleanup is successful.
   3778 	 */
   3779 	if ((dirp = opendir(zonepath)) == NULL)
   3780 		return (Z_OK);
   3781 
   3782 	/*
   3783 	 * Look through the zonepath directory to see if there are any
   3784 	 * non-standard files/dirs.  Also skip .zfs since that might be
   3785 	 * there but we'll handle ZFS file systems as a special case.
   3786 	 */
   3787 	while ((dp = readdir(dirp)) != NULL) {
   3788 		if (strcmp(dp->d_name, ".") == 0 ||
   3789 		    strcmp(dp->d_name, "..") == 0 ||
   3790 		    strcmp(dp->d_name, ".zfs") == 0)
   3791 			continue;
   3792 
   3793 		for (i = 0; std_entries[i] != NULL; i++)
   3794 			if (strcmp(dp->d_name, std_entries[i]) == 0)
   3795 				break;
   3796 
   3797 		if (std_entries[i] == NULL)
   3798 			non_std = B_TRUE;
   3799 	}
   3800 	(void) closedir(dirp);
   3801 
   3802 	if (!all && non_std) {
   3803 		/*
   3804 		 * There are extra, non-standard directories/files in the
   3805 		 * zonepath so we don't want to remove the zonepath.  We
   3806 		 * just want to remove the standard directories and leave
   3807 		 * the user data alone.
   3808 		 */
   3809 		(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND);
   3810 
   3811 		for (i = 0; std_entries[i] != NULL; i++) {
   3812 			char tmpbuf[MAXPATHLEN];
   3813 
   3814 			if (snprintf(tmpbuf, sizeof (tmpbuf), " %s/%s",
   3815 			    zonepath, std_entries[i]) >= sizeof (tmpbuf) ||
   3816 			    strlcat(cmdbuf, tmpbuf, sizeof (cmdbuf)) >=
   3817 			    sizeof (cmdbuf)) {
   3818 				(void) fprintf(stderr,
   3819 				    gettext("path is too long\n"));
   3820 				return (Z_INVAL);
   3821 			}
   3822 		}
   3823 
   3824 		status = do_subproc(cmdbuf);
   3825 
   3826 		(void) fprintf(stderr, gettext("WARNING: Unable to completely "
   3827 		    "remove %s\nbecause it contains additional user data.  "
   3828 		    "Only the standard directory\nentries have been "
   3829 		    "removed.\n"),
   3830 		    zonepath);
   3831 
   3832 		return ((subproc_status(RMCOMMAND, status, B_TRUE) ==
   3833 		    ZONE_SUBPROC_OK) ? Z_OK : Z_ERR);
   3834 	}
   3835 
   3836 	/*
   3837 	 * There is nothing unexpected in the zonepath, try to get rid of the
   3838 	 * whole zonepath directory.
   3839 	 *
   3840 	 * If the zonepath is its own zfs file system, try to destroy the
   3841 	 * file system.  If that fails for some reason (e.g. it has clones)
   3842 	 * then we'll just remove the contents of the zonepath.
   3843 	 */
   3844 	if (is_zonepath_zfs(zonepath)) {
   3845 		if (destroy_zfs(zonepath) == Z_OK)
   3846 			return (Z_OK);
   3847 		(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND
   3848 		    " %s/*", zonepath);
   3849 		status = do_subproc(cmdbuf);
   3850 		return ((subproc_status(RMCOMMAND, status, B_TRUE) ==
   3851 		    ZONE_SUBPROC_OK) ? Z_OK : Z_ERR);
   3852 	}
   3853 
   3854 	(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s",
   3855 	    zonepath);
   3856 	status = do_subproc(cmdbuf);
   3857 
   3858 	return ((subproc_status(RMCOMMAND, status, B_TRUE) == ZONE_SUBPROC_OK)
   3859 	    ? Z_OK : Z_ERR);
   3860 }
   3861 
   3862 static int
   3863 move_func(int argc, char *argv[])
   3864 {
   3865 	char *new_zonepath = NULL;
   3866 	int lockfd;
   3867 	int err, arg;
   3868 	char zonepath[MAXPATHLEN];
   3869 	zone_dochandle_t handle;
   3870 	boolean_t fast;
   3871 	boolean_t is_zfs = B_FALSE;
   3872 	boolean_t root_fs_mounted = B_FALSE;
   3873 	struct dirent *dp;
   3874 	DIR *dirp;
   3875 	boolean_t empty = B_TRUE;
   3876 	boolean_t revert;
   3877 	struct stat zonepath_buf;
   3878 	struct stat new_zonepath_buf;
   3879 	zone_mounts_t mounts;
   3880 
   3881 	if (zonecfg_in_alt_root()) {
   3882 		zerror(gettext("cannot move zone in alternate root"));
   3883 		return (Z_ERR);
   3884 	}
   3885 
   3886 	optind = 0;
   3887 	if ((arg = getopt(argc, argv, "?")) != EOF) {
   3888 		switch (arg) {
   3889 		case '?':
   3890 			sub_usage(SHELP_MOVE, CMD_MOVE);
   3891 			return (optopt == '?' ? Z_OK : Z_USAGE);
   3892 		default:
   3893 			sub_usage(SHELP_MOVE, CMD_MOVE);
   3894 			return (Z_USAGE);
   3895 		}
   3896 	}
   3897 	if (argc != (optind + 1)) {
   3898 		sub_usage(SHELP_MOVE, CMD_MOVE);
   3899 		return (Z_USAGE);
   3900 	}
   3901 	new_zonepath = argv[optind];
   3902 	if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE, B_FALSE)
   3903 	    != Z_OK)
   3904 		return (Z_ERR);
   3905 	if (verify_details(CMD_MOVE, argv) != Z_OK)
   3906 		return (Z_ERR);
   3907 
   3908 	/*
   3909 	 * Check out the new zonepath.  This has the side effect of creating
   3910 	 * a directory for the new zonepath.  We depend on this later when we
   3911 	 * stat to see if we are doing a cross file system move or not.
   3912 	 */
   3913 	if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK)
   3914 		return (Z_ERR);
   3915 
   3916 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
   3917 	    != Z_OK) {
   3918 		errno = err;
   3919 		zperror2(target_zone, gettext("could not get zone path"));
   3920 		return (Z_ERR);
   3921 	}
   3922 
   3923 	if (stat(zonepath, &zonepath_buf) == -1) {
   3924 		zperror(gettext("could not stat zone path"), B_FALSE);
   3925 		return (Z_ERR);
   3926 	}
   3927 
   3928 	if (stat(new_zonepath, &new_zonepath_buf) == -1) {
   3929 		zperror(gettext("could not stat new zone path"), B_FALSE);
   3930 		return (Z_ERR);
   3931 	}
   3932 
   3933 	/*
   3934 	 * Check if the destination directory is empty.
   3935 	 */
   3936 	if ((dirp = opendir(new_zonepath)) == NULL) {
   3937 		zperror(gettext("could not open new zone path"), B_FALSE);
   3938 		return (Z_ERR);
   3939 	}
   3940 	while ((dp = readdir(dirp)) != (struct dirent *)0) {
   3941 		if (strcmp(dp->d_name, ".") == 0 ||
   3942 		    strcmp(dp->d_name, "..") == 0)
   3943 			continue;
   3944 		empty = B_FALSE;
   3945 		break;
   3946 	}
   3947 	(void) closedir(dirp);
   3948 
   3949 	/* Error if there is anything in the destination directory. */
   3950 	if (!empty) {
   3951 		(void) fprintf(stderr, gettext("could not move zone to %s: "
   3952 		    "directory not empty\n"), new_zonepath);
   3953 		return (Z_ERR);
   3954 	}
   3955 
   3956 	/*
   3957 	 * Collect information about mounts within the zone's zonepath.
   3958 	 * Overlay mounts on the zone's root directory are erroneous.
   3959 	 * Bail if we encounter any unexpected mounts.
   3960 	 */
   3961 	if (zone_mounts_init(&mounts, zonepath) != 0)
   3962 		return (Z_ERR);
   3963 	if (mounts.num_root_overlay_mounts != 0) {
   3964 		zerror(gettext("%d overlay mount(s) detected on %s/root."),
   3965 		    mounts.num_root_overlay_mounts, zonepath);
   3966 		goto err_and_mounts_destroy;
   3967 	}
   3968 	if (mounts.num_unexpected_mounts != 0)
   3969 		goto err_and_mounts_destroy;
   3970 
   3971 	/*
   3972 	 * Check if we are moving in the same file system and can do a fast
   3973 	 * move or if we are crossing file systems and have to copy the data.
   3974 	 */
   3975 	fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev);
   3976 
   3977 	if ((handle = zonecfg_init_handle()) == NULL) {
   3978 		zperror(cmd_to_str(CMD_MOVE), B_TRUE);
   3979 		goto err_and_mounts_destroy;
   3980 	}
   3981 
   3982 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
   3983 		errno = err;
   3984 		zperror(cmd_to_str(CMD_MOVE), B_TRUE);
   3985 		goto err_and_fini_handle;
   3986 	}
   3987 
   3988 	if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
   3989 		zerror(gettext("another %s may have an operation in progress."),
   3990 		    "zoneadm");
   3991 		goto err_and_fini_handle;
   3992 	}
   3993 
   3994 	/*
   3995 	 * Unmount the zone's root filesystem before we move the zone's
   3996 	 * zonepath.
   3997 	 */
   3998 	if (zone_unmount_rootfs(&mounts, zonepath, B_FALSE) != 0)
   3999 		goto err_and_rele_lockfile;
   4000 
   4001 	/*
   4002 	 * We're making some file system changes now so we have to clean up
   4003 	 * the file system before we are done.  This will either clean up the
   4004 	 * new zonepath if the zonecfg update failed or it will clean up the
   4005 	 * old zonepath if everything is ok.
   4006 	 */
   4007 	revert = B_TRUE;
   4008 
   4009 	if (is_zonepath_zfs(zonepath) &&
   4010 	    move_zfs(zonepath, new_zonepath) != Z_ERR) {
   4011 		is_zfs = B_TRUE;
   4012 
   4013 	} else if (fast) {
   4014 		/* same file system, use rename for a quick move */
   4015 
   4016 		/*
   4017 		 * Remove the new_zonepath directory that got created above
   4018 		 * during the validation.  It gets in the way of the rename.
   4019 		 */
   4020 		if (rmdir(new_zonepath) != 0) {
   4021 			zperror(gettext("could not rmdir new zone path"),
   4022 			    B_FALSE);
   4023 			(void) zone_mount_rootfs(&mounts, zonepath);
   4024 			goto err_and_rele_lockfile;
   4025 		}
   4026 
   4027 		if (rename(zonepath, new_zonepath) != 0) {
   4028 			/*
   4029 			 * If this fails we don't need to do all of the
   4030 			 * cleanup that happens for the rest of the code
   4031 			 * so just return from this error.
   4032 			 */
   4033 			zperror(gettext("could not move zone"), B_FALSE);
   4034 			(void) zone_mount_rootfs(&mounts, zonepath);
   4035 			goto err_and_rele_lockfile;
   4036 		}
   4037 
   4038 	} else {
   4039 		/*
   4040 		 * Attempt to create a ZFS fs for the new zonepath.  As usual,
   4041 		 * we don't care if this works or not since we always have the
   4042 		 * default behavior of a simple directory for the zonepath.
   4043 		 */
   4044 		create_zfs_zonepath(new_zonepath);
   4045 
   4046 		(void) printf(gettext(
   4047 		    "Moving across file systems; copying zonepath %s..."),
   4048 		    zonepath);
   4049 		(void) fflush(stdout);
   4050 
   4051 		err = copy_zone(zonepath, new_zonepath);
   4052 
   4053 		(void) printf("\n");
   4054 		if (err != Z_OK)
   4055 			goto done;
   4056 	}
   4057 
   4058 	/*
   4059 	 * Mount the zone's root filesystem in the new zonepath if there was
   4060 	 * a root mount prior to the move.
   4061 	 */
   4062 	if (zone_mount_rootfs(&mounts, new_zonepath) != 0) {
   4063 		err = Z_ERR;
   4064 		goto done;
   4065 	}
   4066 	root_fs_mounted = B_TRUE;
   4067 
   4068 	if ((err = zonecfg_set_zonepath(handle, new_zonepath)) != Z_OK) {
   4069 		errno = err;
   4070 		zperror(gettext("could not set new zonepath"), B_TRUE);
   4071 		goto done;
   4072 	}
   4073 
   4074 	if ((err = zonecfg_save(handle)) != Z_OK) {
   4075 		errno = err;
   4076 		zperror(gettext("zonecfg save failed"), B_TRUE);
   4077 		goto done;
   4078 	}
   4079 
   4080 	revert = B_FALSE;
   4081 
   4082 done:
   4083 	zonecfg_fini_handle(handle);
   4084 	zonecfg_release_lock_file(target_zone, lockfd);
   4085 
   4086 	/*
   4087 	 * Clean up the file system based on how things went.  We either
   4088 	 * clean up the new zonepath if the operation failed for some reason
   4089 	 * or we clean up the old zonepath if everything is ok.
   4090 	 */
   4091 	if (revert) {
   4092 		/*
   4093 		 * Check for the unlikely scenario in which the zone's
   4094 		 * zonepath and its root file system moved but libzonecfg
   4095 		 * couldn't save the new zonepath to the zone's configuration
   4096 		 * file.  The mounted root filesystem must be unmounted before
   4097 		 * zoneadm restores the zone's zonepath.
   4098 		 */
   4099 		if (root_fs_mounted && zone_unmount_rootfs(&mounts,
   4100 		    new_zonepath, B_TRUE) != 0) {
   4101 			/*
   4102 			 * We can't forcibly unmount the zone's root file system
   4103 			 * from the new zonepath.  Bail!
   4104 			 */
   4105 			zerror(gettext("fatal error: cannot unmount %s/root\n"),
   4106 			    new_zonepath);
   4107 			goto err_and_mounts_destroy;
   4108 		}
   4109 
   4110 		/* The zonecfg update failed, cleanup the new zonepath. */
   4111 		if (is_zfs) {
   4112 			if (move_zfs(new_zonepath, zonepath) == Z_ERR) {
   4113 				(void) fprintf(stderr, gettext("could not "
   4114 				    "restore zonepath, the zfs mountpoint is "
   4115 				    "set as:\n%s\n"), new_zonepath);
   4116 				/*
   4117 				 * err is already != Z_OK since we're reverting
   4118 				 */
   4119 			} else {
   4120 				(void) zone_mount_rootfs(&mounts, zonepath);
   4121 			}
   4122 		} else if (fast) {
   4123 			if (rename(new_zonepath, zonepath) != 0) {
   4124 				zperror(gettext("could not restore zonepath"),
   4125 				    B_FALSE);
   4126 				/*
   4127 				 * err is already != Z_OK since we're reverting
   4128 				 */
   4129 			} else {
   4130 				(void) zone_mount_rootfs(&mounts, zonepath);
   4131 			}
   4132 		} else {
   4133 			(void) printf(gettext("Cleaning up zonepath %s..."),
   4134 			    new_zonepath);
   4135 			(void) fflush(stdout);
   4136 			err = cleanup_zonepath(new_zonepath, B_TRUE);
   4137 			(void) printf("\n");
   4138 
   4139 			if (err != Z_OK) {
   4140 				errno = err;
   4141 				zperror(gettext("could not remove new "
   4142 				    "zonepath"), B_TRUE);
   4143 			} else {
   4144 				/*
   4145 				 * Because we're reverting we know the mainline
   4146 				 * code failed but we just reused the err
   4147 				 * variable so we reset it back to Z_ERR.
   4148 				 */
   4149 				err = Z_ERR;
   4150 			}
   4151 
   4152 			(void) zone_mount_rootfs(&mounts, zonepath);
   4153 		}
   4154 	} else {
   4155 		/* The move was successful, cleanup the old zonepath. */
   4156 		if (!is_zfs && !fast) {
   4157 			(void) printf(
   4158 			    gettext("Cleaning up zonepath %s..."), zonepath);
   4159 			(void) fflush(stdout);
   4160 			err = cleanup_zonepath(zonepath, B_TRUE);
   4161 			(void) printf("\n");
   4162 
   4163 			if (err != Z_OK) {
   4164 				errno = err;
   4165 				zperror(gettext("could not remove zonepath"),
   4166 				    B_TRUE);
   4167 			}
   4168 		}
   4169 	}
   4170 
   4171 	zone_mounts_destroy(&mounts);
   4172 	return ((err == Z_OK) ? Z_OK : Z_ERR);
   4173 
   4174 err_and_rele_lockfile:
   4175 	zonecfg_release_lock_file(target_zone, lockfd);
   4176 err_and_fini_handle:
   4177 	zonecfg_fini_handle(handle);
   4178 err_and_mounts_destroy:
   4179 	zone_mounts_destroy(&mounts);
   4180 	return (Z_ERR);
   4181 }
   4182 
   4183 /* ARGSUSED */
   4184 static int
   4185 detach_func(int argc, char *argv[])
   4186 {
   4187 	int lockfd = -1;
   4188 	int err, arg;
   4189 	char zonepath[MAXPATHLEN];
   4190 	char cmdbuf[MAXPATHLEN];
   4191 	char precmdbuf[MAXPATHLEN];
   4192 	boolean_t execute = B_TRUE;
   4193 	boolean_t brand_help = B_FALSE;
   4194 	brand_handle_t bh = NULL;
   4195 	int status;
   4196 
   4197 	if (zonecfg_in_alt_root()) {
   4198 		zerror(gettext("cannot detach zone in alternate root"));
   4199 		return (Z_ERR);
   4200 	}
   4201 
   4202 	/* Check the argv string for args we handle internally */
   4203 	optind = 0;
   4204 	opterr = 0;
   4205 	while ((arg = getopt(argc, argv, "?n")) != EOF) {
   4206 		switch (arg) {
   4207 		case '?':
   4208 			if (optopt == '?') {
   4209 				sub_usage(SHELP_DETACH, CMD_DETACH);
   4210 				brand_help = B_TRUE;
   4211 			}
   4212 			/* Ignore unknown options - may be brand specific. */
   4213 			break;
   4214 		case 'n':
   4215 			execute = B_FALSE;
   4216 			break;
   4217 		default:
   4218 			/* Ignore unknown options - may be brand specific. */
   4219 			break;
   4220 		}
   4221 	}
   4222 
   4223 	if (brand_help)
   4224 		execute = B_FALSE;
   4225 
   4226 	if (execute) {
   4227 		if (sanity_check(target_zone, CMD_DETACH, B_FALSE, B_TRUE,
   4228 		    B_FALSE) != Z_OK)
   4229 			return (Z_ERR);
   4230 		if (verify_details(CMD_DETACH, argv) != Z_OK)
   4231 			return (Z_ERR);
   4232 	} else {
   4233 		/*
   4234 		 * We want a dry-run to work for a non-privileged user so we
   4235 		 * only do minimal validation.
   4236 		 */
   4237 		if (target_zone == NULL) {
   4238 			zerror(gettext("no zone specified"));
   4239 			return (Z_ERR);
   4240 		}
   4241 
   4242 		if (strcmp(target_zone, GLOBAL_ZONENAME) == 0) {
   4243 			zerror(gettext("%s operation is invalid for the "
   4244 			    "global zone."), cmd_to_str(CMD_DETACH));
   4245 			return (Z_ERR);
   4246 		}
   4247 	}
   4248 
   4249 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
   4250 	    != Z_OK) {
   4251 		errno = err;
   4252 		zperror2(target_zone, gettext("could not get zone path"));
   4253 		return (Z_ERR);
   4254 	}
   4255 
   4256 	/* Fetch the detach and predetach hooks from the brand configuration. */
   4257 	if ((bh = brand_open(target_brand)) == NULL) {
   4258 		zerror(gettext("missing or invalid brand"));
   4259 		return (Z_ERR);
   4260 	}
   4261 
   4262 	if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_detach, target_zone,
   4263 	    zonepath) != Z_OK) {
   4264 		zerror("invalid brand configuration: missing detach resource");
   4265 		brand_close(bh);
   4266 		return (Z_ERR);
   4267 	}
   4268 
   4269 	if (get_hook(bh, precmdbuf, sizeof (precmdbuf), brand_get_predetach,
   4270 	    target_zone, zonepath) != Z_OK) {
   4271 		zerror("invalid brand configuration: missing predetach "
   4272 		    "resource");
   4273 		brand_close(bh);
   4274 		return (Z_ERR);
   4275 	}
   4276 	brand_close(bh);
   4277 
   4278 	/* Append all options to predetach hook. */
   4279 	if (addoptions(precmdbuf, argv, sizeof (precmdbuf)) != Z_OK)
   4280 		return (Z_ERR);
   4281 
   4282 	/* Append all options to detach hook. */
   4283 	if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK)
   4284 		return (Z_ERR);
   4285 
   4286 	if (execute && zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
   4287 		zerror(gettext("another %s may have an operation in progress."),
   4288 		    "zoneadm");
   4289 		return (Z_ERR);
   4290 	}
   4291 
   4292 	/* If we have a brand predetach hook, run it. */
   4293 	if (!brand_help && precmdbuf[0] != '\0') {
   4294 		status = do_subproc(precmdbuf);
   4295 		if (subproc_status(gettext("brand-specific predetach"),
   4296 		    status, B_FALSE) != ZONE_SUBPROC_OK) {
   4297 
   4298 			if (execute) {
   4299 				assert(lockfd >= 0);
   4300 				zonecfg_release_lock_file(target_zone, lockfd);
   4301 				lockfd = -1;
   4302 			}
   4303 
   4304 			assert(lockfd == -1);
   4305 			return (Z_ERR);
   4306 		}
   4307 	}
   4308 
   4309 	if (cmdbuf[0] != '\0') {
   4310 		/* Run the detach hook */
   4311 		status = do_subproc(cmdbuf);
   4312 		if ((status = subproc_status(gettext("brand-specific detach"),
   4313 		    status, B_FALSE)) != ZONE_SUBPROC_OK) {
   4314 			if (status == ZONE_SUBPROC_USAGE && !brand_help)
   4315 				sub_usage(SHELP_DETACH, CMD_DETACH);
   4316 
   4317 			if (execute) {
   4318 				assert(lockfd >= 0);
   4319 				zonecfg_release_lock_file(target_zone, lockfd);
   4320 				lockfd = -1;
   4321 			}
   4322 
   4323 			assert(lockfd == -1);
   4324 			return (Z_ERR);
   4325 		}
   4326 
   4327 	} else {
   4328 		zone_dochandle_t handle;
   4329 
   4330 		/* If just help, we're done since there is no brand help. */
   4331 		if (brand_help) {
   4332 			assert(lockfd == -1);
   4333 			return (Z_OK);
   4334 		}
   4335 
   4336 		/*
   4337 		 * Run the built-in detach support.  Just generate a simple
   4338 		 * zone definition XML file and detach.
   4339 		 */
   4340 
   4341 		/* Don't detach the zone if anything is still mounted there */
   4342 		if (execute && zonecfg_find_mounts(zonepath, NULL, NULL)) {
   4343 			(void) fprintf(stderr, gettext("These file systems are "
   4344 			    "mounted on subdirectories of %s.\n"), zonepath);
   4345 			(void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
   4346 			err = ZONE_SUBPROC_NOTCOMPLETE;
   4347 			goto done;
   4348 		}
   4349 
   4350 		if ((handle = zonecfg_init_handle()) == NULL) {
   4351 			zperror(cmd_to_str(CMD_DETACH), B_TRUE);
   4352 			err = ZONE_SUBPROC_NOTCOMPLETE;
   4353 			goto done;
   4354 		}
   4355 
   4356 		if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
   4357 			errno = err;
   4358 			zperror(cmd_to_str(CMD_DETACH), B_TRUE);
   4359 
   4360 		} else if ((err = zonecfg_detach_save(handle,
   4361 		    (execute ? 0 : ZONE_DRY_RUN))) != Z_OK) {
   4362 			errno = err;
   4363 			zperror(gettext("saving the detach manifest failed"),
   4364 			    B_TRUE);
   4365 		}
   4366 
   4367 		zonecfg_fini_handle(handle);
   4368 		if (err != Z_OK)
   4369 			goto done;
   4370 	}
   4371 
   4372 	/*
   4373 	 * Set the zone state back to configured unless we are running with the
   4374 	 * no-execute option.
   4375 	 */
   4376 	if (execute && (err = zone_set_state(target_zone,
   4377 	    ZONE_STATE_CONFIGURED)) != Z_OK) {
   4378 		errno = err;
   4379 		zperror(gettext("could not reset state"), B_TRUE);
   4380 	}
   4381 
   4382 done:
   4383 	if (execute) {
   4384 		assert(lockfd >= 0);
   4385 		zonecfg_release_lock_file(target_zone, lockfd);
   4386 		lockfd = -1;
   4387 	}
   4388 
   4389 	assert(lockfd == -1);
   4390 	return ((err == Z_OK) ? Z_OK : Z_ERR);
   4391 }
   4392 
   4393 /*
   4394  * Determine the brand when doing a dry-run attach.  The zone does not have to
   4395  * exist, so we have to read the incoming manifest to determine the zone's
   4396  * brand.
   4397  *
   4398  * Because the manifest has to be processed twice; once to determine the brand
   4399  * and once to do the brand-specific attach logic, we always read it into a tmp
   4400  * file.  This handles the manifest coming from stdin or a regular file.  The
   4401  * tmpname parameter returns the name of the temporary file that the manifest
   4402  * was read into.
   4403  */
   4404 static int
   4405 dryrun_get_brand(char *manifest_path, char *tmpname, int size)
   4406 {
   4407 	int fd;
   4408 	int err;
   4409 	int res = Z_OK;
   4410 	zone_dochandle_t local_handle;
   4411 	zone_dochandle_t rem_handle = NULL;
   4412 	int len;
   4413 	int ofd;
   4414 	char buf[512];
   4415 
   4416 	if (strcmp(manifest_path, "-") == 0) {
   4417 		fd = STDIN_FILENO;
   4418 	} else {
   4419 		if ((fd = open(manifest_path, O_RDONLY)) < 0) {
   4420 			if (getcwd(buf, sizeof (buf)) == NULL)
   4421 				(void) strlcpy(buf, "/", sizeof (buf));
   4422 			zerror(gettext("could not open manifest path %s%s: %s"),
   4423 			    (*manifest_path == '/' ? "" : buf), manifest_path,
   4424 			    strerror(errno));
   4425 			return (Z_ERR);
   4426 		}
   4427 	}
   4428 
   4429 	(void) snprintf(tmpname, size, "/var/run/zone.%d", getpid());
   4430 
   4431 	if ((ofd = open(tmpname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
   4432 		zperror(gettext("could not save manifest"), B_FALSE);
   4433 		(void) close(fd);
   4434 		return (Z_ERR);
   4435 	}
   4436 
   4437 	while ((len = read(fd, buf, sizeof (buf))) > 0) {
   4438 		if (write(ofd, buf, len) == -1) {
   4439 			zperror(gettext("could not save manifest"), B_FALSE);
   4440 			(void) close(ofd);
   4441 			(void) close(fd);
   4442 			return (Z_ERR);
   4443 		}
   4444 	}
   4445 
   4446 	if (close(ofd) != 0) {
   4447 		zperror(gettext("could not save manifest"), B_FALSE);
   4448 		(void) close(fd);
   4449 		return (Z_ERR);
   4450 	}
   4451 
   4452 	(void) close(fd);
   4453 
   4454 	if ((fd = open(tmpname, O_RDONLY)) < 0) {
   4455 		zperror(gettext("could not open manifest path"), B_FALSE);
   4456 		return (Z_ERR);
   4457 	}
   4458 
   4459 	if ((local_handle = zonecfg_init_handle()) == NULL) {
   4460 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
   4461 		res = Z_ERR;
   4462 		goto done;
   4463 	}
   4464 
   4465 	if ((rem_handle = zonecfg_init_handle()) == NULL) {
   4466 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
   4467 		res = Z_ERR;
   4468 		goto done;
   4469 	}
   4470 
   4471 	if ((err = zonecfg_attach_manifest(fd, local_handle, rem_handle))
   4472 	    != Z_OK) {
   4473 		res = Z_ERR;
   4474 
   4475 		if (err == Z_INVALID_DOCUMENT) {
   4476 			struct stat st;
   4477 			char buf[6];
   4478 
   4479 			if (strcmp(manifest_path, "-") == 0) {
   4480 				zerror(gettext("Input is not a valid XML "
   4481 				    "file"));
   4482 				goto done;
   4483 			}
   4484 
   4485 			if (fstat(fd, &st) == -1 || !S_ISREG(st.st_mode)) {
   4486 				zerror(gettext("%s is not an XML file"),
   4487 				    manifest_path);
   4488 				goto done;
   4489 			}
   4490 
   4491 			bzero(buf, sizeof (buf));
   4492 			(void) lseek(fd, 0L, SEEK_SET);
   4493 			if (read(fd, buf, sizeof (buf) - 1) < 0 ||
   4494 			    strncmp(buf, "<?xml", 5) != 0)
   4495 				zerror(gettext("%s is not an XML file"),
   4496 				    manifest_path);
   4497 			else
   4498 				zerror(gettext("Cannot attach to an earlier "
   4499 				    "release of the operating system"));
   4500 		} else {
   4501 			zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
   4502 		}
   4503 		goto done;
   4504 	}
   4505 
   4506 	/* Retrieve remote handle brand type. */
   4507 	if (zonecfg_get_brand(rem_handle, target_brand, sizeof (target_brand))
   4508 	    != Z_OK) {
   4509 		zerror(gettext("missing or invalid brand"));
   4510 		exit(Z_ERR);
   4511 	}
   4512 
   4513 done:
   4514 	zonecfg_fini_handle(local_handle);
   4515 	zonecfg_fini_handle(rem_handle);
   4516 	(void) close(fd);
   4517 
   4518 	return ((res == Z_OK) ? Z_OK : Z_ERR);
   4519 }
   4520 
   4521 /* ARGSUSED */
   4522 static int
   4523 attach_func(int argc, char *argv[])
   4524 {
   4525 	int lockfd = -1;
   4526 	int err, arg;
   4527 	boolean_t force = B_FALSE;
   4528 	zone_dochandle_t handle;
   4529 	char zonepath[MAXPATHLEN];
   4530 	char cmdbuf[MAXPATHLEN];
   4531 	char postcmdbuf[MAXPATHLEN];
   4532 	boolean_t execute = B_TRUE;
   4533 	boolean_t brand_help = B_FALSE;
   4534 	char *manifest_path;
   4535 	char tmpmanifest[80];
   4536 	int manifest_pos;
   4537 	brand_handle_t bh = NULL;
   4538 	int status;
   4539 	int last_index = 0;
   4540 	int offset;
   4541 	char *up;
   4542 	boolean_t forced_update = B_FALSE;
   4543 
   4544 	if (zonecfg_in_alt_root()) {
   4545 		zerror(gettext("cannot attach zone in alternate root"));
   4546 		return (Z_ERR);
   4547 	}
   4548 
   4549 	/* Check the argv string for args we handle internally */
   4550 	optind = 0;
   4551 	opterr = 0;
   4552 	while ((arg = getopt(argc, argv, "?Fn:U")) != EOF) {
   4553 		switch (arg) {
   4554 		case '?':
   4555 			if (optopt == '?') {
   4556 				sub_usage(SHELP_ATTACH, CMD_ATTACH);
   4557 				brand_help = B_TRUE;
   4558 			}
   4559 			/* Ignore unknown options - may be brand specific. */
   4560 			break;
   4561 		case 'F':
   4562 			force = B_TRUE;
   4563 			break;
   4564 		case 'n':
   4565 			execute = B_FALSE;
   4566 			manifest_path = optarg;
   4567 			manifest_pos = optind - 1;
   4568 			break;
   4569 		case 'U':
   4570 			/*
   4571 			 * Undocumented 'force update' option for p2v update on
   4572 			 * attach when zone is in the incomplete state.  Change
   4573 			 * the option back to 'u' and set forced_update flag.
   4574 			 */
   4575 			if (optind == last_index)
   4576 				offset = optind;
   4577 			else
   4578 				offset = optind - 1;
   4579 			if ((up = index(argv[offset], 'U')) != NULL)
   4580 				*up = 'u';
   4581 			forced_update = B_TRUE;
   4582 			break;
   4583 		default:
   4584 			/* Ignore unknown options - may be brand specific. */
   4585 			break;
   4586 		}
   4587 		last_index = optind;
   4588 	}
   4589 
   4590 	if (brand_help) {
   4591 		force = B_FALSE;
   4592 		execute = B_TRUE;
   4593 	}
   4594 
   4595 	/* dry-run and force flags are mutually exclusive */
   4596 	if (!execute && force) {
   4597 		zerror(gettext("-F and -n flags are mutually exclusive"));
   4598 		return (Z_ERR);
   4599 	}
   4600 
   4601 	/*
   4602 	 * If the no-execute option was specified, we don't do validation and
   4603 	 * need to figure out the brand, since there is no zone required to be
   4604 	 * configured for this option.
   4605 	 */
   4606 	if (execute) {
   4607 		if (!brand_help) {
   4608 			if (sanity_check(target_zone, CMD_ATTACH, B_FALSE,
   4609 			    B_TRUE, forced_update) != Z_OK)
   4610 				return (Z_ERR);
   4611 			if (verify_details(CMD_ATTACH, argv) != Z_OK)
   4612 				return (Z_ERR);
   4613 		}
   4614 
   4615 		if ((err = zone_get_zonepath(target_zone, zonepath,
   4616 		    sizeof (zonepath))) != Z_OK) {
   4617 			errno = err;
   4618 			zperror2(target_zone,
   4619 			    gettext("could not get zone path"));
   4620 			return (Z_ERR);
   4621 		}
   4622 	} else {
   4623 		if (dryrun_get_brand(manifest_path, tmpmanifest,
   4624 		    sizeof (tmpmanifest)) != Z_OK)
   4625 			return (Z_ERR);
   4626 
   4627 		argv[manifest_pos] = tmpmanifest;
   4628 		target_zone = "-";
   4629 		(void) strlcpy(zonepath, "-", sizeof (zonepath));
   4630 
   4631 		/* Run the brand's verify_adm hook. */
   4632 		if (verify_brand(NULL, CMD_ATTACH, argv) != Z_OK)
   4633 			return (Z_ERR);
   4634 	}
   4635 
   4636 	/*
   4637 	 * Fetch the attach and postattach hooks from the brand configuration.
   4638 	 */
   4639 	if ((bh = brand_open(target_brand)) == NULL) {
   4640 		zerror(gettext("missing or invalid brand"));
   4641 		return (Z_ERR);
   4642 	}
   4643 
   4644 	if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_attach, target_zone,
   4645 	    zonepath) != Z_OK) {
   4646 		zerror("invalid brand configuration: missing attach resource");
   4647 		brand_close(bh);
   4648 		return (Z_ERR);
   4649 	}
   4650 
   4651 	if (get_hook(bh, postcmdbuf, sizeof (postcmdbuf), brand_get_postattach,
   4652 	    target_zone, zonepath) != Z_OK) {
   4653 		zerror("invalid brand configuration: missing postattach "
   4654 		    "resource");
   4655 		brand_close(bh);
   4656 		return (Z_ERR);
   4657 	}
   4658 	brand_close(bh);
   4659 
   4660 	/* Append all options to attach hook. */
   4661 	if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK)
   4662 		return (Z_ERR);
   4663 
   4664 	/* Append all options to postattach hook. */
   4665 	if (addoptions(postcmdbuf, argv, sizeof (postcmdbuf)) != Z_OK)
   4666 		return (Z_ERR);
   4667 
   4668 	if (execute && !brand_help) {
   4669 		if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
   4670 			zerror(gettext("another %s may have an operation in "
   4671 			    "progress."), "zoneadm");
   4672 			return (Z_ERR);
   4673 		}
   4674 	}
   4675 
   4676 	if (!force) {
   4677 		/*
   4678 		 * Not a force-attach, so we need to actually do the work.
   4679 		 */
   4680 		if (cmdbuf[0] != '\0') {
   4681 			/* Run the attach hook */
   4682 			status = do_subproc(cmdbuf);
   4683 			if ((status = subproc_status(gettext("brand-specific "
   4684 			    "attach"), status, B_FALSE)) != ZONE_SUBPROC_OK) {
   4685 				if (status == ZONE_SUBPROC_USAGE && !brand_help)
   4686 					sub_usage(SHELP_ATTACH, CMD_ATTACH);
   4687 
   4688 				if (execute && !brand_help) {
   4689 					assert(zonecfg_lock_file_held(&lockfd));
   4690 					zonecfg_release_lock_file(target_zone,
   4691 					    lockfd);
   4692 					lockfd = -1;
   4693 				}
   4694 
   4695 				assert(lockfd == -1);
   4696 				return (Z_ERR);
   4697 			}
   4698 		}
   4699 
   4700 		/*
   4701 		 * Else run the built-in attach support.
   4702 		 * This is a no-op since there is nothing to validate.
   4703 		 */
   4704 
   4705 		/* If dry-run or help, then we're done. */
   4706 		if (!execute || brand_help) {
   4707 			if (!execute)
   4708 				(void) unlink(tmpmanifest);
   4709 			assert(lockfd == -1);
   4710 			return (Z_OK);
   4711 		}
   4712 	}
   4713 
   4714 	/* Now we can validate that the zonepath exists. */
   4715 	if (validate_zonepath(zonepath, CMD_ATTACH) != Z_OK) {
   4716 		(void) fprintf(stderr, gettext("could not verify zonepath %s "
   4717 		    "because of the above errors.\n"), zonepath);
   4718 
   4719 		assert(zonecfg_lock_file_held(&lockfd));
   4720 		zonecfg_release_lock_file(target_zone, lockfd);
   4721 		return (Z_ERR);
   4722 	}
   4723 
   4724 	if ((handle = zonecfg_init_handle()) == NULL) {
   4725 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
   4726 		err = Z_ERR;
   4727 	} else if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
   4728 		errno = err;
   4729 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
   4730 		zonecfg_fini_handle(handle);
   4731 	} else {
   4732 		zonecfg_rm_detached(handle, force);
   4733 		zonecfg_fini_handle(handle);
   4734 	}
   4735 
   4736 	if (err == Z_OK &&
   4737 	    (err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
   4738 		errno = err;
   4739 		zperror(gettext("could not reset state"), B_TRUE);
   4740 	}
   4741 
   4742 	assert(zonecfg_lock_file_held(&lockfd));
   4743 	zonecfg_release_lock_file(target_zone, lockfd);
   4744 	lockfd = -1;
   4745 
   4746 	/* If we have a brand postattach hook, run it. */
   4747 	if (err == Z_OK && !force && postcmdbuf[0] != '\0') {
   4748 		status = do_subproc(postcmdbuf);
   4749 		if (subproc_status(gettext("brand-specific postattach"),
   4750 		    status, B_FALSE) != ZONE_SUBPROC_OK) {
   4751 			if ((err = zone_set_state(target_zone,
   4752 			    ZONE_STATE_CONFIGURED)) != Z_OK) {
   4753 				errno = err;
   4754 				zperror(gettext("could not reset state"),
   4755 				    B_TRUE);
   4756 			}
   4757 		}
   4758 	}
   4759 
   4760 	assert(lockfd == -1);
   4761 	return ((err == Z_OK) ? Z_OK : Z_ERR);
   4762 }
   4763 
   4764 /*
   4765  * On input, TRUE => yes, FALSE => no.
   4766  * On return, TRUE => 1, FALSE => 0, could not ask => -1.
   4767  */
   4768 
   4769 static int
   4770 ask_yesno(boolean_t default_answer, const char *question)
   4771 {
   4772 	char line[64];	/* should be large enough to answer yes or no */
   4773 
   4774 	if (!isatty(STDIN_FILENO))
   4775 		return (-1);
   4776 	for (;;) {
   4777 		(void) printf("%s (%s)? ", question,
   4778 		    default_answer ? "[y]/n" : "y/[n]");
   4779 		if (fgets(line, sizeof (line), stdin) == NULL ||
   4780 		    line[0] == '\n')
   4781 			return (default_answer ? 1 : 0);
   4782 		if (tolower(line[0]) == 'y')
   4783 			return (1);
   4784 		if (tolower(line[0]) == 'n')
   4785 			return (0);
   4786 	}
   4787 }
   4788 
   4789 /* ARGSUSED */
   4790 static int
   4791 uninstall_func(int argc, char *argv[])
   4792 {
   4793 	char line[ZONENAME_MAX + 128];	/* Enough for "Are you sure ..." */
   4794 	char rootpath[MAXPATHLEN], zonepath[MAXPATHLEN];
   4795 	char cmdbuf[MAXPATHLEN];
   4796 	char precmdbuf[MAXPATHLEN];
   4797 	boolean_t force = B_FALSE;
   4798 	int lockfd, answer;
   4799 	int err, arg;
   4800 	boolean_t brand_help = B_FALSE;
   4801 	brand_handle_t bh = NULL;
   4802 	int status;
   4803 
   4804 	if (zonecfg_in_alt_root()) {
   4805 		zerror(gettext("cannot uninstall zone in alternate root"));
   4806 		return (Z_ERR);
   4807 	}
   4808 
   4809 	/* Check the argv string for args we handle internally */
   4810 	optind = 0;
   4811 	opterr = 0;
   4812 	while ((arg = getopt(argc, argv, "?F")) != EOF) {
   4813 		switch (arg) {
   4814 		case '?':
   4815 			if (optopt == '?') {
   4816 				sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
   4817 				brand_help = B_TRUE;
   4818 			}
   4819 			/* Ignore unknown options - may be brand specific. */
   4820 			break;
   4821 		case 'F':
   4822 			force = B_TRUE;
   4823 			break;
   4824 		default:
   4825 			/* Ignore unknown options - may be brand specific. */
   4826 			break;
   4827 		}
   4828 	}
   4829 
   4830 	if (!brand_help) {
   4831 		if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE,
   4832 		    B_FALSE) != Z_OK)
   4833 			return (Z_ERR);
   4834 
   4835 		/*
   4836 		 * Invoke brand-specific handler.
   4837 		 */
   4838 		if (invoke_brand_handler(CMD_UNINSTALL, argv) != Z_OK)
   4839 			return (Z_ERR);
   4840 
   4841 		if (!force) {
   4842 			(void) snprintf(line, sizeof (line),
   4843 			    gettext("Are you sure you want to %s zone %s"),
   4844 			    cmd_to_str(CMD_UNINSTALL), target_zone);
   4845 			if ((answer = ask_yesno(B_FALSE, line)) == 0) {
   4846 				return (Z_OK);
   4847 			} else if (answer == -1) {
   4848 				zerror(gettext("Input not from terminal and -F "
   4849 				    "not specified: %s not done."),
   4850 				    cmd_to_str(CMD_UNINSTALL));
   4851 				return (Z_ERR);
   4852 			}
   4853 		}
   4854 	}
   4855 
   4856 	if ((err = zone_get_zonepath(target_zone, zonepath,
   4857 	    sizeof (zonepath))) != Z_OK) {
   4858 		errno = err;
   4859 		zperror2(target_zone, gettext("could not get zone path"));
   4860 		return (Z_ERR);
   4861 	}
   4862 
   4863 	/*
   4864 	 * Fetch the uninstall and preuninstall hooks from the brand
   4865 	 * configuration.
   4866 	 */
   4867 	if ((bh = brand_open(target_brand)) == NULL) {
   4868 		zerror(gettext("missing or invalid brand"));
   4869 		return (Z_ERR);
   4870 	}
   4871 
   4872 	if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_uninstall,
   4873 	    target_zone, zonepath) != Z_OK) {
   4874 		zerror("invalid brand configuration: missing uninstall "
   4875 		    "resource");
   4876 		brand_close(bh);
   4877 		return (Z_ERR);
   4878 	}
   4879 
   4880 	if (get_hook(bh, precmdbuf, sizeof (precmdbuf), brand_get_preuninstall,
   4881 	    target_zone, zonepath) != Z_OK) {
   4882 		zerror("invalid brand configuration: missing preuninstall "
   4883 		    "resource");
   4884 		brand_close(bh);
   4885 		return (Z_ERR);
   4886 	}
   4887 	brand_close(bh);
   4888 
   4889 	/* Append all options to preuninstall hook. */
   4890 	if (addoptions(precmdbuf, argv, sizeof (precmdbuf)) != Z_OK)
   4891 		return (Z_ERR);
   4892 
   4893 	/* Append all options to uninstall hook. */
   4894 	if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK)
   4895 		return (Z_ERR);
   4896 
   4897 	if (!brand_help) {
   4898 		if ((err = zone_get_rootpath(target_zone, rootpath,
   4899 		    sizeof (rootpath))) != Z_OK) {
   4900 			errno = err;
   4901 			zperror2(target_zone, gettext("could not get root "
   4902 			    "path"));
   4903 			return (Z_ERR);
   4904 		}
   4905 
   4906 		/*
   4907 		 * If there seems to be a zoneadmd running for this zone, call
   4908 		 * it to tell it that an uninstall is happening; if all goes
   4909 		 * well it will then shut itself down.
   4910 		 */
   4911 		if (zonecfg_ping_zoneadmd(target_zone) == Z_OK) {
   4912 			zone_cmd_arg_t zarg;
   4913 			zarg.cmd = Z_NOTE_UNINSTALLING;
   4914 			/* we don't care too much if this fails, just plow on */
   4915 			(void) zonecfg_call_zoneadmd(target_zone, &zarg, locale,
   4916 			    B_TRUE);
   4917 		}
   4918 
   4919 		if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
   4920 			zerror(gettext("another %s may have an operation in "
   4921 			    "progress."), "zoneadm");
   4922 			return (Z_ERR);
   4923 		}
   4924 
   4925 		/* Don't uninstall the zone if anything is mounted there */
   4926 		err = zonecfg_find_mounts(rootpath, NULL, NULL);
   4927 		if (err) {
   4928 			zerror(gettext("These file systems are mounted on "
   4929 			    "subdirectories of %s.\n"), rootpath);
   4930 			(void) zonecfg_find_mounts(rootpath, zfm_print, NULL);
   4931 			zonecfg_release_lock_file(target_zone, lockfd);
   4932 			return (Z_ERR);
   4933 		}
   4934 	}
   4935 
   4936 	/* If we have a brand preuninstall hook, run it. */
   4937 	if (!brand_help && precmdbuf[0] != '\0') {
   4938 		status = do_subproc(precmdbuf);
   4939 		if (subproc_status(gettext("brand-specific preuninstall"),
   4940 		    status, B_FALSE) != ZONE_SUBPROC_OK) {
   4941 			zonecfg_release_lock_file(target_zone, lockfd);
   4942 			return (Z_ERR);
   4943 		}
   4944 	}
   4945 
   4946 	if (!brand_help) {
   4947 		err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
   4948 		if (err != Z_OK) {
   4949 			errno = err;
   4950 			zperror2(target_zone, gettext("could not set state"));
   4951 			goto bad;
   4952 		}
   4953 	}
   4954 
   4955 	/*
   4956 	 * If there is a brand uninstall hook, use it, otherwise use the
   4957 	 * built-in uninstall code.
   4958 	 */
   4959 	if (cmdbuf[0] != '\0') {
   4960 		/* Run the uninstall hook */
   4961 		status = do_subproc(cmdbuf);
   4962 		if ((status = subproc_status(gettext("brand-specific "
   4963 		    "uninstall"), status, B_FALSE)) != ZONE_SUBPROC_OK) {
   4964 			if (status == ZONE_SUBPROC_USAGE && !brand_help)
   4965 				sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
   4966 			if (!brand_help)
   4967 				zonecfg_release_lock_file(target_zone, lockfd);
   4968 			return (Z_ERR);
   4969 		}
   4970 
   4971 		if (brand_help)
   4972 			return (Z_OK);
   4973 	} else {
   4974 		/* If just help, we're done since there is no brand help. */
   4975 		if (brand_help)
   4976 			return (Z_OK);
   4977 
   4978 		/* Run the built-in uninstall support. */
   4979 		if ((err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) {
   4980 			errno = err;
   4981 			zperror2(target_zone, gettext("cleaning up zonepath "
   4982 			    "failed"));
   4983 			goto bad;
   4984 		}
   4985 	}
   4986 
   4987 	err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
   4988 	if (err != Z_OK) {
   4989 		errno = err;
   4990 		zperror2(target_zone, gettext("could not reset state"));
   4991 	}
   4992 bad:
   4993 	zonecfg_release_lock_file(target_zone, lockfd);
   4994 	return (err);
   4995 }
   4996 
   4997 /* ARGSUSED */
   4998 static int
   4999 mount_func(int argc, char *argv[])
   5000 {
   5001 	zone_cmd_arg_t zarg;
   5002 	boolean_t force = B_FALSE;
   5003 	int arg;
   5004 
   5005 	/*
   5006 	 * The only supported subargument to the "mount" subcommand is
   5007 	 * "-f", which forces us to mount a zone in the INCOMPLETE state.
   5008 	 */
   5009 	optind = 0;
   5010 	if ((arg = getopt(argc, argv, "f")) != EOF) {
   5011 		switch (arg) {
   5012 		case 'f':
   5013 			force = B_TRUE;
   5014 			break;
   5015 		default:
   5016 			return (Z_USAGE);
   5017 		}
   5018 	}
   5019 	if (argc > optind)
   5020 		return (Z_USAGE);
   5021 
   5022 	if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE, force)
   5023 	    != Z_OK)
   5024 		return (Z_ERR);
   5025 	if (verify_details(CMD_MOUNT, argv) != Z_OK)
   5026 		return (Z_ERR);
   5027 
   5028 	zarg.cmd = force ? Z_FORCEMOUNT : Z_MOUNT;
   5029 	zarg.bootbuf[0] = '\0';
   5030 	if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
   5031 		zerror(gettext("call to %s failed"), "zoneadmd");
   5032 		return (Z_ERR);
   5033 	}
   5034 	return (Z_OK);
   5035 }
   5036 
   5037 /* ARGSUSED */
   5038 static int
   5039 unmount_func(int argc, char *argv[])
   5040 {
   5041 	zone_cmd_arg_t zarg;
   5042 
   5043 	if (argc > 0)
   5044 		return (Z_USAGE);
   5045 	if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE, B_FALSE)
   5046 	    != Z_OK)
   5047 		return (Z_ERR);
   5048 
   5049 	zarg.cmd = Z_UNMOUNT;
   5050 	if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
   5051 		zerror(gettext("call to %s failed"), "zoneadmd");
   5052 		return (Z_ERR);
   5053 	}
   5054 	return (Z_OK);
   5055 }
   5056 
   5057 static int
   5058 mark_func(int argc, char *argv[])
   5059 {
   5060 	int err, lockfd;
   5061 	int arg;
   5062 	boolean_t force = B_FALSE;
   5063 	int state;
   5064 
   5065 	optind = 0;
   5066 	opterr = 0;
   5067 	while ((arg = getopt(argc, argv, "F")) != EOF) {
   5068 		switch (arg) {
   5069 		case 'F':
   5070 			force = B_TRUE;
   5071 			break;
   5072 		default:
   5073 			return (Z_USAGE);
   5074 		}
   5075 	}
   5076 
   5077 	if (argc != (optind + 1))
   5078 		return (Z_USAGE);
   5079 
   5080 	if (strcmp(argv[optind], "configured") == 0)
   5081 		state = ZONE_STATE_CONFIGURED;
   5082 	else if (strcmp(argv[optind], "incomplete") == 0)
   5083 		state = ZONE_STATE_INCOMPLETE;
   5084 	else if (strcmp(argv[optind], "installed") == 0)
   5085 		state = ZONE_STATE_INSTALLED;
   5086 	else
   5087 		return (Z_USAGE);
   5088 
   5089 	if (state != ZONE_STATE_INCOMPLETE && !force)
   5090 		return (Z_USAGE);
   5091 
   5092 	if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_TRUE, B_FALSE)
   5093 	    != Z_OK)
   5094 		return (Z_ERR);
   5095 
   5096 	/*
   5097 	 * Invoke brand-specific handler.
   5098 	 */
   5099 	if (invoke_brand_handler(CMD_MARK, argv) != Z_OK)
   5100 		return (Z_ERR);
   5101 
   5102 	if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
   5103 		zerror(gettext("another %s may have an operation in progress."),
   5104 		    "zoneadm");
   5105 		return (Z_ERR);
   5106 	}
   5107 
   5108 	err = zone_set_state(target_zone, state);
   5109 	if (err != Z_OK) {
   5110 		errno = err;
   5111 		zperror2(target_zone, gettext("could not set state"));
   5112 	}
   5113 	zonecfg_release_lock_file(target_zone, lockfd);
   5114 
   5115 	return (err);
   5116 }
   5117 
   5118 /*
   5119  * Check what scheduling class we're running under and print a warning if
   5120  * we're not using FSS.
   5121  */
   5122 static int
   5123 check_sched_fss(zone_dochandle_t handle)
   5124 {
   5125 	char class_name[PC_CLNMSZ];
   5126 
   5127 	if (zonecfg_get_dflt_sched_class(handle, class_name,
   5128 	    sizeof (class_name)) != Z_OK) {
   5129 		zerror(gettext("WARNING: unable to determine the zone's "
   5130 		    "scheduling class"));
   5131 	} else if (strcmp("FSS", class_name) != 0) {
   5132 		zerror(gettext("WARNING: The zone.cpu-shares rctl is set but\n"
   5133 		    "FSS is not the default scheduling class for this zone.  "
   5134 		    "FSS will be\nused for processes in the zone but to get "
   5135 		    "the full benefit of FSS,\nit should be the default "
   5136 		    "scheduling class.  See dispadmin(1M) for\nmore details."));
   5137 		return (Z_SYSTEM);
   5138 	}
   5139 
   5140 	return (Z_OK);
   5141 }
   5142 
   5143 static int
   5144 check_cpu_shares_sched(zone_dochandle_t handle)
   5145 {
   5146 	int err;
   5147 	int res = Z_OK;
   5148 	struct zone_rctltab rctl;
   5149 
   5150 	if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
   5151 		errno = err;
   5152 		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
   5153 		return (err);
   5154 	}
   5155 
   5156 	while (zonecfg_getrctlent(handle, &rctl) == Z_OK) {
   5157 		if (strcmp(rctl.zone_rctl_name, "zone.cpu-shares") == 0) {
   5158 			if (check_sched_fss(handle) != Z_OK)
   5159 				res = Z_SYSTEM;
   5160 			break;
   5161 		}
   5162 	}
   5163 
   5164 	(void) zonecfg_endrctlent(handle);
   5165 
   5166 	return (res);
   5167 }
   5168 
   5169 /*
   5170  * Check if there is a mix of processes running in different pools within the
   5171  * zone.  This is currently only going to be called for the global zone from
   5172  * apply_func but that could be generalized in the future.
   5173  */
   5174 static boolean_t
   5175 mixed_pools(zoneid_t zoneid)
   5176 {
   5177 	DIR *dirp;
   5178 	dirent_t *dent;
   5179 	boolean_t mixed = B_FALSE;
   5180 	boolean_t poolid_set = B_FALSE;
   5181 	poolid_t last_poolid = 0;
   5182 
   5183 	if ((dirp = opendir("/proc")) == NULL) {
   5184 		zerror(gettext("could not open /proc"));
   5185 		return (B_FALSE);
   5186 	}
   5187 
   5188 	while ((dent = readdir(dirp)) != NULL) {
   5189 		int procfd;
   5190 		psinfo_t ps;
   5191 		char procpath[MAXPATHLEN];
   5192 
   5193 		if (dent->d_name[0] == '.')
   5194 			continue;
   5195 
   5196 		(void) snprintf(procpath, sizeof (procpath), "/proc/%s/psinfo",
   5197 		    dent->d_name);
   5198 
   5199 		if ((procfd = open(procpath, O_RDONLY)) == -1)
   5200 			continue;
   5201 
   5202 		if (read(procfd, &ps, sizeof (ps)) == sizeof (psinfo_t)) {
   5203 			/* skip processes in other zones and system processes */
   5204 			if (zoneid != ps.pr_zoneid || ps.pr_flag & SSYS) {
   5205 				(void) close(procfd);
   5206 				continue;
   5207 			}
   5208 
   5209 			if (poolid_set) {
   5210 				if (ps.pr_poolid != last_poolid)
   5211 					mixed = B_TRUE;
   5212 			} else {
   5213 				last_poolid = ps.pr_poolid;
   5214 				poolid_set = B_TRUE;
   5215 			}
   5216 		}
   5217 
   5218 		(void) close(procfd);
   5219 
   5220 		if (mixed)
   5221 			break;
   5222 	}
   5223 
   5224 	(void) closedir(dirp);
   5225 
   5226 	return (mixed);
   5227 }
   5228 
   5229 /*
   5230  * Check if a persistent or temporary pool is configured for the zone.
   5231  * This is currently only going to be called for the global zone from
   5232  * apply_func but that could be generalized in the future.
   5233  */
   5234 static boolean_t
   5235 pool_configured(zone_dochandle_t handle)
   5236 {
   5237 	int err1, err2;
   5238 	struct zone_psettab pset_tab;
   5239 	char poolname[MAXPATHLEN];
   5240 
   5241 	err1 = zonecfg_lookup_pset(handle, &pset_tab);
   5242 	err2 = zonecfg_get_pool(handle, poolname, sizeof (poolname));
   5243 
   5244 	if (err1 == Z_NO_ENTRY &&
   5245 	    (err2 == Z_NO_ENTRY || (err2 == Z_OK && strlen(poolname) == 0)))
   5246 		return (B_FALSE);
   5247 
   5248 	return (B_TRUE);
   5249 }
   5250 
   5251 /*
   5252  * This is an undocumented interface which is currently only used to apply
   5253  * the global zone resource management settings when the system boots.
   5254  * This function does not yet properly handle updating a running system so
   5255  * any projects running in the zone would be trashed if this function
   5256  * were to run after the zone had booted.  It also does not reset any
   5257  * rctl settings that were removed from zonecfg.  There is still work to be
   5258  * done before we can properly support dynamically updating the resource
   5259  * management settings for a running zone (global or non-global).  Thus, this
   5260  * functionality is undocumented for now.
   5261  */
   5262 /* ARGSUSED */
   5263 static int
   5264 apply_func(int argc, char *argv[])
   5265 {
   5266 	int err;
   5267 	int res = Z_OK;
   5268 	priv_set_t *privset;
   5269 	zoneid_t zoneid;
   5270 	zone_dochandle_t handle;
   5271 	struct zone_mcaptab mcap;
   5272 	char pool_err[128];
   5273 
   5274 	zoneid = getzoneid();
   5275 
   5276 	if (zonecfg_in_alt_root() || zoneid != GLOBAL_ZONEID ||
   5277 	    target_zone == NULL || strcmp(target_zone, GLOBAL_ZONENAME) != 0)
   5278 		return (usage(B_FALSE));
   5279 
   5280 	if ((privset = priv_allocset()) == NULL) {
   5281 		zerror(gettext("%s failed"), "priv_allocset");
   5282 		return (Z_ERR);
   5283 	}
   5284 
   5285 	if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
   5286 		zerror(gettext("%s failed"), "getppriv");
   5287 		priv_freeset(privset);
   5288 		return (Z_ERR);
   5289 	}
   5290 
   5291 	if (priv_isfullset(privset) == B_FALSE) {
   5292 		(void) usage(B_FALSE);
   5293 		priv_freeset(privset);
   5294 		return (Z_ERR);
   5295 	}
   5296 	priv_freeset(privset);
   5297 
   5298 	if ((handle = zonecfg_init_handle()) == NULL) {
   5299 		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
   5300 		return (Z_ERR);
   5301 	}
   5302 
   5303 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
   5304 		errno = err;
   5305 		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
   5306 		zonecfg_fini_handle(handle);
   5307 		return (Z_ERR);
   5308 	}
   5309 
   5310 	/* specific error msgs are printed within apply_rctls */
   5311 	if ((err = zonecfg_apply_rctls(target_zone, handle)) != Z_OK) {
   5312 		errno = err;
   5313 		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
   5314 		res = Z_ERR;
   5315 	}
   5316 
   5317 	if ((err = check_cpu_shares_sched(handle)) != Z_OK)
   5318 		res = Z_ERR;
   5319 
   5320 	if (pool_configured(handle)) {
   5321 		if (mixed_pools(zoneid)) {
   5322 			zerror(gettext("Zone is using multiple resource "
   5323 			    "pools.  The pool\nconfiguration cannot be "
   5324 			    "applied without rebooting."));
   5325 			res = Z_ERR;
   5326 		} else {
   5327 
   5328 			/*
   5329 			 * The next two blocks of code attempt to set up
   5330 			 * temporary pools as well as persistent pools.  In
   5331 			 * both cases we call the functions unconditionally.
   5332 			 * Within each funtion the code will check if the zone
   5333 			 * is actually configured for a temporary pool or
   5334 			 * persistent pool and just return if there is nothing
   5335 			 * to do.
   5336 			 */
   5337 			if ((err = zonecfg_bind_tmp_pool(handle, zoneid,
   5338 			    pool_err, sizeof (pool_err))) != Z_OK) {
   5339 				if (err == Z_POOL || err == Z_POOL_CREATE ||
   5340 				    err == Z_POOL_BIND)
   5341 					zerror("%s: %s", zonecfg_strerror(err),
   5342 					    pool_err);
   5343 				else
   5344 					zerror(gettext("could not bind zone to "
   5345 					    "temporary pool: %s"),
   5346 					    zonecfg_strerror(err));
   5347 				res = Z_ERR;
   5348 			}
   5349 
   5350 			if ((err = zonecfg_bind_pool(handle, zoneid, pool_err,
   5351 			    sizeof (pool_err))) != Z_OK) {
   5352 				if (err == Z_POOL || err == Z_POOL_BIND)
   5353 					zerror("%s: %s", zonecfg_strerror(err),
   5354 					    pool_err);
   5355 				else
   5356 					zerror("%s", zonecfg_strerror(err));
   5357 			}
   5358 		}
   5359 	}
   5360 
   5361 	/*
   5362 	 * If a memory cap is configured, set the cap in the kernel using
   5363 	 * zone_setattr() and make sure the rcapd SMF service is enabled.
   5364 	 */
   5365 	if (zonecfg_getmcapent(handle, &mcap) == Z_OK) {
   5366 		uint64_t num;
   5367 		char smf_err[128];
   5368 
   5369 		num = (uint64_t)strtoll(mcap.zone_physmem_cap, NULL, 10);
   5370 		if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) {
   5371 			zerror(gettext("could not set zone memory cap"));
   5372 			res = Z_ERR;
   5373 		}
   5374 
   5375 		if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
   5376 			zerror(gettext("enabling system/rcap service failed: "
   5377 			    "%s"), smf_err);
   5378 			res = Z_ERR;
   5379 		}
   5380 	}
   5381 
   5382 	zonecfg_fini_handle(handle);
   5383 
   5384 	return (res);
   5385 }
   5386 
   5387 /*
   5388  * This is an undocumented interface that is invoked by the zones SMF service
   5389  * for installed zones that won't automatically boot.
   5390  */
   5391 /* ARGSUSED */
   5392 static int
   5393 sysboot_func(int argc, char *argv[])
   5394 {
   5395 	int err;
   5396 	zone_dochandle_t zone_handle;
   5397 	brand_handle_t brand_handle;
   5398 	char cmdbuf[MAXPATHLEN];
   5399 	char zonepath[MAXPATHLEN];
   5400 
   5401 	/*
   5402 	 * This subcommand can only be executed in the global zone on non-global
   5403 	 * zones.
   5404 	 */
   5405 	if (zonecfg_in_alt_root())
   5406 		return (usage(B_FALSE));
   5407 	if (sanity_check(target_zone, CMD_SYSBOOT, B_FALSE, B_TRUE, B_FALSE) !=
   5408 	    Z_OK)
   5409 		return (Z_ERR);
   5410 
   5411 	/*
   5412 	 * Fetch the sysboot hook from the target zone's brand.
   5413 	 */
   5414 	if ((zone_handle = zonecfg_init_handle()) == NULL) {
   5415 		zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE);
   5416 		return (Z_ERR);
   5417 	}
   5418 	if ((err = zonecfg_get_handle(target_zone, zone_handle)) != Z_OK) {
   5419 		errno = err;
   5420 		zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE);
   5421 		zonecfg_fini_handle(zone_handle);
   5422 		return (Z_ERR);
   5423 	}
   5424 	if ((err = zonecfg_get_zonepath(zone_handle, zonepath,
   5425 	    sizeof (zonepath))) != Z_OK) {
   5426 		errno = err;
   5427 		zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE);
   5428 		zonecfg_fini_handle(zone_handle);
   5429 		return (Z_ERR);
   5430 	}
   5431 	if ((brand_handle = brand_open(target_brand)) == NULL) {
   5432 		zerror(gettext("missing or invalid brand during %s operation: "
   5433 		    "%s"), cmd_to_str(CMD_SYSBOOT), target_brand);
   5434 		zonecfg_fini_handle(zone_handle);
   5435 		return (Z_ERR);
   5436 	}
   5437 	err = get_hook(brand_handle, cmdbuf, sizeof (cmdbuf), brand_get_sysboot,
   5438 	    target_zone, zonepath);
   5439 	brand_close(brand_handle);
   5440 	zonecfg_fini_handle(zone_handle);
   5441 	if (err != Z_OK) {
   5442 		zerror(gettext("unable to get brand hook from brand %s for %s "
   5443 		    "operation"), target_brand, cmd_to_str(CMD_SYSBOOT));
   5444 		return (Z_ERR);
   5445 	}
   5446 
   5447 	/*
   5448 	 * If the hook wasn't defined (which is OK), then indicate success and
   5449 	 * return.  Otherwise, execute the hook.
   5450 	 */
   5451 	if (cmdbuf[0] != '\0')
   5452 		return ((subproc_status(gettext("brand sysboot operation"),
   5453 		    do_subproc(cmdbuf), B_FALSE) == ZONE_SUBPROC_OK) ? Z_OK :
   5454 		    Z_BRAND_ERROR);
   5455 	return (Z_OK);
   5456 }
   5457 
   5458 static int
   5459 help_func(int argc, char *argv[])
   5460 {
   5461 	int arg, cmd_num;
   5462 
   5463 	if (argc == 0) {
   5464 		(void) usage(B_TRUE);
   5465 		return (Z_OK);
   5466 	}
   5467 	optind = 0;
   5468 	if ((arg = getopt(argc, argv, "?")) != EOF) {
   5469 		switch (arg) {
   5470 		case '?':
   5471 			sub_usage(SHELP_HELP, CMD_HELP);
   5472 			return (optopt == '?' ? Z_OK : Z_USAGE);
   5473 		default:
   5474 			sub_usage(SHELP_HELP, CMD_HELP);
   5475 			return (Z_USAGE);
   5476 		}
   5477 	}
   5478 	while (optind < argc) {
   5479 		/* Private commands have NULL short_usage; omit them */
   5480 		if ((cmd_num = cmd_match(argv[optind])) < 0 ||
   5481 		    cmdtab[cmd_num].short_usage == NULL) {
   5482 			sub_usage(SHELP_HELP, CMD_HELP);
   5483 			return (Z_USAGE);
   5484 		}
   5485 		sub_usage(cmdtab[cmd_num].short_usage, cmd_num);
   5486 		optind++;
   5487 	}
   5488 	return (Z_OK);
   5489 }
   5490 
   5491 /*
   5492  * Returns: CMD_MIN thru CMD_MAX on success, -1 on error
   5493  */
   5494 
   5495 static int
   5496 cmd_match(char *cmd)
   5497 {
   5498 	int i;
   5499 
   5500 	for (i = CMD_MIN; i <= CMD_MAX; i++) {
   5501 		/* return only if there is an exact match */
   5502 		if (strcmp(cmd, cmdtab[i].cmd_name) == 0)
   5503 			return (cmdtab[i].cmd_num);
   5504 	}
   5505 	return (-1);
   5506 }
   5507 
   5508 static int
   5509 parse_and_run(int argc, char *argv[])
   5510 {
   5511 	int i = cmd_match(argv[0]);
   5512 
   5513 	if (i < 0)
   5514 		return (usage(B_FALSE));
   5515 	return (cmdtab[i].handler(argc - 1, &(argv[1])));
   5516 }
   5517 
   5518 static char *
   5519 get_execbasename(char *execfullname)
   5520 {
   5521 	char *last_slash, *execbasename;
   5522 
   5523 	/* guard against '/' at end of command invocation */
   5524 	for (;;) {
   5525 		last_slash = strrchr(execfullname, '/');
   5526 		if (last_slash == NULL) {
   5527 			execbasename = execfullname;
   5528 			break;
   5529 		} else {
   5530 			execbasename = last_slash + 1;
   5531 			if (*execbasename == '\0') {
   5532 				*last_slash = '\0';
   5533 				continue;
   5534 			}
   5535 			break;
   5536 		}
   5537 	}
   5538 	return (execbasename);
   5539 }
   5540 
   5541 static char *
   5542 get_username()
   5543 {
   5544 	uid_t uid;
   5545 	struct passwd *nptr;
   5546 
   5547 
   5548 	/*
   5549 	 * Authorizations are checked to restrict access based on the
   5550 	 * requested operation and zone name, It is assumed that the
   5551 	 * program is running with all privileges, but that the real
   5552 	 * user ID is that of the user or role on whose behalf we are
   5553 	 * operating. So we start by getting the username that will be
   5554 	 * used for subsequent authorization checks.
   5555 	 */
   5556 
   5557 	uid = getuid();
   5558 	if ((nptr = getpwuid(uid)) == NULL) {
   5559 		zerror(gettext("could not get user name."));
   5560 		exit(Z_ERR);
   5561 	}
   5562 	return (nptr->pw_name);
   5563 }
   5564 
   5565 int
   5566 main(int argc, char **argv)
   5567 {
   5568 	int arg;
   5569 	zoneid_t zid;
   5570 	struct stat st;
   5571 	char *zone_lock_env;
   5572 	int err;
   5573 
   5574 	if ((locale = setlocale(LC_ALL, "")) == NULL)
   5575 		locale = "C";
   5576 	(void) textdomain(TEXT_DOMAIN);
   5577 	setbuf(stdout, NULL);
   5578 	(void) sigset(SIGHUP, SIG_IGN);
   5579 	execname = get_execbasename(argv[0]);
   5580 	username = get_username();
   5581 	target_zone = NULL;
   5582 	if (chdir("/") != 0) {
   5583 		zerror(gettext("could not change directory to /."));
   5584 		exit(Z_ERR);
   5585 	}
   5586 
   5587 	/*
   5588 	 * Use the default system mask rather than anything that may have been
   5589 	 * set by the caller.
   5590 	 */
   5591 	(void) umask(CMASK);
   5592 
   5593 	if (init_zfs() != Z_OK)
   5594 		exit(Z_ERR);
   5595 
   5596 	while ((arg = getopt(argc, argv, "?u:z:R:")) != EOF) {
   5597 		switch (arg) {
   5598 		case '?':
   5599 			return (usage(B_TRUE));
   5600 		case 'u':
   5601 			target_uuid = optarg;
   5602 			break;
   5603 		case 'z':
   5604 			target_zone = optarg;
   5605 			break;
   5606 		case 'R':	/* private option for admin/install use */
   5607 			if (*optarg != '/') {
   5608 				zerror(gettext("root path must be absolute."));
   5609 				exit(Z_ERR);
   5610 			}
   5611 			if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
   5612 				zerror(
   5613 				    gettext("root path must be a directory."));
   5614 				exit(Z_ERR);
   5615 			}
   5616 			zonecfg_set_root(optarg);
   5617 			break;
   5618 		default:
   5619 			return (usage(B_FALSE));
   5620 		}
   5621 	}
   5622 
   5623 	if (optind >= argc)
   5624 		return (usage(B_FALSE));
   5625 
   5626 	if (target_uuid != NULL && *target_uuid != '\0') {
   5627 		uuid_t uuid;
   5628 		static char newtarget[ZONENAME_MAX];
   5629 
   5630 		if (uuid_parse(target_uuid, uuid) == -1) {
   5631 			zerror(gettext("illegal UUID value specified"));
   5632 			exit(Z_ERR);
   5633 		}
   5634 		if (zonecfg_get_name_by_uuid(uuid, newtarget,
   5635 		    sizeof (newtarget)) == Z_OK)
   5636 			target_zone = newtarget;
   5637 	}
   5638 
   5639 	if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) {
   5640 		errno = Z_NO_ZONE;
   5641 		zperror(target_zone, B_TRUE);
   5642 		exit(Z_ERR);
   5643 	}
   5644 
   5645 	/*
   5646 	 * See if we have inherited the right to manipulate this zone from
   5647 	 * a zoneadm instance in our ancestry.  If so, set zone_lock_cnt to
   5648 	 * indicate it.  If not, make that explicit in our environment.
   5649 	 */
   5650 	zonecfg_init_lock_file(target_zone, &zone_lock_env);
   5651 
   5652 	/* Figure out what the system's default brand is */
   5653 	if (zonecfg_default_brand(default_brand,
   5654 	    sizeof (default_brand)) != Z_OK) {
   5655 		zerror(gettext("unable to determine default brand"));
   5656 		return (Z_ERR);
   5657 	}
   5658 
   5659 	/*
   5660 	 * If we are going to be operating on a single zone, retrieve its
   5661 	 * brand type and determine whether it is native or not.
   5662 	 */
   5663 	if ((target_zone != NULL) &&
   5664 	    (strcmp(target_zone, GLOBAL_ZONENAME) != 0)) {
   5665 		if (zone_get_brand(target_zone, target_brand,
   5666 		    sizeof (target_brand)) != Z_OK) {
   5667 			zerror(gettext("missing or invalid brand"));
   5668 			exit(Z_ERR);
   5669 		}
   5670 		/*
   5671 		 * In the alternate root environment, the only supported
   5672 		 * operations are mount and unmount.  In this case, just treat
   5673 		 * the zone as native if it is cluster.  Cluster zones can be
   5674 		 * native for the purpose of LU or upgrade, and the cluster
   5675 		 * brand may not exist in the miniroot (such as in net install
   5676 		 * upgrade).
   5677 		 */
   5678 		if (strcmp(target_brand, CLUSTER_BRAND_NAME) == 0) {
   5679 			if (zonecfg_in_alt_root()) {
   5680 				(void) strlcpy(target_brand, default_brand,
   5681 				    sizeof (target_brand));
   5682 			}
   5683 		}
   5684 	}
   5685 
   5686 	err = parse_and_run(argc - optind, &argv[optind]);
   5687 
   5688 	return (err);
   5689 }
   5690