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