xref: /illumos-gate/usr/src/cmd/zoneadm/zoneadm.c (revision d12abe7ce2663ac39e686a14960eb4febf560195)
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 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * zoneadm is a command interpreter for zone administration.  It is all in
31  * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
32  * main() calls parse_and_run() which calls cmd_match(), then invokes the
33  * appropriate command's handler function.  The rest of the program is the
34  * handler functions and their helper functions.
35  *
36  * Some of the helper functions are used largely to simplify I18N: reducing
37  * the need for translation notes.  This is particularly true of many of
38  * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
39  * than zerror(gettext("foo failed")) with a translation note indicating
40  * that "foo" need not be translated.
41  */
42 
43 #include <stdio.h>
44 #include <errno.h>
45 #include <unistd.h>
46 #include <signal.h>
47 #include <stdarg.h>
48 #include <ctype.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <wait.h>
52 #include <zone.h>
53 #include <priv.h>
54 #include <locale.h>
55 #include <libintl.h>
56 #include <libzonecfg.h>
57 #include <bsm/adt.h>
58 #include <sys/param.h>
59 #include <sys/types.h>
60 #include <sys/stat.h>
61 #include <sys/statvfs.h>
62 #include <assert.h>
63 #include <sys/sockio.h>
64 #include <sys/mntent.h>
65 #include <limits.h>
66 #include <dirent.h>
67 
68 #include <fcntl.h>
69 #include <door.h>
70 #include <macros.h>
71 #include <libgen.h>
72 #include <fnmatch.h>
73 #include <sys/modctl.h>
74 
75 #include <pool.h>
76 #include <sys/pool.h>
77 
78 #include "zoneadm.h"
79 
80 #define	MAXARGS	8
81 
82 /* Reflects kernel zone entries */
83 typedef struct zone_entry {
84 	zoneid_t	zid;
85 	char		zname[ZONENAME_MAX];
86 	char		*zstate_str;
87 	zone_state_t	zstate_num;
88 	char		zroot[MAXPATHLEN];
89 } zone_entry_t;
90 
91 static zone_entry_t *zents;
92 static size_t nzents;
93 
94 #define	LOOPBACK_IF	"lo0"
95 #define	SOCKET_AF(af)	(((af) == AF_UNSPEC) ? AF_INET : (af))
96 
97 struct net_if {
98 	char	*name;
99 	int	af;
100 };
101 
102 /* 0755 is the default directory mode. */
103 #define	DEFAULT_DIR_MODE \
104 	(S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
105 
106 struct cmd {
107 	uint_t	cmd_num;				/* command number */
108 	char	*cmd_name;				/* command name */
109 	char	*short_usage;				/* short form help */
110 	int	(*handler)(int argc, char *argv[]);	/* function to call */
111 
112 };
113 
114 #define	SHELP_HELP	"help"
115 #define	SHELP_BOOT	"boot [-s]"
116 #define	SHELP_HALT	"halt"
117 #define	SHELP_READY	"ready"
118 #define	SHELP_REBOOT	"reboot"
119 #define	SHELP_LIST	"list [-cipv]"
120 #define	SHELP_VERIFY	"verify"
121 #define	SHELP_INSTALL	"install [-x nodataset]"
122 #define	SHELP_UNINSTALL	"uninstall [-F]"
123 #define	SHELP_CLONE	"clone [-m method] [-s <ZFS snapshot>] zonename"
124 #define	SHELP_MOVE	"move zonepath"
125 #define	SHELP_DETACH	"detach"
126 #define	SHELP_ATTACH	"attach [-F]"
127 
128 static int help_func(int argc, char *argv[]);
129 static int ready_func(int argc, char *argv[]);
130 static int boot_func(int argc, char *argv[]);
131 static int halt_func(int argc, char *argv[]);
132 static int reboot_func(int argc, char *argv[]);
133 static int list_func(int argc, char *argv[]);
134 static int verify_func(int argc, char *argv[]);
135 static int install_func(int argc, char *argv[]);
136 static int uninstall_func(int argc, char *argv[]);
137 static int mount_func(int argc, char *argv[]);
138 static int unmount_func(int argc, char *argv[]);
139 static int clone_func(int argc, char *argv[]);
140 static int move_func(int argc, char *argv[]);
141 static int detach_func(int argc, char *argv[]);
142 static int attach_func(int argc, char *argv[]);
143 static int sanity_check(char *zone, int cmd_num, boolean_t running,
144     boolean_t unsafe_when_running);
145 static int cmd_match(char *cmd);
146 static int verify_details(int);
147 
148 static struct cmd cmdtab[] = {
149 	{ CMD_HELP,		"help",		SHELP_HELP,	help_func },
150 	{ CMD_BOOT,		"boot",		SHELP_BOOT,	boot_func },
151 	{ CMD_HALT,		"halt",		SHELP_HALT,	halt_func },
152 	{ CMD_READY,		"ready",	SHELP_READY,	ready_func },
153 	{ CMD_REBOOT,		"reboot",	SHELP_REBOOT,	reboot_func },
154 	{ CMD_LIST,		"list",		SHELP_LIST,	list_func },
155 	{ CMD_VERIFY,		"verify",	SHELP_VERIFY,	verify_func },
156 	{ CMD_INSTALL,		"install",	SHELP_INSTALL,	install_func },
157 	{ CMD_UNINSTALL,	"uninstall",	SHELP_UNINSTALL,
158 	    uninstall_func },
159 	/* mount and unmount are private commands for admin/install */
160 	{ CMD_MOUNT,		"mount",	NULL,		mount_func },
161 	{ CMD_UNMOUNT,		"unmount",	NULL,		unmount_func },
162 	{ CMD_CLONE,		"clone",	SHELP_CLONE,	clone_func },
163 	{ CMD_MOVE,		"move",		SHELP_MOVE,	move_func },
164 	{ CMD_DETACH,		"detach",	SHELP_DETACH,	detach_func },
165 	{ CMD_ATTACH,		"attach",	SHELP_ATTACH,	attach_func }
166 };
167 
168 /* global variables */
169 
170 /* set early in main(), never modified thereafter, used all over the place */
171 static char *execname;
172 static char *locale;
173 char *target_zone;
174 
175 /* used in do_subproc() and signal handler */
176 static volatile boolean_t child_killed;
177 
178 char *
179 cmd_to_str(int cmd_num)
180 {
181 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
182 	return (cmdtab[cmd_num].cmd_name);
183 }
184 
185 /* This is a separate function because of gettext() wrapping. */
186 static char *
187 long_help(int cmd_num)
188 {
189 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
190 	switch (cmd_num) {
191 	case CMD_HELP:
192 		return (gettext("Print usage message."));
193 	case CMD_BOOT:
194 		return (gettext("Activates (boots) specified zone.  "
195 		    "The -s flag can be used\n\tto boot the zone in "
196 		    "the single-user state."));
197 	case CMD_HALT:
198 		return (gettext("Halts specified zone, bypassing shutdown "
199 		    "scripts and removing runtime\n\tresources of the zone."));
200 	case CMD_READY:
201 		return (gettext("Prepares a zone for running applications but "
202 		    "does not start any user\n\tprocesses in the zone."));
203 	case CMD_REBOOT:
204 		return (gettext("Restarts the zone (equivalent to a halt / "
205 		    "boot sequence).\n\tFails if the zone is not active."));
206 	case CMD_LIST:
207 		return (gettext("Lists the current zones, or a "
208 		    "specific zone if indicated.  By default,\n\tall "
209 		    "running zones are listed, though this can be "
210 		    "expanded to all\n\tinstalled zones with the -i "
211 		    "option or all configured zones with the\n\t-c "
212 		    "option.  When used with the general -z <zone> "
213 		    "option, lists only the\n\tspecified zone, but "
214 		    "lists it regardless of its state, and the -i "
215 		    "and -c\n\toptions are disallowed.  The -v option "
216 		    "can be used to display verbose\n\tinformation: "
217 		    "zone name, id, current state, root directory and "
218 		    "options.\n\tThe -p option can be used to request "
219 		    "machine-parsable output.  The -v\n\tand -p "
220 		    "options are mutually exclusive.  If neither -v "
221 		    "nor -p is used,\n\tjust the zone name is listed."));
222 	case CMD_VERIFY:
223 		return (gettext("Check to make sure the configuration "
224 		    "can safely be instantiated\n\ton the machine: "
225 		    "physical network interfaces exist, etc."));
226 	case CMD_INSTALL:
227 		return (gettext("Install the configuration on to the system.  "
228 		    "The -x nodataset option\n\tcan be used to prevent the "
229 		    "creation of a new ZFS file system for the\n\tzone "
230 		    "(assuming the zonepath is within a ZFS file system)."));
231 	case CMD_UNINSTALL:
232 		return (gettext("Uninstall the configuration from the system.  "
233 		    "The -F flag can be used\n\tto force the action."));
234 	case CMD_CLONE:
235 		return (gettext("Clone the installation of another zone.  "
236 		    "The -m option can be used to\n\tspecify 'copy' which "
237 		    "forces a copy of the source zone.  The -s option\n\t"
238 		    "can be used to specify the name of a ZFS snapshot "
239 		    "that was taken from\n\ta previous clone command.  The "
240 		    "snapshot will be used as the source\n\tinstead of "
241 		    "creating a new ZFS snapshot."));
242 	case CMD_MOVE:
243 		return (gettext("Move the zone to a new zonepath."));
244 	case CMD_DETACH:
245 		return (gettext("Detach the zone from the system. The zone "
246 		    "state is changed to\n\t'configured' (but the files under "
247 		    "the zonepath are untouched).\n\tThe zone can subsequently "
248 		    "be attached, or can be moved to another\n\tsystem and "
249 		    "attached there."));
250 	case CMD_ATTACH:
251 		return (gettext("Attach the zone to the system.  The zone "
252 		    "state must be 'configured'\n\tprior to attach; upon "
253 		    "successful completion, the zone state will be\n\t"
254 		    "'installed'.  The system software on the current "
255 		    "system must be\n\tcompatible with the software on the "
256 		    "zone's original system.\n\tSpecify -F to force the attach "
257 		    "and skip software compatibility tests."));
258 	default:
259 		return ("");
260 	}
261 	/* NOTREACHED */
262 	return (NULL);
263 }
264 
265 /*
266  * Called with explicit B_TRUE when help is explicitly requested, B_FALSE for
267  * unexpected errors.
268  */
269 
270 static int
271 usage(boolean_t explicit)
272 {
273 	int i;
274 	FILE *fd = explicit ? stdout : stderr;
275 
276 	(void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname);
277 	(void) fprintf(fd, "\t%s [-z <zone>] list\n", execname);
278 	(void) fprintf(fd, "\t%s -z <zone> <%s>\n", execname,
279 	    gettext("subcommand"));
280 	(void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands"));
281 	for (i = CMD_MIN; i <= CMD_MAX; i++) {
282 		if (cmdtab[i].short_usage == NULL)
283 			continue;
284 		(void) fprintf(fd, "%s\n", cmdtab[i].short_usage);
285 		if (explicit)
286 			(void) fprintf(fd, "\t%s\n\n", long_help(i));
287 	}
288 	if (!explicit)
289 		(void) fputs("\n", fd);
290 	return (Z_USAGE);
291 }
292 
293 static void
294 sub_usage(char *short_usage, int cmd_num)
295 {
296 	(void) fprintf(stderr, "%s:\t%s\n", gettext("usage"), short_usage);
297 	(void) fprintf(stderr, "\t%s\n", long_help(cmd_num));
298 }
299 
300 /*
301  * zperror() is like perror(3c) except that this also prints the executable
302  * name at the start of the message, and takes a boolean indicating whether
303  * to call libc'c strerror() or that from libzonecfg.
304  */
305 
306 void
307 zperror(const char *str, boolean_t zonecfg_error)
308 {
309 	(void) fprintf(stderr, "%s: %s: %s\n", execname, str,
310 	    zonecfg_error ? zonecfg_strerror(errno) : strerror(errno));
311 }
312 
313 /*
314  * zperror2() is very similar to zperror() above, except it also prints a
315  * supplied zone name after the executable.
316  *
317  * All current consumers of this function want libzonecfg's strerror() rather
318  * than libc's; if this ever changes, this function can be made more generic
319  * like zperror() above.
320  */
321 
322 void
323 zperror2(const char *zone, const char *str)
324 {
325 	(void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str,
326 	    zonecfg_strerror(errno));
327 }
328 
329 /* PRINTFLIKE1 */
330 void
331 zerror(const char *fmt, ...)
332 {
333 	va_list alist;
334 
335 	va_start(alist, fmt);
336 	(void) fprintf(stderr, "%s: ", execname);
337 	if (target_zone != NULL)
338 		(void) fprintf(stderr, "zone '%s': ", target_zone);
339 	(void) vfprintf(stderr, fmt, alist);
340 	(void) fprintf(stderr, "\n");
341 	va_end(alist);
342 }
343 
344 static void *
345 safe_calloc(size_t nelem, size_t elsize)
346 {
347 	void *r = calloc(nelem, elsize);
348 
349 	if (r == NULL) {
350 		zerror(gettext("failed to allocate %lu bytes: %s"),
351 		    (ulong_t)nelem * elsize, strerror(errno));
352 		exit(Z_ERR);
353 	}
354 	return (r);
355 }
356 
357 static void
358 zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable)
359 {
360 	static boolean_t firsttime = B_TRUE;
361 
362 	assert(!(verbose && parsable));
363 	if (firsttime && verbose) {
364 		firsttime = B_FALSE;
365 		(void) printf("%*s %-16s %-14s %-30s\n", ZONEID_WIDTH, "ID",
366 		    "NAME", "STATUS", "PATH");
367 	}
368 	if (!verbose) {
369 		if (!parsable) {
370 			(void) printf("%s\n", zent->zname);
371 			return;
372 		}
373 		if (zent->zid == ZONE_ID_UNDEFINED)
374 			(void) printf("-");
375 		else
376 			(void) printf("%lu", zent->zid);
377 		(void) printf(":%s:%s:%s\n", zent->zname, zent->zstate_str,
378 		    zent->zroot);
379 		return;
380 	}
381 	if (zent->zstate_str != NULL) {
382 		if (zent->zid == ZONE_ID_UNDEFINED)
383 			(void) printf("%*s", ZONEID_WIDTH, "-");
384 		else
385 			(void) printf("%*lu", ZONEID_WIDTH, zent->zid);
386 		(void) printf(" %-16s %-14s %-30s\n", zent->zname,
387 		    zent->zstate_str, zent->zroot);
388 	}
389 }
390 
391 static int
392 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
393 {
394 	char root[MAXPATHLEN], *cp;
395 	int err;
396 
397 	(void) strlcpy(zent->zname, zone_name, sizeof (zent->zname));
398 	(void) strlcpy(zent->zroot, "???", sizeof (zent->zroot));
399 	zent->zstate_str = "???";
400 
401 	zent->zid = zid;
402 
403 	/*
404 	 * For labeled zones which query the zone path of lower-level
405 	 * zones, the path needs to be adjusted to drop the final
406 	 * "/root" component. This adjusted path is then useful
407 	 * for reading down any exported directories from the
408 	 * lower-level zone.
409 	 */
410 	if (is_system_labeled() && zent->zid != ZONE_ID_UNDEFINED) {
411 		if (zone_getattr(zent->zid, ZONE_ATTR_ROOT, zent->zroot,
412 		    sizeof (zent->zroot)) == -1) {
413 			zperror2(zent->zname,
414 			    gettext("could not get zone path."));
415 			return (Z_ERR);
416 		}
417 		cp = zent->zroot + strlen(zent->zroot) - 5;
418 		if (cp > zent->zroot && strcmp(cp, "/root") == 0)
419 			*cp = 0;
420 	} else {
421 		if ((err = zone_get_zonepath(zent->zname, root,
422 		    sizeof (root))) != Z_OK) {
423 			errno = err;
424 			zperror2(zent->zname,
425 			    gettext("could not get zone path."));
426 			return (Z_ERR);
427 		}
428 		(void) strlcpy(zent->zroot, root, sizeof (zent->zroot));
429 	}
430 
431 	if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) {
432 		errno = err;
433 		zperror2(zent->zname, gettext("could not get state"));
434 		return (Z_ERR);
435 	}
436 	zent->zstate_str = zone_state_str(zent->zstate_num);
437 
438 	return (Z_OK);
439 }
440 
441 /*
442  * fetch_zents() calls zone_list(2) to find out how many zones are running
443  * (which is stored in the global nzents), then calls zone_list(2) again
444  * to fetch the list of running zones (stored in the global zents).  This
445  * function may be called multiple times, so if zents is already set, we
446  * return immediately to save work.
447  */
448 
449 static int
450 fetch_zents(void)
451 {
452 	zoneid_t *zids = NULL;
453 	uint_t nzents_saved;
454 	int i, retv;
455 	FILE *fp;
456 	boolean_t inaltroot;
457 	zone_entry_t *zentp;
458 
459 	if (nzents > 0)
460 		return (Z_OK);
461 
462 	if (zone_list(NULL, &nzents) != 0) {
463 		zperror(gettext("failed to get zoneid list"), B_FALSE);
464 		return (Z_ERR);
465 	}
466 
467 again:
468 	if (nzents == 0)
469 		return (Z_OK);
470 
471 	zids = safe_calloc(nzents, sizeof (zoneid_t));
472 	nzents_saved = nzents;
473 
474 	if (zone_list(zids, &nzents) != 0) {
475 		zperror(gettext("failed to get zone list"), B_FALSE);
476 		free(zids);
477 		return (Z_ERR);
478 	}
479 	if (nzents != nzents_saved) {
480 		/* list changed, try again */
481 		free(zids);
482 		goto again;
483 	}
484 
485 	zents = safe_calloc(nzents, sizeof (zone_entry_t));
486 
487 	inaltroot = zonecfg_in_alt_root();
488 	if (inaltroot)
489 		fp = zonecfg_open_scratch("", B_FALSE);
490 	else
491 		fp = NULL;
492 	zentp = zents;
493 	retv = Z_OK;
494 	for (i = 0; i < nzents; i++) {
495 		char name[ZONENAME_MAX];
496 		char altname[ZONENAME_MAX];
497 
498 		if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) {
499 			zperror(gettext("failed to get zone name"), B_FALSE);
500 			retv = Z_ERR;
501 			continue;
502 		}
503 		if (zonecfg_is_scratch(name)) {
504 			/* Ignore scratch zones by default */
505 			if (!inaltroot)
506 				continue;
507 			if (fp == NULL ||
508 			    zonecfg_reverse_scratch(fp, name, altname,
509 			    sizeof (altname), NULL, 0) == -1) {
510 				zerror(gettext("could not resolve scratch "
511 				    "zone %s"), name);
512 				retv = Z_ERR;
513 				continue;
514 			}
515 			(void) strcpy(name, altname);
516 		} else {
517 			/* Ignore non-scratch when in an alternate root */
518 			if (inaltroot && strcmp(name, GLOBAL_ZONENAME) != 0)
519 				continue;
520 		}
521 		if (lookup_zone_info(name, zids[i], zentp) != Z_OK) {
522 			zerror(gettext("failed to get zone data"));
523 			retv = Z_ERR;
524 			continue;
525 		}
526 		zentp++;
527 	}
528 	nzents = zentp - zents;
529 	if (fp != NULL)
530 		zonecfg_close_scratch(fp);
531 
532 	free(zids);
533 	return (retv);
534 }
535 
536 static int
537 zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable)
538 {
539 	int i;
540 	zone_entry_t zent;
541 	FILE *cookie;
542 	char *name;
543 
544 	/*
545 	 * First get the list of running zones from the kernel and print them.
546 	 * If that is all we need, then return.
547 	 */
548 	if ((i = fetch_zents()) != Z_OK) {
549 		/*
550 		 * No need for error messages; fetch_zents() has already taken
551 		 * care of this.
552 		 */
553 		return (i);
554 	}
555 	for (i = 0; i < nzents; i++)
556 		zone_print(&zents[i], verbose, parsable);
557 	if (min_state >= ZONE_STATE_RUNNING)
558 		return (Z_OK);
559 	/*
560 	 * Next, get the full list of zones from the configuration, skipping
561 	 * any we have already printed.
562 	 */
563 	cookie = setzoneent();
564 	while ((name = getzoneent(cookie)) != NULL) {
565 		for (i = 0; i < nzents; i++) {
566 			if (strcmp(zents[i].zname, name) == 0)
567 				break;
568 		}
569 		if (i < nzents) {
570 			free(name);
571 			continue;
572 		}
573 		if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
574 			free(name);
575 			continue;
576 		}
577 		free(name);
578 		if (zent.zstate_num >= min_state)
579 			zone_print(&zent, verbose, parsable);
580 	}
581 	endzoneent(cookie);
582 	return (Z_OK);
583 }
584 
585 static zone_entry_t *
586 lookup_running_zone(char *str)
587 {
588 	zoneid_t zoneid;
589 	char *cp;
590 	int i;
591 
592 	if (fetch_zents() != Z_OK)
593 		return (NULL);
594 
595 	for (i = 0; i < nzents; i++) {
596 		if (strcmp(str, zents[i].zname) == 0)
597 			return (&zents[i]);
598 	}
599 	errno = 0;
600 	zoneid = strtol(str, &cp, 0);
601 	if (zoneid < MIN_ZONEID || zoneid > MAX_ZONEID ||
602 	    errno != 0 || *cp != '\0')
603 		return (NULL);
604 	for (i = 0; i < nzents; i++) {
605 		if (zoneid == zents[i].zid)
606 			return (&zents[i]);
607 	}
608 	return (NULL);
609 }
610 
611 /*
612  * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if
613  * B_FALSE, it should be off.  Return B_TRUE if the mode is bad (incorrect).
614  */
615 static boolean_t
616 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file)
617 {
618 	char *str;
619 
620 	assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR ||
621 	    bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP ||
622 	    bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH);
623 	/*
624 	 * TRANSLATION_NOTE
625 	 * The strings below will be used as part of a larger message,
626 	 * either:
627 	 * (file name) must be (owner|group|world) (read|writ|execut)able
628 	 * or
629 	 * (file name) must not be (owner|group|world) (read|writ|execut)able
630 	 */
631 	switch (bit) {
632 	case S_IRUSR:
633 		str = gettext("owner readable");
634 		break;
635 	case S_IWUSR:
636 		str = gettext("owner writable");
637 		break;
638 	case S_IXUSR:
639 		str = gettext("owner executable");
640 		break;
641 	case S_IRGRP:
642 		str = gettext("group readable");
643 		break;
644 	case S_IWGRP:
645 		str = gettext("group writable");
646 		break;
647 	case S_IXGRP:
648 		str = gettext("group executable");
649 		break;
650 	case S_IROTH:
651 		str = gettext("world readable");
652 		break;
653 	case S_IWOTH:
654 		str = gettext("world writable");
655 		break;
656 	case S_IXOTH:
657 		str = gettext("world executable");
658 		break;
659 	}
660 	if ((mode & bit) == (on ? 0 : bit)) {
661 		/*
662 		 * TRANSLATION_NOTE
663 		 * The first parameter below is a file name; the second
664 		 * is one of the "(owner|group|world) (read|writ|execut)able"
665 		 * strings from above.
666 		 */
667 		/*
668 		 * The code below could be simplified but not in a way
669 		 * that would easily translate to non-English locales.
670 		 */
671 		if (on) {
672 			(void) fprintf(stderr, gettext("%s must be %s.\n"),
673 			    file, str);
674 		} else {
675 			(void) fprintf(stderr, gettext("%s must not be %s.\n"),
676 			    file, str);
677 		}
678 		return (B_TRUE);
679 	}
680 	return (B_FALSE);
681 }
682 
683 /*
684  * We want to make sure that no zone has its zone path as a child node
685  * (in the directory sense) of any other.  We do that by comparing this
686  * zone's path to the path of all other (non-global) zones.  The comparison
687  * in each case is simple: add '/' to the end of the path, then do a
688  * strncmp() of the two paths, using the length of the shorter one.
689  */
690 
691 static int
692 crosscheck_zonepaths(char *path)
693 {
694 	char rpath[MAXPATHLEN];		/* resolved path */
695 	char path_copy[MAXPATHLEN];	/* copy of original path */
696 	char rpath_copy[MAXPATHLEN];	/* copy of original rpath */
697 	struct zoneent *ze;
698 	int res, err;
699 	FILE *cookie;
700 
701 	cookie = setzoneent();
702 	while ((ze = getzoneent_private(cookie)) != NULL) {
703 		/* Skip zones which are not installed. */
704 		if (ze->zone_state < ZONE_STATE_INSTALLED) {
705 			free(ze);
706 			continue;
707 		}
708 		/* Skip the global zone and the current target zone. */
709 		if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0 ||
710 		    strcmp(ze->zone_name, target_zone) == 0) {
711 			free(ze);
712 			continue;
713 		}
714 		if (strlen(ze->zone_path) == 0) {
715 			/* old index file without path, fall back */
716 			if ((err = zone_get_zonepath(ze->zone_name,
717 			    ze->zone_path, sizeof (ze->zone_path))) != Z_OK) {
718 				errno = err;
719 				zperror2(ze->zone_name,
720 				    gettext("could not get zone path"));
721 				free(ze);
722 				continue;
723 			}
724 		}
725 		(void) snprintf(path_copy, sizeof (path_copy), "%s%s",
726 		    zonecfg_get_root(), ze->zone_path);
727 		res = resolvepath(path_copy, rpath, sizeof (rpath));
728 		if (res == -1) {
729 			if (errno != ENOENT) {
730 				zperror(path_copy, B_FALSE);
731 				free(ze);
732 				return (Z_ERR);
733 			}
734 			(void) printf(gettext("WARNING: zone %s is installed, "
735 			    "but its %s %s does not exist.\n"), ze->zone_name,
736 			    "zonepath", path_copy);
737 			free(ze);
738 			continue;
739 		}
740 		rpath[res] = '\0';
741 		(void) snprintf(path_copy, sizeof (path_copy), "%s/", path);
742 		(void) snprintf(rpath_copy, sizeof (rpath_copy), "%s/", rpath);
743 		if (strncmp(path_copy, rpath_copy,
744 		    min(strlen(path_copy), strlen(rpath_copy))) == 0) {
745 			/*
746 			 * TRANSLATION_NOTE
747 			 * zonepath is a literal that should not be translated.
748 			 */
749 			(void) fprintf(stderr, gettext("%s zonepath (%s) and "
750 			    "%s zonepath (%s) overlap.\n"),
751 			    target_zone, path, ze->zone_name, rpath);
752 			free(ze);
753 			return (Z_ERR);
754 		}
755 		free(ze);
756 	}
757 	endzoneent(cookie);
758 	return (Z_OK);
759 }
760 
761 static int
762 validate_zonepath(char *path, int cmd_num)
763 {
764 	int res;			/* result of last library/system call */
765 	boolean_t err = B_FALSE;	/* have we run into an error? */
766 	struct stat stbuf;
767 	struct statvfs vfsbuf;
768 	char rpath[MAXPATHLEN];		/* resolved path */
769 	char ppath[MAXPATHLEN];		/* parent path */
770 	char rppath[MAXPATHLEN];	/* resolved parent path */
771 	char rootpath[MAXPATHLEN];	/* root path */
772 	zone_state_t state;
773 
774 	if (path[0] != '/') {
775 		(void) fprintf(stderr,
776 		    gettext("%s is not an absolute path.\n"), path);
777 		return (Z_ERR);
778 	}
779 	if ((res = resolvepath(path, rpath, sizeof (rpath))) == -1) {
780 		if ((errno != ENOENT) ||
781 		    (cmd_num != CMD_VERIFY && cmd_num != CMD_INSTALL &&
782 		    cmd_num != CMD_CLONE && cmd_num != CMD_MOVE)) {
783 			zperror(path, B_FALSE);
784 			return (Z_ERR);
785 		}
786 		if (cmd_num == CMD_VERIFY) {
787 			/*
788 			 * TRANSLATION_NOTE
789 			 * zoneadm is a literal that should not be translated.
790 			 */
791 			(void) fprintf(stderr, gettext("WARNING: %s does not "
792 			    "exist, so it could not be verified.\nWhen "
793 			    "'zoneadm %s' is run, '%s' will try to create\n%s, "
794 			    "and '%s' will be tried again,\nbut the '%s' may "
795 			    "fail if:\nthe parent directory of %s is group- or "
796 			    "other-writable\nor\n%s overlaps with any other "
797 			    "installed zones.\n"), path,
798 			    cmd_to_str(CMD_INSTALL), cmd_to_str(CMD_INSTALL),
799 			    path, cmd_to_str(CMD_VERIFY),
800 			    cmd_to_str(CMD_VERIFY), path, path);
801 			return (Z_OK);
802 		}
803 		/*
804 		 * The zonepath is supposed to be mode 700 but its
805 		 * parent(s) 755.  So use 755 on the mkdirp() then
806 		 * chmod() the zonepath itself to 700.
807 		 */
808 		if (mkdirp(path, DEFAULT_DIR_MODE) < 0) {
809 			zperror(path, B_FALSE);
810 			return (Z_ERR);
811 		}
812 		/*
813 		 * If the chmod() fails, report the error, but might
814 		 * as well continue the verify procedure.
815 		 */
816 		if (chmod(path, S_IRWXU) != 0)
817 			zperror(path, B_FALSE);
818 		/*
819 		 * Since the mkdir() succeeded, we should not have to
820 		 * worry about a subsequent ENOENT, thus this should
821 		 * only recurse once.
822 		 */
823 		return (validate_zonepath(path, cmd_num));
824 	}
825 	rpath[res] = '\0';
826 	if (strcmp(path, rpath) != 0) {
827 		errno = Z_RESOLVED_PATH;
828 		zperror(path, B_TRUE);
829 		return (Z_ERR);
830 	}
831 	if ((res = stat(rpath, &stbuf)) != 0) {
832 		zperror(rpath, B_FALSE);
833 		return (Z_ERR);
834 	}
835 	if (!S_ISDIR(stbuf.st_mode)) {
836 		(void) fprintf(stderr, gettext("%s is not a directory.\n"),
837 		    rpath);
838 		return (Z_ERR);
839 	}
840 	if ((strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) ||
841 	    (strcmp(stbuf.st_fstype, MNTTYPE_XMEMFS) == 0)) {
842 		(void) printf(gettext("WARNING: %s is on a temporary "
843 		    "file system.\n"), rpath);
844 	}
845 	if (crosscheck_zonepaths(rpath) != Z_OK)
846 		return (Z_ERR);
847 	/*
848 	 * Try to collect and report as many minor errors as possible
849 	 * before returning, so the user can learn everything that needs
850 	 * to be fixed up front.
851 	 */
852 	if (stbuf.st_uid != 0) {
853 		(void) fprintf(stderr, gettext("%s is not owned by root.\n"),
854 		    rpath);
855 		err = B_TRUE;
856 	}
857 	err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath);
858 	err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath);
859 	err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rpath);
860 	err |= bad_mode_bit(stbuf.st_mode, S_IRGRP, B_FALSE, rpath);
861 	err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rpath);
862 	err |= bad_mode_bit(stbuf.st_mode, S_IXGRP, B_FALSE, rpath);
863 	err |= bad_mode_bit(stbuf.st_mode, S_IROTH, B_FALSE, rpath);
864 	err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath);
865 	err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath);
866 
867 	(void) snprintf(ppath, sizeof (ppath), "%s/..", path);
868 	if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) {
869 		zperror(ppath, B_FALSE);
870 		return (Z_ERR);
871 	}
872 	rppath[res] = '\0';
873 	if ((res = stat(rppath, &stbuf)) != 0) {
874 		zperror(rppath, B_FALSE);
875 		return (Z_ERR);
876 	}
877 	/* theoretically impossible */
878 	if (!S_ISDIR(stbuf.st_mode)) {
879 		(void) fprintf(stderr, gettext("%s is not a directory.\n"),
880 		    rppath);
881 		return (Z_ERR);
882 	}
883 	if (stbuf.st_uid != 0) {
884 		(void) fprintf(stderr, gettext("%s is not owned by root.\n"),
885 		    rppath);
886 		err = B_TRUE;
887 	}
888 	err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rppath);
889 	err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rppath);
890 	err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rppath);
891 	err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rppath);
892 	err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rppath);
893 	if (strcmp(rpath, rppath) == 0) {
894 		(void) fprintf(stderr, gettext("%s is its own parent.\n"),
895 		    rppath);
896 		err = B_TRUE;
897 	}
898 
899 	if (statvfs(rpath, &vfsbuf) != 0) {
900 		zperror(rpath, B_FALSE);
901 		return (Z_ERR);
902 	}
903 	if (strcmp(vfsbuf.f_basetype, MNTTYPE_NFS) == 0) {
904 		/*
905 		 * TRANSLATION_NOTE
906 		 * Zonepath and NFS are literals that should not be translated.
907 		 */
908 		(void) fprintf(stderr, gettext("Zonepath %s is on an NFS "
909 		    "mounted file system.\n"
910 		    "\tA local file system must be used.\n"), rpath);
911 		return (Z_ERR);
912 	}
913 	if (vfsbuf.f_flag & ST_NOSUID) {
914 		/*
915 		 * TRANSLATION_NOTE
916 		 * Zonepath and nosuid are literals that should not be
917 		 * translated.
918 		 */
919 		(void) fprintf(stderr, gettext("Zonepath %s is on a nosuid "
920 		    "file system.\n"), rpath);
921 		return (Z_ERR);
922 	}
923 
924 	if ((res = zone_get_state(target_zone, &state)) != Z_OK) {
925 		errno = res;
926 		zperror2(target_zone, gettext("could not get state"));
927 		return (Z_ERR);
928 	}
929 	/*
930 	 * The existence of the root path is only bad in the configured state,
931 	 * as it is *supposed* to be there at the installed and later states.
932 	 * However, the root path is expected to be there if the zone is
933 	 * detached.
934 	 * State/command mismatches are caught earlier in verify_details().
935 	 */
936 	if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) {
937 		if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >=
938 		    sizeof (rootpath)) {
939 			/*
940 			 * TRANSLATION_NOTE
941 			 * Zonepath is a literal that should not be translated.
942 			 */
943 			(void) fprintf(stderr,
944 			    gettext("Zonepath %s is too long.\n"), rpath);
945 			return (Z_ERR);
946 		}
947 		if ((res = stat(rootpath, &stbuf)) == 0) {
948 			if (zonecfg_detached(rpath))
949 				(void) fprintf(stderr,
950 				    gettext("Cannot %s detached "
951 				    "zone.\nUse attach or remove %s "
952 				    "directory.\n"), cmd_to_str(cmd_num),
953 				    rpath);
954 			else
955 				(void) fprintf(stderr,
956 				    gettext("Rootpath %s exists; "
957 				    "remove or move aside prior to %s.\n"),
958 				    rootpath, cmd_to_str(cmd_num));
959 			return (Z_ERR);
960 		}
961 	}
962 
963 	return (err ? Z_ERR : Z_OK);
964 }
965 
966 static void
967 release_lock_file(int lockfd)
968 {
969 	(void) close(lockfd);
970 }
971 
972 static int
973 grab_lock_file(const char *zone_name, int *lockfd)
974 {
975 	char pathbuf[PATH_MAX];
976 	struct flock flock;
977 
978 	if (snprintf(pathbuf, sizeof (pathbuf), "%s%s", zonecfg_get_root(),
979 	    ZONES_TMPDIR) >= sizeof (pathbuf)) {
980 		zerror(gettext("alternate root path is too long"));
981 		return (Z_ERR);
982 	}
983 	if (mkdir(pathbuf, S_IRWXU) < 0 && errno != EEXIST) {
984 		zerror(gettext("could not mkdir %s: %s"), pathbuf,
985 		    strerror(errno));
986 		return (Z_ERR);
987 	}
988 	(void) chmod(pathbuf, S_IRWXU);
989 
990 	/*
991 	 * One of these lock files is created for each zone (when needed).
992 	 * The lock files are not cleaned up (except on system reboot),
993 	 * but since there is only one per zone, there is no resource
994 	 * starvation issue.
995 	 */
996 	if (snprintf(pathbuf, sizeof (pathbuf), "%s%s/%s.zoneadm.lock",
997 	    zonecfg_get_root(), ZONES_TMPDIR, zone_name) >= sizeof (pathbuf)) {
998 		zerror(gettext("alternate root path is too long"));
999 		return (Z_ERR);
1000 	}
1001 	if ((*lockfd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
1002 		zerror(gettext("could not open %s: %s"), pathbuf,
1003 		    strerror(errno));
1004 		return (Z_ERR);
1005 	}
1006 	/*
1007 	 * Lock the file to synchronize with other zoneadmds
1008 	 */
1009 	flock.l_type = F_WRLCK;
1010 	flock.l_whence = SEEK_SET;
1011 	flock.l_start = (off_t)0;
1012 	flock.l_len = (off_t)0;
1013 	if (fcntl(*lockfd, F_SETLKW, &flock) < 0) {
1014 		zerror(gettext("unable to lock %s: %s"), pathbuf,
1015 		    strerror(errno));
1016 		release_lock_file(*lockfd);
1017 		return (Z_ERR);
1018 	}
1019 	return (Z_OK);
1020 }
1021 
1022 static boolean_t
1023 get_doorname(const char *zone_name, char *buffer)
1024 {
1025 	return (snprintf(buffer, PATH_MAX, "%s" ZONE_DOOR_PATH,
1026 	    zonecfg_get_root(), zone_name) < PATH_MAX);
1027 }
1028 
1029 /*
1030  * system daemons are not audited.  For the global zone, this occurs
1031  * "naturally" since init is started with the default audit
1032  * characteristics.  Since zoneadmd is a system daemon and it starts
1033  * init for a zone, it is necessary to clear out the audit
1034  * characteristics inherited from whomever started zoneadmd.  This is
1035  * indicated by the audit id, which is set from the ruid parameter of
1036  * adt_set_user(), below.
1037  */
1038 
1039 static void
1040 prepare_audit_context()
1041 {
1042 	adt_session_data_t	*ah;
1043 	char			*failure = gettext("audit failure: %s");
1044 
1045 	if (adt_start_session(&ah, NULL, 0)) {
1046 		zerror(failure, strerror(errno));
1047 		return;
1048 	}
1049 	if (adt_set_user(ah, ADT_NO_AUDIT, ADT_NO_AUDIT,
1050 	    ADT_NO_AUDIT, ADT_NO_AUDIT, NULL, ADT_NEW)) {
1051 		zerror(failure, strerror(errno));
1052 		(void) adt_end_session(ah);
1053 		return;
1054 	}
1055 	if (adt_set_proc(ah))
1056 		zerror(failure, strerror(errno));
1057 
1058 	(void) adt_end_session(ah);
1059 }
1060 
1061 static int
1062 start_zoneadmd(const char *zone_name)
1063 {
1064 	char doorpath[PATH_MAX];
1065 	pid_t child_pid;
1066 	int error = Z_ERR;
1067 	int doorfd, lockfd;
1068 	struct door_info info;
1069 
1070 	if (!get_doorname(zone_name, doorpath))
1071 		return (Z_ERR);
1072 
1073 	if (grab_lock_file(zone_name, &lockfd) != Z_OK)
1074 		return (Z_ERR);
1075 
1076 	/*
1077 	 * Now that we have the lock, re-confirm that the daemon is
1078 	 * *not* up and working fine.  If it is still down, we have a green
1079 	 * light to start it.
1080 	 */
1081 	if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1082 		if (errno != ENOENT) {
1083 			zperror(doorpath, B_FALSE);
1084 			goto out;
1085 		}
1086 	} else {
1087 		if (door_info(doorfd, &info) == 0 &&
1088 		    ((info.di_attributes & DOOR_REVOKED) == 0)) {
1089 			error = Z_OK;
1090 			(void) close(doorfd);
1091 			goto out;
1092 		}
1093 		(void) close(doorfd);
1094 	}
1095 
1096 	if ((child_pid = fork()) == -1) {
1097 		zperror(gettext("could not fork"), B_FALSE);
1098 		goto out;
1099 	} else if (child_pid == 0) {
1100 		const char *argv[6], **ap;
1101 
1102 		/* child process */
1103 		prepare_audit_context();
1104 
1105 		ap = argv;
1106 		*ap++ = "zoneadmd";
1107 		*ap++ = "-z";
1108 		*ap++ = zone_name;
1109 		if (zonecfg_in_alt_root()) {
1110 			*ap++ = "-R";
1111 			*ap++ = zonecfg_get_root();
1112 		}
1113 		*ap = NULL;
1114 
1115 		(void) execv("/usr/lib/zones/zoneadmd", (char * const *)argv);
1116 		/*
1117 		 * TRANSLATION_NOTE
1118 		 * zoneadmd is a literal that should not be translated.
1119 		 */
1120 		zperror(gettext("could not exec zoneadmd"), B_FALSE);
1121 		_exit(Z_ERR);
1122 	} else {
1123 		/* parent process */
1124 		pid_t retval;
1125 		int pstatus = 0;
1126 
1127 		do {
1128 			retval = waitpid(child_pid, &pstatus, 0);
1129 		} while (retval != child_pid);
1130 		if (WIFSIGNALED(pstatus) || (WIFEXITED(pstatus) &&
1131 		    WEXITSTATUS(pstatus) != 0)) {
1132 			zerror(gettext("could not start %s"), "zoneadmd");
1133 			goto out;
1134 		}
1135 	}
1136 	error = Z_OK;
1137 out:
1138 	release_lock_file(lockfd);
1139 	return (error);
1140 }
1141 
1142 static int
1143 ping_zoneadmd(const char *zone_name)
1144 {
1145 	char doorpath[PATH_MAX];
1146 	int doorfd;
1147 	struct door_info info;
1148 
1149 	if (!get_doorname(zone_name, doorpath))
1150 		return (Z_ERR);
1151 
1152 	if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1153 		return (Z_ERR);
1154 	}
1155 	if (door_info(doorfd, &info) == 0 &&
1156 	    ((info.di_attributes & DOOR_REVOKED) == 0)) {
1157 		(void) close(doorfd);
1158 		return (Z_OK);
1159 	}
1160 	(void) close(doorfd);
1161 	return (Z_ERR);
1162 }
1163 
1164 static int
1165 call_zoneadmd(const char *zone_name, zone_cmd_arg_t *arg)
1166 {
1167 	char doorpath[PATH_MAX];
1168 	int doorfd, result;
1169 	door_arg_t darg;
1170 
1171 	zoneid_t zoneid;
1172 	uint64_t uniqid = 0;
1173 
1174 	zone_cmd_rval_t *rvalp;
1175 	size_t rlen;
1176 	char *cp, *errbuf;
1177 
1178 	rlen = getpagesize();
1179 	if ((rvalp = malloc(rlen)) == NULL) {
1180 		zerror(gettext("failed to allocate %lu bytes: %s"), rlen,
1181 		    strerror(errno));
1182 		return (-1);
1183 	}
1184 
1185 	if ((zoneid = getzoneidbyname(zone_name)) != ZONE_ID_UNDEFINED) {
1186 		(void) zone_getattr(zoneid, ZONE_ATTR_UNIQID, &uniqid,
1187 		    sizeof (uniqid));
1188 	}
1189 	arg->uniqid = uniqid;
1190 	(void) strlcpy(arg->locale, locale, sizeof (arg->locale));
1191 	if (!get_doorname(zone_name, doorpath)) {
1192 		zerror(gettext("alternate root path is too long"));
1193 		free(rvalp);
1194 		return (-1);
1195 	}
1196 
1197 	/*
1198 	 * Loop trying to start zoneadmd; if something goes seriously
1199 	 * wrong we break out and fail.
1200 	 */
1201 	for (;;) {
1202 		if (start_zoneadmd(zone_name) != Z_OK)
1203 			break;
1204 
1205 		if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1206 			zperror(gettext("failed to open zone door"), B_FALSE);
1207 			break;
1208 		}
1209 
1210 		darg.data_ptr = (char *)arg;
1211 		darg.data_size = sizeof (*arg);
1212 		darg.desc_ptr = NULL;
1213 		darg.desc_num = 0;
1214 		darg.rbuf = (char *)rvalp;
1215 		darg.rsize = rlen;
1216 		if (door_call(doorfd, &darg) != 0) {
1217 			(void) close(doorfd);
1218 			/*
1219 			 * We'll get EBADF if the door has been revoked.
1220 			 */
1221 			if (errno != EBADF) {
1222 				zperror(gettext("door_call failed"), B_FALSE);
1223 				break;
1224 			}
1225 			continue;	/* take another lap */
1226 		}
1227 		(void) close(doorfd);
1228 
1229 		if (darg.data_size == 0) {
1230 			/* Door server is going away; kick it again. */
1231 			continue;
1232 		}
1233 
1234 		errbuf = rvalp->errbuf;
1235 		while (*errbuf != '\0') {
1236 			/*
1237 			 * Remove any newlines since zerror()
1238 			 * will append one automatically.
1239 			 */
1240 			cp = strchr(errbuf, '\n');
1241 			if (cp != NULL)
1242 				*cp = '\0';
1243 			zerror("%s", errbuf);
1244 			if (cp == NULL)
1245 				break;
1246 			errbuf = cp + 1;
1247 		}
1248 		result = rvalp->rval == 0 ? 0 : -1;
1249 		free(rvalp);
1250 		return (result);
1251 	}
1252 
1253 	free(rvalp);
1254 	return (-1);
1255 }
1256 
1257 static int
1258 ready_func(int argc, char *argv[])
1259 {
1260 	zone_cmd_arg_t zarg;
1261 	int arg;
1262 
1263 	if (zonecfg_in_alt_root()) {
1264 		zerror(gettext("cannot ready zone in alternate root"));
1265 		return (Z_ERR);
1266 	}
1267 
1268 	optind = 0;
1269 	if ((arg = getopt(argc, argv, "?")) != EOF) {
1270 		switch (arg) {
1271 		case '?':
1272 			sub_usage(SHELP_READY, CMD_READY);
1273 			return (optopt == '?' ? Z_OK : Z_USAGE);
1274 		default:
1275 			sub_usage(SHELP_READY, CMD_READY);
1276 			return (Z_USAGE);
1277 		}
1278 	}
1279 	if (argc > optind) {
1280 		sub_usage(SHELP_READY, CMD_READY);
1281 		return (Z_USAGE);
1282 	}
1283 	if (sanity_check(target_zone, CMD_READY, B_FALSE, B_FALSE) != Z_OK)
1284 		return (Z_ERR);
1285 	if (verify_details(CMD_READY) != Z_OK)
1286 		return (Z_ERR);
1287 
1288 	zarg.cmd = Z_READY;
1289 	if (call_zoneadmd(target_zone, &zarg) != 0) {
1290 		zerror(gettext("call to %s failed"), "zoneadmd");
1291 		return (Z_ERR);
1292 	}
1293 	return (Z_OK);
1294 }
1295 
1296 static int
1297 boot_func(int argc, char *argv[])
1298 {
1299 	zone_cmd_arg_t zarg;
1300 	int arg;
1301 
1302 	if (zonecfg_in_alt_root()) {
1303 		zerror(gettext("cannot boot zone in alternate root"));
1304 		return (Z_ERR);
1305 	}
1306 
1307 	zarg.bootbuf[0] = '\0';
1308 
1309 	/*
1310 	 * At the current time, the only supported subargument to the
1311 	 * "boot" subcommand is "-s" which specifies a single-user boot.
1312 	 * In the future, other boot arguments should be supported
1313 	 * including "-m" for specifying alternate smf(5) milestones.
1314 	 */
1315 	optind = 0;
1316 	if ((arg = getopt(argc, argv, "?s")) != EOF) {
1317 		switch (arg) {
1318 		case '?':
1319 			sub_usage(SHELP_BOOT, CMD_BOOT);
1320 			return (optopt == '?' ? Z_OK : Z_USAGE);
1321 		case 's':
1322 			(void) strlcpy(zarg.bootbuf, "-s",
1323 			    sizeof (zarg.bootbuf));
1324 			break;
1325 		default:
1326 			sub_usage(SHELP_BOOT, CMD_BOOT);
1327 			return (Z_USAGE);
1328 		}
1329 	}
1330 	if (argc > optind) {
1331 		sub_usage(SHELP_BOOT, CMD_BOOT);
1332 		return (Z_USAGE);
1333 	}
1334 	if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE) != Z_OK)
1335 		return (Z_ERR);
1336 	if (verify_details(CMD_BOOT) != Z_OK)
1337 		return (Z_ERR);
1338 	zarg.cmd = Z_BOOT;
1339 	if (call_zoneadmd(target_zone, &zarg) != 0) {
1340 		zerror(gettext("call to %s failed"), "zoneadmd");
1341 		return (Z_ERR);
1342 	}
1343 	return (Z_OK);
1344 }
1345 
1346 static void
1347 fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr)
1348 {
1349 	ssize_t result;
1350 
1351 	zeptr->zid = zid;
1352 	/*
1353 	 * Since we're looking up our own (non-global) zone name,
1354 	 * we can be assured that it will succeed.
1355 	 */
1356 	result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname));
1357 	assert(result >= 0);
1358 	if (!is_system_labeled()) {
1359 		(void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot));
1360 	} else {
1361 		(void) zone_getattr(zid, ZONE_ATTR_ROOT, zeptr->zroot,
1362 		    sizeof (zeptr->zroot));
1363 	}
1364 	zeptr->zstate_str = "running";
1365 }
1366 
1367 static int
1368 list_func(int argc, char *argv[])
1369 {
1370 	zone_entry_t *zentp, zent;
1371 	int arg, retv;
1372 	boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE;
1373 	zone_state_t min_state = ZONE_STATE_RUNNING;
1374 	zoneid_t zone_id = getzoneid();
1375 
1376 	if (target_zone == NULL) {
1377 		/* all zones: default view to running but allow override */
1378 		optind = 0;
1379 		while ((arg = getopt(argc, argv, "?cipv")) != EOF) {
1380 			switch (arg) {
1381 			case '?':
1382 				sub_usage(SHELP_LIST, CMD_LIST);
1383 				return (optopt == '?' ? Z_OK : Z_USAGE);
1384 				/*
1385 				 * The 'i' and 'c' options are not mutually
1386 				 * exclusive so if 'c' is given, then min_state
1387 				 * is set to 0 (ZONE_STATE_CONFIGURED) which is
1388 				 * the lowest possible state.  If 'i' is given,
1389 				 * then min_state is set to be the lowest state
1390 				 * so far.
1391 				 */
1392 			case 'c':
1393 				min_state = ZONE_STATE_CONFIGURED;
1394 				break;
1395 			case 'i':
1396 				min_state = min(ZONE_STATE_INSTALLED,
1397 				    min_state);
1398 
1399 				break;
1400 			case 'p':
1401 				parsable = B_TRUE;
1402 				break;
1403 			case 'v':
1404 				verbose = B_TRUE;
1405 				break;
1406 			default:
1407 				sub_usage(SHELP_LIST, CMD_LIST);
1408 				return (Z_USAGE);
1409 			}
1410 		}
1411 		if (parsable && verbose) {
1412 			zerror(gettext("%s -p and -v are mutually exclusive."),
1413 			    cmd_to_str(CMD_LIST));
1414 			return (Z_ERR);
1415 		}
1416 		if (zone_id == GLOBAL_ZONEID || is_system_labeled()) {
1417 			retv = zone_print_list(min_state, verbose, parsable);
1418 		} else {
1419 			retv = Z_OK;
1420 			fake_up_local_zone(zone_id, &zent);
1421 			zone_print(&zent, verbose, parsable);
1422 		}
1423 		return (retv);
1424 	}
1425 
1426 	/*
1427 	 * Specific target zone: disallow -i/-c suboptions.
1428 	 */
1429 	optind = 0;
1430 	while ((arg = getopt(argc, argv, "?pv")) != EOF) {
1431 		switch (arg) {
1432 		case '?':
1433 			sub_usage(SHELP_LIST, CMD_LIST);
1434 			return (optopt == '?' ? Z_OK : Z_USAGE);
1435 		case 'p':
1436 			parsable = B_TRUE;
1437 			break;
1438 		case 'v':
1439 			verbose = B_TRUE;
1440 			break;
1441 		default:
1442 			sub_usage(SHELP_LIST, CMD_LIST);
1443 			return (Z_USAGE);
1444 		}
1445 	}
1446 	if (parsable && verbose) {
1447 		zerror(gettext("%s -p and -v are mutually exclusive."),
1448 		    cmd_to_str(CMD_LIST));
1449 		return (Z_ERR);
1450 	}
1451 	if (argc > optind) {
1452 		sub_usage(SHELP_LIST, CMD_LIST);
1453 		return (Z_USAGE);
1454 	}
1455 	if (zone_id != GLOBAL_ZONEID) {
1456 		fake_up_local_zone(zone_id, &zent);
1457 		/*
1458 		 * main() will issue a Z_NO_ZONE error if it cannot get an
1459 		 * id for target_zone, which in a non-global zone should
1460 		 * happen for any zone name except `zonename`.  Thus we
1461 		 * assert() that here but don't otherwise check.
1462 		 */
1463 		assert(strcmp(zent.zname, target_zone) == 0);
1464 		zone_print(&zent, verbose, parsable);
1465 		output = B_TRUE;
1466 	} else if ((zentp = lookup_running_zone(target_zone)) != NULL) {
1467 		zone_print(zentp, verbose, parsable);
1468 		output = B_TRUE;
1469 	} else if (lookup_zone_info(target_zone, ZONE_ID_UNDEFINED,
1470 	    &zent) == Z_OK) {
1471 		zone_print(&zent, verbose, parsable);
1472 		output = B_TRUE;
1473 	}
1474 	return (output ? Z_OK : Z_ERR);
1475 }
1476 
1477 static void
1478 sigterm(int sig)
1479 {
1480 	/*
1481 	 * Ignore SIG{INT,TERM}, so we don't end up in an infinite loop,
1482 	 * then propagate the signal to our process group.
1483 	 */
1484 	(void) sigset(SIGINT, SIG_IGN);
1485 	(void) sigset(SIGTERM, SIG_IGN);
1486 	(void) kill(0, sig);
1487 	child_killed = B_TRUE;
1488 }
1489 
1490 static int
1491 do_subproc(char *cmdbuf)
1492 {
1493 	char inbuf[1024];	/* arbitrary large amount */
1494 	FILE *file;
1495 
1496 	child_killed = B_FALSE;
1497 	/*
1498 	 * We use popen(3c) to launch child processes for [un]install;
1499 	 * this library call does not return a PID, so we have to kill
1500 	 * the whole process group.  To avoid killing our parent, we
1501 	 * become a process group leader here.  But doing so can wreak
1502 	 * havoc with reading from stdin when launched by a non-job-control
1503 	 * shell, so we close stdin and reopen it as /dev/null first.
1504 	 */
1505 	(void) close(STDIN_FILENO);
1506 	(void) open("/dev/null", O_RDONLY);
1507 	(void) setpgid(0, 0);
1508 	(void) sigset(SIGINT, sigterm);
1509 	(void) sigset(SIGTERM, sigterm);
1510 	file = popen(cmdbuf, "r");
1511 	for (;;) {
1512 		if (child_killed || fgets(inbuf, sizeof (inbuf), file) == NULL)
1513 			break;
1514 		(void) fputs(inbuf, stdout);
1515 	}
1516 	(void) sigset(SIGINT, SIG_DFL);
1517 	(void) sigset(SIGTERM, SIG_DFL);
1518 	return (pclose(file));
1519 }
1520 
1521 static int
1522 subproc_status(const char *cmd, int status)
1523 {
1524 	if (WIFEXITED(status)) {
1525 		int exit_code = WEXITSTATUS(status);
1526 
1527 		if (exit_code == 0)
1528 			return (Z_OK);
1529 		zerror(gettext("'%s' failed with exit code %d."), cmd,
1530 		    exit_code);
1531 	} else if (WIFSIGNALED(status)) {
1532 		int signal = WTERMSIG(status);
1533 		char sigstr[SIG2STR_MAX];
1534 
1535 		if (sig2str(signal, sigstr) == 0) {
1536 			zerror(gettext("'%s' terminated by signal SIG%s."), cmd,
1537 			    sigstr);
1538 		} else {
1539 			zerror(gettext("'%s' terminated by an unknown signal."),
1540 			    cmd);
1541 		}
1542 	} else {
1543 		zerror(gettext("'%s' failed for unknown reasons."), cmd);
1544 	}
1545 	return (Z_ERR);
1546 }
1547 
1548 /*
1549  * Various sanity checks; make sure:
1550  * 1. We're in the global zone.
1551  * 2. The calling user has sufficient privilege.
1552  * 3. The target zone is neither the global zone nor anything starting with
1553  *    "SUNW".
1554  * 4a. If we're looking for a 'not running' (i.e., configured or installed)
1555  *     zone, the name service knows about it.
1556  * 4b. For some operations which expect a zone not to be running, that it is
1557  *     not already running (or ready).
1558  */
1559 static int
1560 sanity_check(char *zone, int cmd_num, boolean_t running,
1561     boolean_t unsafe_when_running)
1562 {
1563 	zone_entry_t *zent;
1564 	priv_set_t *privset;
1565 	zone_state_t state;
1566 	char kernzone[ZONENAME_MAX];
1567 	FILE *fp;
1568 
1569 	if (getzoneid() != GLOBAL_ZONEID) {
1570 		switch (cmd_num) {
1571 		case CMD_HALT:
1572 			zerror(gettext("use %s to %s this zone."), "halt(1M)",
1573 			    cmd_to_str(cmd_num));
1574 			break;
1575 		case CMD_REBOOT:
1576 			zerror(gettext("use %s to %s this zone."),
1577 			    "reboot(1M)", cmd_to_str(cmd_num));
1578 			break;
1579 		default:
1580 			zerror(gettext("must be in the global zone to %s a "
1581 			    "zone."), cmd_to_str(cmd_num));
1582 			break;
1583 		}
1584 		return (Z_ERR);
1585 	}
1586 
1587 	if ((privset = priv_allocset()) == NULL) {
1588 		zerror(gettext("%s failed"), "priv_allocset");
1589 		return (Z_ERR);
1590 	}
1591 
1592 	if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1593 		zerror(gettext("%s failed"), "getppriv");
1594 		priv_freeset(privset);
1595 		return (Z_ERR);
1596 	}
1597 
1598 	if (priv_isfullset(privset) == B_FALSE) {
1599 		zerror(gettext("only a privileged user may %s a zone."),
1600 		    cmd_to_str(cmd_num));
1601 		priv_freeset(privset);
1602 		return (Z_ERR);
1603 	}
1604 	priv_freeset(privset);
1605 
1606 	if (zone == NULL) {
1607 		zerror(gettext("no zone specified"));
1608 		return (Z_ERR);
1609 	}
1610 
1611 	if (strcmp(zone, GLOBAL_ZONENAME) == 0) {
1612 		zerror(gettext("%s operation is invalid for the global zone."),
1613 		    cmd_to_str(cmd_num));
1614 		return (Z_ERR);
1615 	}
1616 
1617 	if (strncmp(zone, "SUNW", 4) == 0) {
1618 		zerror(gettext("%s operation is invalid for zones starting "
1619 		    "with SUNW."), cmd_to_str(cmd_num));
1620 		return (Z_ERR);
1621 	}
1622 
1623 	if (!zonecfg_in_alt_root()) {
1624 		zent = lookup_running_zone(zone);
1625 	} else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) {
1626 		zent = NULL;
1627 	} else {
1628 		if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(),
1629 		    kernzone, sizeof (kernzone)) == 0)
1630 			zent = lookup_running_zone(kernzone);
1631 		else
1632 			zent = NULL;
1633 		zonecfg_close_scratch(fp);
1634 	}
1635 
1636 	/*
1637 	 * Look up from the kernel for 'running' zones.
1638 	 */
1639 	if (running) {
1640 		if (zent == NULL) {
1641 			zerror(gettext("not running"));
1642 			return (Z_ERR);
1643 		}
1644 	} else {
1645 		int err;
1646 
1647 		if (unsafe_when_running && zent != NULL) {
1648 			/* check whether the zone is ready or running */
1649 			if ((err = zone_get_state(zent->zname,
1650 			    &zent->zstate_num)) != Z_OK) {
1651 				errno = err;
1652 				zperror2(zent->zname,
1653 				    gettext("could not get state"));
1654 				/* can't tell, so hedge */
1655 				zent->zstate_str = "ready/running";
1656 			} else {
1657 				zent->zstate_str =
1658 				    zone_state_str(zent->zstate_num);
1659 			}
1660 			zerror(gettext("%s operation is invalid for %s zones."),
1661 			    cmd_to_str(cmd_num), zent->zstate_str);
1662 			return (Z_ERR);
1663 		}
1664 		if ((err = zone_get_state(zone, &state)) != Z_OK) {
1665 			errno = err;
1666 			zperror2(zone, gettext("could not get state"));
1667 			return (Z_ERR);
1668 		}
1669 		switch (cmd_num) {
1670 		case CMD_UNINSTALL:
1671 			if (state == ZONE_STATE_CONFIGURED) {
1672 				zerror(gettext("is already in state '%s'."),
1673 				    zone_state_str(ZONE_STATE_CONFIGURED));
1674 				return (Z_ERR);
1675 			}
1676 			break;
1677 		case CMD_ATTACH:
1678 		case CMD_CLONE:
1679 		case CMD_INSTALL:
1680 			if (state == ZONE_STATE_INSTALLED) {
1681 				zerror(gettext("is already %s."),
1682 				    zone_state_str(ZONE_STATE_INSTALLED));
1683 				return (Z_ERR);
1684 			} else if (state == ZONE_STATE_INCOMPLETE) {
1685 				zerror(gettext("zone is %s; %s required."),
1686 				    zone_state_str(ZONE_STATE_INCOMPLETE),
1687 				    cmd_to_str(CMD_UNINSTALL));
1688 				return (Z_ERR);
1689 			}
1690 			break;
1691 		case CMD_DETACH:
1692 		case CMD_MOVE:
1693 		case CMD_READY:
1694 		case CMD_BOOT:
1695 		case CMD_MOUNT:
1696 			if (state < ZONE_STATE_INSTALLED) {
1697 				zerror(gettext("must be %s before %s."),
1698 				    zone_state_str(ZONE_STATE_INSTALLED),
1699 				    cmd_to_str(cmd_num));
1700 				return (Z_ERR);
1701 			}
1702 			break;
1703 		case CMD_VERIFY:
1704 			if (state == ZONE_STATE_INCOMPLETE) {
1705 				zerror(gettext("zone is %s; %s required."),
1706 				    zone_state_str(ZONE_STATE_INCOMPLETE),
1707 				    cmd_to_str(CMD_UNINSTALL));
1708 				return (Z_ERR);
1709 			}
1710 			break;
1711 		case CMD_UNMOUNT:
1712 			if (state != ZONE_STATE_MOUNTED) {
1713 				zerror(gettext("must be %s before %s."),
1714 				    zone_state_str(ZONE_STATE_MOUNTED),
1715 				    cmd_to_str(cmd_num));
1716 				return (Z_ERR);
1717 			}
1718 			break;
1719 		}
1720 	}
1721 	return (Z_OK);
1722 }
1723 
1724 static int
1725 halt_func(int argc, char *argv[])
1726 {
1727 	zone_cmd_arg_t zarg;
1728 	int arg;
1729 
1730 	if (zonecfg_in_alt_root()) {
1731 		zerror(gettext("cannot halt zone in alternate root"));
1732 		return (Z_ERR);
1733 	}
1734 
1735 	optind = 0;
1736 	if ((arg = getopt(argc, argv, "?")) != EOF) {
1737 		switch (arg) {
1738 		case '?':
1739 			sub_usage(SHELP_HALT, CMD_HALT);
1740 			return (optopt == '?' ? Z_OK : Z_USAGE);
1741 		default:
1742 			sub_usage(SHELP_HALT, CMD_HALT);
1743 			return (Z_USAGE);
1744 		}
1745 	}
1746 	if (argc > optind) {
1747 		sub_usage(SHELP_HALT, CMD_HALT);
1748 		return (Z_USAGE);
1749 	}
1750 	/*
1751 	 * zoneadmd should be the one to decide whether or not to proceed,
1752 	 * so even though it seems that the fourth parameter below should
1753 	 * perhaps be B_TRUE, it really shouldn't be.
1754 	 */
1755 	if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE) != Z_OK)
1756 		return (Z_ERR);
1757 
1758 	zarg.cmd = Z_HALT;
1759 	return ((call_zoneadmd(target_zone, &zarg) == 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 	if (argc > 0) {
1785 		sub_usage(SHELP_REBOOT, CMD_REBOOT);
1786 		return (Z_USAGE);
1787 	}
1788 	/*
1789 	 * zoneadmd should be the one to decide whether or not to proceed,
1790 	 * so even though it seems that the fourth parameter below should
1791 	 * perhaps be B_TRUE, it really shouldn't be.
1792 	 */
1793 	if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE) != Z_OK)
1794 		return (Z_ERR);
1795 	if (verify_details(CMD_REBOOT) != Z_OK)
1796 		return (Z_ERR);
1797 
1798 	zarg.cmd = Z_REBOOT;
1799 	return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR);
1800 }
1801 
1802 static int
1803 verify_rctls(zone_dochandle_t handle)
1804 {
1805 	struct zone_rctltab rctltab;
1806 	size_t rbs = rctlblk_size();
1807 	rctlblk_t *rctlblk;
1808 	int error = Z_INVAL;
1809 
1810 	if ((rctlblk = malloc(rbs)) == NULL) {
1811 		zerror(gettext("failed to allocate %lu bytes: %s"), rbs,
1812 		    strerror(errno));
1813 		return (Z_NOMEM);
1814 	}
1815 
1816 	if (zonecfg_setrctlent(handle) != Z_OK) {
1817 		zerror(gettext("zonecfg_setrctlent failed"));
1818 		free(rctlblk);
1819 		return (error);
1820 	}
1821 
1822 	rctltab.zone_rctl_valptr = NULL;
1823 	while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
1824 		struct zone_rctlvaltab *rctlval;
1825 		const char *name = rctltab.zone_rctl_name;
1826 
1827 		if (!zonecfg_is_rctl(name)) {
1828 			zerror(gettext("WARNING: Ignoring unrecognized rctl "
1829 			    "'%s'."),  name);
1830 			zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
1831 			rctltab.zone_rctl_valptr = NULL;
1832 			continue;
1833 		}
1834 
1835 		for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL;
1836 		    rctlval = rctlval->zone_rctlval_next) {
1837 			if (zonecfg_construct_rctlblk(rctlval, rctlblk)
1838 			    != Z_OK) {
1839 				zerror(gettext("invalid rctl value: "
1840 				    "(priv=%s,limit=%s,action%s)"),
1841 				    rctlval->zone_rctlval_priv,
1842 				    rctlval->zone_rctlval_limit,
1843 				    rctlval->zone_rctlval_action);
1844 				goto out;
1845 			}
1846 			if (!zonecfg_valid_rctl(name, rctlblk)) {
1847 				zerror(gettext("(priv=%s,limit=%s,action=%s) "
1848 				    "is not a valid value for rctl '%s'"),
1849 				    rctlval->zone_rctlval_priv,
1850 				    rctlval->zone_rctlval_limit,
1851 				    rctlval->zone_rctlval_action,
1852 				    name);
1853 				goto out;
1854 			}
1855 		}
1856 		zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
1857 	}
1858 	rctltab.zone_rctl_valptr = NULL;
1859 	error = Z_OK;
1860 out:
1861 	zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
1862 	(void) zonecfg_endrctlent(handle);
1863 	free(rctlblk);
1864 	return (error);
1865 }
1866 
1867 static int
1868 verify_pool(zone_dochandle_t handle)
1869 {
1870 	char poolname[MAXPATHLEN];
1871 	pool_conf_t *poolconf;
1872 	pool_t *pool;
1873 	int status;
1874 	int error;
1875 
1876 	/*
1877 	 * This ends up being very similar to the check done in zoneadmd.
1878 	 */
1879 	error = zonecfg_get_pool(handle, poolname, sizeof (poolname));
1880 	if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) {
1881 		/*
1882 		 * No pool specified.
1883 		 */
1884 		return (0);
1885 	}
1886 	if (error != Z_OK) {
1887 		zperror(gettext("Unable to retrieve pool name from "
1888 		    "configuration"), B_TRUE);
1889 		return (error);
1890 	}
1891 	/*
1892 	 * Don't do anything if pools aren't enabled.
1893 	 */
1894 	if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) {
1895 		zerror(gettext("WARNING: pools facility not active; "
1896 		    "zone will not be bound to pool '%s'."), poolname);
1897 		return (Z_OK);
1898 	}
1899 	/*
1900 	 * Try to provide a sane error message if the requested pool doesn't
1901 	 * exist.  It isn't clear that pools-related failures should
1902 	 * necessarily translate to a failure to verify the zone configuration,
1903 	 * hence they are not considered errors.
1904 	 */
1905 	if ((poolconf = pool_conf_alloc()) == NULL) {
1906 		zerror(gettext("WARNING: pool_conf_alloc failed; "
1907 		    "using default pool"));
1908 		return (Z_OK);
1909 	}
1910 	if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) !=
1911 	    PO_SUCCESS) {
1912 		zerror(gettext("WARNING: pool_conf_open failed; "
1913 		    "using default pool"));
1914 		pool_conf_free(poolconf);
1915 		return (Z_OK);
1916 	}
1917 	pool = pool_get_pool(poolconf, poolname);
1918 	(void) pool_conf_close(poolconf);
1919 	pool_conf_free(poolconf);
1920 	if (pool == NULL) {
1921 		zerror(gettext("WARNING: pool '%s' not found. "
1922 		    "using default pool"), poolname);
1923 	}
1924 
1925 	return (Z_OK);
1926 }
1927 
1928 static int
1929 verify_ipd(zone_dochandle_t handle)
1930 {
1931 	int return_code = Z_OK;
1932 	struct zone_fstab fstab;
1933 	struct stat st;
1934 	char specdir[MAXPATHLEN];
1935 
1936 	if (zonecfg_setipdent(handle) != Z_OK) {
1937 		/*
1938 		 * TRANSLATION_NOTE
1939 		 * inherit-pkg-dirs is a literal that should not be translated.
1940 		 */
1941 		(void) fprintf(stderr, gettext("could not verify "
1942 		    "inherit-pkg-dirs: unable to enumerate mounts\n"));
1943 		return (Z_ERR);
1944 	}
1945 	while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
1946 		/*
1947 		 * Verify fs_dir exists.
1948 		 */
1949 		(void) snprintf(specdir, sizeof (specdir), "%s%s",
1950 		    zonecfg_get_root(), fstab.zone_fs_dir);
1951 		if (stat(specdir, &st) != 0) {
1952 			/*
1953 			 * TRANSLATION_NOTE
1954 			 * inherit-pkg-dir is a literal that should not be
1955 			 * translated.
1956 			 */
1957 			(void) fprintf(stderr, gettext("could not verify "
1958 			    "inherit-pkg-dir %s: %s\n"),
1959 			    fstab.zone_fs_dir, strerror(errno));
1960 			return_code = Z_ERR;
1961 		}
1962 		if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
1963 			/*
1964 			 * TRANSLATION_NOTE
1965 			 * inherit-pkg-dir and NFS are literals that should
1966 			 * not be translated.
1967 			 */
1968 			(void) fprintf(stderr, gettext("cannot verify "
1969 			    "inherit-pkg-dir %s: NFS mounted file system.\n"
1970 			    "\tA local file system must be used.\n"),
1971 			    fstab.zone_fs_dir);
1972 			return_code = Z_ERR;
1973 		}
1974 	}
1975 	(void) zonecfg_endipdent(handle);
1976 
1977 	return (return_code);
1978 }
1979 
1980 /*
1981  * Verify that the special device/file system exists and is valid.
1982  */
1983 static int
1984 verify_fs_special(struct zone_fstab *fstab)
1985 {
1986 	struct stat st;
1987 
1988 	if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0)
1989 		return (verify_fs_zfs(fstab));
1990 
1991 	if (stat(fstab->zone_fs_special, &st) != 0) {
1992 		(void) fprintf(stderr, gettext("could not verify fs "
1993 		    "%s: could not access %s: %s\n"), fstab->zone_fs_dir,
1994 		    fstab->zone_fs_special, strerror(errno));
1995 		return (Z_ERR);
1996 	}
1997 
1998 	if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
1999 		/*
2000 		 * TRANSLATION_NOTE
2001 		 * fs and NFS are literals that should
2002 		 * not be translated.
2003 		 */
2004 		(void) fprintf(stderr, gettext("cannot verify "
2005 		    "fs %s: NFS mounted file system.\n"
2006 		    "\tA local file system must be used.\n"),
2007 		    fstab->zone_fs_special);
2008 		return (Z_ERR);
2009 	}
2010 
2011 	return (Z_OK);
2012 }
2013 
2014 static int
2015 verify_filesystems(zone_dochandle_t handle)
2016 {
2017 	int return_code = Z_OK;
2018 	struct zone_fstab fstab;
2019 	char cmdbuf[MAXPATHLEN];
2020 	struct stat st;
2021 
2022 	/*
2023 	 * No need to verify inherit-pkg-dir fs types, as their type is
2024 	 * implicitly lofs, which is known.  Therefore, the types are only
2025 	 * verified for regular file systems below.
2026 	 *
2027 	 * Since the actual mount point is not known until the dependent mounts
2028 	 * are performed, we don't attempt any path validation here: that will
2029 	 * happen later when zoneadmd actually does the mounts.
2030 	 */
2031 	if (zonecfg_setfsent(handle) != Z_OK) {
2032 		(void) fprintf(stderr, gettext("could not verify file systems: "
2033 		    "unable to enumerate mounts\n"));
2034 		return (Z_ERR);
2035 	}
2036 	while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
2037 		if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) {
2038 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2039 			    "type %s is not allowed.\n"), fstab.zone_fs_dir,
2040 			    fstab.zone_fs_type);
2041 			return_code = Z_ERR;
2042 			goto next_fs;
2043 		}
2044 		/*
2045 		 * Verify /usr/lib/fs/<fstype>/mount exists.
2046 		 */
2047 		if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount",
2048 		    fstab.zone_fs_type) > sizeof (cmdbuf)) {
2049 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2050 			    "type %s is too long.\n"), fstab.zone_fs_dir,
2051 			    fstab.zone_fs_type);
2052 			return_code = Z_ERR;
2053 			goto next_fs;
2054 		}
2055 		if (stat(cmdbuf, &st) != 0) {
2056 			(void) fprintf(stderr, gettext("could not verify fs "
2057 			    "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
2058 			    cmdbuf, strerror(errno));
2059 			return_code = Z_ERR;
2060 			goto next_fs;
2061 		}
2062 		if (!S_ISREG(st.st_mode)) {
2063 			(void) fprintf(stderr, gettext("could not verify fs "
2064 			    "%s: %s is not a regular file\n"),
2065 			    fstab.zone_fs_dir, cmdbuf);
2066 			return_code = Z_ERR;
2067 			goto next_fs;
2068 		}
2069 		/*
2070 		 * Verify /usr/lib/fs/<fstype>/fsck exists iff zone_fs_raw is
2071 		 * set.
2072 		 */
2073 		if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck",
2074 		    fstab.zone_fs_type) > sizeof (cmdbuf)) {
2075 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2076 			    "type %s is too long.\n"), fstab.zone_fs_dir,
2077 			    fstab.zone_fs_type);
2078 			return_code = Z_ERR;
2079 			goto next_fs;
2080 		}
2081 		if (fstab.zone_fs_raw[0] == '\0' && stat(cmdbuf, &st) == 0) {
2082 			(void) fprintf(stderr, gettext("could not verify fs "
2083 			    "%s: must specify 'raw' device for %s "
2084 			    "file systems\n"),
2085 			    fstab.zone_fs_dir, fstab.zone_fs_type);
2086 			return_code = Z_ERR;
2087 			goto next_fs;
2088 		}
2089 		if (fstab.zone_fs_raw[0] != '\0' &&
2090 		    (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) {
2091 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2092 			    "'raw' device specified but "
2093 			    "no fsck executable exists for %s\n"),
2094 			    fstab.zone_fs_dir, fstab.zone_fs_type);
2095 			return_code = Z_ERR;
2096 			goto next_fs;
2097 		}
2098 
2099 		/* Verify fs_special. */
2100 		if ((return_code = verify_fs_special(&fstab)) != Z_OK)
2101 			goto next_fs;
2102 
2103 		/* Verify fs_raw. */
2104 		if (fstab.zone_fs_raw[0] != '\0' &&
2105 		    stat(fstab.zone_fs_raw, &st) != 0) {
2106 			/*
2107 			 * TRANSLATION_NOTE
2108 			 * fs is a literal that should not be translated.
2109 			 */
2110 			(void) fprintf(stderr, gettext("could not verify fs "
2111 			    "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
2112 			    fstab.zone_fs_raw, strerror(errno));
2113 			return_code = Z_ERR;
2114 			goto next_fs;
2115 		}
2116 next_fs:
2117 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
2118 	}
2119 	(void) zonecfg_endfsent(handle);
2120 
2121 	return (return_code);
2122 }
2123 
2124 static int
2125 verify_limitpriv(zone_dochandle_t handle)
2126 {
2127 	char *privname = NULL;
2128 	int err;
2129 	priv_set_t *privs;
2130 
2131 	if ((privs = priv_allocset()) == NULL) {
2132 		zperror(gettext("failed to allocate privilege set"), B_FALSE);
2133 		return (Z_NOMEM);
2134 	}
2135 	err = zonecfg_get_privset(handle, privs, &privname);
2136 	switch (err) {
2137 	case Z_OK:
2138 		break;
2139 	case Z_PRIV_PROHIBITED:
2140 		(void) fprintf(stderr, gettext("privilege \"%s\" is not "
2141 		    "permitted within the zone's privilege set\n"), privname);
2142 		break;
2143 	case Z_PRIV_REQUIRED:
2144 		(void) fprintf(stderr, gettext("required privilege \"%s\" is "
2145 		    "missing from the zone's privilege set\n"), privname);
2146 		break;
2147 	case Z_PRIV_UNKNOWN:
2148 		(void) fprintf(stderr, gettext("unknown privilege \"%s\" "
2149 		    "specified in the zone's privilege set\n"), privname);
2150 		break;
2151 	default:
2152 		zperror(
2153 		    gettext("failed to determine the zone's privilege set"),
2154 		    B_TRUE);
2155 		break;
2156 	}
2157 	free(privname);
2158 	priv_freeset(privs);
2159 	return (err);
2160 }
2161 
2162 static void
2163 free_local_netifs(int if_cnt, struct net_if **if_list)
2164 {
2165 	int		i;
2166 
2167 	for (i = 0; i < if_cnt; i++) {
2168 		free(if_list[i]->name);
2169 		free(if_list[i]);
2170 	}
2171 	free(if_list);
2172 }
2173 
2174 /*
2175  * Get a list of the network interfaces, along with their address families,
2176  * that are plumbed in the global zone.  See if_tcp(7p) for a description
2177  * of the ioctls used here.
2178  */
2179 static int
2180 get_local_netifs(int *if_cnt, struct net_if ***if_list)
2181 {
2182 	int		s;
2183 	int		i;
2184 	int		res = Z_OK;
2185 	int		space_needed;
2186 	int		cnt = 0;
2187 	struct		lifnum if_num;
2188 	struct		lifconf if_conf;
2189 	struct		lifreq *if_reqp;
2190 	char		*if_buf;
2191 	struct net_if	**local_ifs = NULL;
2192 
2193 	*if_cnt = 0;
2194 	*if_list = NULL;
2195 
2196 	if ((s = socket(SOCKET_AF(AF_INET), SOCK_DGRAM, 0)) < 0)
2197 		return (Z_ERR);
2198 
2199 	/*
2200 	 * Come back here in the unlikely event that the number of interfaces
2201 	 * increases between the time we get the count and the time we do the
2202 	 * SIOCGLIFCONF ioctl.
2203 	 */
2204 retry:
2205 	/* Get the number of interfaces. */
2206 	if_num.lifn_family = AF_UNSPEC;
2207 	if_num.lifn_flags = LIFC_NOXMIT;
2208 	if (ioctl(s, SIOCGLIFNUM, &if_num) < 0) {
2209 		(void) close(s);
2210 		return (Z_ERR);
2211 	}
2212 
2213 	/* Get the interface configuration list. */
2214 	space_needed = if_num.lifn_count * sizeof (struct lifreq);
2215 	if ((if_buf = malloc(space_needed)) == NULL) {
2216 		(void) close(s);
2217 		return (Z_ERR);
2218 	}
2219 	if_conf.lifc_family = AF_UNSPEC;
2220 	if_conf.lifc_flags = LIFC_NOXMIT;
2221 	if_conf.lifc_len = space_needed;
2222 	if_conf.lifc_buf = if_buf;
2223 	if (ioctl(s, SIOCGLIFCONF, &if_conf) < 0) {
2224 		free(if_buf);
2225 		/*
2226 		 * SIOCGLIFCONF returns EINVAL if the buffer we passed in is
2227 		 * too small.  In this case go back and get the new if cnt.
2228 		 */
2229 		if (errno == EINVAL)
2230 			goto retry;
2231 
2232 		(void) close(s);
2233 		return (Z_ERR);
2234 	}
2235 	(void) close(s);
2236 
2237 	/* Get the name and address family for each interface. */
2238 	if_reqp = if_conf.lifc_req;
2239 	for (i = 0; i < (if_conf.lifc_len / sizeof (struct lifreq)); i++) {
2240 		struct net_if	**p;
2241 		struct lifreq	req;
2242 
2243 		if (strcmp(LOOPBACK_IF, if_reqp->lifr_name) == 0) {
2244 			if_reqp++;
2245 			continue;
2246 		}
2247 
2248 		if ((s = socket(SOCKET_AF(if_reqp->lifr_addr.ss_family),
2249 		    SOCK_DGRAM, 0)) == -1) {
2250 			res = Z_ERR;
2251 			break;
2252 		}
2253 
2254 		(void) strncpy(req.lifr_name, if_reqp->lifr_name,
2255 		    sizeof (req.lifr_name));
2256 		if (ioctl(s, SIOCGLIFADDR, &req) < 0) {
2257 			(void) close(s);
2258 			if_reqp++;
2259 			continue;
2260 		}
2261 
2262 		if ((p = (struct net_if **)realloc(local_ifs,
2263 		    sizeof (struct net_if *) * (cnt + 1))) == NULL) {
2264 			res = Z_ERR;
2265 			break;
2266 		}
2267 		local_ifs = p;
2268 
2269 		if ((local_ifs[cnt] = malloc(sizeof (struct net_if))) == NULL) {
2270 			res = Z_ERR;
2271 			break;
2272 		}
2273 
2274 		if ((local_ifs[cnt]->name = strdup(if_reqp->lifr_name))
2275 		    == NULL) {
2276 			free(local_ifs[cnt]);
2277 			res = Z_ERR;
2278 			break;
2279 		}
2280 		local_ifs[cnt]->af = req.lifr_addr.ss_family;
2281 		cnt++;
2282 
2283 		(void) close(s);
2284 		if_reqp++;
2285 	}
2286 
2287 	free(if_buf);
2288 
2289 	if (res != Z_OK) {
2290 		free_local_netifs(cnt, local_ifs);
2291 	} else {
2292 		*if_cnt = cnt;
2293 		*if_list = local_ifs;
2294 	}
2295 
2296 	return (res);
2297 }
2298 
2299 static char *
2300 af2str(int af)
2301 {
2302 	switch (af) {
2303 	case AF_INET:
2304 		return ("IPv4");
2305 	case AF_INET6:
2306 		return ("IPv6");
2307 	default:
2308 		return ("Unknown");
2309 	}
2310 }
2311 
2312 /*
2313  * Cross check the network interface name and address family with the
2314  * interfaces that are set up in the global zone so that we can print the
2315  * appropriate error message.
2316  */
2317 static void
2318 print_net_err(char *phys, char *addr, int af, char *msg)
2319 {
2320 	int		i;
2321 	int		local_if_cnt = 0;
2322 	struct net_if	**local_ifs = NULL;
2323 	boolean_t	found_if = B_FALSE;
2324 	boolean_t	found_af = B_FALSE;
2325 
2326 	if (get_local_netifs(&local_if_cnt, &local_ifs) != Z_OK) {
2327 		(void) fprintf(stderr,
2328 		    gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
2329 		    "net", "address", addr, "physical", phys, msg);
2330 		return;
2331 	}
2332 
2333 	for (i = 0; i < local_if_cnt; i++) {
2334 		if (strcmp(phys, local_ifs[i]->name) == 0) {
2335 			found_if = B_TRUE;
2336 			if (af == local_ifs[i]->af) {
2337 				found_af = B_TRUE;
2338 				break;
2339 			}
2340 		}
2341 	}
2342 
2343 	free_local_netifs(local_if_cnt, local_ifs);
2344 
2345 	if (!found_if) {
2346 		(void) fprintf(stderr,
2347 		    gettext("could not verify %s %s=%s\n\t"
2348 		    "network interface %s is not plumbed in the global zone\n"),
2349 		    "net", "physical", phys, phys);
2350 		return;
2351 	}
2352 
2353 	/*
2354 	 * Print this error if we were unable to find the address family
2355 	 * for this interface.  If the af variable is not initialized to
2356 	 * to something meaningful by the caller (not AF_UNSPEC) then we
2357 	 * also skip this message since it wouldn't be informative.
2358 	 */
2359 	if (!found_af && af != AF_UNSPEC) {
2360 		(void) fprintf(stderr,
2361 		    gettext("could not verify %s %s=%s %s=%s\n\tthe %s address "
2362 		    "family is not configured on this interface in the\n\t"
2363 		    "global zone\n"),
2364 		    "net", "address", addr, "physical", phys, af2str(af));
2365 		return;
2366 	}
2367 
2368 	(void) fprintf(stderr,
2369 	    gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
2370 	    "net", "address", addr, "physical", phys, msg);
2371 }
2372 
2373 static int
2374 verify_details(int cmd_num)
2375 {
2376 	zone_dochandle_t handle;
2377 	struct zone_nwiftab nwiftab;
2378 	char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
2379 	int return_code = Z_OK;
2380 	int err;
2381 	boolean_t in_alt_root;
2382 
2383 	if ((handle = zonecfg_init_handle()) == NULL) {
2384 		zperror(cmd_to_str(cmd_num), B_TRUE);
2385 		return (Z_ERR);
2386 	}
2387 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
2388 		errno = err;
2389 		zperror(cmd_to_str(cmd_num), B_TRUE);
2390 		zonecfg_fini_handle(handle);
2391 		return (Z_ERR);
2392 	}
2393 	if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2394 	    Z_OK) {
2395 		errno = err;
2396 		zperror(cmd_to_str(cmd_num), B_TRUE);
2397 		zonecfg_fini_handle(handle);
2398 		return (Z_ERR);
2399 	}
2400 	/*
2401 	 * zonecfg_get_zonepath() gets its data from the XML repository.
2402 	 * Verify this against the index file, which is checked first by
2403 	 * zone_get_zonepath().  If they don't match, bail out.
2404 	 */
2405 	if ((err = zone_get_zonepath(target_zone, checkpath,
2406 	    sizeof (checkpath))) != Z_OK) {
2407 		errno = err;
2408 		zperror2(target_zone, gettext("could not get zone path"));
2409 		return (Z_ERR);
2410 	}
2411 	if (strcmp(zonepath, checkpath) != 0) {
2412 		/*
2413 		 * TRANSLATION_NOTE
2414 		 * XML and zonepath are literals that should not be translated.
2415 		 */
2416 		(void) fprintf(stderr, gettext("The XML repository has "
2417 		    "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
2418 		    "These must match, so fix the incorrect entry.\n"),
2419 		    zonepath, checkpath);
2420 		return (Z_ERR);
2421 	}
2422 	if (validate_zonepath(zonepath, cmd_num) != Z_OK) {
2423 		(void) fprintf(stderr, gettext("could not verify zonepath %s "
2424 		    "because of the above errors.\n"), zonepath);
2425 		return_code = Z_ERR;
2426 	}
2427 
2428 	in_alt_root = zonecfg_in_alt_root();
2429 	if (in_alt_root)
2430 		goto no_net;
2431 
2432 	if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
2433 		errno = err;
2434 		zperror(cmd_to_str(cmd_num), B_TRUE);
2435 		zonecfg_fini_handle(handle);
2436 		return (Z_ERR);
2437 	}
2438 	while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
2439 		struct lifreq lifr;
2440 		sa_family_t af = AF_UNSPEC;
2441 		int so, res;
2442 
2443 		/* skip any loopback interfaces */
2444 		if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0)
2445 			continue;
2446 		if ((res = zonecfg_valid_net_address(nwiftab.zone_nwif_address,
2447 		    &lifr)) != Z_OK) {
2448 			print_net_err(nwiftab.zone_nwif_physical,
2449 			    nwiftab.zone_nwif_address, af,
2450 			    zonecfg_strerror(res));
2451 			return_code = Z_ERR;
2452 			continue;
2453 		}
2454 		af = lifr.lifr_addr.ss_family;
2455 		(void) memset(&lifr, 0, sizeof (lifr));
2456 		(void) strlcpy(lifr.lifr_name, nwiftab.zone_nwif_physical,
2457 		    sizeof (lifr.lifr_name));
2458 		lifr.lifr_addr.ss_family = af;
2459 		if ((so = socket(af, SOCK_DGRAM, 0)) < 0) {
2460 			(void) fprintf(stderr, gettext("could not verify %s "
2461 			    "%s=%s %s=%s: could not get socket: %s\n"), "net",
2462 			    "address", nwiftab.zone_nwif_address, "physical",
2463 			    nwiftab.zone_nwif_physical, strerror(errno));
2464 			return_code = Z_ERR;
2465 			continue;
2466 		}
2467 		if (ioctl(so, SIOCGLIFFLAGS, &lifr) < 0) {
2468 			print_net_err(nwiftab.zone_nwif_physical,
2469 			    nwiftab.zone_nwif_address, af,
2470 			    strerror(errno));
2471 			return_code = Z_ERR;
2472 		}
2473 		(void) close(so);
2474 	}
2475 	(void) zonecfg_endnwifent(handle);
2476 no_net:
2477 
2478 	/* verify that lofs has not been excluded from the kernel */
2479 	if (modctl(MODLOAD, 1, "fs/lofs", NULL) != 0) {
2480 		if (errno == ENXIO)
2481 			(void) fprintf(stderr, gettext("could not verify "
2482 			    "lofs(7FS): possibly excluded in /etc/system\n"));
2483 		else
2484 			(void) fprintf(stderr, gettext("could not verify "
2485 			    "lofs(7FS): %s\n"), strerror(errno));
2486 		return_code = Z_ERR;
2487 	}
2488 
2489 	if (verify_filesystems(handle) != Z_OK)
2490 		return_code = Z_ERR;
2491 	if (verify_ipd(handle) != Z_OK)
2492 		return_code = Z_ERR;
2493 	if (!in_alt_root && verify_rctls(handle) != Z_OK)
2494 		return_code = Z_ERR;
2495 	if (!in_alt_root && verify_pool(handle) != Z_OK)
2496 		return_code = Z_ERR;
2497 	if (!in_alt_root && verify_datasets(handle) != Z_OK)
2498 		return_code = Z_ERR;
2499 
2500 	/*
2501 	 * As the "mount" command is used for patching/upgrading of zones
2502 	 * or other maintenance processes, the zone's privilege set is not
2503 	 * checked in this case.  Instead, the default, safe set of
2504 	 * privileges will be used when this zone is created in the
2505 	 * kernel.
2506 	 */
2507 	if (!in_alt_root && cmd_num != CMD_MOUNT &&
2508 	    verify_limitpriv(handle) != Z_OK)
2509 		return_code = Z_ERR;
2510 	zonecfg_fini_handle(handle);
2511 	if (return_code == Z_ERR)
2512 		(void) fprintf(stderr,
2513 		    gettext("%s: zone %s failed to verify\n"),
2514 		    execname, target_zone);
2515 	return (return_code);
2516 }
2517 
2518 static int
2519 verify_func(int argc, char *argv[])
2520 {
2521 	int arg;
2522 
2523 	optind = 0;
2524 	if ((arg = getopt(argc, argv, "?")) != EOF) {
2525 		switch (arg) {
2526 		case '?':
2527 			sub_usage(SHELP_VERIFY, CMD_VERIFY);
2528 			return (optopt == '?' ? Z_OK : Z_USAGE);
2529 		default:
2530 			sub_usage(SHELP_VERIFY, CMD_VERIFY);
2531 			return (Z_USAGE);
2532 		}
2533 	}
2534 	if (argc > optind) {
2535 		sub_usage(SHELP_VERIFY, CMD_VERIFY);
2536 		return (Z_USAGE);
2537 	}
2538 	if (sanity_check(target_zone, CMD_VERIFY, B_FALSE, B_FALSE) != Z_OK)
2539 		return (Z_ERR);
2540 	return (verify_details(CMD_VERIFY));
2541 }
2542 
2543 #define	LUCREATEZONE	"/usr/lib/lu/lucreatezone"
2544 
2545 static int
2546 install_func(int argc, char *argv[])
2547 {
2548 	/* 9: "exec " and " -z " */
2549 	char cmdbuf[sizeof (LUCREATEZONE) + ZONENAME_MAX + 9];
2550 	int lockfd;
2551 	int err, arg;
2552 	char zonepath[MAXPATHLEN];
2553 	int status;
2554 	boolean_t nodataset = B_FALSE;
2555 
2556 	if (zonecfg_in_alt_root()) {
2557 		zerror(gettext("cannot install zone in alternate root"));
2558 		return (Z_ERR);
2559 	}
2560 
2561 	optind = 0;
2562 	if ((arg = getopt(argc, argv, "?x:")) != EOF) {
2563 		switch (arg) {
2564 		case '?':
2565 			sub_usage(SHELP_INSTALL, CMD_INSTALL);
2566 			return (optopt == '?' ? Z_OK : Z_USAGE);
2567 		case 'x':
2568 			if (strcmp(optarg, "nodataset") != 0) {
2569 				sub_usage(SHELP_INSTALL, CMD_INSTALL);
2570 				return (Z_USAGE);
2571 			}
2572 			nodataset = B_TRUE;
2573 			break;
2574 		default:
2575 			sub_usage(SHELP_INSTALL, CMD_INSTALL);
2576 			return (Z_USAGE);
2577 		}
2578 	}
2579 	if (argc > optind) {
2580 		sub_usage(SHELP_INSTALL, CMD_INSTALL);
2581 		return (Z_USAGE);
2582 	}
2583 	if (sanity_check(target_zone, CMD_INSTALL, B_FALSE, B_TRUE) != Z_OK)
2584 		return (Z_ERR);
2585 	if (verify_details(CMD_INSTALL) != Z_OK)
2586 		return (Z_ERR);
2587 
2588 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
2589 		zerror(gettext("another %s may have an operation in progress."),
2590 		    "zoneadm");
2591 		return (Z_ERR);
2592 	}
2593 	err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
2594 	if (err != Z_OK) {
2595 		errno = err;
2596 		zperror2(target_zone, gettext("could not set state"));
2597 		goto done;
2598 	}
2599 
2600 	/*
2601 	 * According to the Application Packaging Developer's Guide, a
2602 	 * "checkinstall" script when included in a package is executed as
2603 	 * the user "install", if such a user exists, or by the user
2604 	 * "nobody".  In order to support this dubious behavior, the path
2605 	 * to the zone being constructed is opened up during the life of
2606 	 * the command laying down the zone's root file system.  Once this
2607 	 * has completed, regardless of whether it was successful, the
2608 	 * path to the zone is again restricted.
2609 	 */
2610 	if ((err = zone_get_zonepath(target_zone, zonepath,
2611 	    sizeof (zonepath))) != Z_OK) {
2612 		errno = err;
2613 		zperror2(target_zone, gettext("could not get zone path"));
2614 		goto done;
2615 	}
2616 
2617 	if (!nodataset)
2618 		create_zfs_zonepath(zonepath);
2619 
2620 	if (chmod(zonepath, DEFAULT_DIR_MODE) != 0) {
2621 		zperror(zonepath, B_FALSE);
2622 		err = Z_ERR;
2623 		goto done;
2624 	}
2625 
2626 	/*
2627 	 * "exec" the command so that the returned status is that of
2628 	 * LUCREATEZONE and not the shell.
2629 	 */
2630 	(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " LUCREATEZONE " -z %s",
2631 	    target_zone);
2632 	status = do_subproc(cmdbuf);
2633 	if (chmod(zonepath, S_IRWXU) != 0) {
2634 		zperror(zonepath, B_FALSE);
2635 		err = Z_ERR;
2636 		goto done;
2637 	}
2638 	if ((err = subproc_status(LUCREATEZONE, status)) != Z_OK)
2639 		goto done;
2640 
2641 	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
2642 		errno = err;
2643 		zperror2(target_zone, gettext("could not set state"));
2644 		goto done;
2645 	}
2646 
2647 done:
2648 	release_lock_file(lockfd);
2649 	return ((err == Z_OK) ? Z_OK : Z_ERR);
2650 }
2651 
2652 /*
2653  * Check that the inherited pkg dirs are the same for the clone and its source.
2654  * The easiest way to do that is check that the list of ipds is the same
2655  * by matching each one against the other.  This algorithm should be fine since
2656  * the list of ipds should not be that long.
2657  */
2658 static int
2659 valid_ipd_clone(zone_dochandle_t s_handle, char *source_zone,
2660 	zone_dochandle_t t_handle, char *target_zone)
2661 {
2662 	int err;
2663 	int res = Z_OK;
2664 	int s_cnt = 0;
2665 	int t_cnt = 0;
2666 	struct zone_fstab s_fstab;
2667 	struct zone_fstab t_fstab;
2668 
2669 	/*
2670 	 * First check the source of the clone against the target.
2671 	 */
2672 	if ((err = zonecfg_setipdent(s_handle)) != Z_OK) {
2673 		errno = err;
2674 		zperror2(source_zone, gettext("could not enumerate "
2675 		    "inherit-pkg-dirs"));
2676 		return (Z_ERR);
2677 	}
2678 
2679 	while (zonecfg_getipdent(s_handle, &s_fstab) == Z_OK) {
2680 		boolean_t match = B_FALSE;
2681 
2682 		s_cnt++;
2683 
2684 		if ((err = zonecfg_setipdent(t_handle)) != Z_OK) {
2685 			errno = err;
2686 			zperror2(target_zone, gettext("could not enumerate "
2687 			    "inherit-pkg-dirs"));
2688 			(void) zonecfg_endipdent(s_handle);
2689 			return (Z_ERR);
2690 		}
2691 
2692 		while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK) {
2693 			if (strcmp(s_fstab.zone_fs_dir, t_fstab.zone_fs_dir)
2694 			    == 0) {
2695 				match = B_TRUE;
2696 				break;
2697 			}
2698 		}
2699 		(void) zonecfg_endipdent(t_handle);
2700 
2701 		if (!match) {
2702 			(void) fprintf(stderr, gettext("inherit-pkg-dir "
2703 			    "'%s' is not configured in zone %s.\n"),
2704 			    s_fstab.zone_fs_dir, target_zone);
2705 			res = Z_ERR;
2706 		}
2707 	}
2708 
2709 	(void) zonecfg_endipdent(s_handle);
2710 
2711 	/* skip the next check if we already have errors */
2712 	if (res == Z_ERR)
2713 		return (res);
2714 
2715 	/*
2716 	 * Now check the number of ipds in the target so we can verify
2717 	 * that the source is not a subset of the target.
2718 	 */
2719 	if ((err = zonecfg_setipdent(t_handle)) != Z_OK) {
2720 		errno = err;
2721 		zperror2(target_zone, gettext("could not enumerate "
2722 		    "inherit-pkg-dirs"));
2723 		return (Z_ERR);
2724 	}
2725 
2726 	while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK)
2727 		t_cnt++;
2728 
2729 	(void) zonecfg_endipdent(t_handle);
2730 
2731 	if (t_cnt != s_cnt) {
2732 		(void) fprintf(stderr, gettext("Zone %s is configured "
2733 		    "with inherit-pkg-dirs that are not configured in zone "
2734 		    "%s.\n"), target_zone, source_zone);
2735 		res = Z_ERR;
2736 	}
2737 
2738 	return (res);
2739 }
2740 
2741 static void
2742 warn_dev_match(zone_dochandle_t s_handle, char *source_zone,
2743 	zone_dochandle_t t_handle, char *target_zone)
2744 {
2745 	int err;
2746 	struct zone_devtab s_devtab;
2747 	struct zone_devtab t_devtab;
2748 
2749 	if ((err = zonecfg_setdevent(t_handle)) != Z_OK) {
2750 		errno = err;
2751 		zperror2(target_zone, gettext("could not enumerate devices"));
2752 		return;
2753 	}
2754 
2755 	while (zonecfg_getdevent(t_handle, &t_devtab) == Z_OK) {
2756 		if ((err = zonecfg_setdevent(s_handle)) != Z_OK) {
2757 			errno = err;
2758 			zperror2(source_zone,
2759 			    gettext("could not enumerate devices"));
2760 			(void) zonecfg_enddevent(t_handle);
2761 			return;
2762 		}
2763 
2764 		while (zonecfg_getdevent(s_handle, &s_devtab) == Z_OK) {
2765 			/*
2766 			 * Use fnmatch to catch the case where wildcards
2767 			 * were used in one zone and the other has an
2768 			 * explicit entry (e.g. /dev/dsk/c0t0d0s6 vs.
2769 			 * /dev/\*dsk/c0t0d0s6).
2770 			 */
2771 			if (fnmatch(t_devtab.zone_dev_match,
2772 			    s_devtab.zone_dev_match, FNM_PATHNAME) == 0 ||
2773 			    fnmatch(s_devtab.zone_dev_match,
2774 			    t_devtab.zone_dev_match, FNM_PATHNAME) == 0) {
2775 				(void) fprintf(stderr,
2776 				    gettext("WARNING: device '%s' "
2777 				    "is configured in both zones.\n"),
2778 				    t_devtab.zone_dev_match);
2779 				break;
2780 			}
2781 		}
2782 		(void) zonecfg_enddevent(s_handle);
2783 	}
2784 
2785 	(void) zonecfg_enddevent(t_handle);
2786 }
2787 
2788 /*
2789  * Check if the specified mount option (opt) is contained within the
2790  * options string.
2791  */
2792 static boolean_t
2793 opt_match(char *opt, char *options)
2794 {
2795 	char *p;
2796 	char *lastp;
2797 
2798 	if ((p = strtok_r(options, ",", &lastp)) != NULL) {
2799 		if (strcmp(p, opt) == 0)
2800 			return (B_TRUE);
2801 		while ((p = strtok_r(NULL, ",", &lastp)) != NULL) {
2802 			if (strcmp(p, opt) == 0)
2803 				return (B_TRUE);
2804 		}
2805 	}
2806 
2807 	return (B_FALSE);
2808 }
2809 
2810 #define	RW_LOFS	"WARNING: read-write lofs file system on '%s' is configured " \
2811 	"in both zones.\n"
2812 
2813 static void
2814 print_fs_warnings(struct zone_fstab *s_fstab, struct zone_fstab *t_fstab)
2815 {
2816 	/*
2817 	 * It is ok to have shared lofs mounted fs but we want to warn if
2818 	 * either is rw since this will effect the other zone.
2819 	 */
2820 	if (strcmp(t_fstab->zone_fs_type, "lofs") == 0) {
2821 		zone_fsopt_t *optp;
2822 
2823 		/* The default is rw so no options means rw */
2824 		if (t_fstab->zone_fs_options == NULL ||
2825 		    s_fstab->zone_fs_options == NULL) {
2826 			(void) fprintf(stderr, gettext(RW_LOFS),
2827 			    t_fstab->zone_fs_special);
2828 			return;
2829 		}
2830 
2831 		for (optp = s_fstab->zone_fs_options; optp != NULL;
2832 		    optp = optp->zone_fsopt_next) {
2833 			if (opt_match("rw", optp->zone_fsopt_opt)) {
2834 				(void) fprintf(stderr, gettext(RW_LOFS),
2835 				    s_fstab->zone_fs_special);
2836 				return;
2837 			}
2838 		}
2839 
2840 		for (optp = t_fstab->zone_fs_options; optp != NULL;
2841 		    optp = optp->zone_fsopt_next) {
2842 			if (opt_match("rw", optp->zone_fsopt_opt)) {
2843 				(void) fprintf(stderr, gettext(RW_LOFS),
2844 				    t_fstab->zone_fs_special);
2845 				return;
2846 			}
2847 		}
2848 
2849 		return;
2850 	}
2851 
2852 	/*
2853 	 * TRANSLATION_NOTE
2854 	 * The first variable is the file system type and the second is
2855 	 * the file system special device.  For example,
2856 	 * WARNING: ufs file system on '/dev/dsk/c0t0d0s0' ...
2857 	 */
2858 	(void) fprintf(stderr, gettext("WARNING: %s file system on '%s' "
2859 	    "is configured in both zones.\n"), t_fstab->zone_fs_type,
2860 	    t_fstab->zone_fs_special);
2861 }
2862 
2863 static void
2864 warn_fs_match(zone_dochandle_t s_handle, char *source_zone,
2865 	zone_dochandle_t t_handle, char *target_zone)
2866 {
2867 	int err;
2868 	struct zone_fstab s_fstab;
2869 	struct zone_fstab t_fstab;
2870 
2871 	if ((err = zonecfg_setfsent(t_handle)) != Z_OK) {
2872 		errno = err;
2873 		zperror2(target_zone,
2874 		    gettext("could not enumerate file systems"));
2875 		return;
2876 	}
2877 
2878 	while (zonecfg_getfsent(t_handle, &t_fstab) == Z_OK) {
2879 		if ((err = zonecfg_setfsent(s_handle)) != Z_OK) {
2880 			errno = err;
2881 			zperror2(source_zone,
2882 			    gettext("could not enumerate file systems"));
2883 			(void) zonecfg_endfsent(t_handle);
2884 			return;
2885 		}
2886 
2887 		while (zonecfg_getfsent(s_handle, &s_fstab) == Z_OK) {
2888 			if (strcmp(t_fstab.zone_fs_special,
2889 			    s_fstab.zone_fs_special) == 0) {
2890 				print_fs_warnings(&s_fstab, &t_fstab);
2891 				break;
2892 			}
2893 		}
2894 		(void) zonecfg_endfsent(s_handle);
2895 	}
2896 
2897 	(void) zonecfg_endfsent(t_handle);
2898 }
2899 
2900 /*
2901  * We don't catch the case where you used the same IP address but
2902  * it is not an exact string match.  For example, 192.9.0.128 vs. 192.09.0.128.
2903  * However, we're not going to worry about that but we will check for
2904  * a possible netmask on one of the addresses (e.g. 10.0.0.1 and 10.0.0.1/24)
2905  * and handle that case as a match.
2906  */
2907 static void
2908 warn_ip_match(zone_dochandle_t s_handle, char *source_zone,
2909 	zone_dochandle_t t_handle, char *target_zone)
2910 {
2911 	int err;
2912 	struct zone_nwiftab s_nwiftab;
2913 	struct zone_nwiftab t_nwiftab;
2914 
2915 	if ((err = zonecfg_setnwifent(t_handle)) != Z_OK) {
2916 		errno = err;
2917 		zperror2(target_zone,
2918 		    gettext("could not enumerate network interfaces"));
2919 		return;
2920 	}
2921 
2922 	while (zonecfg_getnwifent(t_handle, &t_nwiftab) == Z_OK) {
2923 		char *p;
2924 
2925 		/* remove an (optional) netmask from the address */
2926 		if ((p = strchr(t_nwiftab.zone_nwif_address, '/')) != NULL)
2927 			*p = '\0';
2928 
2929 		if ((err = zonecfg_setnwifent(s_handle)) != Z_OK) {
2930 			errno = err;
2931 			zperror2(source_zone,
2932 			    gettext("could not enumerate network interfaces"));
2933 			(void) zonecfg_endnwifent(t_handle);
2934 			return;
2935 		}
2936 
2937 		while (zonecfg_getnwifent(s_handle, &s_nwiftab) == Z_OK) {
2938 			/* remove an (optional) netmask from the address */
2939 			if ((p = strchr(s_nwiftab.zone_nwif_address, '/'))
2940 			    != NULL)
2941 				*p = '\0';
2942 
2943 			if (strcmp(t_nwiftab.zone_nwif_address,
2944 			    s_nwiftab.zone_nwif_address) == 0) {
2945 				(void) fprintf(stderr,
2946 				    gettext("WARNING: network address '%s' "
2947 				    "is configured in both zones.\n"),
2948 				    t_nwiftab.zone_nwif_address);
2949 				break;
2950 			}
2951 		}
2952 		(void) zonecfg_endnwifent(s_handle);
2953 	}
2954 
2955 	(void) zonecfg_endnwifent(t_handle);
2956 }
2957 
2958 static void
2959 warn_dataset_match(zone_dochandle_t s_handle, char *source_zone,
2960 	zone_dochandle_t t_handle, char *target_zone)
2961 {
2962 	int err;
2963 	struct zone_dstab s_dstab;
2964 	struct zone_dstab t_dstab;
2965 
2966 	if ((err = zonecfg_setdsent(t_handle)) != Z_OK) {
2967 		errno = err;
2968 		zperror2(target_zone, gettext("could not enumerate datasets"));
2969 		return;
2970 	}
2971 
2972 	while (zonecfg_getdsent(t_handle, &t_dstab) == Z_OK) {
2973 		if ((err = zonecfg_setdsent(s_handle)) != Z_OK) {
2974 			errno = err;
2975 			zperror2(source_zone,
2976 			    gettext("could not enumerate datasets"));
2977 			(void) zonecfg_enddsent(t_handle);
2978 			return;
2979 		}
2980 
2981 		while (zonecfg_getdsent(s_handle, &s_dstab) == Z_OK) {
2982 			if (strcmp(t_dstab.zone_dataset_name,
2983 			    s_dstab.zone_dataset_name) == 0) {
2984 				(void) fprintf(stderr,
2985 				    gettext("WARNING: dataset '%s' "
2986 				    "is configured in both zones.\n"),
2987 				    t_dstab.zone_dataset_name);
2988 				break;
2989 			}
2990 		}
2991 		(void) zonecfg_enddsent(s_handle);
2992 	}
2993 
2994 	(void) zonecfg_enddsent(t_handle);
2995 }
2996 
2997 static int
2998 validate_clone(char *source_zone, char *target_zone)
2999 {
3000 	int err = Z_OK;
3001 	zone_dochandle_t s_handle;
3002 	zone_dochandle_t t_handle;
3003 
3004 	if ((t_handle = zonecfg_init_handle()) == NULL) {
3005 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3006 		return (Z_ERR);
3007 	}
3008 	if ((err = zonecfg_get_handle(target_zone, t_handle)) != Z_OK) {
3009 		errno = err;
3010 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3011 		zonecfg_fini_handle(t_handle);
3012 		return (Z_ERR);
3013 	}
3014 
3015 	if ((s_handle = zonecfg_init_handle()) == NULL) {
3016 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3017 		zonecfg_fini_handle(t_handle);
3018 		return (Z_ERR);
3019 	}
3020 	if ((err = zonecfg_get_handle(source_zone, s_handle)) != Z_OK) {
3021 		errno = err;
3022 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3023 		goto done;
3024 	}
3025 
3026 	/* verify new zone has same inherit-pkg-dirs */
3027 	err = valid_ipd_clone(s_handle, source_zone, t_handle, target_zone);
3028 
3029 	/* warn about imported fs's which are the same */
3030 	warn_fs_match(s_handle, source_zone, t_handle, target_zone);
3031 
3032 	/* warn about imported IP addresses which are the same */
3033 	warn_ip_match(s_handle, source_zone, t_handle, target_zone);
3034 
3035 	/* warn about imported devices which are the same */
3036 	warn_dev_match(s_handle, source_zone, t_handle, target_zone);
3037 
3038 	/* warn about imported datasets which are the same */
3039 	warn_dataset_match(s_handle, source_zone, t_handle, target_zone);
3040 
3041 done:
3042 	zonecfg_fini_handle(t_handle);
3043 	zonecfg_fini_handle(s_handle);
3044 
3045 	return ((err == Z_OK) ? Z_OK : Z_ERR);
3046 }
3047 
3048 static int
3049 copy_zone(char *src, char *dst)
3050 {
3051 	boolean_t out_null = B_FALSE;
3052 	int status;
3053 	int err;
3054 	char *outfile;
3055 	char cmdbuf[MAXPATHLEN * 2 + 128];
3056 
3057 	if ((outfile = tempnam("/var/log", "zone")) == NULL) {
3058 		outfile = "/dev/null";
3059 		out_null = B_TRUE;
3060 	}
3061 
3062 	/*
3063 	 * Use find to get the list of files to copy.  We need to skip
3064 	 * files of type "socket" since cpio can't handle those but that
3065 	 * should be ok since the app will recreate the socket when it runs.
3066 	 * We also need to filter out anything under the .zfs subdir.  Since
3067 	 * find is running depth-first, we need the extra egrep to filter .zfs.
3068 	 */
3069 	(void) snprintf(cmdbuf, sizeof (cmdbuf),
3070 	    "cd %s && /usr/bin/find . -type s -prune -o -depth -print | "
3071 	    "/usr/bin/egrep -v '^\\./\\.zfs$|^\\./\\.zfs/' | "
3072 	    "/usr/bin/cpio -pdmuP@ %s > %s 2>&1",
3073 	    src, dst, outfile);
3074 
3075 	status = do_subproc(cmdbuf);
3076 
3077 	if ((err = subproc_status("copy", status)) != Z_OK) {
3078 		if (!out_null)
3079 			(void) fprintf(stderr, gettext("\nThe copy failed.\n"
3080 			    "More information can be found in %s\n"), outfile);
3081 		return (err);
3082 	}
3083 
3084 	if (!out_null)
3085 		(void) unlink(outfile);
3086 
3087 	return (Z_OK);
3088 }
3089 
3090 /*
3091  * Run sys-unconfig on a zone.  This will leave the zone in the installed
3092  * state as long as there were no errors during the sys-unconfig.
3093  */
3094 static int
3095 unconfigure_zone(char *zonepath)
3096 {
3097 	int		err;
3098 	int		status;
3099 	struct stat	unconfig_buf;
3100 	zone_cmd_arg_t	zarg;
3101 	char		cmdbuf[MAXPATHLEN + 51];
3102 
3103 	/* The zone has to be installed in order to mount the scratch zone. */
3104 	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
3105 		errno = err;
3106 		zperror2(target_zone, gettext("could not set state"));
3107 		return (Z_ERR);
3108 	}
3109 
3110 	/*
3111 	 * Trusted Extensions requires that cloned zones use the
3112 	 * same sysid configuration, so it is not appropriate to
3113 	 * unconfigure the zone.
3114 	 */
3115 	if (is_system_labeled())
3116 		return (Z_OK);
3117 
3118 	/*
3119 	 * Check if the zone is already sys-unconfiged.  This saves us
3120 	 * the work of bringing up the scratch zone so we can unconfigure it.
3121 	 */
3122 	(void) snprintf(cmdbuf, sizeof (cmdbuf), "%s/root/etc/.UNCONFIGURED",
3123 	    zonepath);
3124 	if (stat(cmdbuf, &unconfig_buf) == 0)
3125 		return (Z_OK);
3126 
3127 	zarg.cmd = Z_MOUNT;
3128 	if (call_zoneadmd(target_zone, &zarg) != 0) {
3129 		zerror(gettext("call to %s failed"), "zoneadmd");
3130 		(void) zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
3131 		return (Z_ERR);
3132 	}
3133 
3134 	(void) snprintf(cmdbuf, sizeof (cmdbuf),
3135 	    "/usr/sbin/zlogin -S %s /usr/sbin/sys-unconfig -R /a", target_zone);
3136 
3137 	status = do_subproc(cmdbuf);
3138 	if ((err = subproc_status("sys-unconfig", status)) != Z_OK) {
3139 		errno = err;
3140 		zperror2(target_zone, gettext("sys-unconfig failed\n"));
3141 		(void) zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
3142 	}
3143 
3144 	zarg.cmd = Z_UNMOUNT;
3145 	if (call_zoneadmd(target_zone, &zarg) != 0) {
3146 		zerror(gettext("call to %s failed"), "zoneadmd");
3147 		(void) fprintf(stderr, gettext("could not unmount zone\n"));
3148 		return (Z_ERR);
3149 	}
3150 
3151 	return ((err == Z_OK) ? Z_OK : Z_ERR);
3152 }
3153 
3154 /* ARGSUSED */
3155 static int
3156 zfm_print(const char *p, void *r) {
3157 	zerror("  %s\n", p);
3158 	return (0);
3159 }
3160 
3161 int
3162 clone_copy(char *source_zonepath, char *zonepath)
3163 {
3164 	int err;
3165 
3166 	/* Don't clone the zone if anything is still mounted there */
3167 	if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) {
3168 		zerror(gettext("These file systems are mounted on "
3169 		    "subdirectories of %s.\n"), source_zonepath);
3170 		(void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL);
3171 		return (Z_ERR);
3172 	}
3173 
3174 	/*
3175 	 * Attempt to create a ZFS fs for the zonepath.  As usual, we don't
3176 	 * care if this works or not since we always have the default behavior
3177 	 * of a simple directory for the zonepath.
3178 	 */
3179 	create_zfs_zonepath(zonepath);
3180 
3181 	(void) printf(gettext("Copying %s..."), source_zonepath);
3182 	(void) fflush(stdout);
3183 
3184 	err = copy_zone(source_zonepath, zonepath);
3185 
3186 	(void) printf("\n");
3187 
3188 	return (err);
3189 }
3190 
3191 static int
3192 clone_func(int argc, char *argv[])
3193 {
3194 	char *source_zone = NULL;
3195 	int lockfd;
3196 	int err, arg;
3197 	char zonepath[MAXPATHLEN];
3198 	char source_zonepath[MAXPATHLEN];
3199 	zone_state_t state;
3200 	zone_entry_t *zent;
3201 	char *method = NULL;
3202 	char *snapshot = NULL;
3203 
3204 	if (zonecfg_in_alt_root()) {
3205 		zerror(gettext("cannot clone zone in alternate root"));
3206 		return (Z_ERR);
3207 	}
3208 
3209 	optind = 0;
3210 	if ((arg = getopt(argc, argv, "?m:s:")) != EOF) {
3211 		switch (arg) {
3212 		case '?':
3213 			sub_usage(SHELP_CLONE, CMD_CLONE);
3214 			return (optopt == '?' ? Z_OK : Z_USAGE);
3215 		case 'm':
3216 			method = optarg;
3217 			break;
3218 		case 's':
3219 			snapshot = optarg;
3220 			break;
3221 		default:
3222 			sub_usage(SHELP_CLONE, CMD_CLONE);
3223 			return (Z_USAGE);
3224 		}
3225 	}
3226 	if (argc != (optind + 1) ||
3227 	    (method != NULL && strcmp(method, "copy") != 0)) {
3228 		sub_usage(SHELP_CLONE, CMD_CLONE);
3229 		return (Z_USAGE);
3230 	}
3231 	source_zone = argv[optind];
3232 	if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE) != Z_OK)
3233 		return (Z_ERR);
3234 	if (verify_details(CMD_CLONE) != Z_OK)
3235 		return (Z_ERR);
3236 
3237 	/*
3238 	 * We also need to do some extra validation on the source zone.
3239 	 */
3240 	if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) {
3241 		zerror(gettext("%s operation is invalid for the global zone."),
3242 		    cmd_to_str(CMD_CLONE));
3243 		return (Z_ERR);
3244 	}
3245 
3246 	if (strncmp(source_zone, "SUNW", 4) == 0) {
3247 		zerror(gettext("%s operation is invalid for zones starting "
3248 		    "with SUNW."), cmd_to_str(CMD_CLONE));
3249 		return (Z_ERR);
3250 	}
3251 
3252 	zent = lookup_running_zone(source_zone);
3253 	if (zent != NULL) {
3254 		/* check whether the zone is ready or running */
3255 		if ((err = zone_get_state(zent->zname, &zent->zstate_num))
3256 		    != Z_OK) {
3257 			errno = err;
3258 			zperror2(zent->zname, gettext("could not get state"));
3259 			/* can't tell, so hedge */
3260 			zent->zstate_str = "ready/running";
3261 		} else {
3262 			zent->zstate_str = zone_state_str(zent->zstate_num);
3263 		}
3264 		zerror(gettext("%s operation is invalid for %s zones."),
3265 		    cmd_to_str(CMD_CLONE), zent->zstate_str);
3266 		return (Z_ERR);
3267 	}
3268 
3269 	if ((err = zone_get_state(source_zone, &state)) != Z_OK) {
3270 		errno = err;
3271 		zperror2(source_zone, gettext("could not get state"));
3272 		return (Z_ERR);
3273 	}
3274 	if (state != ZONE_STATE_INSTALLED) {
3275 		(void) fprintf(stderr,
3276 		    gettext("%s: zone %s is %s; %s is required.\n"),
3277 		    execname, source_zone, zone_state_str(state),
3278 		    zone_state_str(ZONE_STATE_INSTALLED));
3279 		return (Z_ERR);
3280 	}
3281 
3282 	/*
3283 	 * The source zone checks out ok, continue with the clone.
3284 	 */
3285 
3286 	if (validate_clone(source_zone, target_zone) != Z_OK)
3287 		return (Z_ERR);
3288 
3289 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
3290 		zerror(gettext("another %s may have an operation in progress."),
3291 		    "zoneadm");
3292 		return (Z_ERR);
3293 	}
3294 
3295 	if ((err = zone_get_zonepath(source_zone, source_zonepath,
3296 	    sizeof (source_zonepath))) != Z_OK) {
3297 		errno = err;
3298 		zperror2(source_zone, gettext("could not get zone path"));
3299 		goto done;
3300 	}
3301 
3302 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3303 	    != Z_OK) {
3304 		errno = err;
3305 		zperror2(target_zone, gettext("could not get zone path"));
3306 		goto done;
3307 	}
3308 
3309 	if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE))
3310 	    != Z_OK) {
3311 		errno = err;
3312 		zperror2(target_zone, gettext("could not set state"));
3313 		goto done;
3314 	}
3315 
3316 	if (snapshot != NULL) {
3317 		err = clone_snapshot_zfs(snapshot, zonepath);
3318 	} else {
3319 		/*
3320 		 * We always copy the clone unless the source is ZFS and a
3321 		 * ZFS clone worked.  We fallback to copying if the ZFS clone
3322 		 * fails for some reason.
3323 		 */
3324 		err = Z_ERR;
3325 		if (method == NULL && is_zonepath_zfs(source_zonepath))
3326 			err = clone_zfs(source_zone, source_zonepath, zonepath);
3327 
3328 		if (err != Z_OK)
3329 			err = clone_copy(source_zonepath, zonepath);
3330 	}
3331 
3332 	if (err == Z_OK)
3333 		err = unconfigure_zone(zonepath);
3334 
3335 done:
3336 	release_lock_file(lockfd);
3337 	return ((err == Z_OK) ? Z_OK : Z_ERR);
3338 }
3339 
3340 #define	RMCOMMAND	"/usr/bin/rm -rf"
3341 
3342 /*
3343  * Used when removing a zonepath after uninstalling or cleaning up after
3344  * the move subcommand.  This handles a zonepath that has non-standard
3345  * contents so that we will only cleanup the stuff we know about and leave
3346  * any user data alone.
3347  *
3348  * If the "all" parameter is true then we should remove the whole zonepath
3349  * even if it has non-standard files/directories in it.  This can be used when
3350  * we need to cleanup after moving the zonepath across file systems.
3351  *
3352  * We "exec" the RMCOMMAND so that the returned status is that of RMCOMMAND
3353  * and not the shell.
3354  */
3355 static int
3356 cleanup_zonepath(char *zonepath, boolean_t all)
3357 {
3358 	int		status;
3359 	int		i;
3360 	boolean_t	non_std = B_FALSE;
3361 	struct dirent	*dp;
3362 	DIR		*dirp;
3363 	char		*std_entries[] = {"dev", "lu", "root", NULL};
3364 			/* (MAXPATHLEN * 3) is for the 3 std_entries dirs */
3365 	char		cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 3) + 64];
3366 
3367 	/*
3368 	 * We shouldn't need these checks but lets be paranoid since we
3369 	 * could blow away the whole system here if we got the wrong zonepath.
3370 	 */
3371 	if (*zonepath == NULL || strcmp(zonepath, "/") == 0) {
3372 		(void) fprintf(stderr, "invalid zonepath '%s'\n", zonepath);
3373 		return (Z_INVAL);
3374 	}
3375 
3376 	/*
3377 	 * If the dirpath is already gone (maybe it was manually removed) then
3378 	 * we just return Z_OK so that the cleanup is successful.
3379 	 */
3380 	if ((dirp = opendir(zonepath)) == NULL)
3381 		return (Z_OK);
3382 
3383 	/*
3384 	 * Look through the zonepath directory to see if there are any
3385 	 * non-standard files/dirs.  Also skip .zfs since that might be
3386 	 * there but we'll handle ZFS file systems as a special case.
3387 	 */
3388 	while ((dp = readdir(dirp)) != NULL) {
3389 		if (strcmp(dp->d_name, ".") == 0 ||
3390 		    strcmp(dp->d_name, "..") == 0 ||
3391 		    strcmp(dp->d_name, ".zfs") == 0)
3392 			continue;
3393 
3394 		for (i = 0; std_entries[i] != NULL; i++)
3395 			if (strcmp(dp->d_name, std_entries[i]) == 0)
3396 				break;
3397 
3398 		if (std_entries[i] == NULL)
3399 			non_std = B_TRUE;
3400 	}
3401 	(void) closedir(dirp);
3402 
3403 	if (!all && non_std) {
3404 		/*
3405 		 * There are extra, non-standard directories/files in the
3406 		 * zonepath so we don't want to remove the zonepath.  We
3407 		 * just want to remove the standard directories and leave
3408 		 * the user data alone.
3409 		 */
3410 		(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND);
3411 
3412 		for (i = 0; std_entries[i] != NULL; i++) {
3413 			char tmpbuf[MAXPATHLEN];
3414 
3415 			if (snprintf(tmpbuf, sizeof (tmpbuf), " %s/%s",
3416 			    zonepath, std_entries[i]) >= sizeof (tmpbuf) ||
3417 			    strlcat(cmdbuf, tmpbuf, sizeof (cmdbuf)) >=
3418 			    sizeof (cmdbuf)) {
3419 				(void) fprintf(stderr,
3420 				    gettext("path is too long\n"));
3421 				return (Z_INVAL);
3422 			}
3423 		}
3424 
3425 		status = do_subproc(cmdbuf);
3426 
3427 		(void) fprintf(stderr, gettext("WARNING: Unable to completely "
3428 		    "remove %s\nbecause it contains additional user data.  "
3429 		    "Only the standard directory\nentries have been "
3430 		    "removed.\n"),
3431 		    zonepath);
3432 
3433 		return (subproc_status(RMCOMMAND, status));
3434 	}
3435 
3436 	/*
3437 	 * There is nothing unexpected in the zonepath, try to get rid of the
3438 	 * whole zonepath directory.
3439 	 *
3440 	 * If the zonepath is its own zfs file system, try to destroy the
3441 	 * file system.  If that fails for some reason (e.g. it has clones)
3442 	 * then we'll just remove the contents of the zonepath.
3443 	 */
3444 	if (is_zonepath_zfs(zonepath)) {
3445 		if (destroy_zfs(zonepath) == Z_OK)
3446 			return (Z_OK);
3447 		(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND
3448 		    " %s/*", zonepath);
3449 		status = do_subproc(cmdbuf);
3450 		return (subproc_status(RMCOMMAND, status));
3451 	}
3452 
3453 	(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s",
3454 	    zonepath);
3455 	status = do_subproc(cmdbuf);
3456 	return (subproc_status(RMCOMMAND, status));
3457 }
3458 
3459 static int
3460 move_func(int argc, char *argv[])
3461 {
3462 	char *new_zonepath = NULL;
3463 	int lockfd;
3464 	int err, arg;
3465 	char zonepath[MAXPATHLEN];
3466 	zone_dochandle_t handle;
3467 	boolean_t fast;
3468 	boolean_t is_zfs = B_FALSE;
3469 	struct dirent *dp;
3470 	DIR *dirp;
3471 	boolean_t empty = B_TRUE;
3472 	boolean_t revert;
3473 	struct stat zonepath_buf;
3474 	struct stat new_zonepath_buf;
3475 
3476 	if (zonecfg_in_alt_root()) {
3477 		zerror(gettext("cannot move zone in alternate root"));
3478 		return (Z_ERR);
3479 	}
3480 
3481 	optind = 0;
3482 	if ((arg = getopt(argc, argv, "?")) != EOF) {
3483 		switch (arg) {
3484 		case '?':
3485 			sub_usage(SHELP_MOVE, CMD_MOVE);
3486 			return (optopt == '?' ? Z_OK : Z_USAGE);
3487 		default:
3488 			sub_usage(SHELP_MOVE, CMD_MOVE);
3489 			return (Z_USAGE);
3490 		}
3491 	}
3492 	if (argc != (optind + 1)) {
3493 		sub_usage(SHELP_MOVE, CMD_MOVE);
3494 		return (Z_USAGE);
3495 	}
3496 	new_zonepath = argv[optind];
3497 	if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE) != Z_OK)
3498 		return (Z_ERR);
3499 	if (verify_details(CMD_MOVE) != Z_OK)
3500 		return (Z_ERR);
3501 
3502 	/*
3503 	 * Check out the new zonepath.  This has the side effect of creating
3504 	 * a directory for the new zonepath.  We depend on this later when we
3505 	 * stat to see if we are doing a cross file system move or not.
3506 	 */
3507 	if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK)
3508 		return (Z_ERR);
3509 
3510 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3511 	    != Z_OK) {
3512 		errno = err;
3513 		zperror2(target_zone, gettext("could not get zone path"));
3514 		return (Z_ERR);
3515 	}
3516 
3517 	if (stat(zonepath, &zonepath_buf) == -1) {
3518 		zperror(gettext("could not stat zone path"), B_FALSE);
3519 		return (Z_ERR);
3520 	}
3521 
3522 	if (stat(new_zonepath, &new_zonepath_buf) == -1) {
3523 		zperror(gettext("could not stat new zone path"), B_FALSE);
3524 		return (Z_ERR);
3525 	}
3526 
3527 	/*
3528 	 * Check if the destination directory is empty.
3529 	 */
3530 	if ((dirp = opendir(new_zonepath)) == NULL) {
3531 		zperror(gettext("could not open new zone path"), B_FALSE);
3532 		return (Z_ERR);
3533 	}
3534 	while ((dp = readdir(dirp)) != (struct dirent *)0) {
3535 		if (strcmp(dp->d_name, ".") == 0 ||
3536 		    strcmp(dp->d_name, "..") == 0)
3537 			continue;
3538 		empty = B_FALSE;
3539 		break;
3540 	}
3541 	(void) closedir(dirp);
3542 
3543 	/* Error if there is anything in the destination directory. */
3544 	if (!empty) {
3545 		(void) fprintf(stderr, gettext("could not move zone to %s: "
3546 		    "directory not empty\n"), new_zonepath);
3547 		return (Z_ERR);
3548 	}
3549 
3550 	/* Don't move the zone if anything is still mounted there */
3551 	if (zonecfg_find_mounts(zonepath, NULL, NULL)) {
3552 		zerror(gettext("These file systems are mounted on "
3553 		    "subdirectories of %s.\n"), zonepath);
3554 		(void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
3555 		return (Z_ERR);
3556 	}
3557 
3558 	/*
3559 	 * Check if we are moving in the same file system and can do a fast
3560 	 * move or if we are crossing file systems and have to copy the data.
3561 	 */
3562 	fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev);
3563 
3564 	if ((handle = zonecfg_init_handle()) == NULL) {
3565 		zperror(cmd_to_str(CMD_MOVE), B_TRUE);
3566 		return (Z_ERR);
3567 	}
3568 
3569 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
3570 		errno = err;
3571 		zperror(cmd_to_str(CMD_MOVE), B_TRUE);
3572 		zonecfg_fini_handle(handle);
3573 		return (Z_ERR);
3574 	}
3575 
3576 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
3577 		zerror(gettext("another %s may have an operation in progress."),
3578 		    "zoneadm");
3579 		zonecfg_fini_handle(handle);
3580 		return (Z_ERR);
3581 	}
3582 
3583 	/*
3584 	 * We're making some file system changes now so we have to clean up
3585 	 * the file system before we are done.  This will either clean up the
3586 	 * new zonepath if the zonecfg update failed or it will clean up the
3587 	 * old zonepath if everything is ok.
3588 	 */
3589 	revert = B_TRUE;
3590 
3591 	if (is_zonepath_zfs(zonepath) &&
3592 	    move_zfs(zonepath, new_zonepath) != Z_ERR) {
3593 		is_zfs = B_TRUE;
3594 
3595 	} else if (fast) {
3596 		/* same file system, use rename for a quick move */
3597 
3598 		/*
3599 		 * Remove the new_zonepath directory that got created above
3600 		 * during the validation.  It gets in the way of the rename.
3601 		 */
3602 		if (rmdir(new_zonepath) != 0) {
3603 			zperror(gettext("could not rmdir new zone path"),
3604 			    B_FALSE);
3605 			zonecfg_fini_handle(handle);
3606 			release_lock_file(lockfd);
3607 			return (Z_ERR);
3608 		}
3609 
3610 		if (rename(zonepath, new_zonepath) != 0) {
3611 			/*
3612 			 * If this fails we don't need to do all of the
3613 			 * cleanup that happens for the rest of the code
3614 			 * so just return from this error.
3615 			 */
3616 			zperror(gettext("could not move zone"), B_FALSE);
3617 			zonecfg_fini_handle(handle);
3618 			release_lock_file(lockfd);
3619 			return (Z_ERR);
3620 		}
3621 
3622 	} else {
3623 		/*
3624 		 * Attempt to create a ZFS fs for the new zonepath.  As usual,
3625 		 * we don't care if this works or not since we always have the
3626 		 * default behavior of a simple directory for the zonepath.
3627 		 */
3628 		create_zfs_zonepath(new_zonepath);
3629 
3630 		(void) printf(gettext(
3631 		    "Moving across file systems; copying zonepath %s..."),
3632 		    zonepath);
3633 		(void) fflush(stdout);
3634 
3635 		err = copy_zone(zonepath, new_zonepath);
3636 
3637 		(void) printf("\n");
3638 		if (err != Z_OK)
3639 			goto done;
3640 	}
3641 
3642 	if ((err = zonecfg_set_zonepath(handle, new_zonepath)) != Z_OK) {
3643 		errno = err;
3644 		zperror(gettext("could not set new zonepath"), B_TRUE);
3645 		goto done;
3646 	}
3647 
3648 	if ((err = zonecfg_save(handle)) != Z_OK) {
3649 		errno = err;
3650 		zperror(gettext("zonecfg save failed"), B_TRUE);
3651 		goto done;
3652 	}
3653 
3654 	revert = B_FALSE;
3655 
3656 done:
3657 	zonecfg_fini_handle(handle);
3658 	release_lock_file(lockfd);
3659 
3660 	/*
3661 	 * Clean up the file system based on how things went.  We either
3662 	 * clean up the new zonepath if the operation failed for some reason
3663 	 * or we clean up the old zonepath if everything is ok.
3664 	 */
3665 	if (revert) {
3666 		/* The zonecfg update failed, cleanup the new zonepath. */
3667 		if (is_zfs) {
3668 			if (move_zfs(new_zonepath, zonepath) == Z_ERR) {
3669 				(void) fprintf(stderr, gettext("could not "
3670 				    "restore zonepath, the zfs mountpoint is "
3671 				    "set as:\n%s\n"), new_zonepath);
3672 				/*
3673 				 * err is already != Z_OK since we're reverting
3674 				 */
3675 			}
3676 
3677 		} else if (fast) {
3678 			if (rename(new_zonepath, zonepath) != 0) {
3679 				zperror(gettext("could not restore zonepath"),
3680 				    B_FALSE);
3681 				/*
3682 				 * err is already != Z_OK since we're reverting
3683 				 */
3684 			}
3685 		} else {
3686 			(void) printf(gettext("Cleaning up zonepath %s..."),
3687 			    new_zonepath);
3688 			(void) fflush(stdout);
3689 			err = cleanup_zonepath(new_zonepath, B_TRUE);
3690 			(void) printf("\n");
3691 
3692 			if (err != Z_OK) {
3693 				errno = err;
3694 				zperror(gettext("could not remove new "
3695 				    "zonepath"), B_TRUE);
3696 			} else {
3697 				/*
3698 				 * Because we're reverting we know the mainline
3699 				 * code failed but we just reused the err
3700 				 * variable so we reset it back to Z_ERR.
3701 				 */
3702 				err = Z_ERR;
3703 			}
3704 		}
3705 
3706 	} else {
3707 		/* The move was successful, cleanup the old zonepath. */
3708 		if (!is_zfs && !fast) {
3709 			(void) printf(
3710 			    gettext("Cleaning up zonepath %s..."), zonepath);
3711 			(void) fflush(stdout);
3712 			err = cleanup_zonepath(zonepath, B_TRUE);
3713 			(void) printf("\n");
3714 
3715 			if (err != Z_OK) {
3716 				errno = err;
3717 				zperror(gettext("could not remove zonepath"),
3718 				    B_TRUE);
3719 			}
3720 		}
3721 	}
3722 
3723 	return ((err == Z_OK) ? Z_OK : Z_ERR);
3724 }
3725 
3726 static int
3727 detach_func(int argc, char *argv[])
3728 {
3729 	int lockfd;
3730 	int err, arg;
3731 	char zonepath[MAXPATHLEN];
3732 	zone_dochandle_t handle;
3733 
3734 	if (zonecfg_in_alt_root()) {
3735 		zerror(gettext("cannot detach zone in alternate root"));
3736 		return (Z_ERR);
3737 	}
3738 
3739 	optind = 0;
3740 	if ((arg = getopt(argc, argv, "?")) != EOF) {
3741 		switch (arg) {
3742 		case '?':
3743 			sub_usage(SHELP_DETACH, CMD_DETACH);
3744 			return (optopt == '?' ? Z_OK : Z_USAGE);
3745 		default:
3746 			sub_usage(SHELP_DETACH, CMD_DETACH);
3747 			return (Z_USAGE);
3748 		}
3749 	}
3750 	if (sanity_check(target_zone, CMD_DETACH, B_FALSE, B_TRUE) != Z_OK)
3751 		return (Z_ERR);
3752 	if (verify_details(CMD_DETACH) != Z_OK)
3753 		return (Z_ERR);
3754 
3755 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3756 	    != Z_OK) {
3757 		errno = err;
3758 		zperror2(target_zone, gettext("could not get zone path"));
3759 		return (Z_ERR);
3760 	}
3761 
3762 	/* Don't detach the zone if anything is still mounted there */
3763 	if (zonecfg_find_mounts(zonepath, NULL, NULL)) {
3764 		zerror(gettext("These file systems are mounted on "
3765 		    "subdirectories of %s.\n"), zonepath);
3766 		(void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
3767 		return (Z_ERR);
3768 	}
3769 
3770 	if ((handle = zonecfg_init_handle()) == NULL) {
3771 		zperror(cmd_to_str(CMD_DETACH), B_TRUE);
3772 		return (Z_ERR);
3773 	}
3774 
3775 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
3776 		errno = err;
3777 		zperror(cmd_to_str(CMD_DETACH), B_TRUE);
3778 		zonecfg_fini_handle(handle);
3779 		return (Z_ERR);
3780 	}
3781 
3782 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
3783 		zerror(gettext("another %s may have an operation in progress."),
3784 		    "zoneadm");
3785 		zonecfg_fini_handle(handle);
3786 		return (Z_ERR);
3787 	}
3788 
3789 	if ((err = zonecfg_get_detach_info(handle, B_TRUE)) != Z_OK) {
3790 		errno = err;
3791 		zperror(gettext("getting the detach information failed"),
3792 		    B_TRUE);
3793 		goto done;
3794 	}
3795 
3796 	if ((err = zonecfg_detach_save(handle)) != Z_OK) {
3797 		errno = err;
3798 		zperror(gettext("saving the detach manifest failed"), B_TRUE);
3799 		goto done;
3800 	}
3801 
3802 	if ((err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED))
3803 	    != Z_OK) {
3804 		errno = err;
3805 		zperror(gettext("could not reset state"), B_TRUE);
3806 	}
3807 
3808 done:
3809 	zonecfg_fini_handle(handle);
3810 	release_lock_file(lockfd);
3811 
3812 	return ((err == Z_OK) ? Z_OK : Z_ERR);
3813 }
3814 
3815 /*
3816  * During attach we go through and fix up the /dev entries for the zone
3817  * we are attaching.  In order to regenerate /dev with the correct devices,
3818  * the old /dev will be removed, the zone readied (which generates a new
3819  * /dev) then halted, then we use the info from the manifest to update
3820  * the modes, owners, etc. on the new /dev.
3821  */
3822 static int
3823 dev_fix(zone_dochandle_t handle)
3824 {
3825 	int			res;
3826 	int			err;
3827 	int			status;
3828 	struct zone_devpermtab	devtab;
3829 	zone_cmd_arg_t		zarg;
3830 	char			devpath[MAXPATHLEN];
3831 				/* 6: "exec " and " " */
3832 	char			cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6];
3833 
3834 	if ((res = zonecfg_get_zonepath(handle, devpath, sizeof (devpath)))
3835 	    != Z_OK)
3836 		return (res);
3837 
3838 	if (strlcat(devpath, "/dev", sizeof (devpath)) >= sizeof (devpath))
3839 		return (Z_TOO_BIG);
3840 
3841 	/*
3842 	 * "exec" the command so that the returned status is that of
3843 	 * RMCOMMAND and not the shell.
3844 	 */
3845 	(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s",
3846 	    devpath);
3847 	status = do_subproc(cmdbuf);
3848 	if ((err = subproc_status(RMCOMMAND, status)) != Z_OK) {
3849 		(void) fprintf(stderr,
3850 		    gettext("could not remove existing /dev\n"));
3851 		return (Z_ERR);
3852 	}
3853 
3854 	/* In order to ready the zone, it must be in the installed state */
3855 	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
3856 		errno = err;
3857 		zperror(gettext("could not reset state"), B_TRUE);
3858 		return (Z_ERR);
3859 	}
3860 
3861 	/* We have to ready the zone to regen the dev tree */
3862 	zarg.cmd = Z_READY;
3863 	if (call_zoneadmd(target_zone, &zarg) != 0) {
3864 		zerror(gettext("call to %s failed"), "zoneadmd");
3865 		return (Z_ERR);
3866 	}
3867 
3868 	zarg.cmd = Z_HALT;
3869 	if (call_zoneadmd(target_zone, &zarg) != 0) {
3870 		zerror(gettext("call to %s failed"), "zoneadmd");
3871 		return (Z_ERR);
3872 	}
3873 
3874 	if (zonecfg_setdevperment(handle) != Z_OK) {
3875 		(void) fprintf(stderr,
3876 		    gettext("unable to enumerate device entries\n"));
3877 		return (Z_ERR);
3878 	}
3879 
3880 	while (zonecfg_getdevperment(handle, &devtab) == Z_OK) {
3881 		int err;
3882 
3883 		if ((err = zonecfg_devperms_apply(handle,
3884 		    devtab.zone_devperm_name, devtab.zone_devperm_uid,
3885 		    devtab.zone_devperm_gid, devtab.zone_devperm_mode,
3886 		    devtab.zone_devperm_acl)) != Z_OK && err != Z_INVAL)
3887 			(void) fprintf(stderr, gettext("error updating device "
3888 			    "%s: %s\n"), devtab.zone_devperm_name,
3889 			    zonecfg_strerror(err));
3890 
3891 		free(devtab.zone_devperm_acl);
3892 	}
3893 
3894 	(void) zonecfg_enddevperment(handle);
3895 
3896 	return (Z_OK);
3897 }
3898 
3899 static int
3900 attach_func(int argc, char *argv[])
3901 {
3902 	int lockfd;
3903 	int err, arg;
3904 	boolean_t force = B_FALSE;
3905 	zone_dochandle_t handle;
3906 	zone_dochandle_t athandle = NULL;
3907 	char zonepath[MAXPATHLEN];
3908 
3909 	if (zonecfg_in_alt_root()) {
3910 		zerror(gettext("cannot attach zone in alternate root"));
3911 		return (Z_ERR);
3912 	}
3913 
3914 	optind = 0;
3915 	if ((arg = getopt(argc, argv, "?F")) != EOF) {
3916 		switch (arg) {
3917 		case '?':
3918 			sub_usage(SHELP_ATTACH, CMD_ATTACH);
3919 			return (optopt == '?' ? Z_OK : Z_USAGE);
3920 		case 'F':
3921 			force = B_TRUE;
3922 			break;
3923 		default:
3924 			sub_usage(SHELP_ATTACH, CMD_ATTACH);
3925 			return (Z_USAGE);
3926 		}
3927 	}
3928 	if (sanity_check(target_zone, CMD_ATTACH, B_FALSE, B_TRUE) != Z_OK)
3929 		return (Z_ERR);
3930 	if (verify_details(CMD_ATTACH) != Z_OK)
3931 		return (Z_ERR);
3932 
3933 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3934 	    != Z_OK) {
3935 		errno = err;
3936 		zperror2(target_zone, gettext("could not get zone path"));
3937 		return (Z_ERR);
3938 	}
3939 
3940 	if ((handle = zonecfg_init_handle()) == NULL) {
3941 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
3942 		return (Z_ERR);
3943 	}
3944 
3945 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
3946 		errno = err;
3947 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
3948 		zonecfg_fini_handle(handle);
3949 		return (Z_ERR);
3950 	}
3951 
3952 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
3953 		zerror(gettext("another %s may have an operation in progress."),
3954 		    "zoneadm");
3955 		zonecfg_fini_handle(handle);
3956 		return (Z_ERR);
3957 	}
3958 
3959 	if (force)
3960 		goto forced;
3961 
3962 	if ((athandle = zonecfg_init_handle()) == NULL) {
3963 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
3964 		goto done;
3965 	}
3966 
3967 	if ((err = zonecfg_get_attach_handle(zonepath, target_zone, B_TRUE,
3968 	    athandle)) != Z_OK) {
3969 		if (err == Z_NO_ZONE)
3970 			zerror(gettext("Not a detached zone"));
3971 		else if (err == Z_INVALID_DOCUMENT)
3972 			zerror(gettext("Cannot attach to an earlier release "
3973 			    "of the operating system"));
3974 		else
3975 			zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
3976 		goto done;
3977 	}
3978 
3979 	/* Get the detach information for the locally defined zone. */
3980 	if ((err = zonecfg_get_detach_info(handle, B_FALSE)) != Z_OK) {
3981 		errno = err;
3982 		zperror(gettext("getting the attach information failed"),
3983 		    B_TRUE);
3984 		goto done;
3985 	}
3986 
3987 	/* sw_cmp prints error msgs as necessary */
3988 	if ((err = sw_cmp(handle, athandle, SW_CMP_NONE)) != Z_OK)
3989 		goto done;
3990 
3991 	if ((err = dev_fix(athandle)) != Z_OK)
3992 		goto done;
3993 
3994 forced:
3995 
3996 	zonecfg_rm_detached(handle, force);
3997 
3998 	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
3999 		errno = err;
4000 		zperror(gettext("could not reset state"), B_TRUE);
4001 	}
4002 
4003 done:
4004 	zonecfg_fini_handle(handle);
4005 	release_lock_file(lockfd);
4006 	if (athandle != NULL)
4007 		zonecfg_fini_handle(athandle);
4008 
4009 	return ((err == Z_OK) ? Z_OK : Z_ERR);
4010 }
4011 
4012 /*
4013  * On input, TRUE => yes, FALSE => no.
4014  * On return, TRUE => 1, FALSE => 0, could not ask => -1.
4015  */
4016 
4017 static int
4018 ask_yesno(boolean_t default_answer, const char *question)
4019 {
4020 	char line[64];	/* should be large enough to answer yes or no */
4021 
4022 	if (!isatty(STDIN_FILENO))
4023 		return (-1);
4024 	for (;;) {
4025 		(void) printf("%s (%s)? ", question,
4026 		    default_answer ? "[y]/n" : "y/[n]");
4027 		if (fgets(line, sizeof (line), stdin) == NULL ||
4028 		    line[0] == '\n')
4029 			return (default_answer ? 1 : 0);
4030 		if (tolower(line[0]) == 'y')
4031 			return (1);
4032 		if (tolower(line[0]) == 'n')
4033 			return (0);
4034 	}
4035 }
4036 
4037 static int
4038 uninstall_func(int argc, char *argv[])
4039 {
4040 	char line[ZONENAME_MAX + 128];	/* Enough for "Are you sure ..." */
4041 	char rootpath[MAXPATHLEN], zonepath[MAXPATHLEN];
4042 	boolean_t force = B_FALSE;
4043 	int lockfd, answer;
4044 	int err, arg;
4045 
4046 	if (zonecfg_in_alt_root()) {
4047 		zerror(gettext("cannot uninstall zone in alternate root"));
4048 		return (Z_ERR);
4049 	}
4050 
4051 	optind = 0;
4052 	while ((arg = getopt(argc, argv, "?F")) != EOF) {
4053 		switch (arg) {
4054 		case '?':
4055 			sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
4056 			return (optopt == '?' ? Z_OK : Z_USAGE);
4057 		case 'F':
4058 			force = B_TRUE;
4059 			break;
4060 		default:
4061 			sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
4062 			return (Z_USAGE);
4063 		}
4064 	}
4065 	if (argc > optind) {
4066 		sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
4067 		return (Z_USAGE);
4068 	}
4069 
4070 	if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE) != Z_OK)
4071 		return (Z_ERR);
4072 
4073 	if (!force) {
4074 		(void) snprintf(line, sizeof (line),
4075 		    gettext("Are you sure you want to %s zone %s"),
4076 		    cmd_to_str(CMD_UNINSTALL), target_zone);
4077 		if ((answer = ask_yesno(B_FALSE, line)) == 0) {
4078 			return (Z_OK);
4079 		} else if (answer == -1) {
4080 			zerror(gettext("Input not from terminal and -F "
4081 			    "not specified: %s not done."),
4082 			    cmd_to_str(CMD_UNINSTALL));
4083 			return (Z_ERR);
4084 		}
4085 	}
4086 
4087 	if ((err = zone_get_zonepath(target_zone, zonepath,
4088 	    sizeof (zonepath))) != Z_OK) {
4089 		errno = err;
4090 		zperror2(target_zone, gettext("could not get zone path"));
4091 		return (Z_ERR);
4092 	}
4093 	if ((err = zone_get_rootpath(target_zone, rootpath,
4094 	    sizeof (rootpath))) != Z_OK) {
4095 		errno = err;
4096 		zperror2(target_zone, gettext("could not get root path"));
4097 		return (Z_ERR);
4098 	}
4099 
4100 	/*
4101 	 * If there seems to be a zoneadmd running for this zone, call it
4102 	 * to tell it that an uninstall is happening; if all goes well it
4103 	 * will then shut itself down.
4104 	 */
4105 	if (ping_zoneadmd(target_zone) == Z_OK) {
4106 		zone_cmd_arg_t zarg;
4107 		zarg.cmd = Z_NOTE_UNINSTALLING;
4108 		/* we don't care too much if this fails... just plow on */
4109 		(void) call_zoneadmd(target_zone, &zarg);
4110 	}
4111 
4112 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
4113 		zerror(gettext("another %s may have an operation in progress."),
4114 		    "zoneadm");
4115 		return (Z_ERR);
4116 	}
4117 
4118 	/* Don't uninstall the zone if anything is mounted there */
4119 	err = zonecfg_find_mounts(rootpath, NULL, NULL);
4120 	if (err) {
4121 		zerror(gettext("These file systems are mounted on "
4122 		    "subdirectories of %s.\n"), rootpath);
4123 		(void) zonecfg_find_mounts(rootpath, zfm_print, NULL);
4124 		return (Z_ERR);
4125 	}
4126 
4127 	err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
4128 	if (err != Z_OK) {
4129 		errno = err;
4130 		zperror2(target_zone, gettext("could not set state"));
4131 		goto bad;
4132 	}
4133 
4134 	if ((err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) {
4135 		errno = err;
4136 		zperror2(target_zone, gettext("cleaning up zonepath failed"));
4137 		goto bad;
4138 	}
4139 
4140 	err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
4141 	if (err != Z_OK) {
4142 		errno = err;
4143 		zperror2(target_zone, gettext("could not reset state"));
4144 	}
4145 bad:
4146 	release_lock_file(lockfd);
4147 	return (err);
4148 }
4149 
4150 /* ARGSUSED */
4151 static int
4152 mount_func(int argc, char *argv[])
4153 {
4154 	zone_cmd_arg_t zarg;
4155 
4156 	if (argc > 0)
4157 		return (Z_USAGE);
4158 	if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE) != Z_OK)
4159 		return (Z_ERR);
4160 	if (verify_details(CMD_MOUNT) != Z_OK)
4161 		return (Z_ERR);
4162 
4163 	zarg.cmd = Z_MOUNT;
4164 	if (call_zoneadmd(target_zone, &zarg) != 0) {
4165 		zerror(gettext("call to %s failed"), "zoneadmd");
4166 		return (Z_ERR);
4167 	}
4168 	return (Z_OK);
4169 }
4170 
4171 /* ARGSUSED */
4172 static int
4173 unmount_func(int argc, char *argv[])
4174 {
4175 	zone_cmd_arg_t zarg;
4176 
4177 	if (argc > 0)
4178 		return (Z_USAGE);
4179 	if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE) != Z_OK)
4180 		return (Z_ERR);
4181 
4182 	zarg.cmd = Z_UNMOUNT;
4183 	if (call_zoneadmd(target_zone, &zarg) != 0) {
4184 		zerror(gettext("call to %s failed"), "zoneadmd");
4185 		return (Z_ERR);
4186 	}
4187 	return (Z_OK);
4188 }
4189 
4190 static int
4191 help_func(int argc, char *argv[])
4192 {
4193 	int arg, cmd_num;
4194 
4195 	if (argc == 0) {
4196 		(void) usage(B_TRUE);
4197 		return (Z_OK);
4198 	}
4199 	optind = 0;
4200 	if ((arg = getopt(argc, argv, "?")) != EOF) {
4201 		switch (arg) {
4202 		case '?':
4203 			sub_usage(SHELP_HELP, CMD_HELP);
4204 			return (optopt == '?' ? Z_OK : Z_USAGE);
4205 		default:
4206 			sub_usage(SHELP_HELP, CMD_HELP);
4207 			return (Z_USAGE);
4208 		}
4209 	}
4210 	while (optind < argc) {
4211 		/* Private commands have NULL short_usage; omit them */
4212 		if ((cmd_num = cmd_match(argv[optind])) < 0 ||
4213 		    cmdtab[cmd_num].short_usage == NULL) {
4214 			sub_usage(SHELP_HELP, CMD_HELP);
4215 			return (Z_USAGE);
4216 		}
4217 		sub_usage(cmdtab[cmd_num].short_usage, cmd_num);
4218 		optind++;
4219 	}
4220 	return (Z_OK);
4221 }
4222 
4223 /*
4224  * Returns: CMD_MIN thru CMD_MAX on success, -1 on error
4225  */
4226 
4227 static int
4228 cmd_match(char *cmd)
4229 {
4230 	int i;
4231 
4232 	for (i = CMD_MIN; i <= CMD_MAX; i++) {
4233 		/* return only if there is an exact match */
4234 		if (strcmp(cmd, cmdtab[i].cmd_name) == 0)
4235 			return (cmdtab[i].cmd_num);
4236 	}
4237 	return (-1);
4238 }
4239 
4240 static int
4241 parse_and_run(int argc, char *argv[])
4242 {
4243 	int i = cmd_match(argv[0]);
4244 
4245 	if (i < 0)
4246 		return (usage(B_FALSE));
4247 	return (cmdtab[i].handler(argc - 1, &(argv[1])));
4248 }
4249 
4250 static char *
4251 get_execbasename(char *execfullname)
4252 {
4253 	char *last_slash, *execbasename;
4254 
4255 	/* guard against '/' at end of command invocation */
4256 	for (;;) {
4257 		last_slash = strrchr(execfullname, '/');
4258 		if (last_slash == NULL) {
4259 			execbasename = execfullname;
4260 			break;
4261 		} else {
4262 			execbasename = last_slash + 1;
4263 			if (*execbasename == '\0') {
4264 				*last_slash = '\0';
4265 				continue;
4266 			}
4267 			break;
4268 		}
4269 	}
4270 	return (execbasename);
4271 }
4272 
4273 int
4274 main(int argc, char **argv)
4275 {
4276 	int arg;
4277 	zoneid_t zid;
4278 	struct stat st;
4279 
4280 	if ((locale = setlocale(LC_ALL, "")) == NULL)
4281 		locale = "C";
4282 	(void) textdomain(TEXT_DOMAIN);
4283 	setbuf(stdout, NULL);
4284 	(void) sigset(SIGHUP, SIG_IGN);
4285 	execname = get_execbasename(argv[0]);
4286 	target_zone = NULL;
4287 	if (chdir("/") != 0) {
4288 		zerror(gettext("could not change directory to /."));
4289 		exit(Z_ERR);
4290 	}
4291 
4292 	while ((arg = getopt(argc, argv, "?z:R:")) != EOF) {
4293 		switch (arg) {
4294 		case '?':
4295 			return (usage(B_TRUE));
4296 		case 'z':
4297 			target_zone = optarg;
4298 			break;
4299 		case 'R':	/* private option for admin/install use */
4300 			if (*optarg != '/') {
4301 				zerror(gettext("root path must be absolute."));
4302 				exit(Z_ERR);
4303 			}
4304 			if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
4305 				zerror(
4306 				    gettext("root path must be a directory."));
4307 				exit(Z_ERR);
4308 			}
4309 			zonecfg_set_root(optarg);
4310 			break;
4311 		default:
4312 			return (usage(B_FALSE));
4313 		}
4314 	}
4315 
4316 	if (optind >= argc)
4317 		return (usage(B_FALSE));
4318 	if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) {
4319 		errno = Z_NO_ZONE;
4320 		zperror(target_zone, B_TRUE);
4321 		exit(Z_ERR);
4322 	}
4323 	return (parse_and_run(argc - optind, &argv[optind]));
4324 }
4325