summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcarlsonj <none@none>2006-06-29 12:12:49 -0700
committercarlsonj <none@none>2006-06-29 12:12:49 -0700
commit555afedfc38adf0cc5fbc1de696dc811973eaaca (patch)
tree5900355bf83e141f219bd32bf2fe74ef4e19b5a2
parent368eb9166ea32e85e3565e5902f9fa4bafe50220 (diff)
downloadillumos-joyent-555afedfc38adf0cc5fbc1de696dc811973eaaca.tar.gz
PSARC 2006/387 Zones Features For Zulu
6365741 RFE: add unique identifier to facilitate asset tracking (similar to hostid) 6384962 libzonecfg doesn't preserve owner/mode on changes 6394273 fix for CR 6305641 missed one of the hard-coded constants 6431731 zoneadm list -p (parseable) output isn't 6436841 Zonecfg needs to address alternate roots to adjust file paths 6436853 Zoneadm should allow zones to be marked as incomplete
-rw-r--r--usr/src/cmd/zoneadm/Makefile2
-rw-r--r--usr/src/cmd/zoneadm/zoneadm.c126
-rw-r--r--usr/src/cmd/zoneadm/zoneadm.h3
-rw-r--r--usr/src/cmd/zoneadmd/Makefile2
-rw-r--r--usr/src/cmd/zoneadmd/vplat.c85
-rw-r--r--usr/src/cmd/zoneadmd/zoneadmd.c6
-rw-r--r--usr/src/cmd/zoneadmd/zoneadmd.h7
-rw-r--r--usr/src/cmd/zonecfg/zonecfg.c52
-rw-r--r--usr/src/cmd/zonecfg/zonecfg_grammar.y13
-rw-r--r--usr/src/head/libzonecfg.h10
-rw-r--r--usr/src/lib/libzonecfg/common/getzoneent.c3
-rw-r--r--usr/src/lib/libzonecfg/common/libzonecfg.c22
-rw-r--r--usr/src/lib/libzonecfg/common/zonecfg_impl.h19
13 files changed, 302 insertions, 48 deletions
diff --git a/usr/src/cmd/zoneadm/Makefile b/usr/src/cmd/zoneadm/Makefile
index 6ff4eab038..bf4e21d47e 100644
--- a/usr/src/cmd/zoneadm/Makefile
+++ b/usr/src/cmd/zoneadm/Makefile
@@ -43,7 +43,7 @@ SRCS = $(OBJS:.o=.c)
POFILE=zoneadm_all.po
POFILES= $(OBJS:%.o=%.po)
-LDLIBS += -lzonecfg -lsocket -lgen -lpool -lbsm -lzfs
+LDLIBS += -lzonecfg -lsocket -lgen -lpool -lbsm -lzfs -luuid
.KEEP_STATE:
diff --git a/usr/src/cmd/zoneadm/zoneadm.c b/usr/src/cmd/zoneadm/zoneadm.c
index 891f9e80e8..6e39d48d36 100644
--- a/usr/src/cmd/zoneadm/zoneadm.c
+++ b/usr/src/cmd/zoneadm/zoneadm.c
@@ -64,6 +64,7 @@
#include <sys/mntent.h>
#include <limits.h>
#include <dirent.h>
+#include <uuid/uuid.h>
#include <fcntl.h>
#include <door.h>
@@ -86,6 +87,7 @@ typedef struct zone_entry {
char *zstate_str;
zone_state_t zstate_num;
char zroot[MAXPATHLEN];
+ char zuuid[UUID_PRINTABLE_STRING_LENGTH];
} zone_entry_t;
static zone_entry_t *zents;
@@ -124,6 +126,7 @@ struct cmd {
#define SHELP_MOVE "move zonepath"
#define SHELP_DETACH "detach [-n]"
#define SHELP_ATTACH "attach [-F] [-n <path>]"
+#define SHELP_MARK "mark incomplete"
static int help_func(int argc, char *argv[]);
static int ready_func(int argc, char *argv[]);
@@ -140,6 +143,7 @@ static int clone_func(int argc, char *argv[]);
static int move_func(int argc, char *argv[]);
static int detach_func(int argc, char *argv[]);
static int attach_func(int argc, char *argv[]);
+static int mark_func(int argc, char *argv[]);
static int sanity_check(char *zone, int cmd_num, boolean_t running,
boolean_t unsafe_when_running);
static int cmd_match(char *cmd);
@@ -162,7 +166,8 @@ static struct cmd cmdtab[] = {
{ CMD_CLONE, "clone", SHELP_CLONE, clone_func },
{ CMD_MOVE, "move", SHELP_MOVE, move_func },
{ CMD_DETACH, "detach", SHELP_DETACH, detach_func },
- { CMD_ATTACH, "attach", SHELP_ATTACH, attach_func }
+ { CMD_ATTACH, "attach", SHELP_ATTACH, attach_func },
+ { CMD_MARK, "mark", SHELP_MARK, mark_func }
};
/* global variables */
@@ -171,6 +176,7 @@ static struct cmd cmdtab[] = {
static char *execname;
static char *locale;
char *target_zone;
+static char *target_uuid;
/* used in do_subproc() and signal handler */
static volatile boolean_t child_killed;
@@ -209,16 +215,16 @@ long_help(int cmd_num)
"running zones are listed, though this can be "
"expanded to all\n\tinstalled zones with the -i "
"option or all configured zones with the\n\t-c "
- "option. When used with the general -z <zone> "
- "option, lists only the\n\tspecified zone, but "
- "lists it regardless of its state, and the -i "
- "and -c\n\toptions are disallowed. The -v option "
- "can be used to display verbose\n\tinformation: "
- "zone name, id, current state, root directory and "
- "options.\n\tThe -p option can be used to request "
- "machine-parsable output. The -v\n\tand -p "
- "options are mutually exclusive. If neither -v "
- "nor -p is used,\n\tjust the zone name is listed."));
+ "option. When used with the general -z <zone> and/or -u "
+ "<uuid-match>\n\toptions, lists only the specified "
+ "matching zone, but lists it\n\tregardless of its state, "
+ "and the -i and -c options are disallowed. The\n\t-v "
+ "option can be used to display verbose information: zone "
+ "name, id,\n\tcurrent state, root directory and options. "
+ "The -p option can be used\n\tto request machine-parsable "
+ "output. The -v and -p options are mutually\n\texclusive."
+ " If neither -v nor -p is used, just the zone name is "
+ "listed."));
case CMD_VERIFY:
return (gettext("Check to make sure the configuration "
"can safely be instantiated\n\ton the machine: "
@@ -263,6 +269,12 @@ long_help(int cmd_num)
"from the\n\tspecified path and the configuration is only "
"validated. The path can\n\tbe '-' to specify standard "
"input."));
+ case CMD_MARK:
+ return (gettext("Set the state of the zone. This can be used "
+ "to force the zone\n\tstate to 'incomplete' "
+ "administratively if some activity has rendered\n\tthe "
+ "zone permanently unusable. The only valid state that "
+ "may be\n\tspecified is 'incomplete'."));
default:
return ("");
}
@@ -282,8 +294,9 @@ usage(boolean_t explicit)
FILE *fd = explicit ? stdout : stderr;
(void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname);
- (void) fprintf(fd, "\t%s [-z <zone>] list\n", execname);
- (void) fprintf(fd, "\t%s -z <zone> <%s>\n", execname,
+ (void) fprintf(fd, "\t%s [-z <zone>] [-u <uuid-match>] list\n",
+ execname);
+ (void) fprintf(fd, "\t%s {-z <zone>|-u <uuid-match>} <%s>\n", execname,
gettext("subcommand"));
(void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands"));
for (i = CMD_MIN; i <= CMD_MAX; i++) {
@@ -374,6 +387,8 @@ zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable)
"NAME", "STATUS", "PATH");
}
if (!verbose) {
+ char *cp, *clim;
+
if (!parsable) {
(void) printf("%s\n", zent->zname);
return;
@@ -382,8 +397,13 @@ zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable)
(void) printf("-");
else
(void) printf("%lu", zent->zid);
- (void) printf(":%s:%s:%s\n", zent->zname, zent->zstate_str,
- zent->zroot);
+ (void) printf(":%s:%s:", zent->zname, zent->zstate_str);
+ cp = zent->zroot;
+ while ((clim = strchr(cp, ':')) != NULL) {
+ (void) printf("%.*s\\:", clim - cp, cp);
+ cp = clim + 1;
+ }
+ (void) printf("%s:%s\n", cp, zent->zuuid);
return;
}
if (zent->zstate_str != NULL) {
@@ -401,6 +421,7 @@ lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
{
char root[MAXPATHLEN], *cp;
int err;
+ uuid_t uuid;
(void) strlcpy(zent->zname, zone_name, sizeof (zent->zname));
(void) strlcpy(zent->zroot, "???", sizeof (zent->zroot));
@@ -408,6 +429,12 @@ lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
zent->zid = zid;
+ if (zonecfg_get_uuid(zone_name, uuid) == Z_OK &&
+ !uuid_is_null(uuid))
+ uuid_unparse(uuid, zent->zuuid);
+ else
+ zent->zuuid[0] = '\0';
+
/*
* For labeled zones which query the zone path of lower-level
* zones, the path needs to be adjusted to drop the final
@@ -1374,21 +1401,38 @@ static void
fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr)
{
ssize_t result;
+ uuid_t uuid;
+ FILE *fp;
+
+ (void) memset(zeptr, 0, sizeof (*zeptr));
zeptr->zid = zid;
+
/*
* Since we're looking up our own (non-global) zone name,
* we can be assured that it will succeed.
*/
result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname));
assert(result >= 0);
- if (!is_system_labeled()) {
- (void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot));
- } else {
+ if (zonecfg_is_scratch(zeptr->zname) &&
+ (fp = zonecfg_open_scratch("", B_FALSE)) != NULL) {
+ (void) zonecfg_reverse_scratch(fp, zeptr->zname, zeptr->zname,
+ sizeof (zeptr->zname), NULL, 0);
+ zonecfg_close_scratch(fp);
+ }
+
+ if (is_system_labeled()) {
(void) zone_getattr(zid, ZONE_ATTR_ROOT, zeptr->zroot,
sizeof (zeptr->zroot));
+ } else {
+ (void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot));
}
+
zeptr->zstate_str = "running";
+
+ if (zonecfg_get_uuid(zeptr->zname, uuid) == Z_OK &&
+ !uuid_is_null(uuid))
+ uuid_unparse(uuid, zeptr->zuuid);
}
static int
@@ -1720,6 +1764,7 @@ sanity_check(char *zone, int cmd_num, boolean_t running,
case CMD_READY:
case CMD_BOOT:
case CMD_MOUNT:
+ case CMD_MARK:
if (state < ZONE_STATE_INSTALLED) {
zerror(gettext("must be %s before %s."),
zone_state_str(ZONE_STATE_INSTALLED),
@@ -4364,6 +4409,32 @@ unmount_func(int argc, char *argv[])
}
static int
+mark_func(int argc, char *argv[])
+{
+ int err, lockfd;
+
+ if (argc != 1 || strcmp(argv[0], "incomplete") != 0)
+ return (Z_USAGE);
+ if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_FALSE) != Z_OK)
+ return (Z_ERR);
+
+ if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
+ zerror(gettext("another %s may have an operation in progress."),
+ "zoneadm");
+ return (Z_ERR);
+ }
+
+ err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
+ if (err != Z_OK) {
+ errno = err;
+ zperror2(target_zone, gettext("could not set state"));
+ }
+ release_lock_file(lockfd);
+
+ return (err);
+}
+
+static int
help_func(int argc, char *argv[])
{
int arg, cmd_num;
@@ -4468,10 +4539,13 @@ main(int argc, char **argv)
if (init_zfs() != Z_OK)
exit(Z_ERR);
- while ((arg = getopt(argc, argv, "?z:R:")) != EOF) {
+ while ((arg = getopt(argc, argv, "?u:z:R:")) != EOF) {
switch (arg) {
case '?':
return (usage(B_TRUE));
+ case 'u':
+ target_uuid = optarg;
+ break;
case 'z':
target_zone = optarg;
break;
@@ -4494,6 +4568,20 @@ main(int argc, char **argv)
if (optind >= argc)
return (usage(B_FALSE));
+
+ if (target_uuid != NULL && *target_uuid != '\0') {
+ uuid_t uuid;
+ static char newtarget[ZONENAME_MAX];
+
+ if (uuid_parse(target_uuid, uuid) == -1) {
+ zerror(gettext("illegal UUID value specified"));
+ exit(Z_ERR);
+ }
+ if (zonecfg_get_name_by_uuid(uuid, newtarget,
+ sizeof (newtarget)) == Z_OK)
+ target_zone = newtarget;
+ }
+
if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) {
errno = Z_NO_ZONE;
zperror(target_zone, B_TRUE);
diff --git a/usr/src/cmd/zoneadm/zoneadm.h b/usr/src/cmd/zoneadm/zoneadm.h
index d6aa67798d..a94053e258 100644
--- a/usr/src/cmd/zoneadm/zoneadm.h
+++ b/usr/src/cmd/zoneadm/zoneadm.h
@@ -44,9 +44,10 @@
#define CMD_MOVE 12
#define CMD_DETACH 13
#define CMD_ATTACH 14
+#define CMD_MARK 15
#define CMD_MIN CMD_HELP
-#define CMD_MAX CMD_ATTACH
+#define CMD_MAX CMD_MARK
#if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
diff --git a/usr/src/cmd/zoneadmd/Makefile b/usr/src/cmd/zoneadmd/Makefile
index 33c89cd085..2d9082894a 100644
--- a/usr/src/cmd/zoneadmd/Makefile
+++ b/usr/src/cmd/zoneadmd/Makefile
@@ -43,7 +43,7 @@ CFLAGS += $(CCVERBOSE)
LAZYLIBS = $(ZLAZYLOAD) -ltsol $(ZNOLAZYLOAD)
lint := LAZYLIBS = -ltsol
LDLIBS += -lsocket -lzonecfg -lnsl -ldevinfo -ldevice -lnvpair -lpool \
- -lgen -lbsm -lcontract -lzfs -ltsnet $(LAZYLIBS)
+ -lgen -lbsm -lcontract -lzfs -ltsnet -luuid $(LAZYLIBS)
XGETFLAGS += -a -x zoneadmd.xcl
.KEEP_STATE:
diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c
index f018c4436c..16d79f91fa 100644
--- a/usr/src/cmd/zoneadmd/vplat.c
+++ b/usr/src/cmd/zoneadmd/vplat.c
@@ -78,7 +78,6 @@
#include <arpa/inet.h>
#include <netinet/in.h>
#include <net/route.h>
-#include <netdb.h>
#include <stdio.h>
#include <errno.h>
@@ -94,6 +93,9 @@
#include <libzfs.h>
#include <zone.h>
#include <assert.h>
+#include <libcontract.h>
+#include <libcontract_priv.h>
+#include <uuid/uuid.h>
#include <sys/mntio.h>
#include <sys/mnttab.h>
@@ -3542,8 +3544,84 @@ error:
return (rval);
}
+/*
+ * Enter the zone and write a /etc/zones/index file there. This allows
+ * libzonecfg (and thus zoneadm) to report the UUID and potentially other zone
+ * details from inside the zone.
+ */
+static void
+write_index_file(zoneid_t zoneid)
+{
+ FILE *zef;
+ FILE *zet;
+ struct zoneent *zep;
+ pid_t child;
+ int tmpl_fd;
+ ctid_t ct;
+ int fd;
+ char uuidstr[UUID_PRINTABLE_STRING_LENGTH];
+
+ /* Locate the zone entry in the global zone's index file */
+ if ((zef = setzoneent()) == NULL)
+ return;
+ while ((zep = getzoneent_private(zef)) != NULL) {
+ if (strcmp(zep->zone_name, zone_name) == 0)
+ break;
+ free(zep);
+ }
+ endzoneent(zef);
+ if (zep == NULL)
+ return;
+
+ if ((tmpl_fd = init_template()) == -1) {
+ free(zep);
+ return;
+ }
+
+ if ((child = fork()) == -1) {
+ (void) ct_tmpl_clear(tmpl_fd);
+ (void) close(tmpl_fd);
+ free(zep);
+ return;
+ }
+
+ /* parent waits for child to finish */
+ if (child != 0) {
+ free(zep);
+ if (contract_latest(&ct) == -1)
+ ct = -1;
+ (void) ct_tmpl_clear(tmpl_fd);
+ (void) close(tmpl_fd);
+ (void) waitpid(child, NULL, 0);
+ (void) contract_abandon_id(ct);
+ return;
+ }
+
+ /* child enters zone and sets up index file */
+ (void) ct_tmpl_clear(tmpl_fd);
+ if (zone_enter(zoneid) != -1) {
+ (void) mkdir(ZONE_CONFIG_ROOT, ZONE_CONFIG_MODE);
+ (void) chown(ZONE_CONFIG_ROOT, ZONE_CONFIG_UID,
+ ZONE_CONFIG_GID);
+ fd = open(ZONE_INDEX_FILE, O_WRONLY|O_CREAT|O_TRUNC,
+ ZONE_INDEX_MODE);
+ if (fd != -1 && (zet = fdopen(fd, "w")) != NULL) {
+ (void) fchown(fd, ZONE_INDEX_UID, ZONE_INDEX_GID);
+ if (uuid_is_null(zep->zone_uuid))
+ uuidstr[0] = '\0';
+ else
+ uuid_unparse(zep->zone_uuid, uuidstr);
+ (void) fprintf(zet, "%s:%s:/:%s\n", zep->zone_name,
+ zone_state_str(zep->zone_state),
+ uuidstr);
+ (void) fclose(zet);
+ }
+ }
+ _exit(0);
+}
+
int
-vplat_bringup(zlog_t *zlogp, boolean_t mount_cmd)
+vplat_bringup(zlog_t *zlogp, boolean_t mount_cmd, zoneid_t zoneid)
{
if (!mount_cmd && validate_datasets(zlogp) != 0) {
lofs_discard_mnttab();
@@ -3560,6 +3638,9 @@ vplat_bringup(zlog_t *zlogp, boolean_t mount_cmd)
lofs_discard_mnttab();
return (-1);
}
+
+ write_index_file(zoneid);
+
lofs_discard_mnttab();
return (0);
}
diff --git a/usr/src/cmd/zoneadmd/zoneadmd.c b/usr/src/cmd/zoneadmd/zoneadmd.c
index 050e5f1480..ca6e04e50f 100644
--- a/usr/src/cmd/zoneadmd/zoneadmd.c
+++ b/usr/src/cmd/zoneadmd/zoneadmd.c
@@ -459,7 +459,7 @@ zone_ready(zlog_t *zlogp, boolean_t mount_cmd)
zonecfg_strerror(err));
return (-1);
}
- if (vplat_bringup(zlogp, mount_cmd) != 0) {
+ if (vplat_bringup(zlogp, mount_cmd, zone_id) != 0) {
bringup_failure_recovery = B_TRUE;
(void) vplat_teardown(NULL, mount_cmd);
if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
@@ -471,8 +471,8 @@ zone_ready(zlog_t *zlogp, boolean_t mount_cmd)
return (0);
}
-static int
-init_template()
+int
+init_template(void)
{
int fd;
int err = 0;
diff --git a/usr/src/cmd/zoneadmd/zoneadmd.h b/usr/src/cmd/zoneadmd/zoneadmd.h
index 591a75fd77..a048d5dd25 100644
--- a/usr/src/cmd/zoneadmd/zoneadmd.h
+++ b/usr/src/cmd/zoneadmd/zoneadmd.h
@@ -99,7 +99,7 @@ extern void eventstream_write(zone_evt_t evt);
* Virtual platform interfaces.
*/
extern zoneid_t vplat_create(zlog_t *, boolean_t);
-extern int vplat_bringup(zlog_t *, boolean_t);
+extern int vplat_bringup(zlog_t *, boolean_t, zoneid_t);
extern int vplat_teardown(zlog_t *, boolean_t);
@@ -112,6 +112,11 @@ extern void reset_slave_terminal(zlog_t *);
extern int init_console(zlog_t *);
extern void serve_console(zlog_t *);
+/*
+ * Contract handling.
+ */
+extern int init_template(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/zonecfg/zonecfg.c b/usr/src/cmd/zonecfg/zonecfg.c
index e5882454dc..1c4b512273 100644
--- a/usr/src/cmd/zonecfg/zonecfg.c
+++ b/usr/src/cmd/zonecfg/zonecfg.c
@@ -68,7 +68,6 @@
#include <locale.h>
#include <libintl.h>
#include <alloca.h>
-#include <regex.h>
#include <signal.h>
#include <libtecla.h>
#include <libzfs.h>
@@ -2668,15 +2667,31 @@ void
set_func(cmd_t *cmd)
{
char *prop_id;
- int err, res_type, prop_type;
+ int arg, err, res_type, prop_type;
property_value_ptr_t pp;
boolean_t autoboot;
+ boolean_t force_set = FALSE;
if (zone_is_read_only(CMD_SET))
return;
assert(cmd != NULL);
+ optind = opterr = 0;
+ while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
+ switch (arg) {
+ case 'F':
+ force_set = TRUE;
+ break;
+ default:
+ if (optopt == '?')
+ longer_usage(CMD_SET);
+ else
+ short_usage(CMD_SET);
+ return;
+ }
+ }
+
prop_type = cmd->cmd_prop_name[0];
if (global_scope) {
if (prop_type == PT_ZONENAME) {
@@ -2701,6 +2716,20 @@ set_func(cmd_t *cmd)
res_type = resource_scope;
}
+ if (force_set) {
+ if (res_type != RT_ZONEPATH) {
+ zerr(gettext("Only zonepath setting can be forced."));
+ saw_error = TRUE;
+ return;
+ }
+ if (!zonecfg_in_alt_root()) {
+ zerr(gettext("Zonepath is changeable only in an "
+ "alternate root."));
+ saw_error = TRUE;
+ return;
+ }
+ }
+
pp = cmd->cmd_property_ptr[0];
/*
* A nasty expression but not that complicated:
@@ -2756,7 +2785,7 @@ set_func(cmd_t *cmd)
}
return;
case RT_ZONEPATH:
- if (state_atleast(ZONE_STATE_INSTALLED)) {
+ if (!force_set && state_atleast(ZONE_STATE_INSTALLED)) {
zerr(gettext("Zone %s already installed; %s %s not "
"allowed."), zone, cmd_to_str(CMD_SET),
rt_to_str(RT_ZONEPATH));
@@ -4603,6 +4632,7 @@ int
main(int argc, char *argv[])
{
int err, arg;
+ struct stat st;
/* This must be before anything goes to stdout. */
setbuf(stdout, NULL);
@@ -4629,7 +4659,7 @@ main(int argc, char *argv[])
exit(Z_OK);
}
- while ((arg = getopt(argc, argv, "?f:z:")) != EOF) {
+ while ((arg = getopt(argc, argv, "?f:R:z:")) != EOF) {
switch (arg) {
case '?':
if (optopt == '?')
@@ -4642,6 +4672,20 @@ main(int argc, char *argv[])
cmd_file_name = optarg;
cmd_file_mode = TRUE;
break;
+ case 'R':
+ if (*optarg != '/') {
+ zerr(gettext("root path must be absolute: %s"),
+ optarg);
+ exit(Z_USAGE);
+ }
+ if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
+ zerr(gettext(
+ "root path must be a directory: %s"),
+ optarg);
+ exit(Z_USAGE);
+ }
+ zonecfg_set_root(optarg);
+ break;
case 'z':
if (zonecfg_validate_zonename(optarg) != Z_OK) {
zone_perror(optarg, Z_BOGUS_ZONE_NAME, TRUE);
diff --git a/usr/src/cmd/zonecfg/zonecfg_grammar.y b/usr/src/cmd/zonecfg/zonecfg_grammar.y
index b9a8d744e2..d47aac79ae 100644
--- a/usr/src/cmd/zonecfg/zonecfg_grammar.y
+++ b/usr/src/cmd/zonecfg/zonecfg_grammar.y
@@ -659,6 +659,19 @@ set_command: SET
$$->cmd_prop_name[0] = $2;
$$->cmd_property_ptr[0] = &property[0];
}
+ | SET TOKEN ZONEPATH EQUAL property_value
+ {
+ if (($$ = alloc_cmd()) == NULL)
+ YYERROR;
+ cmd = $$;
+ $$->cmd_argc = 1;
+ $$->cmd_argv[0] = $2;
+ $$->cmd_argv[1] = NULL;
+ $$->cmd_handler = &set_func;
+ $$->cmd_prop_nv_pairs = 1;
+ $$->cmd_prop_name[0] = PT_ZONEPATH;
+ $$->cmd_property_ptr[0] = &property[0];
+ }
verify_command: VERIFY
{
diff --git a/usr/src/head/libzonecfg.h b/usr/src/head/libzonecfg.h
index 056600e20d..3030bb42e8 100644
--- a/usr/src/head/libzonecfg.h
+++ b/usr/src/head/libzonecfg.h
@@ -110,6 +110,16 @@ extern "C" {
#define ZONE_CONFIG_ROOT "/etc/zones"
#define ZONE_INDEX_FILE ZONE_CONFIG_ROOT "/index"
+/* Owner, group, and mode (defined by packaging) for the config directory */
+#define ZONE_CONFIG_UID 0 /* root */
+#define ZONE_CONFIG_GID 3 /* sys */
+#define ZONE_CONFIG_MODE 0755
+
+/* Owner, group, and mode (defined by packaging) for the index file */
+#define ZONE_INDEX_UID 0 /* root */
+#define ZONE_INDEX_GID 3 /* sys */
+#define ZONE_INDEX_MODE 0644
+
/* The maximum length of the VERSION string in the pkginfo(4) file. */
#define ZONE_PKG_VERSMAX 256
diff --git a/usr/src/lib/libzonecfg/common/getzoneent.c b/usr/src/lib/libzonecfg/common/getzoneent.c
index c75ce2f096..c623152933 100644
--- a/usr/src/lib/libzonecfg/common/getzoneent.c
+++ b/usr/src/lib/libzonecfg/common/getzoneent.c
@@ -308,6 +308,8 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
(void) unlock_index_file(lock_fd);
return (Z_TEMP_FILE);
}
+ (void) fchmod(tmp_file_desc, ZONE_INDEX_MODE);
+ (void) fchown(tmp_file_desc, ZONE_INDEX_UID, ZONE_INDEX_GID);
if ((tmp_file = fdopen(tmp_file_desc, "w")) == NULL) {
(void) close(tmp_file_desc);
err = Z_MISC_FS;
@@ -454,7 +456,6 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
goto error;
}
tmp_file = NULL;
- (void) chmod(tmp_file_name, 0644);
if (rename(tmp_file_name, path) == -1) {
err = errno == EACCES ? Z_ACCES : Z_MISC_FS;
goto error;
diff --git a/usr/src/lib/libzonecfg/common/libzonecfg.c b/usr/src/lib/libzonecfg/common/libzonecfg.c
index 023a96888f..19ca573b0c 100644
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c
@@ -828,6 +828,17 @@ zonecfg_get_zonepath(zone_dochandle_t handle, char *path, size_t pathsize)
int
zonecfg_set_zonepath(zone_dochandle_t handle, char *zonepath)
{
+ size_t len;
+
+ /*
+ * The user deals in absolute paths in the running global zone, but the
+ * internal configuration files deal with boot environment relative
+ * paths. Strip out the alternate root when specified.
+ */
+ len = strlen(zonecfg_root);
+ if (strncmp(zonepath, zonecfg_root, len) != 0 || zonepath[len] != '/')
+ return (Z_BAD_PROPERTY);
+ zonepath += len;
return (setrootattr(handle, DTD_ATTR_ZONEPATH, zonepath));
}
@@ -923,7 +934,8 @@ zonecfg_refresh_index_file(zone_dochandle_t handle)
if ((err = zonecfg_get_zonepath(handle, zonepath,
sizeof (zonepath))) != Z_OK)
return (err);
- (void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path));
+ (void) strlcpy(ze.zone_path, zonepath + strlen(zonecfg_root),
+ sizeof (ze.zone_path));
if (is_renaming(handle)) {
opcode = PZE_MODIFY;
@@ -4012,22 +4024,24 @@ zone_state_str(zone_state_t state_num)
* doesn't touch this buffer on failure.
*/
int
-zonecfg_get_name_by_uuid(const uuid_t uuid, char *zonename, size_t namelen)
+zonecfg_get_name_by_uuid(const uuid_t uuidin, char *zonename, size_t namelen)
{
FILE *fp;
struct zoneent *ze;
+ uchar_t *uuid;
/*
* A small amount of subterfuge via casts is necessary here because
* libuuid doesn't use const correctly, but we don't want to export
* this brokenness to our clients.
*/
- if (uuid_is_null(*(uuid_t *)&uuid))
+ uuid = (uchar_t *)uuidin;
+ if (uuid_is_null(uuid))
return (Z_NO_ZONE);
if ((fp = setzoneent()) == NULL)
return (Z_NO_ZONE);
while ((ze = getzoneent_private(fp)) != NULL) {
- if (uuid_compare(*(uuid_t *)&uuid, ze->zone_uuid) == 0)
+ if (uuid_compare(uuid, ze->zone_uuid) == 0)
break;
free(ze);
}
diff --git a/usr/src/lib/libzonecfg/common/zonecfg_impl.h b/usr/src/lib/libzonecfg/common/zonecfg_impl.h
index b24f94ab1e..d6be1387e4 100644
--- a/usr/src/lib/libzonecfg/common/zonecfg_impl.h
+++ b/usr/src/lib/libzonecfg/common/zonecfg_impl.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -34,6 +33,7 @@ extern "C" {
#endif
#include <zone.h>
+#include <sys/uuid.h>
#if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
@@ -57,15 +57,12 @@ typedef enum {
/*
* ":::\n" => 4, no need to count '\0' as ZONENAME_MAX covers that.
*
- * Note that both ZONE_STATE_MAXSTRLEN and MAXPATHLEN include a NUL byte, and
- * this extra count of 2 bytes covers the quotes that may be placed around the
- * path.
- *
- * The swilly "36" constant here is to cover the fact that libuuid is broken;
- * see CR 6305641.
+ * Note that ZONE_STATE_MAXSTRLEN, MAXPATHLEN, and UUID_PRINTABLE_STRING_LENGTH
+ * all include a NUL byte, and this extra count of 2 bytes covers the quotes
+ * that may be placed around the path plus one more.
*/
#define MAX_INDEX_LEN (ZONENAME_MAX + ZONE_STATE_MAXSTRLEN + MAXPATHLEN + \
- 36 + 4)
+ UUID_PRINTABLE_STRING_LENGTH + 3)
#define ZONE_INDEX_LOCK_DIR ZONE_SNAPSHOT_ROOT
#define ZONE_INDEX_LOCK_FILE "/index.lock"