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