summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcarlsonj <none@none>2006-02-13 11:54:12 -0800
committercarlsonj <none@none>2006-02-13 11:54:12 -0800
commiteb8bc87559eb2a3f971b8ebb3eff91ca35ae6093 (patch)
tree50199edd0049b729247e3763c752f699c0cdbaf9
parent00ab1250ca6296131437f41e529d52b2a88a2501 (diff)
downloadillumos-joyent-eb8bc87559eb2a3f971b8ebb3eff91ca35ae6093.tar.gz
6379341 zones in /etc/zones/index has non-unique UUID
-rw-r--r--usr/src/lib/libzonecfg/common/getzoneent.c202
-rw-r--r--usr/src/pkgdefs/SUNWzoner/postinstall54
-rw-r--r--usr/src/pkgdefs/SUNWzoner/prototype_com8
-rw-r--r--usr/src/tools/scripts/bfu.sh28
4 files changed, 198 insertions, 94 deletions
diff --git a/usr/src/lib/libzonecfg/common/getzoneent.c b/usr/src/lib/libzonecfg/common/getzoneent.c
index 64d5ff8b33..c75ce2f096 100644
--- a/usr/src/lib/libzonecfg/common/getzoneent.c
+++ b/usr/src/lib/libzonecfg/common/getzoneent.c
@@ -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.
@@ -272,15 +271,14 @@ int
putzoneent(struct zoneent *ze, zoneent_op_t operation)
{
FILE *index_file, *tmp_file;
- char *tmp_file_name, buf[MAX_INDEX_LEN], orig_buf[MAX_INDEX_LEN];
- char zone[ZONENAME_MAX];
- char line[MAX_INDEX_LEN];
+ char *tmp_file_name, buf[MAX_INDEX_LEN];
int tmp_file_desc, lock_fd, err;
- boolean_t exists = B_FALSE, need_quotes;
- char *cp, *p;
+ boolean_t exist, need_quotes;
+ char *cp;
char path[MAXPATHLEN];
char uuidstr[UUID_PRINTABLE_STRING_LENGTH];
- size_t tlen;
+ size_t tlen, namelen;
+ const char *zone_name, *zone_state, *zone_path, *zone_uuid;
assert(ze != NULL);
if (operation == PZE_ADD &&
@@ -324,104 +322,128 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
goto error;
}
- /*
- * We need to quote a path which contains a ":"; this should only
- * affect the zonepath, as zone names do not allow such characters,
- * and zone states do not have them either. Same with double-quotes
- * themselves: they are not allowed in zone names, and do not occur
- * in zone states, and in theory should never occur in a zonepath
- * since zonecfg does not support a method for escaping them.
- */
- need_quotes = (strchr(ze->zone_path, ':') != NULL);
-
- /*
- * If this zone doesn't yet have a unique identifier, then give it one.
- */
- if (uuid_is_null(ze->zone_uuid))
- uuid_generate(ze->zone_uuid);
- uuid_unparse(ze->zone_uuid, uuidstr);
-
- (void) snprintf(line, sizeof (line), "%s:%s:%s%s%s:%s\n",
- ze->zone_name, zone_state_str(ze->zone_state),
- need_quotes ? "\"" : "", ze->zone_path, need_quotes ? "\"" : "",
- uuidstr);
+ exist = B_FALSE;
+ zone_name = ze->zone_name;
+ namelen = strlen(zone_name);
for (;;) {
if (fgets(buf, sizeof (buf), index_file) == NULL) {
- if (operation == PZE_ADD && !exists)
- (void) fputs(line, tmp_file);
+ if (operation == PZE_ADD && !exist) {
+ zone_state = zone_state_str(ze->zone_state);
+ zone_path = ze->zone_path;
+ zone_uuid = "";
+ goto add_entry;
+ }
+ /*
+ * It's not considered an error to delete something
+ * that doesn't exist, but we can't modify a missing
+ * record.
+ */
+ if (operation == PZE_MODIFY && !exist) {
+ err = Z_UPDATING_INDEX;
+ goto error;
+ }
break;
}
- (void) strlcpy(orig_buf, buf, sizeof (orig_buf));
- if ((cp = strpbrk(buf, "\r\n")) == NULL) {
- /* this represents a line that's too long */
+ if (buf[0] == '#') {
+ /* skip and preserve comment lines */
+ (void) fputs(buf, tmp_file);
continue;
}
- *cp = '\0';
- cp = buf;
- if (*cp == '#') {
- /* skip comment lines */
- (void) fputs(orig_buf, tmp_file);
+
+ if (strncmp(buf, zone_name, namelen) != 0 ||
+ buf[namelen] != ':') {
+ /* skip and preserve non-target lines */
+ (void) fputs(buf, tmp_file);
continue;
}
- p = gettok(&cp);
- if (*p == '\0' || strlen(p) >= ZONENAME_MAX) {
- /*
- * empty or very long zone names are not allowed
- */
+
+ if ((cp = strpbrk(buf, "\r\n")) == NULL) {
+ /* this represents a line that's too long; delete */
continue;
}
- (void) strlcpy(zone, p, ZONENAME_MAX);
+ *cp = '\0';
- if (strcmp(zone, ze->zone_name) == 0) {
- exists = B_TRUE; /* already there */
- if (operation == PZE_ADD) {
- /* can't add same zone */
- err = Z_UPDATING_INDEX;
- 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) {
- /* use specified values */
- (void) fputs(line, tmp_file);
- continue;
- }
- /* use existing value for state */
- p = gettok(&cp);
- if (*p == '\0') {
- /* state field should not be empty */
- err = Z_UPDATING_INDEX;
- goto error;
- }
- (void) strlcpy(tmp_state,
- (ze->zone_state < 0) ? p :
- zone_state_str(ze->zone_state),
- sizeof (tmp_state));
-
- p = gettok(&cp);
+ /*
+ * Skip over the zone name. Because we've already matched the
+ * target zone (above), we know for certain here that the zone
+ * name is present and correctly formed. No need to check.
+ */
+ cp = strchr(buf, ':') + 1;
+
+ zone_state = gettok(&cp);
+ if (*zone_state == '\0') {
+ /* state field should not be empty */
+ err = Z_UPDATING_INDEX;
+ goto error;
+ }
+ zone_path = gettok(&cp);
+ zone_uuid = gettok(&cp);
+
+ switch (operation) {
+ case PZE_ADD:
+ /* can't add same zone */
+ err = Z_UPDATING_INDEX;
+ goto error;
+
+ case PZE_MODIFY:
+ /*
+ * If the caller specified a new state for the zone,
+ * then use that. Otherwise, use the current state.
+ */
+ if (ze->zone_state >= 0) {
+ zone_state = zone_state_str(ze->zone_state);
/*
- * If a new name is supplied, use it.
+ * If the caller is uninstalling this zone,
+ * then wipe out the uuid. The zone's contents
+ * are no longer known.
*/
- 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:%s\n",
- tmp_name, tmp_state,
- need_quotes ? "\"" : "",
- (strlen(ze->zone_path) == 0) ? p :
- ze->zone_path, need_quotes ? "\"" : "",
- uuidstr);
+ if (ze->zone_state < ZONE_STATE_INSTALLED)
+ zone_uuid = "";
}
- /* else if (operation == PZE_REMOVE) { no-op } */
- } else {
- (void) fputs(orig_buf, tmp_file);
+
+ /* If a new name is supplied, use it. */
+ if (ze->zone_newname[0] != '\0')
+ zone_name = ze->zone_newname;
+
+ if (ze->zone_path[0] != '\0')
+ zone_path = ze->zone_path;
+ break;
+
+ case PZE_REMOVE:
+ default:
+ continue;
+ }
+
+ add_entry:
+ /*
+ * If the entry in the file is in greater than configured
+ * state, then we must have a UUID. Make sure that we do.
+ * (Note that the file entry is only tokenized, not fully
+ * parsed, so we need to do a string comparison here.)
+ */
+ if (strcmp(zone_state, ZONE_STATE_STR_CONFIGURED) != 0 &&
+ *zone_uuid == '\0') {
+ if (uuid_is_null(ze->zone_uuid))
+ uuid_generate(ze->zone_uuid);
+ uuid_unparse(ze->zone_uuid, uuidstr);
+ zone_uuid = uuidstr;
}
+ /*
+ * We need to quote a path that contains a ":"; this should
+ * only affect the zonepath, as zone names do not allow such
+ * characters, and zone states do not have them either. Same
+ * with double-quotes themselves: they are not allowed in zone
+ * names, and do not occur in zone states, and in theory should
+ * never occur in a zonepath since zonecfg does not support a
+ * method for escaping them.
+ */
+ need_quotes = (strchr(zone_path, ':') != NULL);
+ (void) fprintf(tmp_file, "%s:%s:%s%s%s:%s\n", zone_name,
+ zone_state, need_quotes ? "\"" : "", zone_path,
+ need_quotes ? "\"" : "", zone_uuid);
+ exist = B_TRUE;
}
(void) fclose(index_file);
diff --git a/usr/src/pkgdefs/SUNWzoner/postinstall b/usr/src/pkgdefs/SUNWzoner/postinstall
new file mode 100644
index 0000000000..864f7f129b
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWzoner/postinstall
@@ -0,0 +1,54 @@
+#!/usr/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# 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.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+# Detect and repair any UUID duplicates.
+index=$BASEDIR/etc/zones/index
+if [ -f $index ]; then
+ if nawk -F: '
+ /^\#/ || NF != 4 { print $0; next; }
+ {
+ if (flags[$4])
+ sub(/:[-0-9a-z]*$/,":");
+ print $0;
+ flags[$4]=1;
+ }
+ ' < $index > ${index}.pkg.$$; then
+ if cmp -s $index ${index}.pkg.$$; then
+ rm -f ${index}.pkg.$$
+ else
+ chown root:sys ${index}.pkg.$$
+ chmod 644 ${index}.pkg.$$
+ mv ${index}.pkg.$$ $index
+ fi
+ else
+ rm -f ${index}.pkg.$$
+ fi
+fi
+
+exit 0
diff --git a/usr/src/pkgdefs/SUNWzoner/prototype_com b/usr/src/pkgdefs/SUNWzoner/prototype_com
index 3b81942c4c..e2c70b4240 100644
--- a/usr/src/pkgdefs/SUNWzoner/prototype_com
+++ b/usr/src/pkgdefs/SUNWzoner/prototype_com
@@ -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 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -40,6 +39,7 @@
i pkginfo
i copyright
i depend
+i postinstall
i i.preserve
i i.manifest
i r.manifest
diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh
index dc15a45252..423dbabc88 100644
--- a/usr/src/tools/scripts/bfu.sh
+++ b/usr/src/tools/scripts/bfu.sh
@@ -6089,6 +6089,34 @@ mondo_loop() {
disable_boot_service
fi
fi
+
+ # Check for damage due to CR 6379341. This was actually fixed
+ # back in snv_24, but users BFUing from an S10 build up to
+ # Nevada can still encounter it.
+ rzi=$root/etc/zones/index
+ if [ -f $rzi ]; then
+ # Look for duplicated UUIDs. If there are any, then
+ # just wipe them out.
+ if nawk -F: '
+ /^\#/ || NF != 4 { print $0; next; }
+ {
+ if (flags[$4])
+ sub(/:[-0-9a-z]*$/,":");
+ print $0;
+ flags[$4]=1;
+ }
+ ' < $rzi > ${rzi}.bfu.$$; then
+ if cmp -s $rzi ${rzi}.bfu.$$; then
+ rm -f ${rzi}.bfu.$$
+ else
+ chown root:sys ${rzi}.bfu.$$
+ chmod 644 ${rzi}.bfu.$$
+ mv ${rzi}.bfu.$$ $rzi
+ fi
+ else
+ rm -f ${rzi}.bfu.$$
+ fi
+ fi
fi