Print this page
PSARC 2008/766 native zones p2v
6667924 physical to virtual utility for native zones


   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 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * zoneadm is a command interpreter for zone administration.  It is all in
  29  * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
  30  * main() calls parse_and_run() which calls cmd_match(), then invokes the
  31  * appropriate command's handler function.  The rest of the program is the
  32  * handler functions and their helper functions.
  33  *
  34  * Some of the helper functions are used largely to simplify I18N: reducing
  35  * the need for translation notes.  This is particularly true of many of
  36  * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
  37  * than zerror(gettext("foo failed")) with a translation note indicating
  38  * that "foo" need not be translated.
  39  */
  40 
  41 #include <stdio.h>
  42 #include <errno.h>
  43 #include <unistd.h>


  85 #include "zoneadm.h"
  86 
  87 #define MAXARGS 8
  88 
  89 /* Reflects kernel zone entries */
  90 typedef struct zone_entry {
  91         zoneid_t        zid;
  92         char            zname[ZONENAME_MAX];
  93         char            *zstate_str;
  94         zone_state_t    zstate_num;
  95         char            zbrand[MAXNAMELEN];
  96         char            zroot[MAXPATHLEN];
  97         char            zuuid[UUID_PRINTABLE_STRING_LENGTH];
  98         zone_iptype_t   ziptype;
  99 } zone_entry_t;
 100 
 101 #define CLUSTER_BRAND_NAME      "cluster"
 102 
 103 static zone_entry_t *zents;
 104 static size_t nzents;
 105 static boolean_t is_native_zone = B_TRUE;
 106 
 107 #define LOOPBACK_IF     "lo0"
 108 #define SOCKET_AF(af)   (((af) == AF_UNSPEC) ? AF_INET : (af))
 109 
 110 struct net_if {
 111         char    *name;
 112         int     af;
 113 };
 114 
 115 /* 0755 is the default directory mode. */
 116 #define DEFAULT_DIR_MODE \
 117         (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
 118 
 119 struct cmd {
 120         uint_t  cmd_num;                                /* command number */
 121         char    *cmd_name;                              /* command name */
 122         char    *short_usage;                           /* short form help */
 123         int     (*handler)(int argc, char *argv[]);     /* function to call */
 124 
 125 };


1070         }
1071         /*
1072          * The existence of the root path is only bad in the configured state,
1073          * as it is *supposed* to be there at the installed and later states.
1074          * However, the root path is expected to be there if the zone is
1075          * detached.
1076          * State/command mismatches are caught earlier in verify_details().
1077          */
1078         if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) {
1079                 if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >=
1080                     sizeof (rootpath)) {
1081                         /*
1082                          * TRANSLATION_NOTE
1083                          * Zonepath is a literal that should not be translated.
1084                          */
1085                         (void) fprintf(stderr,
1086                             gettext("Zonepath %s is too long.\n"), rpath);
1087                         return (Z_ERR);
1088                 }
1089                 if ((res = stat(rootpath, &stbuf)) == 0) {
1090                         struct dirent   *dp;
1091                         DIR             *dirp;
1092                         boolean_t       empty = B_TRUE;
1093 
1094                         if (zonecfg_detached(rpath)) {
1095                                 (void) fprintf(stderr,
1096                                     gettext("Cannot %s detached "
1097                                     "zone.\nUse attach or remove %s "
1098                                     "directory.\n"), cmd_to_str(cmd_num),
1099                                     rpath);
1100                                 return (Z_ERR);
1101                         }
1102 
1103                         /* Not detached, check if it really looks ok. */
1104 
1105                         if (!S_ISDIR(stbuf.st_mode)) {
1106                                 (void) fprintf(stderr, gettext("%s is not a "
1107                                     "directory.\n"), rootpath);
1108                                 return (Z_ERR);
1109                         }
1110 
1111                         if (stbuf.st_uid != 0) {
1112                                 (void) fprintf(stderr, gettext("%s is not "
1113                                     "owned by root.\n"), rootpath);
1114                                 return (Z_ERR);
1115                         }
1116 
1117                         if ((stbuf.st_mode & 0777) != 0755) {
1118                                 (void) fprintf(stderr, gettext("%s mode is not "
1119                                     "0755.\n"), rootpath);
1120                                 return (Z_ERR);
1121                         }
1122 
1123                         if ((dirp = opendir(rootpath)) == NULL) {
1124                                 (void) fprintf(stderr, gettext("Could not "
1125                                     "open rootpath %s\n"), rootpath);
1126                                 return (Z_ERR);
1127                         }
1128 
1129                         /* Verify that the dir is empty. */
1130                         while ((dp = readdir(dirp)) != NULL) {
1131                                 if (strcmp(dp->d_name, ".") == 0 ||
1132                                     strcmp(dp->d_name, "..") == 0)
1133                                         continue;
1134 
1135                                 empty = B_FALSE;
1136                                 break;
1137                         }
1138                         (void) closedir(dirp);
1139 
1140                         if (!empty) {
1141                                 (void) fprintf(stderr, gettext("Rootpath %s "
1142                                     "exists and contains data; remove or move "
1143                                     "aside prior to %s.\n"), rootpath,
1144                                     cmd_to_str(cmd_num));
1145                                 return (Z_ERR);
1146                         }
1147 
1148                 }
1149         }
1150 
1151         return (err ? Z_ERR : Z_OK);
1152 }
1153 
1154 static int
1155 invoke_brand_handler(int cmd_num, char *argv[])
1156 {
1157         zone_dochandle_t handle;
1158         int err;
1159 
1160         if ((handle = zonecfg_init_handle()) == NULL) {
1161                 zperror(cmd_to_str(cmd_num), B_TRUE);
1162                 return (Z_ERR);
1163         }
1164         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
1165                 errno = err;
1166                 zperror(cmd_to_str(cmd_num), B_TRUE);
1167                 zonecfg_fini_handle(handle);
1168                 return (Z_ERR);
1169         }
1170         if (verify_brand(handle, cmd_num, argv) != Z_OK) {


1696                                     zone_state_str(zent->zstate_num);
1697                         }
1698                         zerror(gettext("%s operation is invalid for %s zones."),
1699                             cmd_to_str(cmd_num), zent->zstate_str);
1700                         return (Z_ERR);
1701                 }
1702                 if ((err = zone_get_state(zone, &state)) != Z_OK) {
1703                         errno = err;
1704                         zperror2(zone, gettext("could not get state"));
1705                         return (Z_ERR);
1706                 }
1707                 switch (cmd_num) {
1708                 case CMD_UNINSTALL:
1709                         if (state == ZONE_STATE_CONFIGURED) {
1710                                 zerror(gettext("is already in state '%s'."),
1711                                     zone_state_str(ZONE_STATE_CONFIGURED));
1712                                 return (Z_ERR);
1713                         }
1714                         break;
1715                 case CMD_ATTACH:











1716                 case CMD_CLONE:
1717                 case CMD_INSTALL:
1718                         if (state == ZONE_STATE_INSTALLED) {
1719                                 zerror(gettext("is already %s."),
1720                                     zone_state_str(ZONE_STATE_INSTALLED));
1721                                 return (Z_ERR);
1722                         } else if (state == ZONE_STATE_INCOMPLETE) {
1723                                 zerror(gettext("zone is %s; %s required."),
1724                                     zone_state_str(ZONE_STATE_INCOMPLETE),
1725                                     cmd_to_str(CMD_UNINSTALL));
1726                                 return (Z_ERR);
1727                         }
1728                         break;
1729                 case CMD_DETACH:
1730                 case CMD_MOVE:
1731                 case CMD_READY:
1732                 case CMD_BOOT:
1733                 case CMD_MOUNT:
1734                 case CMD_MARK:
1735                         if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
1736                             force)
1737                                 min_state = ZONE_STATE_INCOMPLETE;


1738                         else
1739                                 min_state = ZONE_STATE_INSTALLED;
1740 
1741                         if (force && cmd_num == CMD_BOOT && is_native_zone) {
1742                                 zerror(gettext("Only branded zones may be "
1743                                     "force-booted."));
1744                                 return (Z_ERR);
1745                         }
1746 
1747                         if (state < min_state) {
1748                                 zerror(gettext("must be %s before %s."),
1749                                     zone_state_str(min_state),
1750                                     cmd_to_str(cmd_num));
1751                                 return (Z_ERR);
1752                         }
1753                         break;
1754                 case CMD_VERIFY:
1755                         if (state == ZONE_STATE_INCOMPLETE) {
1756                                 zerror(gettext("zone is %s; %s required."),
1757                                     zone_state_str(ZONE_STATE_INCOMPLETE),
1758                                     cmd_to_str(CMD_UNINSTALL));
1759                                 return (Z_ERR);
1760                         }
1761                         break;
1762                 case CMD_UNMOUNT:
1763                         if (state != ZONE_STATE_MOUNTED) {
1764                                 zerror(gettext("must be %s before %s."),
1765                                     zone_state_str(ZONE_STATE_MOUNTED),
1766                                     cmd_to_str(cmd_num));


4608 }
4609 
4610 /* ARGSUSED */
4611 static int
4612 attach_func(int argc, char *argv[])
4613 {
4614         int lockfd = -1;
4615         int err, arg;
4616         boolean_t force = B_FALSE;
4617         zone_dochandle_t handle;
4618         char zonepath[MAXPATHLEN];
4619         char cmdbuf[MAXPATHLEN];
4620         char postcmdbuf[MAXPATHLEN];
4621         boolean_t execute = B_TRUE;
4622         boolean_t brand_help = B_FALSE;
4623         char *manifest_path;
4624         char tmpmanifest[80];
4625         int manifest_pos;
4626         brand_handle_t bh = NULL;
4627         int status;




4628 
4629         if (zonecfg_in_alt_root()) {
4630                 zerror(gettext("cannot attach zone in alternate root"));
4631                 return (Z_ERR);
4632         }
4633 
4634         /* Check the argv string for args we handle internally */
4635         optind = 0;
4636         opterr = 0;
4637         while ((arg = getopt(argc, argv, "?Fn:")) != EOF) {
4638                 switch (arg) {
4639                 case '?':
4640                         if (optopt == '?') {
4641                                 sub_usage(SHELP_ATTACH, CMD_ATTACH);
4642                                 brand_help = B_TRUE;
4643                         }
4644                         /* Ignore unknown options - may be brand specific. */
4645                         break;
4646                 case 'F':
4647                         force = B_TRUE;
4648                         break;
4649                 case 'n':
4650                         execute = B_FALSE;
4651                         manifest_path = optarg;
4652                         manifest_pos = optind - 1;
4653                         break;














4654                 default:
4655                         /* Ignore unknown options - may be brand specific. */
4656                         break;
4657                 }

4658         }
4659 
4660         if (brand_help) {
4661                 force = B_FALSE;
4662                 execute = B_TRUE;
4663         }
4664 
4665         /* dry-run and force flags are mutually exclusive */
4666         if (!execute && force) {
4667                 zerror(gettext("-F and -n flags are mutually exclusive"));
4668                 return (Z_ERR);
4669         }
4670 
4671         /*
4672          * If the no-execute option was specified, we don't do validation and
4673          * need to figure out the brand, since there is no zone required to be
4674          * configured for this option.
4675          */
4676         if (execute) {
4677                 if (!brand_help) {
4678                         if (sanity_check(target_zone, CMD_ATTACH, B_FALSE,
4679                             B_TRUE, B_FALSE) != Z_OK)
4680                                 return (Z_ERR);
4681                         if (verify_details(CMD_ATTACH, argv) != Z_OK)
4682                                 return (Z_ERR);
4683                 }
4684 
4685                 if ((err = zone_get_zonepath(target_zone, zonepath,
4686                     sizeof (zonepath))) != Z_OK) {
4687                         errno = err;
4688                         zperror2(target_zone,
4689                             gettext("could not get zone path"));
4690                         return (Z_ERR);
4691                 }
4692         } else {
4693                 if (dryrun_get_brand(manifest_path, tmpmanifest,
4694                     sizeof (tmpmanifest)) != Z_OK)
4695                         return (Z_ERR);
4696 
4697                 argv[manifest_pos] = tmpmanifest;
4698                 target_zone = "-";
4699                 (void) strlcpy(zonepath, "-", sizeof (zonepath));


4732                 return (Z_ERR);
4733 
4734         /* Append all options to postattach hook. */
4735         if (addoptions(postcmdbuf, argv, sizeof (postcmdbuf)) != Z_OK)
4736                 return (Z_ERR);
4737 
4738         if (execute && !brand_help) {
4739                 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
4740                         zerror(gettext("another %s may have an operation in "
4741                             "progress."), "zoneadm");
4742                         return (Z_ERR);
4743                 }
4744         }
4745 
4746         if (!force) {
4747                 /*
4748                  * Not a force-attach, so we need to actually do the work.
4749                  */
4750                 if (cmdbuf[0] != '\0') {
4751                         /* Run the attach hook */
4752                         status = do_subproc_interactive(cmdbuf);
4753                         if ((status = subproc_status(gettext("brand-specific "
4754                             "attach"), status, B_FALSE)) != ZONE_SUBPROC_OK) {
4755                                 if (status == ZONE_SUBPROC_USAGE && !brand_help)
4756                                         sub_usage(SHELP_ATTACH, CMD_ATTACH);
4757 
4758                                 if (execute && !brand_help) {
4759                                         assert(lockfd >= 0);
4760                                         zonecfg_release_lock_file(target_zone,
4761                                             lockfd);
4762                                         lockfd = -1;
4763                                 }
4764 
4765                                 assert(lockfd == -1);
4766                                 return (Z_ERR);
4767                         }
4768                 }
4769 
4770                 /*
4771                  * Else run the built-in attach support.
4772                  * This is a no-op since there is nothing to validate.
4773                  */
4774 
4775                 /* If dry-run or help, then we're done. */
4776                 if (!execute || brand_help) {
4777                         if (!execute)
4778                                 (void) unlink(tmpmanifest);
4779                         assert(lockfd == -1);


4782         }
4783 
4784         if ((handle = zonecfg_init_handle()) == NULL) {
4785                 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4786                 err = Z_ERR;
4787         } else if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4788                 errno = err;
4789                 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4790                 zonecfg_fini_handle(handle);
4791         } else {
4792                 zonecfg_rm_detached(handle, force);
4793                 zonecfg_fini_handle(handle);
4794         }
4795 
4796         if (err == Z_OK &&
4797             (err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
4798                 errno = err;
4799                 zperror(gettext("could not reset state"), B_TRUE);
4800         }
4801 
4802         assert(lockfd >= 0);
4803         zonecfg_release_lock_file(target_zone, lockfd);
4804         lockfd = -1;
4805 
4806         /* If we have a brand postattach hook, run it. */
4807         if (err == Z_OK && !force && postcmdbuf[0] != '\0') {
4808                 status = do_subproc(postcmdbuf);
4809                 if (subproc_status(gettext("brand-specific postattach"),
4810                     status, B_FALSE) != ZONE_SUBPROC_OK) {
4811                         if ((err = zone_set_state(target_zone,
4812                             ZONE_STATE_CONFIGURED)) != Z_OK) {
4813                                 errno = err;
4814                                 zperror(gettext("could not reset state"),
4815                                     B_TRUE);
4816                         }
4817                 }
4818         }
4819 
4820         assert(lockfd == -1);
4821         return ((err == Z_OK) ? Z_OK : Z_ERR);
4822 }


5101         zone_cmd_arg_t zarg;
5102 
5103         if (argc > 0)
5104                 return (Z_USAGE);
5105         if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE, B_FALSE)
5106             != Z_OK)
5107                 return (Z_ERR);
5108 
5109         zarg.cmd = Z_UNMOUNT;
5110         if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
5111                 zerror(gettext("call to %s failed"), "zoneadmd");
5112                 return (Z_ERR);
5113         }
5114         return (Z_OK);
5115 }
5116 
5117 static int
5118 mark_func(int argc, char *argv[])
5119 {
5120         int err, lockfd;



5121 
5122         if (argc != 1 || strcmp(argv[0], "incomplete") != 0)







5123                 return (Z_USAGE);
5124         if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_FALSE, B_FALSE)


















5125             != Z_OK)
5126                 return (Z_ERR);
5127 
5128         /*
5129          * Invoke brand-specific handler.
5130          */
5131         if (invoke_brand_handler(CMD_MARK, argv) != Z_OK)
5132                 return (Z_ERR);
5133 
5134         if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
5135                 zerror(gettext("another %s may have an operation in progress."),
5136                     "zoneadm");
5137                 return (Z_ERR);
5138         }
5139 
5140         err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
5141         if (err != Z_OK) {
5142                 errno = err;
5143                 zperror2(target_zone, gettext("could not set state"));
5144         }
5145         zonecfg_release_lock_file(target_zone, lockfd);
5146 
5147         return (err);
5148 }
5149 
5150 /*
5151  * Check what scheduling class we're running under and print a warning if
5152  * we're not using FSS.
5153  */
5154 static int
5155 check_sched_fss(zone_dochandle_t handle)
5156 {
5157         char class_name[PC_CLNMSZ];
5158 
5159         if (zonecfg_get_dflt_sched_class(handle, class_name,
5160             sizeof (class_name)) != Z_OK) {


5575         /*
5576          * See if we have inherited the right to manipulate this zone from
5577          * a zoneadm instance in our ancestry.  If so, set zone_lock_cnt to
5578          * indicate it.  If not, make that explicit in our environment.
5579          */
5580         zonecfg_init_lock_file(target_zone, &zone_lock_env);
5581         if (zone_lock_env != NULL)
5582                 zoneadm_is_nested = B_TRUE;
5583 
5584         /*
5585          * If we are going to be operating on a single zone, retrieve its
5586          * brand type and determine whether it is native or not.
5587          */
5588         if ((target_zone != NULL) &&
5589             (strcmp(target_zone, GLOBAL_ZONENAME) != 0)) {
5590                 if (zone_get_brand(target_zone, target_brand,
5591                     sizeof (target_brand)) != Z_OK) {
5592                         zerror(gettext("missing or invalid brand"));
5593                         exit(Z_ERR);
5594                 }
5595                 is_native_zone = (strcmp(target_brand, NATIVE_BRAND_NAME) == 0);
5596         }
5597 
5598         err = parse_and_run(argc - optind, &argv[optind]);
5599 
5600         return (err);
5601 }


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * zoneadm is a command interpreter for zone administration.  It is all in
  29  * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
  30  * main() calls parse_and_run() which calls cmd_match(), then invokes the
  31  * appropriate command's handler function.  The rest of the program is the
  32  * handler functions and their helper functions.
  33  *
  34  * Some of the helper functions are used largely to simplify I18N: reducing
  35  * the need for translation notes.  This is particularly true of many of
  36  * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
  37  * than zerror(gettext("foo failed")) with a translation note indicating
  38  * that "foo" need not be translated.
  39  */
  40 
  41 #include <stdio.h>
  42 #include <errno.h>
  43 #include <unistd.h>


  85 #include "zoneadm.h"
  86 
  87 #define MAXARGS 8
  88 
  89 /* Reflects kernel zone entries */
  90 typedef struct zone_entry {
  91         zoneid_t        zid;
  92         char            zname[ZONENAME_MAX];
  93         char            *zstate_str;
  94         zone_state_t    zstate_num;
  95         char            zbrand[MAXNAMELEN];
  96         char            zroot[MAXPATHLEN];
  97         char            zuuid[UUID_PRINTABLE_STRING_LENGTH];
  98         zone_iptype_t   ziptype;
  99 } zone_entry_t;
 100 
 101 #define CLUSTER_BRAND_NAME      "cluster"
 102 
 103 static zone_entry_t *zents;
 104 static size_t nzents;

 105 
 106 #define LOOPBACK_IF     "lo0"
 107 #define SOCKET_AF(af)   (((af) == AF_UNSPEC) ? AF_INET : (af))
 108 
 109 struct net_if {
 110         char    *name;
 111         int     af;
 112 };
 113 
 114 /* 0755 is the default directory mode. */
 115 #define DEFAULT_DIR_MODE \
 116         (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
 117 
 118 struct cmd {
 119         uint_t  cmd_num;                                /* command number */
 120         char    *cmd_name;                              /* command name */
 121         char    *short_usage;                           /* short form help */
 122         int     (*handler)(int argc, char *argv[]);     /* function to call */
 123 
 124 };


1069         }
1070         /*
1071          * The existence of the root path is only bad in the configured state,
1072          * as it is *supposed* to be there at the installed and later states.
1073          * However, the root path is expected to be there if the zone is
1074          * detached.
1075          * State/command mismatches are caught earlier in verify_details().
1076          */
1077         if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) {
1078                 if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >=
1079                     sizeof (rootpath)) {
1080                         /*
1081                          * TRANSLATION_NOTE
1082                          * Zonepath is a literal that should not be translated.
1083                          */
1084                         (void) fprintf(stderr,
1085                             gettext("Zonepath %s is too long.\n"), rpath);
1086                         return (Z_ERR);
1087                 }
1088                 if ((res = stat(rootpath, &stbuf)) == 0) {




1089                         if (zonecfg_detached(rpath)) {
1090                                 (void) fprintf(stderr,
1091                                     gettext("Cannot %s detached "
1092                                     "zone.\nUse attach or remove %s "
1093                                     "directory.\n"), cmd_to_str(cmd_num),
1094                                     rpath);
1095                                 return (Z_ERR);
1096                         }
1097 
1098                         /* Not detached, check if it really looks ok. */
1099 
1100                         if (!S_ISDIR(stbuf.st_mode)) {
1101                                 (void) fprintf(stderr, gettext("%s is not a "
1102                                     "directory.\n"), rootpath);
1103                                 return (Z_ERR);
1104                         }
1105 
1106                         if (stbuf.st_uid != 0) {
1107                                 (void) fprintf(stderr, gettext("%s is not "
1108                                     "owned by root.\n"), rootpath);
1109                                 return (Z_ERR);
1110                         }
1111 
1112                         if ((stbuf.st_mode & 0777) != 0755) {
1113                                 (void) fprintf(stderr, gettext("%s mode is not "
1114                                     "0755.\n"), rootpath);
1115                                 return (Z_ERR);
1116                         }





1117                 }









1118         }

1119 











1120         return (err ? Z_ERR : Z_OK);
1121 }
1122 
1123 static int
1124 invoke_brand_handler(int cmd_num, char *argv[])
1125 {
1126         zone_dochandle_t handle;
1127         int err;
1128 
1129         if ((handle = zonecfg_init_handle()) == NULL) {
1130                 zperror(cmd_to_str(cmd_num), B_TRUE);
1131                 return (Z_ERR);
1132         }
1133         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
1134                 errno = err;
1135                 zperror(cmd_to_str(cmd_num), B_TRUE);
1136                 zonecfg_fini_handle(handle);
1137                 return (Z_ERR);
1138         }
1139         if (verify_brand(handle, cmd_num, argv) != Z_OK) {


1665                                     zone_state_str(zent->zstate_num);
1666                         }
1667                         zerror(gettext("%s operation is invalid for %s zones."),
1668                             cmd_to_str(cmd_num), zent->zstate_str);
1669                         return (Z_ERR);
1670                 }
1671                 if ((err = zone_get_state(zone, &state)) != Z_OK) {
1672                         errno = err;
1673                         zperror2(zone, gettext("could not get state"));
1674                         return (Z_ERR);
1675                 }
1676                 switch (cmd_num) {
1677                 case CMD_UNINSTALL:
1678                         if (state == ZONE_STATE_CONFIGURED) {
1679                                 zerror(gettext("is already in state '%s'."),
1680                                     zone_state_str(ZONE_STATE_CONFIGURED));
1681                                 return (Z_ERR);
1682                         }
1683                         break;
1684                 case CMD_ATTACH:
1685                         if (state == ZONE_STATE_INSTALLED) {
1686                                 zerror(gettext("is already %s."),
1687                                     zone_state_str(ZONE_STATE_INSTALLED));
1688                                 return (Z_ERR);
1689                         } else if (state == ZONE_STATE_INCOMPLETE && !force) {
1690                                 zerror(gettext("zone is %s; %s required."),
1691                                     zone_state_str(ZONE_STATE_INCOMPLETE),
1692                                     cmd_to_str(CMD_UNINSTALL));
1693                                 return (Z_ERR);
1694                         }
1695                         break;
1696                 case CMD_CLONE:
1697                 case CMD_INSTALL:
1698                         if (state == ZONE_STATE_INSTALLED) {
1699                                 zerror(gettext("is already %s."),
1700                                     zone_state_str(ZONE_STATE_INSTALLED));
1701                                 return (Z_ERR);
1702                         } else if (state == ZONE_STATE_INCOMPLETE) {
1703                                 zerror(gettext("zone is %s; %s required."),
1704                                     zone_state_str(ZONE_STATE_INCOMPLETE),
1705                                     cmd_to_str(CMD_UNINSTALL));
1706                                 return (Z_ERR);
1707                         }
1708                         break;
1709                 case CMD_DETACH:
1710                 case CMD_MOVE:
1711                 case CMD_READY:
1712                 case CMD_BOOT:
1713                 case CMD_MOUNT:
1714                 case CMD_MARK:
1715                         if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
1716                             force)
1717                                 min_state = ZONE_STATE_INCOMPLETE;
1718                         else if (cmd_num == CMD_MARK)
1719                                 min_state = ZONE_STATE_CONFIGURED;
1720                         else
1721                                 min_state = ZONE_STATE_INSTALLED;
1722 






1723                         if (state < min_state) {
1724                                 zerror(gettext("must be %s before %s."),
1725                                     zone_state_str(min_state),
1726                                     cmd_to_str(cmd_num));
1727                                 return (Z_ERR);
1728                         }
1729                         break;
1730                 case CMD_VERIFY:
1731                         if (state == ZONE_STATE_INCOMPLETE) {
1732                                 zerror(gettext("zone is %s; %s required."),
1733                                     zone_state_str(ZONE_STATE_INCOMPLETE),
1734                                     cmd_to_str(CMD_UNINSTALL));
1735                                 return (Z_ERR);
1736                         }
1737                         break;
1738                 case CMD_UNMOUNT:
1739                         if (state != ZONE_STATE_MOUNTED) {
1740                                 zerror(gettext("must be %s before %s."),
1741                                     zone_state_str(ZONE_STATE_MOUNTED),
1742                                     cmd_to_str(cmd_num));


4584 }
4585 
4586 /* ARGSUSED */
4587 static int
4588 attach_func(int argc, char *argv[])
4589 {
4590         int lockfd = -1;
4591         int err, arg;
4592         boolean_t force = B_FALSE;
4593         zone_dochandle_t handle;
4594         char zonepath[MAXPATHLEN];
4595         char cmdbuf[MAXPATHLEN];
4596         char postcmdbuf[MAXPATHLEN];
4597         boolean_t execute = B_TRUE;
4598         boolean_t brand_help = B_FALSE;
4599         char *manifest_path;
4600         char tmpmanifest[80];
4601         int manifest_pos;
4602         brand_handle_t bh = NULL;
4603         int status;
4604         int last_index = 0;
4605         int offset;
4606         char *up;
4607         boolean_t forced_update = B_FALSE;
4608 
4609         if (zonecfg_in_alt_root()) {
4610                 zerror(gettext("cannot attach zone in alternate root"));
4611                 return (Z_ERR);
4612         }
4613 
4614         /* Check the argv string for args we handle internally */
4615         optind = 0;
4616         opterr = 0;
4617         while ((arg = getopt(argc, argv, "?Fn:U")) != EOF) {
4618                 switch (arg) {
4619                 case '?':
4620                         if (optopt == '?') {
4621                                 sub_usage(SHELP_ATTACH, CMD_ATTACH);
4622                                 brand_help = B_TRUE;
4623                         }
4624                         /* Ignore unknown options - may be brand specific. */
4625                         break;
4626                 case 'F':
4627                         force = B_TRUE;
4628                         break;
4629                 case 'n':
4630                         execute = B_FALSE;
4631                         manifest_path = optarg;
4632                         manifest_pos = optind - 1;
4633                         break;
4634                 case 'U':
4635                         /*
4636                          * Undocumented 'force update' option for p2v update on
4637                          * attach when zone is in the incomplete state.  Change
4638                          * the option back to 'u' and set forced_update flag.
4639                          */
4640                         if (optind == last_index)
4641                                 offset = optind;
4642                         else
4643                                 offset = optind - 1;
4644                         if ((up = index(argv[offset], 'U')) != NULL)
4645                                 *up = 'u';
4646                         forced_update = B_TRUE;
4647                         break;
4648                 default:
4649                         /* Ignore unknown options - may be brand specific. */
4650                         break;
4651                 }
4652                 last_index = optind;
4653         }
4654 
4655         if (brand_help) {
4656                 force = B_FALSE;
4657                 execute = B_TRUE;
4658         }
4659 
4660         /* dry-run and force flags are mutually exclusive */
4661         if (!execute && force) {
4662                 zerror(gettext("-F and -n flags are mutually exclusive"));
4663                 return (Z_ERR);
4664         }
4665 
4666         /*
4667          * If the no-execute option was specified, we don't do validation and
4668          * need to figure out the brand, since there is no zone required to be
4669          * configured for this option.
4670          */
4671         if (execute) {
4672                 if (!brand_help) {
4673                         if (sanity_check(target_zone, CMD_ATTACH, B_FALSE,
4674                             B_TRUE, forced_update) != Z_OK)
4675                                 return (Z_ERR);
4676                         if (verify_details(CMD_ATTACH, argv) != Z_OK)
4677                                 return (Z_ERR);
4678                 }
4679 
4680                 if ((err = zone_get_zonepath(target_zone, zonepath,
4681                     sizeof (zonepath))) != Z_OK) {
4682                         errno = err;
4683                         zperror2(target_zone,
4684                             gettext("could not get zone path"));
4685                         return (Z_ERR);
4686                 }
4687         } else {
4688                 if (dryrun_get_brand(manifest_path, tmpmanifest,
4689                     sizeof (tmpmanifest)) != Z_OK)
4690                         return (Z_ERR);
4691 
4692                 argv[manifest_pos] = tmpmanifest;
4693                 target_zone = "-";
4694                 (void) strlcpy(zonepath, "-", sizeof (zonepath));


4727                 return (Z_ERR);
4728 
4729         /* Append all options to postattach hook. */
4730         if (addoptions(postcmdbuf, argv, sizeof (postcmdbuf)) != Z_OK)
4731                 return (Z_ERR);
4732 
4733         if (execute && !brand_help) {
4734                 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
4735                         zerror(gettext("another %s may have an operation in "
4736                             "progress."), "zoneadm");
4737                         return (Z_ERR);
4738                 }
4739         }
4740 
4741         if (!force) {
4742                 /*
4743                  * Not a force-attach, so we need to actually do the work.
4744                  */
4745                 if (cmdbuf[0] != '\0') {
4746                         /* Run the attach hook */
4747                         status = do_subproc(cmdbuf);
4748                         if ((status = subproc_status(gettext("brand-specific "
4749                             "attach"), status, B_FALSE)) != ZONE_SUBPROC_OK) {
4750                                 if (status == ZONE_SUBPROC_USAGE && !brand_help)
4751                                         sub_usage(SHELP_ATTACH, CMD_ATTACH);
4752 
4753                                 if (execute && !brand_help) {
4754                                         assert(zonecfg_lock_file_held(&lockfd));
4755                                         zonecfg_release_lock_file(target_zone,
4756                                             lockfd);
4757                                         lockfd = -1;
4758                                 }
4759 
4760                                 assert(lockfd == -1);
4761                                 return (Z_ERR);
4762                         }
4763                 }
4764 
4765                 /*
4766                  * Else run the built-in attach support.
4767                  * This is a no-op since there is nothing to validate.
4768                  */
4769 
4770                 /* If dry-run or help, then we're done. */
4771                 if (!execute || brand_help) {
4772                         if (!execute)
4773                                 (void) unlink(tmpmanifest);
4774                         assert(lockfd == -1);


4777         }
4778 
4779         if ((handle = zonecfg_init_handle()) == NULL) {
4780                 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4781                 err = Z_ERR;
4782         } else if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4783                 errno = err;
4784                 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4785                 zonecfg_fini_handle(handle);
4786         } else {
4787                 zonecfg_rm_detached(handle, force);
4788                 zonecfg_fini_handle(handle);
4789         }
4790 
4791         if (err == Z_OK &&
4792             (err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
4793                 errno = err;
4794                 zperror(gettext("could not reset state"), B_TRUE);
4795         }
4796 
4797         assert(zonecfg_lock_file_held(&lockfd));
4798         zonecfg_release_lock_file(target_zone, lockfd);
4799         lockfd = -1;
4800 
4801         /* If we have a brand postattach hook, run it. */
4802         if (err == Z_OK && !force && postcmdbuf[0] != '\0') {
4803                 status = do_subproc(postcmdbuf);
4804                 if (subproc_status(gettext("brand-specific postattach"),
4805                     status, B_FALSE) != ZONE_SUBPROC_OK) {
4806                         if ((err = zone_set_state(target_zone,
4807                             ZONE_STATE_CONFIGURED)) != Z_OK) {
4808                                 errno = err;
4809                                 zperror(gettext("could not reset state"),
4810                                     B_TRUE);
4811                         }
4812                 }
4813         }
4814 
4815         assert(lockfd == -1);
4816         return ((err == Z_OK) ? Z_OK : Z_ERR);
4817 }


5096         zone_cmd_arg_t zarg;
5097 
5098         if (argc > 0)
5099                 return (Z_USAGE);
5100         if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE, B_FALSE)
5101             != Z_OK)
5102                 return (Z_ERR);
5103 
5104         zarg.cmd = Z_UNMOUNT;
5105         if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
5106                 zerror(gettext("call to %s failed"), "zoneadmd");
5107                 return (Z_ERR);
5108         }
5109         return (Z_OK);
5110 }
5111 
5112 static int
5113 mark_func(int argc, char *argv[])
5114 {
5115         int err, lockfd;
5116         int arg;
5117         boolean_t force = B_FALSE;
5118         int state;
5119 
5120         optind = 0;
5121         opterr = 0;
5122         while ((arg = getopt(argc, argv, "F")) != EOF) {
5123                 switch (arg) {
5124                 case 'F':
5125                         force = B_TRUE;
5126                         break;
5127                 default:
5128                         return (Z_USAGE);
5129                 }
5130         }
5131 
5132         if (argc != (optind + 1))
5133                 return (Z_USAGE);
5134 
5135         if (strcmp(argv[optind], "configured") == 0)
5136                 state = ZONE_STATE_CONFIGURED;
5137         else if (strcmp(argv[optind], "incomplete") == 0)
5138                 state = ZONE_STATE_INCOMPLETE;
5139         else if (strcmp(argv[optind], "installed") == 0)
5140                 state = ZONE_STATE_INSTALLED;
5141         else
5142                 return (Z_USAGE);
5143 
5144         if (state != ZONE_STATE_INCOMPLETE && !force)
5145                 return (Z_USAGE);
5146 
5147         if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_TRUE, B_FALSE)
5148             != Z_OK)
5149                 return (Z_ERR);
5150 
5151         /*
5152          * Invoke brand-specific handler.
5153          */
5154         if (invoke_brand_handler(CMD_MARK, argv) != Z_OK)
5155                 return (Z_ERR);
5156 
5157         if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
5158                 zerror(gettext("another %s may have an operation in progress."),
5159                     "zoneadm");
5160                 return (Z_ERR);
5161         }
5162 
5163         err = zone_set_state(target_zone, state);
5164         if (err != Z_OK) {
5165                 errno = err;
5166                 zperror2(target_zone, gettext("could not set state"));
5167         }
5168         zonecfg_release_lock_file(target_zone, lockfd);
5169 
5170         return (err);
5171 }
5172 
5173 /*
5174  * Check what scheduling class we're running under and print a warning if
5175  * we're not using FSS.
5176  */
5177 static int
5178 check_sched_fss(zone_dochandle_t handle)
5179 {
5180         char class_name[PC_CLNMSZ];
5181 
5182         if (zonecfg_get_dflt_sched_class(handle, class_name,
5183             sizeof (class_name)) != Z_OK) {


5598         /*
5599          * See if we have inherited the right to manipulate this zone from
5600          * a zoneadm instance in our ancestry.  If so, set zone_lock_cnt to
5601          * indicate it.  If not, make that explicit in our environment.
5602          */
5603         zonecfg_init_lock_file(target_zone, &zone_lock_env);
5604         if (zone_lock_env != NULL)
5605                 zoneadm_is_nested = B_TRUE;
5606 
5607         /*
5608          * If we are going to be operating on a single zone, retrieve its
5609          * brand type and determine whether it is native or not.
5610          */
5611         if ((target_zone != NULL) &&
5612             (strcmp(target_zone, GLOBAL_ZONENAME) != 0)) {
5613                 if (zone_get_brand(target_zone, target_brand,
5614                     sizeof (target_brand)) != Z_OK) {
5615                         zerror(gettext("missing or invalid brand"));
5616                         exit(Z_ERR);
5617                 }

5618         }
5619 
5620         err = parse_and_run(argc - optind, &argv[optind]);
5621 
5622         return (err);
5623 }