Print this page
OS-192 zone_create() warning on headnode


   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  * Copyright (c) 2015 by Delphix. All rights reserved.

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


  84 #include <pwd.h>
  85 #include <auth_list.h>
  86 #include <auth_attr.h>
  87 #include <secdb.h>
  88 
  89 #include "zoneadm.h"
  90 
  91 #define MAXARGS 8
  92 #define SOURCE_ZONE (CMD_MAX + 1)
  93 
  94 /* Reflects kernel zone entries */
  95 typedef struct zone_entry {
  96         zoneid_t        zid;
  97         char            zname[ZONENAME_MAX];
  98         char            *zstate_str;
  99         zone_state_t    zstate_num;
 100         char            zbrand[MAXNAMELEN];
 101         char            zroot[MAXPATHLEN];
 102         char            zuuid[UUID_PRINTABLE_STRING_LENGTH];
 103         zone_iptype_t   ziptype;

 104 } zone_entry_t;
 105 
 106 #define CLUSTER_BRAND_NAME      "cluster"
 107 
 108 static zone_entry_t *zents;
 109 static size_t nzents;
 110 
 111 #define LOOPBACK_IF     "lo0"
 112 #define SOCKET_AF(af)   (((af) == AF_UNSPEC) ? AF_INET : (af))
 113 
 114 struct net_if {
 115         char    *name;
 116         int     af;
 117 };
 118 
 119 /* 0755 is the default directory mode. */
 120 #define DEFAULT_DIR_MODE \
 121         (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
 122 
 123 struct cmd {


 426         char *ip_type_str;
 427 
 428         /* Skip a zone that shutdown while we were collecting data. */
 429         if (zent->zname[0] == '\0')
 430                 return;
 431 
 432         if (zent->ziptype == ZS_EXCLUSIVE)
 433                 ip_type_str = "excl";
 434         else
 435                 ip_type_str = "shared";
 436 
 437         assert(!(verbose && parsable));
 438         if (firsttime && verbose) {
 439                 firsttime = B_FALSE;
 440                 (void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
 441                     ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
 442                     "IP");
 443         }
 444         if (!verbose) {
 445                 char *cp, *clim;

 446 
 447                 if (!parsable) {
 448                         (void) printf("%s\n", zent->zname);
 449                         return;
 450                 }
 451                 if (zent->zid == ZONE_ID_UNDEFINED)
 452                         (void) printf("-");
 453                 else
 454                         (void) printf("%lu", zent->zid);
 455                 (void) printf(":%s:%s:", zent->zname, zent->zstate_str);
 456                 cp = zent->zroot;
 457                 while ((clim = strchr(cp, ':')) != NULL) {
 458                         (void) printf("%.*s\\:", clim - cp, cp);
 459                         cp = clim + 1;
 460                 }
 461                 (void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
 462                     ip_type_str);




 463                 return;
 464         }
 465         if (zent->zstate_str != NULL) {
 466                 if (zent->zid == ZONE_ID_UNDEFINED)
 467                         (void) printf("%*s", ZONEID_WIDTH, "-");
 468                 else
 469                         (void) printf("%*lu", ZONEID_WIDTH, zent->zid);
 470                 (void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
 471                     zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
 472         }
 473 }
 474 
 475 static int
 476 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
 477 {
 478         char root[MAXPATHLEN], *cp;
 479         int err;
 480         uuid_t uuid;
 481         zone_dochandle_t handle;
 482 


 537          */
 538         if (getzoneid() != GLOBAL_ZONEID) {
 539                 assert(is_system_labeled() != 0);
 540                 (void) strlcpy(zent->zbrand, default_brand,
 541                     sizeof (zent->zbrand));
 542         } else if (zone_get_brand(zent->zname, zent->zbrand,
 543             sizeof (zent->zbrand)) != Z_OK) {
 544                 zperror2(zent->zname, gettext("could not get brand name"));
 545                 return (Z_ERR);
 546         }
 547 
 548         /*
 549          * Get ip type of the zone.
 550          * Note for global zone, ZS_SHARED is set always.
 551          */
 552         if (zid == GLOBAL_ZONEID) {
 553                 zent->ziptype = ZS_SHARED;
 554                 return (Z_OK);
 555         }
 556 
















 557         /*
 558          * There is a race condition where the zone could boot while
 559          * we're walking the index file.  In this case the zone state
 560          * could be seen as running from the call above, but the zoneid
 561          * would be undefined.
 562          *
 563          * There is also a race condition where the zone could shutdown after
 564          * we got its running state above.  This is also not an error and
 565          * we fall back to getting the ziptype from the zone configuration.
 566          */
 567         if (zent->zstate_num == ZONE_STATE_RUNNING &&
 568             zid != ZONE_ID_UNDEFINED) {
 569                 ushort_t flags;
 570 
 571                 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
 572                     sizeof (flags)) >= 0) {
 573                         if (flags & ZF_NET_EXCL)
 574                                 zent->ziptype = ZS_EXCLUSIVE;
 575                         else
 576                                 zent->ziptype = ZS_SHARED;
 577                         return (Z_OK);
 578                 }
 579         }
 580 
 581         if ((handle = zonecfg_init_handle()) == NULL) {
 582                 zperror2(zent->zname, gettext("could not init handle"));
 583                 return (Z_ERR);
 584         }
 585         if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) {
 586                 zperror2(zent->zname, gettext("could not get handle"));
 587                 zonecfg_fini_handle(handle);
 588                 return (Z_ERR);
 589         }
 590 
 591         if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) {
 592                 zperror2(zent->zname, gettext("could not get ip-type"));
 593                 zonecfg_fini_handle(handle);
 594                 return (Z_ERR);
 595         }
 596         zonecfg_fini_handle(handle);
 597 
 598         return (Z_OK);
 599 }
 600 
 601 /*
 602  * fetch_zents() calls zone_list(2) to find out how many zones are running
 603  * (which is stored in the global nzents), then calls zone_list(2) again
 604  * to fetch the list of running zones (stored in the global zents).  This
 605  * function may be called multiple times, so if zents is already set, we
 606  * return immediately to save work.
 607  *
 608  * Note that the data about running zones can change while this function
 609  * is running, so its possible that the list of zones will have empty slots
 610  * at the end.
 611  */
 612 
 613 static int
 614 fetch_zents(void)
 615 {
 616         zoneid_t *zids = NULL;


2775                 return_code = Z_ERR;
2776         if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK)
2777                 return_code = Z_ERR;
2778         if (!in_alt_root && verify_datasets(handle) != Z_OK)
2779                 return_code = Z_ERR;
2780 
2781         /*
2782          * As the "mount" command is used for patching/upgrading of zones
2783          * or other maintenance processes, the zone's privilege set is not
2784          * checked in this case.  Instead, the default, safe set of
2785          * privileges will be used when this zone is created in the
2786          * kernel.
2787          */
2788         if (!in_alt_root && cmd_num != CMD_MOUNT &&
2789             verify_limitpriv(handle) != Z_OK)
2790                 return_code = Z_ERR;
2791 
2792         return (return_code);
2793 }
2794 























































2795 static int
2796 verify_details(int cmd_num, char *argv[])
2797 {
2798         zone_dochandle_t handle;
2799         char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
2800         int return_code = Z_OK;
2801         int err;
2802 
2803         if ((handle = zonecfg_init_handle()) == NULL) {
2804                 zperror(cmd_to_str(cmd_num), B_TRUE);
2805                 return (Z_ERR);
2806         }
2807         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
2808                 errno = err;
2809                 zperror(cmd_to_str(cmd_num), B_TRUE);
2810                 zonecfg_fini_handle(handle);
2811                 return (Z_ERR);
2812         }
2813         if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2814             Z_OK) {


2834                  * TRANSLATION_NOTE
2835                  * XML and zonepath are literals that should not be translated.
2836                  */
2837                 (void) fprintf(stderr, gettext("The XML repository has "
2838                     "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
2839                     "These must match, so fix the incorrect entry.\n"),
2840                     zonepath, checkpath);
2841                 zonecfg_fini_handle(handle);
2842                 return (Z_ERR);
2843         }
2844         if (cmd_num != CMD_ATTACH &&
2845             validate_zonepath(zonepath, cmd_num) != Z_OK) {
2846                 (void) fprintf(stderr, gettext("could not verify zonepath %s "
2847                     "because of the above errors.\n"), zonepath);
2848                 return_code = Z_ERR;
2849         }
2850 
2851         if (verify_handle(cmd_num, handle, argv) != Z_OK)
2852                 return_code = Z_ERR;
2853 






2854         zonecfg_fini_handle(handle);
2855         if (return_code == Z_ERR)
2856                 (void) fprintf(stderr,
2857                     gettext("%s: zone %s failed to verify\n"),
2858                     execname, target_zone);
2859         return (return_code);
2860 }
2861 
2862 static int
2863 verify_func(int argc, char *argv[])
2864 {
2865         int arg;
2866 
2867         optind = 0;
2868         if ((arg = getopt(argc, argv, "?")) != EOF) {
2869                 switch (arg) {
2870                 case '?':
2871                         sub_usage(SHELP_VERIFY, CMD_VERIFY);
2872                         return (optopt == '?' ? Z_OK : Z_USAGE);
2873                 default:




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


  85 #include <pwd.h>
  86 #include <auth_list.h>
  87 #include <auth_attr.h>
  88 #include <secdb.h>
  89 
  90 #include "zoneadm.h"
  91 
  92 #define MAXARGS 8
  93 #define SOURCE_ZONE (CMD_MAX + 1)
  94 
  95 /* Reflects kernel zone entries */
  96 typedef struct zone_entry {
  97         zoneid_t        zid;
  98         char            zname[ZONENAME_MAX];
  99         char            *zstate_str;
 100         zone_state_t    zstate_num;
 101         char            zbrand[MAXNAMELEN];
 102         char            zroot[MAXPATHLEN];
 103         char            zuuid[UUID_PRINTABLE_STRING_LENGTH];
 104         zone_iptype_t   ziptype;
 105         zoneid_t        zdid;
 106 } zone_entry_t;
 107 
 108 #define CLUSTER_BRAND_NAME      "cluster"
 109 
 110 static zone_entry_t *zents;
 111 static size_t nzents;
 112 
 113 #define LOOPBACK_IF     "lo0"
 114 #define SOCKET_AF(af)   (((af) == AF_UNSPEC) ? AF_INET : (af))
 115 
 116 struct net_if {
 117         char    *name;
 118         int     af;
 119 };
 120 
 121 /* 0755 is the default directory mode. */
 122 #define DEFAULT_DIR_MODE \
 123         (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
 124 
 125 struct cmd {


 428         char *ip_type_str;
 429 
 430         /* Skip a zone that shutdown while we were collecting data. */
 431         if (zent->zname[0] == '\0')
 432                 return;
 433 
 434         if (zent->ziptype == ZS_EXCLUSIVE)
 435                 ip_type_str = "excl";
 436         else
 437                 ip_type_str = "shared";
 438 
 439         assert(!(verbose && parsable));
 440         if (firsttime && verbose) {
 441                 firsttime = B_FALSE;
 442                 (void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
 443                     ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
 444                     "IP");
 445         }
 446         if (!verbose) {
 447                 char *cp, *clim;
 448                 char zdid[80];
 449 
 450                 if (!parsable) {
 451                         (void) printf("%s\n", zent->zname);
 452                         return;
 453                 }
 454                 if (zent->zid == ZONE_ID_UNDEFINED)
 455                         (void) printf("-");
 456                 else
 457                         (void) printf("%lu", zent->zid);
 458                 (void) printf(":%s:%s:", zent->zname, zent->zstate_str);
 459                 cp = zent->zroot;
 460                 while ((clim = strchr(cp, ':')) != NULL) {
 461                         (void) printf("%.*s\\:", clim - cp, cp);
 462                         cp = clim + 1;
 463                 }
 464                 if (zent->zdid == -1)
 465                         zdid[0] = '\0';
 466                 else
 467                         (void) snprintf(zdid, sizeof (zdid), "%d", zent->zdid);
 468                 (void) printf("%s:%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
 469                     ip_type_str, zdid);
 470                 return;
 471         }
 472         if (zent->zstate_str != NULL) {
 473                 if (zent->zid == ZONE_ID_UNDEFINED)
 474                         (void) printf("%*s", ZONEID_WIDTH, "-");
 475                 else
 476                         (void) printf("%*lu", ZONEID_WIDTH, zent->zid);
 477                 (void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
 478                     zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
 479         }
 480 }
 481 
 482 static int
 483 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
 484 {
 485         char root[MAXPATHLEN], *cp;
 486         int err;
 487         uuid_t uuid;
 488         zone_dochandle_t handle;
 489 


 544          */
 545         if (getzoneid() != GLOBAL_ZONEID) {
 546                 assert(is_system_labeled() != 0);
 547                 (void) strlcpy(zent->zbrand, default_brand,
 548                     sizeof (zent->zbrand));
 549         } else if (zone_get_brand(zent->zname, zent->zbrand,
 550             sizeof (zent->zbrand)) != Z_OK) {
 551                 zperror2(zent->zname, gettext("could not get brand name"));
 552                 return (Z_ERR);
 553         }
 554 
 555         /*
 556          * Get ip type of the zone.
 557          * Note for global zone, ZS_SHARED is set always.
 558          */
 559         if (zid == GLOBAL_ZONEID) {
 560                 zent->ziptype = ZS_SHARED;
 561                 return (Z_OK);
 562         }
 563 
 564         if ((handle = zonecfg_init_handle()) == NULL) {
 565                 zperror2(zent->zname, gettext("could not init handle"));
 566                 return (Z_ERR);
 567         }
 568         if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) {
 569                 zperror2(zent->zname, gettext("could not get handle"));
 570                 zonecfg_fini_handle(handle);
 571                 return (Z_ERR);
 572         }
 573 
 574         if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) {
 575                 zperror2(zent->zname, gettext("could not get ip-type"));
 576                 zonecfg_fini_handle(handle);
 577                 return (Z_ERR);
 578         }
 579 
 580         /*
 581          * There is a race condition where the zone could boot while
 582          * we're walking the index file.  In this case the zone state
 583          * could be seen as running from the call above, but the zoneid
 584          * would be undefined.
 585          *
 586          * There is also a race condition where the zone could shutdown after
 587          * we got its running state above.  This is also not an error and
 588          * we fall back to getting the ziptype from the zone configuration.
 589          */
 590         if (zent->zstate_num == ZONE_STATE_RUNNING &&
 591             zid != ZONE_ID_UNDEFINED) {
 592                 ushort_t flags;
 593 
 594                 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
 595                     sizeof (flags)) >= 0) {
 596                         if (flags & ZF_NET_EXCL)
 597                                 zent->ziptype = ZS_EXCLUSIVE;
 598                         else
 599                                 zent->ziptype = ZS_SHARED;

 600                 }
 601         }
 602 
 603         zent->zdid = zonecfg_get_did(handle);








 604 


 605         zonecfg_fini_handle(handle);



 606 
 607         return (Z_OK);
 608 }
 609 
 610 /*
 611  * fetch_zents() calls zone_list(2) to find out how many zones are running
 612  * (which is stored in the global nzents), then calls zone_list(2) again
 613  * to fetch the list of running zones (stored in the global zents).  This
 614  * function may be called multiple times, so if zents is already set, we
 615  * return immediately to save work.
 616  *
 617  * Note that the data about running zones can change while this function
 618  * is running, so its possible that the list of zones will have empty slots
 619  * at the end.
 620  */
 621 
 622 static int
 623 fetch_zents(void)
 624 {
 625         zoneid_t *zids = NULL;


2784                 return_code = Z_ERR;
2785         if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK)
2786                 return_code = Z_ERR;
2787         if (!in_alt_root && verify_datasets(handle) != Z_OK)
2788                 return_code = Z_ERR;
2789 
2790         /*
2791          * As the "mount" command is used for patching/upgrading of zones
2792          * or other maintenance processes, the zone's privilege set is not
2793          * checked in this case.  Instead, the default, safe set of
2794          * privileges will be used when this zone is created in the
2795          * kernel.
2796          */
2797         if (!in_alt_root && cmd_num != CMD_MOUNT &&
2798             verify_limitpriv(handle) != Z_OK)
2799                 return_code = Z_ERR;
2800 
2801         return (return_code);
2802 }
2803 
2804 /*
2805  * Called when readying or booting a zone.  We double check that the zone's
2806  * debug ID is set and is unique.  This covers the case of pre-existing zones
2807  * with no ID.  Also, its possible that a zone was migrated to this host
2808  * and as a result it has a duplicate ID.  In this case we preserve the ID
2809  * of the first zone we match on in the index file (since it was there before
2810  * the current zone) and we assign a new unique ID to the current zone.
2811  * Return true if we assigned a new ID, indicating that the zone configuration
2812  * needs to be saved.
2813  */
2814 static boolean_t
2815 verify_fix_did(zone_dochandle_t handle)
2816 {
2817         zoneid_t mydid;
2818         zone_entry_t zent;
2819         FILE *cookie;
2820         char *name;
2821         boolean_t fix = B_FALSE;
2822 
2823         mydid = zonecfg_get_did(handle);
2824         if (mydid == -1) {
2825                 zonecfg_set_did(handle);
2826                 return (B_TRUE);
2827         }
2828 
2829         /* Get the full list of zones from the configuration. */
2830         cookie = setzoneent();
2831         while ((name = getzoneent(cookie)) != NULL) {
2832                 if (strcmp(target_zone, name) == 0) {
2833                         free(name);
2834                         break;  /* Once we find our entry, stop. */
2835                 }
2836 
2837                 if (strcmp(name, "global") == 0 ||
2838                     lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
2839                         free(name);
2840                         continue;
2841                 }
2842 
2843                 free(name);
2844                 if (zent.zdid == mydid) {
2845                         fix = B_TRUE;
2846                         break;
2847                 }
2848         }
2849         endzoneent(cookie);
2850 
2851         if (fix) {
2852                 zonecfg_set_did(handle);
2853                 return (B_TRUE);
2854         }
2855 
2856         return (B_FALSE);
2857 }
2858 
2859 static int
2860 verify_details(int cmd_num, char *argv[])
2861 {
2862         zone_dochandle_t handle;
2863         char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
2864         int return_code = Z_OK;
2865         int err;
2866 
2867         if ((handle = zonecfg_init_handle()) == NULL) {
2868                 zperror(cmd_to_str(cmd_num), B_TRUE);
2869                 return (Z_ERR);
2870         }
2871         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
2872                 errno = err;
2873                 zperror(cmd_to_str(cmd_num), B_TRUE);
2874                 zonecfg_fini_handle(handle);
2875                 return (Z_ERR);
2876         }
2877         if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2878             Z_OK) {


2898                  * TRANSLATION_NOTE
2899                  * XML and zonepath are literals that should not be translated.
2900                  */
2901                 (void) fprintf(stderr, gettext("The XML repository has "
2902                     "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
2903                     "These must match, so fix the incorrect entry.\n"),
2904                     zonepath, checkpath);
2905                 zonecfg_fini_handle(handle);
2906                 return (Z_ERR);
2907         }
2908         if (cmd_num != CMD_ATTACH &&
2909             validate_zonepath(zonepath, cmd_num) != Z_OK) {
2910                 (void) fprintf(stderr, gettext("could not verify zonepath %s "
2911                     "because of the above errors.\n"), zonepath);
2912                 return_code = Z_ERR;
2913         }
2914 
2915         if (verify_handle(cmd_num, handle, argv) != Z_OK)
2916                 return_code = Z_ERR;
2917 
2918         if (cmd_num == CMD_READY || cmd_num == CMD_BOOT)
2919                 if (verify_fix_did(handle))
2920                         if (zonecfg_save(handle) != Z_OK)
2921                                 (void) fprintf(stderr, gettext("Could not save "
2922                                     "debug ID.\n"));
2923 
2924         zonecfg_fini_handle(handle);
2925         if (return_code == Z_ERR)
2926                 (void) fprintf(stderr,
2927                     gettext("%s: zone %s failed to verify\n"),
2928                     execname, target_zone);
2929         return (return_code);
2930 }
2931 
2932 static int
2933 verify_func(int argc, char *argv[])
2934 {
2935         int arg;
2936 
2937         optind = 0;
2938         if ((arg = getopt(argc, argv, "?")) != EOF) {
2939                 switch (arg) {
2940                 case '?':
2941                         sub_usage(SHELP_VERIFY, CMD_VERIFY);
2942                         return (optopt == '?' ? Z_OK : Z_USAGE);
2943                 default: