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