summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/zonecfg/zonecfg.c600
-rw-r--r--usr/src/cmd/zonecfg/zonecfg.h54
-rw-r--r--usr/src/cmd/zonecfg/zonecfg_grammar.y18
-rw-r--r--usr/src/cmd/zonecfg/zonecfg_lex.l5
-rw-r--r--usr/src/head/libzonecfg.h15
-rw-r--r--usr/src/lib/libzonecfg/common/getzoneent.c29
-rw-r--r--usr/src/lib/libzonecfg/common/libzonecfg.c500
-rw-r--r--usr/src/lib/libzonecfg/spec/libzonecfg.spec26
8 files changed, 830 insertions, 417 deletions
diff --git a/usr/src/cmd/zonecfg/zonecfg.c b/usr/src/cmd/zonecfg/zonecfg.c
index 46f389a768..69e931e1a9 100644
--- a/usr/src/cmd/zonecfg/zonecfg.c
+++ b/usr/src/cmd/zonecfg/zonecfg.c
@@ -143,6 +143,7 @@ static struct help helptab[] = {
/* These *must* match the order of the RT_ define's from zonecfg.h */
static char *res_types[] = {
"unknown",
+ "zonename",
"zonepath",
"autoboot",
"pool",
@@ -158,6 +159,7 @@ static char *res_types[] = {
/* These *must* match the order of the PT_ define's from zonecfg.h */
static char *prop_types[] = {
"unknown",
+ "zonename",
"zonepath",
"autoboot",
"pool",
@@ -221,19 +223,20 @@ static const char *add_cmds[] = {
};
static const char *select_cmds[] = {
- "select fs",
- "select inherit-pkg-dir",
- "select net",
- "select device",
- "select rctl",
- "select attr",
+ "select fs ",
+ "select inherit-pkg-dir ",
+ "select net ",
+ "select device ",
+ "select rctl ",
+ "select attr ",
NULL
};
static const char *set_cmds[] = {
- "set zonepath",
- "set autoboot",
- "set pool",
+ "set zonename=",
+ "set zonepath=",
+ "set autoboot=",
+ "set pool=",
NULL
};
@@ -314,7 +317,8 @@ static char *execname;
static zone_dochandle_t handle;
/* used all over the place */
-static char *zone;
+static char zone[ZONENAME_MAX];
+static char revert_zone[ZONENAME_MAX];
/* set in modifying functions, checked in read_input() */
static bool need_to_commit = FALSE;
@@ -344,9 +348,6 @@ static bool interactive_mode;
/* set in main(), checked in multiple places */
static bool read_only_mode;
-/* set in check_if_zone_already_exists(), checked in save_it() */
-static bool new_zone = FALSE;
-
static bool global_scope = TRUE; /* scope is outer/global or inner/resource */
static int resource_scope; /* should be in the RT_ list from zonecfg.h */
static int end_op = -1; /* operation on end is either add or modify */
@@ -849,6 +850,8 @@ usage(bool verbose, uint_t flags)
(void) fprintf(fp, gettext("For resource type ... there are "
"property types ...:\n"));
(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
+ pt_to_str(PT_ZONENAME));
+ (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
pt_to_str(PT_ZONEPATH));
(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
pt_to_str(PT_AUTOBOOT));
@@ -942,6 +945,23 @@ initialize(bool handle_expected)
return (Z_OK);
}
+static bool
+state_atleast(zone_state_t state)
+{
+ zone_state_t state_num;
+ int err;
+
+ if ((err = zone_get_state(zone, &state_num)) != Z_OK) {
+ /* all states are greater than "non-existent" */
+ if (err == Z_NO_ZONE)
+ return (B_FALSE);
+ zerr(gettext("Unexpectedly failed to determine state "
+ "of zone %s: %s"), zone, zonecfg_strerror(err));
+ exit(Z_ERR);
+ }
+ return (state_num >= state);
+}
+
/*
* short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
*/
@@ -1023,10 +1043,13 @@ ask_yesno(bool default_answer, const char *question)
return (-1);
}
for (;;) {
- (void) printf("%s (%s)? ", question,
- default_answer ? "[y]/n" : "y/[n]");
- if (fgets(line, sizeof (line), stdin) == NULL ||
- line[0] == '\n')
+ if (printf("%s (%s)? ", question,
+ default_answer ? "[y]/n" : "y/[n]") < 0)
+ return (-1);
+ if (fgets(line, sizeof (line), stdin) == NULL)
+ return (-1);
+
+ if (line[0] == '\n')
return (default_answer ? 1 : 0);
if (tolower(line[0]) == 'y')
return (1);
@@ -1048,7 +1071,6 @@ static int
check_if_zone_already_exists(bool force)
{
char line[ZONENAME_MAX + 128]; /* enough to ask a question */
- zone_state_t state_num;
zone_dochandle_t tmphandle;
int res, answer;
@@ -1058,12 +1080,10 @@ check_if_zone_already_exists(bool force)
}
res = zonecfg_get_handle(zone, tmphandle);
zonecfg_fini_handle(tmphandle);
- if (res != Z_OK) {
- new_zone = TRUE;
+ if (res != Z_OK)
return (Z_OK);
- }
- if (zone_get_state(zone, &state_num) == Z_OK &&
- state_num >= ZONE_STATE_INSTALLED) {
+
+ if (state_atleast(ZONE_STATE_INSTALLED)) {
zerr(gettext("Zone %s already installed; %s not allowed."),
zone, cmd_to_str(CMD_CREATE));
return (Z_ERR);
@@ -1167,17 +1187,17 @@ create_func(cmd_t *cmd)
zone_perror(execname, Z_NOMEM, TRUE);
exit(Z_ERR);
}
- if ((err = zonecfg_get_handle(zone_template, tmphandle)) != Z_OK) {
+ if ((err = zonecfg_get_template_handle(zone_template, zone,
+ tmphandle)) != Z_OK) {
zonecfg_fini_handle(tmphandle);
zone_perror(zone_template, err, TRUE);
return;
}
+
+ need_to_commit = TRUE;
zonecfg_fini_handle(handle);
handle = tmphandle;
- if ((err = zonecfg_set_name(handle, zone)) == Z_OK)
- need_to_commit = TRUE;
- else
- zone_perror(zone, err, TRUE);
+ got_handle = TRUE;
}
/*
@@ -1456,7 +1476,6 @@ static void
add_resource(cmd_t *cmd)
{
int type;
- zone_state_t state_num;
if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
long_usage(CMD_ADD, TRUE);
@@ -1468,8 +1487,7 @@ add_resource(cmd_t *cmd)
bzero(&in_progress_fstab, sizeof (in_progress_fstab));
return;
case RT_IPD:
- if (zone_get_state(zone, &state_num) == Z_OK &&
- state_num >= ZONE_STATE_INSTALLED) {
+ if (state_atleast(ZONE_STATE_INSTALLED)) {
zerr(gettext("Zone %s already installed; %s %s not "
"allowed."), zone, cmd_to_str(CMD_ADD),
rt_to_str(RT_IPD));
@@ -1722,13 +1740,20 @@ add_func(cmd_t *cmd)
add_property(cmd);
}
+/*
+ * This routine has an unusual implementation, because it tries very
+ * hard to succeed in the face of a variety of failure modes.
+ * The most common and most vexing occurs when the index file and
+ * the /etc/zones/<zonename.xml> file are not both present. In
+ * this case, delete must eradicate as much of the zone state as is left
+ * so that the user can later create a new zone with the same name.
+ */
void
delete_func(cmd_t *cmd)
{
int err, arg, answer;
char line[ZONENAME_MAX + 128]; /* enough to ask a question */
bool force = FALSE;
- zone_state_t state_num;
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
@@ -1752,54 +1777,70 @@ delete_func(cmd_t *cmd)
if (zone_is_read_only(CMD_DELETE))
return;
- if (zone_get_state(zone, &state_num) == Z_OK &&
- state_num >= ZONE_STATE_INCOMPLETE) {
- zerr(gettext("Zone %s not in %s state; %s not allowed."),
- zone, zone_state_str(ZONE_STATE_CONFIGURED),
- cmd_to_str(CMD_DELETE));
- saw_error = TRUE;
- return;
- }
-
- if (initialize(TRUE) != Z_OK)
- return;
-
if (!force) {
+ /*
+ * Initialize sets up the global called "handle" and warns the
+ * user if the zone is not configured. In force mode, we don't
+ * trust that evaluation, and hence skip it. (We don't need the
+ * handle to be loaded anyway, since zonecfg_destroy is done by
+ * zonename). However, we also have to take care to emulate the
+ * messages spit out by initialize; see below.
+ */
+ if (initialize(TRUE) != Z_OK)
+ return;
+
(void) snprintf(line, sizeof (line),
gettext("Are you sure you want to delete zone %s"), zone);
if ((answer = ask_yesno(FALSE, line)) == -1) {
- zerr(gettext("Input not from "
- "terminal and -F not specified:\n%s command "
- "ignored, exiting."), cmd_to_str(CMD_DELETE));
+ zerr(gettext("Input not from terminal and -F not "
+ "specified:\n%s command ignored, exiting."),
+ cmd_to_str(CMD_DELETE));
exit(Z_ERR);
}
if (answer != 1)
return;
}
- if ((err = zonecfg_delete_index(zone)) != Z_OK) {
- zone_perror(zone, err, TRUE);
- return;
+ if ((err = zonecfg_destroy(zone, force)) != Z_OK) {
+ if ((err == Z_BAD_ZONE_STATE) && !force) {
+ zerr(gettext("Zone %s not in %s state; %s not "
+ "allowed. Use -F to force %s."),
+ zone, zone_state_str(ZONE_STATE_CONFIGURED),
+ cmd_to_str(CMD_DELETE), cmd_to_str(CMD_DELETE));
+ } else {
+ zone_perror(zone, err, TRUE);
+ }
}
-
need_to_commit = FALSE;
- if ((err = zonecfg_destroy(zone)) != Z_OK)
- zone_perror(zone, err, TRUE);
+
+ /*
+ * Emulate initialize's messaging; if there wasn't a valid handle to
+ * begin with, then user had typed delete (or delete -F) multiple
+ * times. So we emit a message.
+ *
+ * We only do this in the 'force' case because normally, initialize()
+ * takes care of this for us.
+ */
+ if (force && zonecfg_check_handle(handle) != Z_OK && interactive_mode)
+ (void) printf(gettext("Use '%s' to begin "
+ "configuring a new zone.\n"), cmd_to_str(CMD_CREATE));
/*
* Time for a new handle: finish the old one off first
* then get a new one properly to avoid leaks.
*/
- zonecfg_fini_handle(handle);
- if ((handle = zonecfg_init_handle()) == NULL) {
- zone_perror(execname, Z_NOMEM, TRUE);
- exit(Z_ERR);
- }
- if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) {
- /* If there was no zone before, that's OK */
- if (err != Z_NO_ZONE)
- zone_perror(zone, err, TRUE);
- got_handle = FALSE;
+ if (got_handle) {
+ zonecfg_fini_handle(handle);
+ if ((handle = zonecfg_init_handle()) == NULL) {
+ zone_perror(execname, Z_NOMEM, TRUE);
+ exit(Z_ERR);
+ }
+ if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) {
+ /* If there was no zone before, that's OK */
+ if (err != Z_NO_ZONE)
+ zone_perror(zone, err, TRUE);
+ got_handle = FALSE;
+ }
}
}
@@ -2045,7 +2086,6 @@ remove_resource(cmd_t *cmd)
struct zone_devtab devtab;
struct zone_attrtab attrtab;
struct zone_rctltab rctltab;
- zone_state_t state_num;
if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
long_usage(CMD_REMOVE, TRUE);
@@ -2068,8 +2108,7 @@ remove_resource(cmd_t *cmd)
zonecfg_free_fs_option_list(fstab.zone_fs_options);
return;
case RT_IPD:
- if (zone_get_state(zone, &state_num) == Z_OK &&
- state_num >= ZONE_STATE_INSTALLED) {
+ if (state_atleast(ZONE_STATE_INSTALLED)) {
zerr(gettext("Zone %s already installed; %s %s not "
"allowed."), zone, cmd_to_str(CMD_REMOVE),
rt_to_str(RT_IPD));
@@ -2278,7 +2317,6 @@ void
select_func(cmd_t *cmd)
{
int type, err;
- zone_state_t state_num;
if (zone_is_read_only(CMD_SELECT))
return;
@@ -2312,8 +2350,7 @@ select_func(cmd_t *cmd)
sizeof (struct zone_fstab));
return;
case RT_IPD:
- if (zone_get_state(zone, &state_num) == Z_OK &&
- state_num >= ZONE_STATE_INCOMPLETE) {
+ if (state_atleast(ZONE_STATE_INCOMPLETE)) {
zerr(gettext("Zone %s not in %s state; %s %s not "
"allowed."), zone,
zone_state_str(ZONE_STATE_CONFIGURED),
@@ -2473,7 +2510,7 @@ valid_fs_type(const char *type)
*/
if (strchr(type, '/') != NULL || type[0] == '\0' ||
strcmp(type, ".") == 0 || strcmp(type, "..") == 0)
- return (B_FALSE);
+ return (B_FALSE);
/*
* More detailed verification happens later by zoneadm(1m).
*/
@@ -2486,7 +2523,6 @@ set_func(cmd_t *cmd)
char *prop_id;
int err, res_type, prop_type;
property_value_ptr_t pp;
- zone_state_t state_num;
boolean_t autoboot;
if (zone_is_read_only(CMD_SET))
@@ -2496,7 +2532,9 @@ set_func(cmd_t *cmd)
prop_type = cmd->cmd_prop_name[0];
if (global_scope) {
- if (prop_type == PT_ZONEPATH) {
+ if (prop_type == PT_ZONENAME) {
+ res_type = RT_ZONENAME;
+ } else if (prop_type == PT_ZONEPATH) {
res_type = RT_ZONEPATH;
} else if (prop_type == PT_AUTOBOOT) {
res_type = RT_AUTOBOOT;
@@ -2533,13 +2571,35 @@ set_func(cmd_t *cmd)
return;
}
+ /*
+ * Special case: the user can change the zone name prior to 'create';
+ * if the zone already exists, we fall through letting initialize()
+ * and the rest of the logic run.
+ */
+ if (res_type == RT_ZONENAME && got_handle == FALSE &&
+ !state_atleast(ZONE_STATE_CONFIGURED)) {
+ (void) strlcpy(zone, prop_id, sizeof (zone));
+ return;
+ }
+
if (initialize(TRUE) != Z_OK)
return;
switch (res_type) {
+ case RT_ZONENAME:
+ if ((err = zonecfg_set_name(handle, prop_id)) != Z_OK) {
+ /*
+ * Use prop_id instead of 'zone' here, since we're
+ * reporting a problem about the *new* zonename.
+ */
+ zone_perror(prop_id, err, TRUE);
+ } else {
+ need_to_commit = TRUE;
+ (void) strlcpy(zone, prop_id, sizeof (zone));
+ }
+ return;
case RT_ZONEPATH:
- if (zone_get_state(zone, &state_num) == Z_OK &&
- state_num >= ZONE_STATE_INSTALLED) {
+ if (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));
@@ -2759,8 +2819,21 @@ output_prop(FILE *fp, int pnum, char *pval, bool print_notspec)
(void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);
free(qstr);
} else if (print_notspec)
- (void) fprintf(fp, "\t%s %s\n", pt_to_str(pnum),
- gettext("not specified"));
+ (void) fprintf(fp, gettext("\t%s not specified\n"),
+ pt_to_str(pnum));
+}
+
+static void
+info_zonename(zone_dochandle_t handle, FILE *fp)
+{
+ char zonename[ZONENAME_MAX];
+
+ if (zonecfg_get_name(handle, zonename, sizeof (zonename)) == Z_OK)
+ (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONENAME),
+ zonename);
+ else
+ (void) fprintf(fp, gettext("%s not specified\n"),
+ pt_to_str(PT_ZONENAME));
}
static void
@@ -2771,9 +2844,10 @@ info_zonepath(zone_dochandle_t handle, FILE *fp)
if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK)
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONEPATH),
zonepath);
- else
- (void) fprintf(fp, "%s %s\n", pt_to_str(PT_ZONEPATH),
- gettext("not specified"));
+ else {
+ (void) fprintf(fp, gettext("%s not specified\n"),
+ pt_to_str(PT_ZONEPATH));
+ }
}
static void
@@ -3124,6 +3198,7 @@ info_func(cmd_t *cmd)
switch (cmd->cmd_res_type) {
case RT_UNKNOWN:
+ info_zonename(handle, fp);
info_zonepath(handle, fp);
info_autoboot(handle, fp);
info_pool(handle, fp);
@@ -3134,6 +3209,9 @@ info_func(cmd_t *cmd)
info_rctl(handle, fp, cmd);
info_attr(handle, fp, cmd);
break;
+ case RT_ZONENAME:
+ info_zonename(handle, fp);
+ break;
case RT_ZONEPATH:
info_zonepath(handle, fp);
break;
@@ -3171,22 +3249,20 @@ cleanup:
(void) pclose(fp);
}
-static int
-save_it(char *zonepath)
+/*
+ * Helper function for verify-- checks that a required string property
+ * exists.
+ */
+static void
+check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
{
- int err;
-
- if (new_zone) {
- err = zonecfg_add_index(zone, zonepath);
- if (err != Z_OK) {
- zone_perror(zone, err, TRUE);
- return (err);
- }
- new_zone = FALSE;
+ if (strlen(attr) == 0) {
+ zerr(gettext("%s: %s not specified"), rt_to_str(rt),
+ pt_to_str(pt));
+ saw_error = TRUE;
+ if (*ret_val == Z_OK)
+ *ret_val = Z_REQD_PROPERTY_MISSING;
}
- if ((err = zonecfg_save(handle)) == Z_OK)
- need_to_commit = FALSE;
- return (err);
}
/*
@@ -3236,13 +3312,12 @@ verify_func(cmd_t *cmd)
return;
if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) != Z_OK) {
- zerr("%s %s", pt_to_str(PT_ZONEPATH), gettext("not specified"));
+ zerr(gettext("%s not specified"), pt_to_str(PT_ZONEPATH));
ret_val = Z_REQD_RESOURCE_MISSING;
saw_error = TRUE;
}
if (strlen(zonepath) == 0) {
- zerr("%s %s", pt_to_str(PT_ZONEPATH),
- gettext("cannot be empty."));
+ zerr(gettext("%s cannot be empty."), pt_to_str(PT_ZONEPATH));
ret_val = Z_REQD_RESOURCE_MISSING;
saw_error = TRUE;
}
@@ -3252,13 +3327,7 @@ verify_func(cmd_t *cmd)
return;
}
while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
- if (strlen(fstab.zone_fs_dir) == 0) {
- zerr("%s: %s %s", rt_to_str(RT_IPD), pt_to_str(PT_DIR),
- gettext("not specified"));
- saw_error = TRUE;
- if (ret_val == Z_OK)
- ret_val = Z_REQD_PROPERTY_MISSING;
- }
+ check_reqd_prop(fstab.zone_fs_dir, RT_IPD, PT_DIR, &ret_val);
}
(void) zonecfg_endipdent(handle);
@@ -3267,27 +3336,11 @@ verify_func(cmd_t *cmd)
return;
}
while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
- if (strlen(fstab.zone_fs_dir) == 0) {
- zerr("%s: %s %s", rt_to_str(RT_FS), pt_to_str(PT_DIR),
- gettext("not specified"));
- saw_error = TRUE;
- if (ret_val == Z_OK)
- ret_val = Z_REQD_PROPERTY_MISSING;
- }
- if (strlen(fstab.zone_fs_special) == 0) {
- zerr("%s: %s %s", rt_to_str(RT_FS),
- pt_to_str(PT_SPECIAL), gettext("not specified"));
- saw_error = TRUE;
- if (ret_val == Z_OK)
- ret_val = Z_REQD_PROPERTY_MISSING;
- }
- if (strlen(fstab.zone_fs_type) == 0) {
- zerr("%s: %s %s", rt_to_str(RT_FS), pt_to_str(PT_TYPE),
- gettext("not specified"));
- saw_error = TRUE;
- if (ret_val == Z_OK)
- ret_val = Z_REQD_PROPERTY_MISSING;
- }
+ check_reqd_prop(fstab.zone_fs_dir, RT_FS, PT_DIR, &ret_val);
+ check_reqd_prop(fstab.zone_fs_special, RT_FS, PT_SPECIAL,
+ &ret_val);
+ check_reqd_prop(fstab.zone_fs_type, RT_FS, PT_TYPE, &ret_val);
+
zonecfg_free_fs_option_list(fstab.zone_fs_options);
}
(void) zonecfg_endfsent(handle);
@@ -3297,20 +3350,10 @@ verify_func(cmd_t *cmd)
return;
}
while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
- if (strlen(nwiftab.zone_nwif_address) == 0) {
- zerr("%s: %s %s", rt_to_str(RT_NET),
- pt_to_str(PT_ADDRESS), gettext("not specified"));
- saw_error = TRUE;
- if (ret_val == Z_OK)
- ret_val = Z_REQD_PROPERTY_MISSING;
- }
- if (strlen(nwiftab.zone_nwif_physical) == 0) {
- zerr("%s: %s %s", rt_to_str(RT_NET),
- pt_to_str(PT_PHYSICAL), gettext("not specified"));
- saw_error = TRUE;
- if (ret_val == Z_OK)
- ret_val = Z_REQD_PROPERTY_MISSING;
- }
+ check_reqd_prop(nwiftab.zone_nwif_address, RT_NET,
+ PT_ADDRESS, &ret_val);
+ check_reqd_prop(nwiftab.zone_nwif_physical, RT_NET,
+ PT_PHYSICAL, &ret_val);
}
(void) zonecfg_endnwifent(handle);
@@ -3319,13 +3362,9 @@ verify_func(cmd_t *cmd)
return;
}
while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
- if (strlen(rctltab.zone_rctl_name) == 0) {
- zerr("%s: %s %s", rt_to_str(RT_RCTL),
- pt_to_str(PT_NAME), gettext("not specified"));
- saw_error = TRUE;
- if (ret_val == Z_OK)
- ret_val = Z_REQD_PROPERTY_MISSING;
- }
+ check_reqd_prop(rctltab.zone_rctl_name, RT_RCTL, PT_NAME,
+ &ret_val);
+
if (rctltab.zone_rctl_valptr == NULL) {
zerr(gettext("%s: no %s specified"),
rt_to_str(RT_RCTL), pt_to_str(PT_VALUE));
@@ -3343,27 +3382,12 @@ verify_func(cmd_t *cmd)
return;
}
while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
- if (strlen(attrtab.zone_attr_name) == 0) {
- zerr("%s: %s %s", rt_to_str(RT_ATTR),
- pt_to_str(PT_NAME), gettext("not specified"));
- saw_error = TRUE;
- if (ret_val == Z_OK)
- ret_val = Z_REQD_PROPERTY_MISSING;
- }
- if (strlen(attrtab.zone_attr_type) == 0) {
- zerr("%s: %s %s", rt_to_str(RT_ATTR),
- pt_to_str(PT_TYPE), gettext("not specified"));
- saw_error = TRUE;
- if (ret_val == Z_OK)
- ret_val = Z_REQD_PROPERTY_MISSING;
- }
- if (strlen(attrtab.zone_attr_value) == 0) {
- zerr("%s: %s %s", rt_to_str(RT_ATTR),
- pt_to_str(PT_VALUE), gettext("not specified"));
- saw_error = TRUE;
- if (ret_val == Z_OK)
- ret_val = Z_REQD_PROPERTY_MISSING;
- }
+ check_reqd_prop(attrtab.zone_attr_name, RT_ATTR, PT_NAME,
+ &ret_val);
+ check_reqd_prop(attrtab.zone_attr_type, RT_ATTR, PT_TYPE,
+ &ret_val);
+ check_reqd_prop(attrtab.zone_attr_value, RT_ATTR, PT_VALUE,
+ &ret_val);
}
(void) zonecfg_endattrent(handle);
@@ -3375,10 +3399,15 @@ verify_func(cmd_t *cmd)
}
if (save) {
- if (ret_val == Z_OK)
- ret_val = save_it(zonepath);
- else
- zerr("zone %s %s", zone, gettext("failed to verify"));
+ if (ret_val == Z_OK) {
+ if ((ret_val = zonecfg_save(handle)) == Z_OK) {
+ need_to_commit = FALSE;
+ (void) strlcpy(revert_zone, zone,
+ sizeof (revert_zone));
+ }
+ } else {
+ zerr(gettext("Zone %s failed to verify"), zone);
+ }
}
if (ret_val != Z_OK)
zone_perror(zone, ret_val, TRUE);
@@ -3486,6 +3515,21 @@ validate_attr_type_val(struct zone_attrtab *attrtab)
return (Z_ERR);
}
+/*
+ * Helper function for end_func-- checks the existence of a given property
+ * and emits a message if not specified.
+ */
+static int
+end_check_reqd(char *attr, int pt, bool *validation_failed)
+{
+ if (strlen(attr) == 0) {
+ *validation_failed = TRUE;
+ zerr(gettext("%s not specified"), pt_to_str(pt));
+ return (Z_ERR);
+ }
+ return (Z_OK);
+}
+
void
end_func(cmd_t *cmd)
{
@@ -3525,36 +3569,35 @@ end_func(cmd_t *cmd)
switch (resource_scope) {
case RT_FS:
/* First make sure everything was filled in. */
- if (strlen(in_progress_fstab.zone_fs_dir) == 0) {
- zerr("dir %s", gettext("not specified"));
- saw_error = TRUE;
- validation_failed = TRUE;
- } else if (in_progress_fstab.zone_fs_dir[0] != '/') {
- zerr("dir %s %s", in_progress_fstab.zone_fs_dir,
- gettext("is not an absolute path."));
- saw_error = TRUE;
- validation_failed = TRUE;
- }
- if (strlen(in_progress_fstab.zone_fs_special) == 0) {
- zerr("special %s", gettext("not specified"));
- saw_error = TRUE;
- validation_failed = TRUE;
+ if (end_check_reqd(in_progress_fstab.zone_fs_dir,
+ PT_DIR, &validation_failed) == Z_OK) {
+ if (in_progress_fstab.zone_fs_dir[0] != '/') {
+ zerr(gettext("%s %s is not an absolute path."),
+ pt_to_str(PT_DIR),
+ in_progress_fstab.zone_fs_dir);
+ validation_failed = TRUE;
+ }
}
+
+ (void) end_check_reqd(in_progress_fstab.zone_fs_special,
+ PT_SPECIAL, &validation_failed);
+
if (in_progress_fstab.zone_fs_raw[0] != '\0' &&
in_progress_fstab.zone_fs_raw[0] != '/') {
- zerr("raw device %s %s",
- in_progress_fstab.zone_fs_raw,
- gettext("is not an absolute path."));
- saw_error = TRUE;
+ zerr(gettext("%s %s is not an absolute path."),
+ pt_to_str(PT_RAW),
+ in_progress_fstab.zone_fs_raw);
validation_failed = TRUE;
}
- if (strlen(in_progress_fstab.zone_fs_type) == 0) {
- zerr("type %s", gettext("not specified"));
+
+ (void) end_check_reqd(in_progress_fstab.zone_fs_type, PT_TYPE,
+ &validation_failed);
+
+ if (validation_failed) {
saw_error = TRUE;
- validation_failed = TRUE;
- }
- if (validation_failed)
return;
+ }
+
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
bzero(&tmp_fstab, sizeof (tmp_fstab));
@@ -3580,20 +3623,23 @@ end_func(cmd_t *cmd)
zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
in_progress_fstab.zone_fs_options = NULL;
break;
+
case RT_IPD:
/* First make sure everything was filled in. */
- if (strlen(in_progress_ipdtab.zone_fs_dir) == 0) {
- zerr("dir %s", gettext("not specified"));
- saw_error = TRUE;
- validation_failed = TRUE;
- } else if (in_progress_ipdtab.zone_fs_dir[0] != '/') {
- zerr("dir %s %s", in_progress_ipdtab.zone_fs_dir,
- gettext("is not an absolute path."));
- saw_error = TRUE;
- validation_failed = TRUE;
+ if (end_check_reqd(in_progress_ipdtab.zone_fs_dir, PT_DIR,
+ &validation_failed) == Z_OK) {
+ if (in_progress_ipdtab.zone_fs_dir[0] != '/') {
+ zerr(gettext("%s %s is not an absolute path."),
+ pt_to_str(PT_DIR),
+ in_progress_ipdtab.zone_fs_dir);
+ validation_failed = TRUE;
+ }
}
- if (validation_failed)
+ if (validation_failed) {
+ saw_error = TRUE;
return;
+ }
+
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
bzero(&tmp_fstab, sizeof (tmp_fstab));
@@ -3617,18 +3663,16 @@ end_func(cmd_t *cmd)
break;
case RT_NET:
/* First make sure everything was filled in. */
- if (strlen(in_progress_nwiftab.zone_nwif_physical) == 0) {
- zerr("physical %s", gettext("not specified"));
- saw_error = TRUE;
- validation_failed = TRUE;
- }
- if (strlen(in_progress_nwiftab.zone_nwif_address) == 0) {
- zerr("address %s", gettext("not specified"));
+ (void) end_check_reqd(in_progress_nwiftab.zone_nwif_physical,
+ PT_PHYSICAL, &validation_failed);
+ (void) end_check_reqd(in_progress_nwiftab.zone_nwif_address,
+ PT_ADDRESS, &validation_failed);
+
+ if (validation_failed) {
saw_error = TRUE;
- validation_failed = TRUE;
- }
- if (validation_failed)
return;
+ }
+
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
bzero(&tmp_nwiftab, sizeof (tmp_nwiftab));
@@ -3649,15 +3693,17 @@ end_func(cmd_t *cmd)
&in_progress_nwiftab);
}
break;
+
case RT_DEVICE:
/* First make sure everything was filled in. */
- if (strlen(in_progress_devtab.zone_dev_match) == 0) {
- zerr("match %s", gettext("not specified"));
+ (void) end_check_reqd(in_progress_devtab.zone_dev_match,
+ PT_MATCH, &validation_failed);
+
+ if (validation_failed) {
saw_error = TRUE;
- validation_failed = TRUE;
- }
- if (validation_failed)
return;
+ }
+
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
(void) strlcpy(tmp_devtab.zone_dev_match,
@@ -3677,20 +3723,22 @@ end_func(cmd_t *cmd)
&in_progress_devtab);
}
break;
+
case RT_RCTL:
/* First make sure everything was filled in. */
- if (strlen(in_progress_rctltab.zone_rctl_name) == 0) {
- zerr("name %s", gettext("not specified"));
- saw_error = TRUE;
- validation_failed = TRUE;
- }
+ (void) end_check_reqd(in_progress_rctltab.zone_rctl_name,
+ PT_NAME, &validation_failed);
+
if (in_progress_rctltab.zone_rctl_valptr == NULL) {
zerr(gettext("no %s specified"), pt_to_str(PT_VALUE));
- saw_error = TRUE;
validation_failed = TRUE;
}
- if (validation_failed)
+
+ if (validation_failed) {
+ saw_error = TRUE;
return;
+ }
+
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
(void) strlcpy(tmp_rctltab.zone_rctl_name,
@@ -3719,34 +3767,27 @@ end_func(cmd_t *cmd)
in_progress_rctltab.zone_rctl_valptr = NULL;
}
break;
+
case RT_ATTR:
/* First make sure everything was filled in. */
- if (strlen(in_progress_attrtab.zone_attr_name) == 0) {
- zerr("name %s", gettext("not specified"));
- saw_error = TRUE;
- validation_failed = TRUE;
- }
- if (strlen(in_progress_attrtab.zone_attr_type) == 0) {
- zerr("type %s", gettext("not specified"));
- saw_error = TRUE;
- validation_failed = TRUE;
- }
- if (strlen(in_progress_attrtab.zone_attr_value) == 0) {
- zerr("value %s", gettext("not specified"));
- saw_error = TRUE;
- validation_failed = TRUE;
- }
+ (void) end_check_reqd(in_progress_attrtab.zone_attr_name,
+ PT_NAME, &validation_failed);
+ (void) end_check_reqd(in_progress_attrtab.zone_attr_type,
+ PT_TYPE, &validation_failed);
+ (void) end_check_reqd(in_progress_attrtab.zone_attr_value,
+ PT_VALUE, &validation_failed);
+
if (validate_attr_name(in_progress_attrtab.zone_attr_name) !=
- Z_OK) {
- saw_error = TRUE;
+ Z_OK)
validation_failed = TRUE;
- }
- if (validate_attr_type_val(&in_progress_attrtab) != Z_OK) {
- saw_error = TRUE;
+
+ if (validate_attr_type_val(&in_progress_attrtab) != Z_OK)
validation_failed = TRUE;
- }
- if (validation_failed)
+
+ if (validation_failed) {
+ saw_error = TRUE;
return;
+ }
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
bzero(&tmp_attrtab, sizeof (tmp_attrtab));
@@ -3882,15 +3923,16 @@ revert_func(cmd_t *cmd)
zone_perror(execname, Z_NOMEM, TRUE);
exit(Z_ERR);
}
- if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) {
+ if ((err = zonecfg_get_handle(revert_zone, handle)) != Z_OK) {
saw_error = TRUE;
got_handle = FALSE;
if (err == Z_NO_ZONE)
zerr(gettext("%s: no such saved zone to revert to."),
- zone);
+ revert_zone);
else
zone_perror(zone, err, TRUE);
}
+ (void) strlcpy(zone, revert_zone, sizeof (zone));
}
void
@@ -4109,9 +4151,9 @@ do_interactive(void)
*/
(void) initialize(FALSE);
}
- do
+ do {
err = read_input();
- while (err == Z_REPEAT);
+ } while (err == Z_REPEAT);
return (err);
}
@@ -4231,42 +4273,6 @@ get_execbasename(char *execfullname)
return (execbasename);
}
-static void
-validate_zone_name()
-{
- regex_t reg;
- char *locale = NULL, locale_buf[MAXPATHLEN];
-
- if (strcmp(zone, GLOBAL_ZONENAME) == 0)
- goto err;
-
- /*
- * The regex(5) functions below are locale-sensitive, so save the
- * user's locale, then set it to "C" for the regex's, and restore
- * it afterwards.
- */
- if ((locale = setlocale(LC_ALL, NULL)) != NULL) {
- (void) strlcpy(locale_buf, locale, sizeof (locale_buf));
- locale = locale_buf;
- }
- (void) setlocale(LC_ALL, "C");
- if (regcomp(&reg, "^" ZONENAME_REGEXP "$", REG_EXTENDED|REG_NOSUB) != 0)
- goto err;
-
- if (regexec(&reg, zone, (size_t)0, NULL, 0) != 0)
- goto err;
-
- regfree(&reg);
- (void) setlocale(LC_ALL, locale);
- return;
-
-err:
- (void) setlocale(LC_ALL, locale);
- zone_perror(zone, Z_BOGUS_ZONE_NAME, TRUE);
- usage(FALSE, HELP_SYNTAX);
- exit(Z_USAGE);
-}
-
int
main(int argc, char *argv[])
{
@@ -4297,7 +4303,6 @@ main(int argc, char *argv[])
exit(Z_OK);
}
- zone = NULL;
while ((arg = getopt(argc, argv, "?f:z:")) != EOF) {
switch (arg) {
case '?':
@@ -4312,7 +4317,13 @@ main(int argc, char *argv[])
cmd_file_mode = TRUE;
break;
case 'z':
- zone = optarg;
+ if (zonecfg_validate_zonename(optarg) != Z_OK) {
+ zone_perror(optarg, Z_BOGUS_ZONE_NAME, TRUE);
+ usage(FALSE, HELP_SYNTAX);
+ exit(Z_USAGE);
+ }
+ (void) strlcpy(zone, optarg, sizeof (zone));
+ (void) strlcpy(revert_zone, optarg, sizeof (zone));
break;
default:
usage(FALSE, HELP_USAGE);
@@ -4320,21 +4331,24 @@ main(int argc, char *argv[])
}
}
- if (optind > argc || zone == NULL) {
+ if (optind > argc || strcmp(zone, "") == 0) {
usage(FALSE, HELP_USAGE);
exit(Z_USAGE);
}
- validate_zone_name();
- if (zonecfg_access(zone, W_OK) == Z_OK) {
+ if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
read_only_mode = FALSE;
- } else {
+ } else if (err == Z_ACCES) {
read_only_mode = TRUE;
/* skip this message in one-off from command line mode */
if (optind == argc)
(void) fprintf(stderr, gettext("WARNING: you do not "
"have write access to this zone's configuration "
"file;\ngoing into read-only mode.\n"));
+ } else {
+ fprintf(stderr, "%s: Could not access zone configuration "
+ "store: %s\n", execname, zonecfg_strerror(err));
+ exit(Z_ERR);
}
if ((handle = zonecfg_init_handle()) == NULL) {
diff --git a/usr/src/cmd/zonecfg/zonecfg.h b/usr/src/cmd/zonecfg/zonecfg.h
index 8337811ac1..e0fca7a02d 100644
--- a/usr/src/cmd/zonecfg/zonecfg.h
+++ b/usr/src/cmd/zonecfg/zonecfg.h
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -69,37 +69,39 @@ typedef int bool;
/* resource types: increment RT_MAX when expanding this list */
#define RT_UNKNOWN 0
-#define RT_ZONEPATH 1 /* really a property, but for info ... */
-#define RT_AUTOBOOT 2 /* really a property, but for info ... */
-#define RT_POOL 3 /* really a property, but for info ... */
-#define RT_FS 4
-#define RT_IPD 5
-#define RT_NET 6
-#define RT_DEVICE 7
-#define RT_RCTL 8
-#define RT_ATTR 9
+#define RT_ZONENAME 1 /* really a property, but for info ... */
+#define RT_ZONEPATH 2 /* really a property, but for info ... */
+#define RT_AUTOBOOT 3 /* really a property, but for info ... */
+#define RT_POOL 4 /* really a property, but for info ... */
+#define RT_FS 5
+#define RT_IPD 6
+#define RT_NET 7
+#define RT_DEVICE 8
+#define RT_RCTL 9
+#define RT_ATTR 10
#define RT_MIN RT_UNKNOWN
#define RT_MAX RT_ATTR
/* property types: increment PT_MAX when expanding this list */
#define PT_UNKNOWN 0
-#define PT_ZONEPATH 1
-#define PT_AUTOBOOT 2
-#define PT_POOL 3
-#define PT_DIR 4
-#define PT_SPECIAL 5
-#define PT_TYPE 6
-#define PT_OPTIONS 7
-#define PT_ADDRESS 8
-#define PT_PHYSICAL 9
-#define PT_NAME 10
-#define PT_VALUE 11
-#define PT_MATCH 12
-#define PT_PRIV 13
-#define PT_LIMIT 14
-#define PT_ACTION 15
-#define PT_RAW 16
+#define PT_ZONENAME 1
+#define PT_ZONEPATH 2
+#define PT_AUTOBOOT 3
+#define PT_POOL 4
+#define PT_DIR 5
+#define PT_SPECIAL 6
+#define PT_TYPE 7
+#define PT_OPTIONS 8
+#define PT_ADDRESS 9
+#define PT_PHYSICAL 10
+#define PT_NAME 11
+#define PT_VALUE 12
+#define PT_MATCH 13
+#define PT_PRIV 14
+#define PT_LIMIT 15
+#define PT_ACTION 16
+#define PT_RAW 17
#define PT_MIN PT_UNKNOWN
#define PT_MAX PT_RAW
diff --git a/usr/src/cmd/zonecfg/zonecfg_grammar.y b/usr/src/cmd/zonecfg/zonecfg_grammar.y
index 2927233b95..abca323bed 100644
--- a/usr/src/cmd/zonecfg/zonecfg_grammar.y
+++ b/usr/src/cmd/zonecfg/zonecfg_grammar.y
@@ -58,9 +58,9 @@ extern void yyerror(char *s);
%start commands
%token HELP CREATE EXPORT ADD DELETE REMOVE SELECT SET INFO CANCEL END VERIFY
-%token COMMIT REVERT EXIT SEMICOLON TOKEN ZONEPATH AUTOBOOT POOL NET FS IPD ATTR
-%token DEVICE RCTL SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL NAME
-%token MATCH PRIV LIMIT ACTION VALUE EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
+%token COMMIT REVERT EXIT SEMICOLON TOKEN ZONENAME ZONEPATH AUTOBOOT POOL NET
+%token FS IPD ATTR DEVICE RCTL SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL
+%token NAME MATCH PRIV LIMIT ACTION VALUE EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
%token OPEN_PAREN CLOSE_PAREN COMMA
%type <strval> TOKEN EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
@@ -68,7 +68,7 @@ extern void yyerror(char *s);
%type <complex> complex_piece complex_prop_val
%type <ival> resource_type NET FS IPD DEVICE RCTL ATTR
%type <ival> property_name SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL NAME
- MATCH ZONEPATH AUTOBOOT POOL VALUE PRIV LIMIT ACTION
+ MATCH ZONENAME ZONEPATH AUTOBOOT POOL VALUE PRIV LIMIT ACTION
%type <cmd> command
%type <cmd> add_command ADD
%type <cmd> cancel_command CANCEL
@@ -402,6 +402,15 @@ info_command: INFO
$$->cmd_res_type = $2;
$$->cmd_prop_nv_pairs = 0;
}
+ | INFO ZONENAME
+ {
+ if (($$ = alloc_cmd()) == NULL)
+ YYERROR;
+ cmd = $$;
+ $$->cmd_handler = &info_func;
+ $$->cmd_res_type = RT_ZONENAME;
+ $$->cmd_prop_nv_pairs = 0;
+ }
| INFO ZONEPATH
{
if (($$ = alloc_cmd()) == NULL)
@@ -665,6 +674,7 @@ property_name: SPECIAL { $$ = PT_SPECIAL; }
| DIR { $$ = PT_DIR; }
| TYPE { $$ = PT_TYPE; }
| OPTIONS { $$ = PT_OPTIONS; }
+ | ZONENAME { $$ = PT_ZONENAME; }
| ZONEPATH { $$ = PT_ZONEPATH; }
| AUTOBOOT { $$ = PT_AUTOBOOT; }
| POOL { $$ = PT_POOL; }
diff --git a/usr/src/cmd/zonecfg/zonecfg_lex.l b/usr/src/cmd/zonecfg/zonecfg_lex.l
index 1beafcd7f0..1a5de3659e 100644
--- a/usr/src/cmd/zonecfg/zonecfg_lex.l
+++ b/usr/src/cmd/zonecfg/zonecfg_lex.l
@@ -20,7 +20,7 @@
*
* CDDL HEADER END
*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -156,6 +156,9 @@ char *safe_strdup(char *s);
<TSTATE>attr { return ATTR; }
+<TSTATE>zonename { return ZONENAME; }
+<CSTATE>zonename { return ZONENAME; }
+
<TSTATE>zonepath { return ZONEPATH; }
<CSTATE>zonepath { return ZONEPATH; }
diff --git a/usr/src/head/libzonecfg.h b/usr/src/head/libzonecfg.h
index e5c3f9a451..dd3c1d41ef 100644
--- a/usr/src/head/libzonecfg.h
+++ b/usr/src/head/libzonecfg.h
@@ -72,9 +72,9 @@ extern "C" {
#define Z_NO_RESOURCE_ID 18 /* no/wrong resource id */
#define Z_NO_PROPERTY_TYPE 19 /* no/wrong property type */
#define Z_NO_PROPERTY_ID 20 /* no/wrong property id */
-#define Z_RESOURCE_EXISTS 21 /* resource already exists */
+#define Z_BAD_ZONE_STATE 21 /* zone state invalid for given task */
#define Z_INVALID_DOCUMENT 22 /* libxml can't validate against DTD */
-#define Z_ID_IN_USE 23 /* add_index conflict */
+#define Z_NAME_IN_USE 23 /* zone name already in use (rename) */
#define Z_NO_SUCH_ID 24 /* delete_index: no old ID */
#define Z_UPDATING_INDEX 25 /* add/modify/delete_index problem */
#define Z_LOCKING_FILE 26 /* problem locking index file */
@@ -108,6 +108,7 @@ struct zoneent {
char zone_name[ZONENAME_MAX]; /* name of the zone */
int zone_state; /* configured | incomplete | installed */
char zone_path[MAXPATHLEN];
+ char zone_newname[ZONENAME_MAX]; /* for doing renames */
};
typedef struct zone_dochandle *zone_dochandle_t; /* opaque handle */
@@ -160,9 +161,10 @@ struct zone_attrtab {
extern zone_dochandle_t zonecfg_init_handle(void);
extern int zonecfg_get_handle(char *, zone_dochandle_t);
extern int zonecfg_get_snapshot_handle(char *, zone_dochandle_t);
+extern int zonecfg_get_template_handle(char *, char *, zone_dochandle_t);
extern int zonecfg_check_handle(zone_dochandle_t);
extern void zonecfg_fini_handle(zone_dochandle_t);
-extern int zonecfg_destroy(const char *);
+extern int zonecfg_destroy(const char *, boolean_t);
extern int zonecfg_destroy_snapshot(char *);
extern int zonecfg_save(zone_dochandle_t);
extern int zonecfg_create_snapshot(char *);
@@ -172,6 +174,7 @@ extern int zonecfg_access(const char *, int);
/*
* Zone name, path to zone directory, autoboot setting and pool.
*/
+extern int zonecfg_validate_zonename(char *);
extern int zonecfg_get_name(zone_dochandle_t, char *, size_t);
extern int zonecfg_set_name(zone_dochandle_t, char *);
extern int zonecfg_get_zonepath(zone_dochandle_t, char *, size_t);
@@ -279,12 +282,6 @@ extern int zonecfg_endrctlent(zone_dochandle_t);
extern int zonecfg_get_privset(priv_set_t *);
/*
- * Index update routines.
- */
-extern int zonecfg_add_index(char *, char *);
-extern int zonecfg_delete_index(char *);
-
-/*
* Higher-level routines.
*/
extern int zone_get_rootpath(char *, char *, size_t);
diff --git a/usr/src/lib/libzonecfg/common/getzoneent.c b/usr/src/lib/libzonecfg/common/getzoneent.c
index 1ac5730c9d..4a62bddaa9 100644
--- a/usr/src/lib/libzonecfg/common/getzoneent.c
+++ b/usr/src/lib/libzonecfg/common/getzoneent.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -228,17 +228,20 @@ unlock_index_file(int lock_fd)
*
* If ze->zone_state is < 0, it means leave the
* existing value unchanged; this is only meaningful when operation ==
- * PZE_MODIFY (i.e., it's bad on PZE_ADD and a no-op on PZE_DELETE).
+ * PZE_MODIFY (i.e., it's bad on PZE_ADD and a no-op on PZE_REMOVE).
*
- * Likewise, a zero-length ze->zone_path means leave the existing value
+ * A zero-length ze->zone_path means leave the existing value
* unchanged; this is only meaningful when operation == PZE_MODIFY
- * (i.e., it's bad on PZE_ADD and a no-op on PZE_DELETE).
+ * (i.e., it's bad on PZE_ADD and a no-op on PZE_REMOVE).
+ *
+ * A zero-length ze->zone_newname means leave the existing name
+ * unchanged; otherwise the zone is renamed to zone_newname. This is
+ * only meaningful when operation == PZE_MODIFY.
*
* Locking and unlocking is done via the functions above.
* The file itself is not modified in place; rather, a copy is made which
* is modified, then the copy is atomically renamed back to the main file.
*/
-
int
putzoneent(struct zoneent *ze, zoneent_op_t operation)
{
@@ -254,6 +257,10 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
if (operation == PZE_ADD &&
(ze->zone_state < 0 || strlen(ze->zone_path) == 0))
return (Z_INVAL);
+
+ if (operation != PZE_MODIFY && strlen(ze->zone_newname) != 0)
+ return (Z_INVAL);
+
if ((err = lock_index_file(&lock_fd)) != Z_OK)
return (err);
tmp_file_name = strdup(_PATH_TMPFILE);
@@ -331,6 +338,7 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
goto error;
} else if (operation == PZE_MODIFY) {
char tmp_state[ZONE_STATE_MAXSTRLEN + 1];
+ char *tmp_name;
if (ze->zone_state >= 0 &&
strlen(ze->zone_path) > 0) {
@@ -351,12 +359,21 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
p = gettok(&cp);
+ /*
+ * If a new name is supplied, use it.
+ */
+ if (strlen(ze->zone_newname) != 0)
+ tmp_name = ze->zone_newname;
+ else
+ tmp_name = ze->zone_name;
+
(void) fprintf(tmp_file, "%s:%s:%s%s%s\n",
- ze->zone_name, tmp_state,
+ tmp_name, tmp_state,
need_quotes ? "\"" : "",
(strlen(ze->zone_path) == 0) ? p :
ze->zone_path, need_quotes ? "\"" : "");
}
+ /* else if (operation == PZE_REMOVE) { no-op } */
} else {
(void) fputs(orig_buf, tmp_file);
}
diff --git a/usr/src/lib/libzonecfg/common/libzonecfg.c b/usr/src/lib/libzonecfg/common/libzonecfg.c
index 87d2e45c52..b9d80dbefa 100644
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c
@@ -38,6 +38,7 @@
#include <ctype.h>
#include <sys/mntio.h>
#include <sys/mnttab.h>
+#include <sys/types.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -99,6 +100,9 @@ struct zone_dochandle {
xmlDocPtr zone_dh_doc;
xmlNodePtr zone_dh_cur;
xmlNodePtr zone_dh_top;
+ boolean_t zone_dh_newzone;
+ boolean_t zone_dh_snapshot;
+ char zone_dh_delete_name[ZONENAME_MAX];
};
/*
@@ -140,14 +144,11 @@ zonecfg_error_func(void *ctx, const char *msg, ...)
zone_dochandle_t
zonecfg_init_handle(void)
{
- zone_dochandle_t handle = malloc(sizeof (struct zone_dochandle));
+ zone_dochandle_t handle = calloc(1, sizeof (struct zone_dochandle));
if (handle == NULL) {
errno = Z_NOMEM;
return (NULL);
}
- handle->zone_dh_doc = NULL;
- handle->zone_dh_cur = NULL;
- handle->zone_dh_top = NULL;
/* generic libxml initialization */
xmlLineNumbersDefault(1);
@@ -191,12 +192,62 @@ zonecfg_destroy_impl(char *filename)
}
int
-zonecfg_destroy(const char *zonename)
+zonecfg_destroy(const char *zonename, boolean_t force)
{
char path[MAXPATHLEN];
+ struct zoneent ze;
+ int err, state_err;
+ zone_state_t state;
config_file_path(zonename, path);
- return (zonecfg_destroy_impl(path));
+
+ state_err = zone_get_state((char *)zonename, &state);
+ err = access(path, W_OK);
+
+ /*
+ * If there is no file, and no index entry, reliably indicate that no
+ * such zone exists.
+ */
+ if ((state_err == Z_NO_ZONE) && (err == -1) && (errno == ENOENT))
+ return (Z_NO_ZONE);
+
+ /*
+ * Handle any other filesystem related errors (except if the XML
+ * file is missing, which we treat silently), unless we're forcing,
+ * in which case we plow on.
+ */
+ if (err == -1 && errno != ENOENT) {
+ if (errno == EACCES)
+ return (Z_ACCES);
+ else if (!force)
+ return (Z_MISC_FS);
+ }
+
+ if (state > ZONE_STATE_INSTALLED)
+ return (Z_BAD_ZONE_STATE);
+
+ if (!force && state > ZONE_STATE_CONFIGURED)
+ return (Z_BAD_ZONE_STATE);
+
+ /*
+ * Index deletion succeeds even if the entry doesn't exist. So this
+ * will fail only if we've had some more severe problem.
+ */
+ bzero(&ze, sizeof (ze));
+ (void) strlcpy(ze.zone_name, zonename, sizeof (ze.zone_name));
+ if ((err = putzoneent(&ze, PZE_REMOVE)) != Z_OK)
+ if (!force)
+ return (err);
+
+ err = zonecfg_destroy_impl(path);
+
+ /*
+ * Treat failure to find the XML file silently, since, well, it's
+ * gone, and with the index file cleaned up, we're done.
+ */
+ if (err == Z_OK || err == Z_NO_ZONE)
+ return (Z_OK);
+ return (err);
}
int
@@ -277,12 +328,39 @@ setrootattr(zone_dochandle_t handle, const xmlChar *propname, char *propval)
return (Z_OK);
}
+static void
+addcomment(zone_dochandle_t handle, const char *comment)
+{
+ xmlNodePtr node;
+ node = xmlNewComment((xmlChar *) comment);
+
+ if (node != NULL)
+ (void) xmlAddPrevSibling(handle->zone_dh_top, node);
+}
+
+static void
+stripcomments(zone_dochandle_t handle)
+{
+ xmlDocPtr top;
+ xmlNodePtr child, next;
+
+ top = handle->zone_dh_doc;
+ for (child = top->xmlChildrenNode; child != NULL; child = next) {
+ next = child->next;
+ if (child->name == NULL)
+ continue;
+ if (xmlStrcmp(child->name, DTD_ELEM_COMMENT) == 0) {
+ next = child->next;
+ xmlUnlinkNode(child);
+ xmlFreeNode(child);
+ }
+ }
+}
+
static int
zonecfg_get_handle_impl(char *zonename, char *filename, zone_dochandle_t handle)
{
xmlValidCtxtPtr cvp;
- xmlDocPtr top;
- xmlNodePtr child, next;
struct stat statbuf;
int valid;
@@ -302,18 +380,9 @@ zonecfg_get_handle_impl(char *zonename, char *filename, zone_dochandle_t handle)
xmlFreeValidCtxt(cvp);
if (valid == 0)
return (Z_INVALID_DOCUMENT);
+
/* delete any comments such as inherited Sun copyright / ident str */
- top = handle->zone_dh_doc;
- for (child = top->xmlChildrenNode; child != NULL; child = next) {
- next = child->next;
- if (child->name == NULL)
- continue;
- if (xmlStrcmp(child->name, DTD_ELEM_COMMENT) == 0) {
- next = child->next;
- xmlUnlinkNode(child);
- xmlFreeNode(child);
- }
- }
+ stripcomments(handle);
return (Z_OK);
}
@@ -323,6 +392,8 @@ zonecfg_get_handle(char *zonename, zone_dochandle_t handle)
char path[MAXPATHLEN];
config_file_path(zonename, path);
+ handle->zone_dh_newzone = B_FALSE;
+
return (zonecfg_get_handle_impl(zonename, path, handle));
}
@@ -332,10 +403,84 @@ zonecfg_get_snapshot_handle(char *zonename, zone_dochandle_t handle)
char path[MAXPATHLEN];
snap_file_path(zonename, path);
+ handle->zone_dh_newzone = B_FALSE;
return (zonecfg_get_handle_impl(zonename, path, handle));
}
int
+zonecfg_get_template_handle(char *template, char *zonename,
+ zone_dochandle_t handle)
+{
+ char path[MAXPATHLEN];
+ int err;
+
+ config_file_path(template, path);
+
+ if ((err = zonecfg_get_handle_impl(template, path, handle)) != Z_OK)
+ return (err);
+ handle->zone_dh_newzone = B_TRUE;
+ return (setrootattr(handle, DTD_ATTR_NAME, zonename));
+}
+
+static boolean_t
+is_renaming(zone_dochandle_t handle)
+{
+ if (handle->zone_dh_newzone)
+ return (B_FALSE);
+ if (strlen(handle->zone_dh_delete_name) > 0)
+ return (B_TRUE);
+ return (B_FALSE);
+}
+
+static boolean_t
+is_new(zone_dochandle_t handle)
+{
+ return (handle->zone_dh_newzone || handle->zone_dh_snapshot);
+}
+
+static boolean_t
+is_snapshot(zone_dochandle_t handle)
+{
+ return (handle->zone_dh_snapshot);
+}
+
+/*
+ * It would be great to be able to use libc's ctype(3c) macros, but we
+ * can't, as they are locale sensitive, and it would break our limited thread
+ * safety if this routine had to change the app locale on the fly.
+ */
+int
+zonecfg_validate_zonename(char *zone)
+{
+ int i;
+
+ if (strcmp(zone, GLOBAL_ZONENAME) == 0)
+ return (Z_BOGUS_ZONE_NAME);
+
+ if (strlen(zone) >= ZONENAME_MAX)
+ return (Z_BOGUS_ZONE_NAME);
+
+ if (!((zone[0] >= 'a' && zone[0] <= 'z') ||
+ (zone[0] >= 'A' && zone[0] <= 'Z') ||
+ (zone[0] >= '0' && zone[0] <= '9')))
+ return (Z_BOGUS_ZONE_NAME);
+
+ for (i = 1; zone[i] != '\0'; i++) {
+ if (!((zone[i] >= 'a' && zone[i] <= 'z') ||
+ (zone[i] >= 'A' && zone[i] <= 'Z') ||
+ (zone[i] >= '0' && zone[i] <= '9') ||
+ (zone[i] == '-') || (zone[i] == '_') || (zone[i] == '.')))
+ return (Z_BOGUS_ZONE_NAME);
+ }
+
+ return (Z_OK);
+}
+
+/*
+ * Changing the zone name requires us to track both the old and new
+ * name of the zone until commit time.
+ */
+int
zonecfg_get_name(zone_dochandle_t handle, char *name, size_t namesize)
{
return (getrootattr(handle, DTD_ATTR_NAME, name, namesize));
@@ -344,7 +489,85 @@ zonecfg_get_name(zone_dochandle_t handle, char *name, size_t namesize)
int
zonecfg_set_name(zone_dochandle_t handle, char *name)
{
- return (setrootattr(handle, DTD_ATTR_NAME, name));
+ zone_state_t state;
+ char curname[ZONENAME_MAX], old_delname[ZONENAME_MAX];
+ int err;
+
+ if ((err = getrootattr(handle, DTD_ATTR_NAME, curname,
+ sizeof (curname))) != Z_OK)
+ return (err);
+
+ if (strcmp(name, curname) == 0)
+ return (Z_OK);
+
+ /*
+ * Switching zone names to one beginning with SUNW is not permitted.
+ */
+ if (strncmp(name, "SUNW", 4) == 0)
+ return (Z_BOGUS_ZONE_NAME);
+
+ if ((err = zonecfg_validate_zonename(name)) != Z_OK)
+ return (err);
+
+ /*
+ * Setting the name back to the original name (effectively a revert of
+ * the name) is fine. But if we carry on, we'll falsely identify the
+ * name as "in use," so special case here.
+ */
+ if (strcmp(name, handle->zone_dh_delete_name) == 0) {
+ err = setrootattr(handle, DTD_ATTR_NAME, name);
+ handle->zone_dh_delete_name[0] = '\0';
+ return (err);
+ }
+
+ /* Check to see if new name chosen is already in use */
+ if (zone_get_state(name, &state) != Z_NO_ZONE)
+ return (Z_NAME_IN_USE);
+
+ /*
+ * If this isn't already "new" or in a renaming transition, then
+ * we're initiating a rename here; so stash the "delete name"
+ * (i.e. the name of the zone we'll be removing) for the rename.
+ */
+ (void) strlcpy(old_delname, handle->zone_dh_delete_name,
+ sizeof (old_delname));
+ if (!is_new(handle) && !is_renaming(handle)) {
+ /*
+ * Name change is allowed only when the zone we're altering
+ * is not ready or running.
+ */
+ err = zone_get_state(curname, &state);
+ if (err == Z_OK) {
+ if (state > ZONE_STATE_INSTALLED)
+ return (Z_BAD_ZONE_STATE);
+ } else if (err != Z_NO_ZONE) {
+ return (err);
+ }
+
+ (void) strlcpy(handle->zone_dh_delete_name, curname,
+ sizeof (handle->zone_dh_delete_name));
+ assert(is_renaming(handle));
+ } else if (is_renaming(handle)) {
+ err = zone_get_state(handle->zone_dh_delete_name, &state);
+ if (err == Z_OK) {
+ if (state > ZONE_STATE_INSTALLED)
+ return (Z_BAD_ZONE_STATE);
+ } else if (err != Z_NO_ZONE) {
+ return (err);
+ }
+ }
+
+ if ((err = setrootattr(handle, DTD_ATTR_NAME, name)) != Z_OK) {
+ /*
+ * Restore the deletename to whatever it was at the
+ * top of the routine, since we've had a failure.
+ */
+ (void) strlcpy(handle->zone_dh_delete_name, old_delname,
+ sizeof (handle->zone_dh_delete_name));
+ return (err);
+ }
+
+ return (Z_OK);
}
int
@@ -402,6 +625,11 @@ zonecfg_set_pool(zone_dochandle_t handle, char *pool)
* in the <zonename>.xml file: the path to the zone. This is for performance,
* since we need to walk all zonepath's in order to be able to detect conflicts
* (see crosscheck_zonepaths() in the zoneadm command).
+ *
+ * An additional complexity is that when doing a rename, we'd like the entire
+ * index update operation (rename, and potential state changes) to be atomic.
+ * In general, the operation of this function should succeed or fail as
+ * a unit.
*/
int
zonecfg_refresh_index_file(zone_dochandle_t handle)
@@ -409,25 +637,94 @@ zonecfg_refresh_index_file(zone_dochandle_t handle)
char name[ZONENAME_MAX], zonepath[MAXPATHLEN];
struct zoneent ze;
int err;
+ int opcode;
+ char *zn;
+
+ bzero(&ze, sizeof (ze));
+ ze.zone_state = -1; /* Preserve existing state in index */
if ((err = zonecfg_get_name(handle, name, sizeof (name))) != Z_OK)
return (err);
+ (void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name));
+
if ((err = zonecfg_get_zonepath(handle, zonepath,
sizeof (zonepath))) != Z_OK)
return (err);
- (void) strlcpy(ze.zone_name, name, sizeof (ze.zone_name));
- ze.zone_state = -1;
(void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path));
- return (putzoneent(&ze, PZE_MODIFY));
+
+ if (is_renaming(handle)) {
+ opcode = PZE_MODIFY;
+ (void) strlcpy(ze.zone_name, handle->zone_dh_delete_name,
+ sizeof (ze.zone_name));
+ (void) strlcpy(ze.zone_newname, name, sizeof (ze.zone_newname));
+ } else if (is_new(handle)) {
+ FILE *cookie;
+ /*
+ * Be tolerant of the zone already existing in the index file,
+ * since we might be forcibly overwriting an existing
+ * configuration with a new one (for example 'create -F'
+ * in zonecfg).
+ */
+ opcode = PZE_ADD;
+ cookie = setzoneent();
+ while ((zn = getzoneent(cookie)) != NULL) {
+ if (strcmp(zn, name) == 0) {
+ opcode = PZE_MODIFY;
+ free(zn);
+ break;
+ }
+ free(zn);
+ }
+ endzoneent(cookie);
+ ze.zone_state = ZONE_STATE_CONFIGURED;
+ } else {
+ opcode = PZE_MODIFY;
+ }
+
+ if ((err = putzoneent(&ze, opcode)) != Z_OK)
+ return (err);
+
+ return (Z_OK);
}
+/*
+ * The goal of this routine is to cause the index file update and the
+ * document save to happen as an atomic operation. We do the document
+ * first, saving a backup copy using a hard link; if that succeeds, we go
+ * on to the index. If that fails, we roll the document back into place.
+ *
+ * Strategy:
+ *
+ * New zone 'foo' configuration:
+ * Create tmpfile (zonecfg.xxxxxx)
+ * Write XML to tmpfile
+ * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml)
+ * Add entry to index file
+ * If it fails, delete foo.xml, leaving nothing behind.
+ *
+ * Save existing zone 'foo':
+ * Make backup of foo.xml -> .backup
+ * Create tmpfile (zonecfg.xxxxxx)
+ * Write XML to tmpfile
+ * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml)
+ * Modify index file as needed
+ * If it fails, recover from .backup -> foo.xml
+ *
+ * Rename 'foo' to 'bar':
+ * Create tmpfile (zonecfg.xxxxxx)
+ * Write XML to tmpfile
+ * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> bar.xml)
+ * Add entry for 'bar' to index file, Remove entry for 'foo' (refresh)
+ * If it fails, delete bar.xml; foo.xml is left behind.
+ */
static int
zonecfg_save_impl(zone_dochandle_t handle, char *filename)
{
char tmpfile[MAXPATHLEN];
- int tmpfd;
+ char bakdir[MAXPATHLEN], bakbase[MAXPATHLEN], bakfile[MAXPATHLEN];
+ int tmpfd, err;
xmlValidCtxt cvp = { NULL };
- xmlNodePtr comment;
+ boolean_t backup;
(void) strlcpy(tmpfile, filename, sizeof (tmpfile));
(void) dirname(tmpfile);
@@ -443,28 +740,82 @@ zonecfg_save_impl(zone_dochandle_t handle, char *filename)
cvp.error = zonecfg_error_func;
cvp.warning = zonecfg_error_func;
- if ((comment = xmlNewComment((xmlChar *) "\n DO NOT EDIT THIS "
- "FILE. Use zonecfg(1M) instead.\n")) == NULL)
- goto err;
- if (xmlAddPrevSibling(handle->zone_dh_top, comment) == 0)
- goto err;
-
- if (xmlValidateDocument(&cvp, handle->zone_dh_doc) == 0)
- goto err;
+ /*
+ * We do a final validation of the document-- but the library has
+ * malfunctioned if it fails to validate, so it's an assert.
+ */
+ assert(xmlValidateDocument(&cvp, handle->zone_dh_doc) != 0);
if (xmlSaveFormatFile(tmpfile, handle->zone_dh_doc, 1) <= 0)
goto err;
+
(void) chmod(tmpfile, 0644);
+ /*
+ * In the event we are doing a standard save, hard link a copy of the
+ * original file in .backup.<pid>.filename so we can restore it if
+ * something goes wrong.
+ */
+ if (!is_new(handle) && !is_renaming(handle)) {
+ backup = B_TRUE;
+
+ (void) strlcpy(bakdir, filename, sizeof (bakdir));
+ (void) strlcpy(bakbase, filename, sizeof (bakbase));
+ (void) snprintf(bakfile, sizeof (bakfile), "%s/.backup.%d.%s",
+ dirname(bakdir), getpid(), basename(bakbase));
+
+ if (link(filename, bakfile) == -1) {
+ err = errno;
+ (void) unlink(tmpfile);
+ if (errno == EACCES)
+ return (Z_ACCES);
+ return (Z_MISC_FS);
+ }
+ }
+
+ /*
+ * Move the new document over top of the old.
+ * i.e.: zonecfg.XXXXXX -> myzone.xml
+ */
if (rename(tmpfile, filename) == -1) {
+ err = errno;
(void) unlink(tmpfile);
- if (errno == EACCES)
+ if (backup)
+ (void) unlink(bakfile);
+ if (err == EACCES)
return (Z_ACCES);
return (Z_MISC_FS);
}
- /* now update the cached copy of the zone path in the index file */
- return (zonecfg_refresh_index_file(handle));
+ /*
+ * If this is a snapshot, we're done-- don't add an index entry.
+ */
+ if (is_snapshot(handle))
+ return (Z_OK);
+
+ /* now update the index file to reflect whatever we just did */
+ if ((err = zonecfg_refresh_index_file(handle)) != Z_OK) {
+ if (backup) {
+ /*
+ * Try to restore from our backup.
+ */
+ (void) unlink(filename);
+ (void) rename(bakfile, filename);
+ } else {
+ /*
+ * Either the zone is new, in which case we can delete
+ * new.xml, or we're doing a rename, so ditto.
+ */
+ assert(is_new(handle) || is_renaming(handle));
+ (void) unlink(filename);
+ }
+ return (Z_UPDATING_INDEX);
+ }
+
+ if (backup)
+ (void) unlink(bakfile);
+
+ return (Z_OK);
err:
(void) unlink(tmpfile);
@@ -474,14 +825,43 @@ err:
int
zonecfg_save(zone_dochandle_t handle)
{
- char zname[MAXPATHLEN], path[MAXPATHLEN];
- int err;
+ char zname[ZONENAME_MAX], path[MAXPATHLEN];
+ char delpath[MAXPATHLEN];
+ int err = Z_SAVING_FILE;
+
+ if (zonecfg_check_handle(handle) != Z_OK)
+ return (Z_BAD_HANDLE);
- if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK) {
+ /*
+ * We don't support saving snapshots at this time.
+ */
+ if (handle->zone_dh_snapshot)
+ return (Z_INVAL);
+
+ if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK)
return (err);
- }
+
config_file_path(zname, path);
- return (zonecfg_save_impl(handle, path));
+
+ addcomment(handle, "\n DO NOT EDIT THIS "
+ "FILE. Use zonecfg(1M) instead.\n");
+
+ err = zonecfg_save_impl(handle, path);
+
+ stripcomments(handle);
+
+ if (err != Z_OK)
+ return (err);
+
+ handle->zone_dh_newzone = B_FALSE;
+
+ if (is_renaming(handle)) {
+ config_file_path(handle->zone_dh_delete_name, delpath);
+ (void) unlink(delpath);
+ handle->zone_dh_delete_name[0] = '\0';
+ }
+
+ return (Z_OK);
}
/*
@@ -519,6 +899,9 @@ zonecfg_create_snapshot(char *zonename)
return (Z_NOMEM);
}
+ handle->zone_dh_newzone = B_TRUE;
+ handle->zone_dh_snapshot = B_TRUE;
+
if ((error = zonecfg_get_handle(zonename, handle)) != Z_OK)
goto out;
if ((error = operation_prep(handle)) != Z_OK)
@@ -548,8 +931,14 @@ zonecfg_create_snapshot(char *zonename)
}
snap_file_path(zonename, path);
+
+ addcomment(handle, "\n DO NOT EDIT THIS FILE. "
+ "It is a snapshot of running zone state.\n");
+
error = zonecfg_save_impl(handle, path);
+ stripcomments(handle);
+
out:
zonecfg_fini_handle(handle);
return (error);
@@ -2142,13 +2531,13 @@ zonecfg_strerror(int errnum)
return (dgettext(TEXT_DOMAIN, "No such property type"));
case Z_NO_PROPERTY_ID:
return (dgettext(TEXT_DOMAIN, "No such property with that id"));
- case Z_RESOURCE_EXISTS:
+ case Z_BAD_ZONE_STATE:
return (dgettext(TEXT_DOMAIN,
- "Resource already exists with that id"));
+ "Zone state is invalid for the requested operation"));
case Z_INVALID_DOCUMENT:
return (dgettext(TEXT_DOMAIN, "Invalid document"));
- case Z_ID_IN_USE:
- return (dgettext(TEXT_DOMAIN, "Zone ID in use"));
+ case Z_NAME_IN_USE:
+ return (dgettext(TEXT_DOMAIN, "Zone name already in use"));
case Z_NO_SUCH_ID:
return (dgettext(TEXT_DOMAIN, "No such zone ID"));
case Z_UPDATING_INDEX:
@@ -2578,26 +2967,6 @@ zonecfg_get_privset(priv_set_t *privs)
}
int
-zonecfg_add_index(char *zone, char *path)
-{
- struct zoneent ze;
-
- (void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
- ze.zone_state = ZONE_STATE_CONFIGURED;
- (void) strlcpy(ze.zone_path, path, sizeof (ze.zone_path));
- return (putzoneent(&ze, PZE_ADD));
-}
-
-int
-zonecfg_delete_index(char *zone)
-{
- struct zoneent ze;
-
- (void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
- return (putzoneent(&ze, PZE_REMOVE));
-}
-
-int
zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz)
{
zone_dochandle_t handle;
@@ -2733,6 +3102,7 @@ zone_set_state(char *zone, zone_state_t state)
state != ZONE_STATE_INCOMPLETE)
return (Z_INVAL);
+ bzero(&ze, sizeof (ze));
(void) strlcpy(ze.zone_name, zone, sizeof (ze.zone_name));
ze.zone_state = state;
(void) strlcpy(ze.zone_path, "", sizeof (ze.zone_path));
diff --git a/usr/src/lib/libzonecfg/spec/libzonecfg.spec b/usr/src/lib/libzonecfg/spec/libzonecfg.spec
index 7c7c1a456a..3d3a84a12f 100644
--- a/usr/src/lib/libzonecfg/spec/libzonecfg.spec
+++ b/usr/src/lib/libzonecfg/spec/libzonecfg.spec
@@ -44,6 +44,12 @@ declaration int zonecfg_get_snapshot_handle(char *, zone_dochandle_t)
version SUNWprivate_1.1
end
+function zonecfg_get_template_handle
+include <libzonecfg.h>
+declaration int zonecfg_get_template_handle(char *, char *, zone_dochandle_t)
+version SUNWprivate_1.1
+end
+
function zonecfg_check_handle
include <libzonecfg.h>
declaration int zonecfg_check_handle(zone_dochandle_t)
@@ -68,6 +74,12 @@ declaration int zonecfg_set_name(zone_dochandle_t, char *)
version SUNWprivate_1.1
end
+function zonecfg_validate_zonename
+include <libzonecfg.h>
+declaration int zonecfg_validate_zonename(char *)
+version SUNWprivate_1.1
+end
+
function zonecfg_get_zonepath
include <libzonecfg.h>
declaration int zonecfg_get_zonepath(zone_dochandle_t, char *, size_t)
@@ -430,7 +442,7 @@ end
function zonecfg_destroy
include <libzonecfg.h>
-declaration int zonecfg_destroy(const char *)
+declaration int zonecfg_destroy(const char *, boolean_t)
version SUNWprivate_1.1
end
@@ -495,18 +507,6 @@ declaration void putzoneent(struct zoneent *, int)
version SUNWprivate_1.1
end
-function zonecfg_add_index
-include <libzonecfg.h>
-declaration int zonecfg_add_index(char *, char *)
-version SUNWprivate_1.1
-end
-
-function zonecfg_delete_index
-include <libzonecfg.h>
-declaration int zonecfg_delete_index(char *)
-version SUNWprivate_1.1
-end
-
function zone_get_id
include <libzonecfg.h>
declaration int zone_get_id(const char *, zoneid_t *);