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