--- a/usr/src/cmd/auto-install/auto_parse.c Tue Aug 17 18:22:44 2010 -0400
+++ b/usr/src/cmd/auto-install/auto_parse.c Fri Aug 20 11:31:18 2010 -0600
@@ -79,9 +79,10 @@
/*
* Dump errors found during syntactic validation of AI manifest -
- * capture stdout and stderr of xmllint(1M) called with following parameters:
+ * repeat the xmllint(1) call made on the Python side to capture the
+ * stdout and stderr. xmllint will be called with following parameters:
*
- * /usr/bin/xmllint --noout --relaxng <schema> <manifest> 2>&1
+ * /usr/bin/xmllint --noout --dtdvalid <schema> --dtdattr <manifest> 2>&1
*
* Returns
* -1 - failed to dump syntactic errors
@@ -93,13 +94,12 @@
char *cmd;
size_t cmd_ln;
int ret;
+ char *dtd_xmllint =
+ "/usr/bin/xmllint --noout --dtdvalid %s --dtdattr %s 2>&1";
- /* calculate size of command string - account for string terminator */
- cmd_ln = sizeof ("/usr/bin/xmllint --noout --relaxng ") +
- strlen(manifest) + sizeof (" ") + strlen(schema) +
- sizeof (" 2>&1") + 1;
-
- cmd = malloc(cmd_ln);
+ /* calculate size of command string */
+ cmd_ln = snprintf(NULL, 0, dtd_xmllint, schema, manifest);
+ cmd = (char *)malloc(cmd_ln + 1);
if (cmd == NULL) {
auto_debug_print(AUTO_DBGLVL_ERR, "malloc() failed\n");
@@ -107,8 +107,7 @@
return (-1);
}
- (void) snprintf(cmd, cmd_ln,
- "/usr/bin/xmllint --noout --relaxng %s %s 2>&1", schema, manifest);
+ (void) snprintf(cmd, cmd_ln + 1, dtd_xmllint, schema, manifest);
ret = ai_exec_cmd(cmd);
@@ -126,6 +125,115 @@
}
/*
+ * Translate size units from manifest into auto_size_units_t values.
+ *
+ * Defaults to AI_SIZE_UNITS_MEGABYTES if no value given or value
+ * not recognized.
+ *
+ * Returns
+ * auto_size_units_t
+ */
+static auto_size_units_t
+get_size_units(char *p_str)
+{
+ if ((p_str == NULL) || (! strlen(p_str))) {
+ return (AI_SIZE_UNITS_MEGABYTES);
+ }
+
+ switch (p_str[0]) {
+ case 's':
+ case 'S':
+ return (AI_SIZE_UNITS_SECTORS);
+ case 'g':
+ case 'G':
+ return (AI_SIZE_UNITS_GIGABYTES);
+ case 't':
+ case 'T':
+ return (AI_SIZE_UNITS_TERABYTES);
+ case 'm':
+ case 'M':
+ default:
+ return (AI_SIZE_UNITS_MEGABYTES);
+ }
+}
+
+/*
+ * Convert size from one unit of measurement to another.
+ *
+ * Supported units are the auto_size_units_t enumeration:
+ * AI_SIZE_UNITS_SECTORS
+ * AI_SIZE_UNITS_MEGABYTES
+ * AI_SIZE_UNITS_GIGABYTES
+ * AI_SIZE_UNITS_TERABYTES
+ * If either from_units or to_units params are not recognized, disk_size is
+ * returned unaltered.
+ *
+ * Returns
+ * uint64_t
+ */
+static uint64_t
+convert_disk_size(uint64_t disk_size, auto_size_units_t from_units,
+ auto_size_units_t to_units)
+{
+ uint64_t retval = disk_size;
+
+ switch (to_units) {
+ case AI_SIZE_UNITS_SECTORS:
+ switch (from_units) {
+ case AI_SIZE_UNITS_SECTORS:
+ retval = disk_size;
+ case AI_SIZE_UNITS_MEGABYTES:
+ retval = disk_size * MB_TO_SECTORS;
+ case AI_SIZE_UNITS_GIGABYTES:
+ retval = disk_size * GB_TO_MB *
+ MB_TO_SECTORS;
+ case AI_SIZE_UNITS_TERABYTES:
+ retval = disk_size * TB_TO_GB *
+ GB_TO_MB * MB_TO_SECTORS;
+ }
+ case AI_SIZE_UNITS_MEGABYTES:
+ switch (from_units) {
+ case AI_SIZE_UNITS_SECTORS:
+ retval = disk_size / MB_TO_SECTORS;
+ case AI_SIZE_UNITS_MEGABYTES:
+ retval = disk_size;
+ case AI_SIZE_UNITS_GIGABYTES:
+ retval = disk_size * GB_TO_MB;
+ case AI_SIZE_UNITS_TERABYTES:
+ retval = disk_size * TB_TO_GB *
+ GB_TO_MB;
+ }
+ case AI_SIZE_UNITS_GIGABYTES:
+ switch (from_units) {
+ case AI_SIZE_UNITS_SECTORS:
+ retval = disk_size / GB_TO_MB /
+ MB_TO_SECTORS;
+ case AI_SIZE_UNITS_MEGABYTES:
+ retval = disk_size / GB_TO_MB;
+ case AI_SIZE_UNITS_GIGABYTES:
+ retval = disk_size;
+ case AI_SIZE_UNITS_TERABYTES:
+ retval = disk_size * TB_TO_GB;
+ }
+ case AI_SIZE_UNITS_TERABYTES:
+ switch (from_units) {
+ case AI_SIZE_UNITS_SECTORS:
+ retval = disk_size / MB_TO_SECTORS /
+ GB_TO_MB / TB_TO_GB;
+ case AI_SIZE_UNITS_MEGABYTES:
+ retval = disk_size / GB_TO_MB /
+ TB_TO_GB;
+ case AI_SIZE_UNITS_GIGABYTES:
+ retval = disk_size / TB_TO_GB;
+ case AI_SIZE_UNITS_TERABYTES:
+ retval = disk_size;
+ }
+ }
+
+ return (retval);
+}
+
+/*
* Create the manifest data image in memory. (Does not validate it.)
*
* Import the manifest into an in-memory tree
@@ -226,18 +334,6 @@
ai_free_manifest_value_list(value_list);
}
-static char **
-ai_get_manifest_partition_action(int *len)
-{
- char **value;
-
- value = ai_get_manifest_values(AIM_PARTITION_ACTION, len);
-
- if (*len > 0)
- return (value);
- return (NULL);
-}
-
/*
* ai_get_manifest_element_value() - return value given xml element
*/
@@ -288,6 +384,10 @@
{
char *p;
+ p = ai_get_manifest_element_value(AIM_TARGET_DISK_KEYWORD);
+ if (p != NULL)
+ (void) strncpy(adi->diskkeyword, p, sizeof (adi->diskkeyword));
+
p = ai_get_manifest_element_value(AIM_TARGET_DEVICE_NAME);
if (p != NULL)
(void) strncpy(adi->diskname, p, sizeof (adi->diskname));
@@ -314,27 +414,57 @@
sizeof (adi->diskdevicepath));
p = ai_get_manifest_element_value(AIM_TARGET_DEVICE_SIZE);
- if (p != NULL)
- adi->disksize = (uint64_t)strtoull(p, NULL, 0);
+ if (p != NULL) {
+ char *endptr;
+ uint64_t disk_size;
+ auto_size_units_t size_units;
+
+ errno = 0;
+
+ /* Get the numerical portion of the size value */
+ disk_size = (uint64_t)strtoull(p, &endptr, 0);
+
+ if (errno == 0 && endptr != p) {
+ /*
+ * Get the units portion of the size val and then
+ * convert the size from given units into number
+ * of disk sectors.
+ */
+ size_units = get_size_units(endptr);
+ adi->disksize = convert_disk_size(disk_size, size_units,
+ AI_SIZE_UNITS_SECTORS);
+
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "Requested target size [%s] converted "
+ "to [%lld] sectors\n",
+ p, adi->disksize);
+ } else {
+ auto_log_print(
+ "Invalid target device size specified: [%s]",
+ p);
+ return (AUTO_INSTALL_FAILURE);
+ }
+ }
p = ai_get_manifest_element_value(
AIM_TARGET_DEVICE_USE_SOLARIS_PARTITION);
if (p != NULL) {
#ifdef __sparc
auto_log_print("Warning: ignoring manifest element "
- "target_device_use_solaris_partition on SPARC\n");
+ "partition action='use_existing' on SPARC\n");
#else
- (void) strncpy(adi->diskusepart, p, sizeof (adi->diskusepart));
+ /*
+ * In this Schema, a partition with attribute
+ * action="use_existing" corresponds to
+ * target_device_use_solaris_partition="true"
+ * in the previous schema.
+ */
+ (void) strncpy(adi->diskusepart, "true",
+ sizeof (adi->diskusepart));
#endif
}
p = ai_get_manifest_element_value(
- AIM_TARGET_DEVICE_OVERWRITE_ROOT_ZFS_POOL);
- if (p != NULL)
- (void) strncpy(adi->diskoverwrite_rpool, p,
- sizeof (adi->diskoverwrite_rpool));
-
- p = ai_get_manifest_element_value(
AIM_TARGET_DEVICE_INSTALL_SLICE_NUMBER);
if (p != NULL) {
int install_slice_number;
@@ -367,24 +497,6 @@
adi->diskiscsi.port = strtoll(p, NULL, 0);
p = ai_get_manifest_element_value(
- AIM_TARGET_DEVICE_ISCSI_TARGET_CHAP_NAME);
- if (p != NULL)
- (void) strncpy(adi->diskiscsi.chapname, p,
- sizeof (adi->diskiscsi.chapname));
-
- p = ai_get_manifest_element_value(
- AIM_TARGET_DEVICE_ISCSI_TARGET_CHAP_SECRET);
- if (p != NULL)
- (void) strncpy(adi->diskiscsi.chapsecret, p,
- sizeof (adi->diskiscsi.chapsecret));
-
- p = ai_get_manifest_element_value(
- AIM_TARGET_DEVICE_ISCSI_TARGET_INITIATOR);
- if (p != NULL)
- (void) strncpy(adi->diskiscsi.initiator, p,
- sizeof (adi->diskiscsi.initiator));
-
- p = ai_get_manifest_element_value(
AIM_TARGET_DEVICE_ISCSI_PARAMETER_SOURCE);
if (p == NULL)
adi->diskiscsi.parm_src = AI_ISCSI_PARM_SRC_MANIFEST;
@@ -404,6 +516,43 @@
}
}
+ /* Debug - print disk info out to log */
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "Disk info from Manifest:\n");
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskkeyword\t\t\t: [%s]\n", adi->diskkeyword);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskname\t\t\t: [%s]\n", adi->diskname);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdisktype\t\t\t: [%s]\n", adi->disktype);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskvendor\t\t\t: [%s]\n", adi->diskvendor);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskvolname\t\t\t: [%s]\n", adi->diskvolname);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskdevid\t\t\t: [%s]\n", adi->diskdevid);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskdevicepath\t\t: [%s]\n", adi->diskdevicepath);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdisksize\t\t\t: [%d]\n", adi->disksize);
+#ifndef __sparc
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskusepart\t\t\t: [%s]\n", adi->diskusepart);
+#endif
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskiscsi.name\t\t: [%s]\n", adi->diskiscsi.name);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskiscsi.ip\t\t: [%s]\n", adi->diskiscsi.ip);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskiscsi.port\t\t: [%d]\n", adi->diskiscsi.port);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskiscsi.lun\t\t: [%s]\n", adi->diskiscsi.lun);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tdiskiscsi.parm_src\t: [%d] (= %s)\n", adi->diskiscsi.parm_src,
+ adi->diskiscsi.parm_src ? "DHCP" : "MANIFEST");
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tinstall_slice_num.\t: [%d]\n", adi->install_slice_number);
+
return (AUTO_INSTALL_SUCCESS);
}
@@ -422,10 +571,28 @@
adsi->swap_size = -1;
p = ai_get_manifest_element_value(AIM_SWAP_SIZE);
if (p != NULL) {
- if (sscanf(p, "%ld", &adsi->swap_size) > 0) {
+ char *endptr;
+ int32_t swap_size;
+ auto_size_units_t size_units;
+
+ errno = 0;
+
+ /* Get the numerical portion of the size value */
+ swap_size = (int32_t)strtol(p, &endptr, 0);
+
+ if (errno == 0 && endptr != p) {
+ /*
+ * Get the units portion of the size val and
+ * then convert the size from given units into MB.
+ */
+ size_units = get_size_units(endptr);
+ adsi->swap_size = (int32_t)convert_disk_size(swap_size,
+ size_units,
+ AI_SIZE_UNITS_MEGABYTES);
+
auto_debug_print(AUTO_DBGLVL_INFO,
- "Swap Size Requested=%lu\n",
- adsi->swap_size);
+ "Requested swap size [%s] converted to [%d] MB\n",
+ p, adsi->swap_size);
} else {
adsi->swap_size = 0;
auto_log_print("Invalid swap size "
@@ -454,10 +621,28 @@
addi->dump_size = -1;
p = ai_get_manifest_element_value(AIM_DUMP_SIZE);
if (p != NULL) {
- if (sscanf(p, "%ld", &addi->dump_size) > 0) {
+ char *endptr;
+ int32_t dump_size;
+ auto_size_units_t size_units;
+
+ errno = 0;
+
+ /* Get the numerical portion of the size value */
+ dump_size = (int32_t)strtol(p, &endptr, 0);
+
+ if (errno == 0 && endptr != p) {
+ /*
+ * Get the units portion of the size val and
+ * then convert the size from given units into MB.
+ */
+ size_units = get_size_units(endptr);
+ addi->dump_size = (int32_t)convert_disk_size(dump_size,
+ size_units,
+ AI_SIZE_UNITS_MEGABYTES);
+
auto_debug_print(AUTO_DBGLVL_INFO,
- "Dump Size Requested=%lu\n",
- addi->dump_size);
+ "Requested dump size [%s] converted to [%d] MB\n",
+ p, addi->dump_size);
} else {
addi->dump_size = 0;
auto_log_print("Invalid dump device size "
@@ -472,6 +657,167 @@
}
/*
+ * Create a partition info struct and populate it with details
+ * from the manifest matching the specified tags (enhanced
+ * nodepaths).
+ *
+ * pstatus - return status pointer, must point to valid storage
+ * If no problems in validating partition info,
+ * set to zero, otherwise set to non-zero value
+ *
+ * This function allocates memory for an auto_partition_info
+ * struct. The caller MUST free this memory.
+ */
+static auto_partition_info *
+get_partition_by_tags(char *number_tag, char *action_tag,
+ char *start_tag, char *size_tag, char *type_tag, int *pstatus)
+{
+ auto_partition_info *api;
+ char *p;
+ char *endptr;
+
+ api = calloc(sizeof (auto_partition_info), 1);
+ if (api == NULL)
+ return (NULL);
+
+ /* Get the name (number) for this partition */
+ p = ai_get_manifest_element_value(number_tag);
+ if (p != NULL) {
+ errno = 0;
+ api->partition_number = (int) strtoul(p, &endptr, 10);
+ if (errno != 0 || endptr == p) {
+ auto_debug_print(AUTO_DBGLVL_ERR,
+ "Partition name in manifest (%s) is "
+ "not a valid value.\n",
+ p);
+ *pstatus = 1;
+ free(api);
+ errno = 0;
+ return (NULL);
+ }
+ }
+
+ /* Get the action for this partition */
+ p = ai_get_manifest_element_value(action_tag);
+ if (p != NULL)
+ (void) strlcpy(api->partition_action, p,
+ sizeof (api->partition_action));
+
+ /*
+ * Get the start_sector for this partition
+ *
+ * set default for starting sector (unspecified)
+ * stored as unsigned in C, * but signed in XML
+ * so that -1 can be used in default value manifest
+ * to tell AI to find best location when starting sector not specified
+ * see om_create_partition()
+ */
+ api->partition_start_sector = (uint64_t)-1LL;
+ p = ai_get_manifest_element_value(start_tag);
+ if (p != NULL) {
+ api->partition_start_sector =
+ (uint64_t)strtoll(p, NULL, 0);
+ }
+
+ /*
+ * Get the size (value + units) for this partition.
+ * This is only used for "create" action.
+ */
+ if (strcmp(api->partition_action, "create") == 0) {
+ p = ai_get_manifest_element_value(size_tag);
+ if (p != NULL) {
+ errno = 0;
+
+ /* Get the numerical portion of the size value */
+ api->partition_size = strtoull(p, &endptr, 0);
+
+ if (errno == 0 && endptr != p) {
+ /* Get the units portion of the size value */
+ api->partition_size_units =
+ get_size_units(endptr);
+ } else {
+ auto_debug_print(AUTO_DBGLVL_ERR,
+ "Partition size in manifest (%s) is "
+ "not a valid value.\n",
+ p);
+ *pstatus = 1;
+ free(api);
+ errno = 0;
+ return (NULL);
+ }
+ } else {
+ /*
+ * Default to 0mb. This is not strictly necessary,
+ * as both these values correspond to 0, which was
+ * the value they were already set to when the struct
+ * was calloc()ed.
+ */
+ api->partition_size = (uint64_t) 0;
+ api->partition_size_units = AI_SIZE_UNITS_MEGABYTES;
+ }
+ }
+
+ /* Get the filesystem type for this partition */
+ p = ai_get_manifest_element_value(type_tag);
+ if (p != NULL) {
+ /* allow some common partition type names */
+ if (strcasecmp(p, "SOLARIS") == 0) {
+ api->partition_type = SUNIXOS2;
+ auto_log_print(
+ "New Solaris2 partition requested\n");
+ } else if (strcasecmp(p, "DOS16") == 0) {
+ api->partition_type = DOSOS16;
+ auto_log_print(
+ "New 16-bit DOS partition requested\n");
+ } else if (strcasecmp(p, "FAT32") == 0) {
+ api->partition_type = FDISK_WINDOWS;
+ auto_log_print(
+ "New FAT32 partition requested\n");
+ } else if (strcasecmp(p, "DOSEXT") == 0) {
+ api->partition_type = EXTDOS;
+ auto_log_print(
+ "New DOS extended partition requested\n");
+ } else if (strcasecmp(p, "DOSEXTLBA") == 0) {
+ api->partition_type = FDISK_EXTLBA;
+ auto_log_print(
+ "New DOS extended LBA partition requested"
+ "\n");
+ } else {
+ /*
+ * Use partition type number, eg "191" to
+ * represent a Solaris partition.
+ */
+ char *endptr;
+
+ errno = 0;
+ api->partition_type =
+ strtoull(p, &endptr, 0);
+ if (errno != 0 || endptr == p) {
+ auto_debug_print(AUTO_DBGLVL_ERR,
+ "Partition type in manifest (%s) is "
+ "not a valid number or partition type.\n",
+ p);
+ *pstatus = 1;
+ free(api);
+ errno = 0;
+ return (NULL);
+ }
+ }
+ }
+
+ /*
+ * Determine if this is a logical partition
+ * This is inferred from the partition number. Numbers of
+ * 5 or greater imply the partition must be logical.
+ */
+ if (api->partition_number >= 5) {
+ api->partition_is_logical = B_TRUE;
+ }
+
+ return (api);
+}
+
+/*
* Retrieve the information about the partitions
* that need to be configured
*
@@ -485,189 +831,245 @@
auto_partition_info *
ai_get_manifest_partition_info(int *pstatus)
{
+ auto_partition_info *ret_api;
auto_partition_info *api;
- int i, len;
- char **p;
+ int i, j;
+ int actions_len = 0;
+ int numbered_len = 0;
+ int unnumbered_len = 0;
+ char **partition_actions;
+ char **numbered_partitions;
+ char **unnumbered_partitions;
+ char *p;
+ char number_tag[MAXPATHLEN];
+ char action_tag[MAXPATHLEN];
+ char start_tag[MAXPATHLEN];
+ char size_tag[MAXPATHLEN];
+ char type_tag[MAXPATHLEN];
*pstatus = 0; /* assume no parsing errors */
- p = ai_get_manifest_partition_action(&len);
- if (p == NULL)
+ /*
+ * The name (number) is not mandatory for partitions, but if a partition
+ * does not have a name then it must have the action 'use_existing'.
+ * There can only be one 'use_existing' partition specified and it may
+ * or may not be named.
+ * We will first see if there is an un-named 'use_existing' partition
+ * in the manifest and if so, fetch its details. Then we will fetch
+ * details for all the named partitions, using name+action as a unique
+ * key.
+ */
+
+ unnumbered_partitions = ai_get_manifest_values(
+ AIM_USE_EXISTING_PARTITIONS, &unnumbered_len);
+ numbered_partitions = ai_get_manifest_values(
+ AIM_NUMBERED_PARTITIONS, &numbered_len);
+
+ if (unnumbered_partitions == NULL) {
+ /* ai_get_manifest_values sets len to -1 if none found */
+ unnumbered_len = 0;
+ } else {
+ if (unnumbered_len > 1) {
+ auto_debug_print(AUTO_DBGLVL_ERR,
+ "Only one 'use_existing' partition is permitted, "
+ "%d were specified.\n", unnumbered_len);
+ *pstatus = 1;
+ return (NULL);
+ }
+
+ p = ai_get_manifest_element_value(
+ AIM_UNNUMBERED_PARTITION_NUMBER);
+ if (p != NULL) {
+ /*
+ * There is one 'use_existing' partition but a
+ * name (number) was specified with it, so it
+ * will be handled along with numbered
+ * partitions - no need for specical handling here.
+ */
+ unnumbered_len = 0;
+ }
+ }
+
+ if (numbered_partitions == NULL) {
+ /* ai_get_manifest_values sets len to -1 if none found */
+ numbered_len = 0;
+ }
+
+ if ((unnumbered_len + numbered_len) == 0)
return (NULL);
/* len+1 -- '1' for the NULL entry */
- api = calloc(sizeof (auto_partition_info), len + 1);
+ ret_api = calloc(sizeof (auto_partition_info),
+ numbered_len + unnumbered_len + 1);
+ if (ret_api == NULL)
+ return (NULL);
- for (i = 0; i < len; i++) {
- if (strlcpy((api + i)->partition_action, p[i],
- AUTO_MAX_ACTION_LEN) >= AUTO_MAX_ACTION_LEN) {
- auto_debug_print(AUTO_DBGLVL_ERR,
- "Partition action in manifest is too long (%s)\n",
- p[i]);
- *pstatus = 1;
- free(api);
+ if (unnumbered_len) {
+ /*
+ * We have exactly one partition whose action is 'use_existing'
+ * which does not have a name (number) specified. We need
+ * to fetch its details seperately from the numbered partitions.
+ */
+ (void) snprintf(number_tag, sizeof (number_tag),
+ AIM_UNNUMBERED_PARTITION_NUMBER);
+ (void) snprintf(action_tag, sizeof (action_tag),
+ AIM_UNNUMBERED_PARTITION_ACTION);
+ (void) snprintf(start_tag, sizeof (start_tag),
+ AIM_UNNUMBERED_PARTITION_START_SECTOR);
+ (void) snprintf(size_tag, sizeof (size_tag),
+ AIM_UNNUMBERED_PARTITION_SIZE);
+ (void) snprintf(type_tag, sizeof (type_tag),
+ AIM_UNNUMBERED_PARTITION_TYPE);
+
+ api = get_partition_by_tags(number_tag, action_tag,
+ start_tag, size_tag, type_tag, pstatus);
+
+ if (api == NULL) {
+ free(unnumbered_partitions);
+ free(ret_api);
return (NULL);
}
- }
- free(p);
- p = get_manifest_element_array(AIM_PARTITION_NUMBER);
- if (p != NULL) {
- for (i = 0; i < len; i++) {
- (api + i)->partition_number = atoi(p[i]);
- }
- free(p);
+ (void) memcpy(ret_api, api, sizeof (auto_partition_info));
+ free(api);
+
+ free(unnumbered_partitions);
}
- /*
- * set default for starting sector (unspecified)
- * stored as unsigned in C, * but signed in XML
- * so that -1 can be used in default value manifest
- * to tell AI to find best location when starting sector not specified
- * see om_create_partition()
- */
- for (i = 0; i < len; i++) /* if not specified, AI finds best location */
- (api + i)->partition_start_sector = (uint64_t)-1LL;
- p = get_manifest_element_array(AIM_PARTITION_START_SECTOR);
- if (p != NULL) {
- for (i = 0; i < len; i++) {
- (api + i)->partition_start_sector =
- (uint64_t)strtoll(p[i], NULL, 0);
+ if (numbered_len) {
+ partition_actions = ai_get_manifest_values(
+ AIM_PARTITION_ACTIONS, &actions_len);
+
+ if (partition_actions == NULL) {
+ auto_debug_print(AUTO_DBGLVL_ERR,
+ "Error fetching partition actions.\n");
+ *pstatus = 1;
+ free(numbered_partitions);
+ free(ret_api);
+ return (NULL);
}
- free(p);
- }
- p = get_manifest_element_array(AIM_PARTITION_SIZE);
- if (p != NULL) {
- for (i = 0; i < len; i++) {
- /* if action is create, size is mandatory */
- if (strcmp((api + i)->partition_action, "create") != 0)
- continue;
- if (p[i] == NULL) { /* if size not provided */
- /* size required for create action */
+ if (unnumbered_len) {
+ /*
+ * Remove the unnamed 'use_existing' partition from
+ * partition_actions.
+ */
+ for (i = 0; i < actions_len; i++) {
+ if (strcmp(partition_actions[i],
+ "use_existing") == 0) {
+ /*
+ * Shuffle the remaining items up
+ * one position.
+ */
+ for (j = i; j < (actions_len - 1);
+ j++) {
+ partition_actions[j] =
+ partition_actions[j+1];
+ }
+ partition_actions[actions_len] = NULL;
+ actions_len--;
+ }
+ }
+ }
+
+ if (numbered_len != actions_len) {
+ if (numbered_len < actions_len) {
+ /*
+ * If this mismatch occurs, there must have
+ * been an unnamed partion whose action is
+ * not 'use_existing'.
+ */
auto_debug_print(AUTO_DBGLVL_ERR,
- "Partition size for create action "
- "is missing from manifest.\n");
+ "Invalid unnamed partition specified in "
+ "manifest. Only one unnamed partition "
+ "allowed, whose action must be "
+ "'use_existing'.\n");
*pstatus = 1;
- free(api);
+ free(numbered_partitions);
+ free(partition_actions);
+ free(ret_api);
return (NULL);
- }
- if (strcasecmp(p[i], "max_size") == 0) {
- (api + i)->partition_size = OM_MAX_SIZE;
- /* zero will indicate maximum size */
- auto_log_print("Maximum size requested for "
- "new partition. (%d)\n", i);
} else {
- char *endptr;
-
- errno = 0;
- (api + i)->partition_size =
- strtoull(p[i], &endptr, 0);
- if (errno == 0 && endptr != p[i])
- continue;
auto_debug_print(AUTO_DBGLVL_ERR,
- "Partition size in manifest (%s) is "
- "not a valid number or \"max_size\".\n",
- p[i]);
+ "Error matching partition actions to "
+ "names.\n");
*pstatus = 1;
- free(api);
- errno = 0;
+ free(numbered_partitions);
+ free(partition_actions);
+ free(ret_api);
return (NULL);
}
}
- free(p);
- }
- p = get_manifest_element_array(AIM_PARTITION_TYPE);
- if (p != NULL) {
- for (i = 0; i < len; i++) {
- /* allow some common partition type names */
- if (strcasecmp(p[i], "SOLARIS") == 0) {
- (api + i)->partition_type = SUNIXOS2;
- auto_log_print(
- "New Solaris2 partition requested\n");
- } else if (strcasecmp(p[i], "DOS16") == 0) {
- (api + i)->partition_type = DOSOS16;
- auto_log_print(
- "New 16-bit DOS partition requested\n");
- } else if (strcasecmp(p[i], "FAT32") == 0) {
- (api + i)->partition_type = FDISK_WINDOWS;
- auto_log_print(
- "New FAT32 partition requested\n");
- } else if (strcasecmp(p[i], "DOSEXT") == 0) {
- (api + i)->partition_type = EXTDOS;
- auto_log_print(
- "New DOS extended partition requested\n");
- } else if (strcasecmp(p[i], "DOSEXTLBA") == 0) {
- (api + i)->partition_type = FDISK_EXTLBA;
- auto_log_print(
- "New DOS extended LBA partition requested"
- "\n");
- } else { /* use partition type number */
- char *endptr;
+ /*
+ * One or more numbered partitions have been specified.
+ * Fetch the necessary details for each.
+ */
+ for (i = 0; i < numbered_len; i++) {
+ (void) snprintf(number_tag, sizeof (number_tag),
+ AIM_NUMBERED_PARTITION_NUMBER,
+ numbered_partitions[i], partition_actions[i]);
+ (void) snprintf(action_tag, sizeof (action_tag),
+ AIM_NUMBERED_PARTITION_ACTION,
+ numbered_partitions[i], partition_actions[i]);
+ (void) snprintf(start_tag, sizeof (start_tag),
+ AIM_NUMBERED_PARTITION_START_SECTOR,
+ numbered_partitions[i], partition_actions[i]);
+ (void) snprintf(size_tag, sizeof (size_tag),
+ AIM_NUMBERED_PARTITION_SIZE,
+ numbered_partitions[i], partition_actions[i]);
+ (void) snprintf(type_tag, sizeof (type_tag),
+ AIM_NUMBERED_PARTITION_TYPE,
+ numbered_partitions[i], partition_actions[i]);
- errno = 0;
- (api + i)->partition_type =
- strtoull(p[i], &endptr, 0);
- if (errno == 0 && endptr != p[i])
- continue;
- auto_debug_print(AUTO_DBGLVL_ERR,
- "Partition type in manifest (%s) is "
- "not a valid number or partition type.\n",
- p[i]);
- *pstatus = 1;
- free(api);
- errno = 0;
+ api = get_partition_by_tags(number_tag, action_tag,
+ start_tag, size_tag, type_tag, pstatus);
+
+ if (api == NULL) {
+ free(numbered_partitions);
+ free(ret_api);
return (NULL);
}
+
+ (void) memcpy((ret_api + unnumbered_len + i),
+ api, sizeof (auto_partition_info));
+ free(api);
}
- free(p);
+
+ free(numbered_partitions);
}
- p = get_manifest_element_array(AIM_PARTITION_SIZE_UNITS);
- /* partition size units can be sectors, GB, TB, or MB (default) */
- if (p != NULL) {
- for (i = 0; i < len; i++) {
- if (p[i] == NULL) { /* default to MB */
- (api + i)->partition_size_units =
- AI_SIZE_UNITS_MEGABYTES;
- continue;
- }
- switch (p[i][0]) {
- case 's':
- case 'S':
- (api + i)->partition_size_units =
- AI_SIZE_UNITS_SECTORS;
- break;
- case 'g':
- case 'G':
- (api + i)->partition_size_units =
- AI_SIZE_UNITS_GIGABYTES;
- break;
- case 't':
- case 'T':
- (api + i)->partition_size_units =
- AI_SIZE_UNITS_TERABYTES;
- break;
- case 'm':
- case 'M':
- default:
- (api + i)->partition_size_units =
- AI_SIZE_UNITS_MEGABYTES;
- break;
- }
- }
- free(p);
+ /* Debug - print partition info out to log */
+ api = ret_api;
+ for (; api->partition_action[0] != '\0'; api++) {
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "Partition details from Manifest:\n");
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tpartition_action\t\t: [%s]\n",
+ api->partition_action);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tpartition_number\t\t: [%d]\n",
+ api->partition_number);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tpartition_start_sector\t: [%lld]\n",
+ api->partition_start_sector);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tpartition_size\t\t\t: [%lld]\n",
+ api->partition_size);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tpartition_type\t\t\t: [%d]\n",
+ api->partition_type);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tpartition_size_units\t: [%d] (= %s)\n",
+ (int)api->partition_size_units,
+ CONVERT_UNITS_TO_TEXT(api->partition_size_units));
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tpartition_is_logical\t: [%d] (= %s)\n",
+ (int)api->partition_is_logical,
+ api->partition_is_logical ? "true" : "false");
}
- /*
- * mark any partitions marked as logical
- */
- p = get_manifest_element_array(AIM_PARTITION_IS_LOGICAL);
- if (p != NULL)
- for (i = 0; i < len; i++)
- if (strcasecmp(p[i], "true") == 0)
- (api + i)->partition_is_logical = B_TRUE;
- return (api);
+
+ return (ret_api);
}
/*
@@ -684,133 +1086,154 @@
ai_get_manifest_slice_info(int *pstatus)
{
auto_slice_info *asi;
- int i, len = 0;
- char **p;
+ auto_slice_info *tmp_asi;
+ int i, names_len = 0, actions_len = 0;
+ char *p;
+ char **slice_names;
+ char **slice_actions;
+ char tag[MAXPATHLEN];
+ char *endptr;
*pstatus = 0; /* assume no parsing errors */
- p = ai_get_manifest_values(AIM_SLICE_ACTION, &len);
- if (p == NULL || len <= 0)
+
+ /*
+ * The name (number) and action attributes are mandatory for slices, so
+ * we will use these two values as the unique key for slice elements.
+ * First we fetch all the slice numbers and actions, then we query the
+ * manifest using these values to fetch the additional details for
+ * each slice.
+ */
+
+ slice_names = ai_get_manifest_values(AIM_SLICE_NUMBER, &names_len);
+
+ if (slice_names == NULL || names_len <= 0)
return (NULL);
+ slice_actions = ai_get_manifest_values(AIM_SLICE_ACTION, &actions_len);
+
+ if (actions_len != names_len) {
+ auto_debug_print(AUTO_DBGLVL_ERR,
+ "Error matching slice names to actions.\n");
+ *pstatus = 1;
+ free(slice_names);
+ free(slice_actions);
+ return (NULL);
+ }
+
/* len+1 -- '1' for end of array marker */
- asi = calloc(sizeof (auto_slice_info), len + 1);
+ asi = calloc(sizeof (auto_slice_info), names_len + 1);
- for (i = 0; i < len; i++) {
- if (strlcpy((asi + i)->slice_action, p[i],
- AUTO_MAX_ACTION_LEN) >= AUTO_MAX_ACTION_LEN) {
- auto_debug_print(AUTO_DBGLVL_ERR,
- "Slice action in manifest is too long (%s)\n",
- p[i]);
- *pstatus = 1;
- free(asi);
- return (NULL);
- }
- }
- free(p);
-
- p = get_manifest_element_array(AIM_SLICE_NUMBER);
- if (p != NULL) {
- for (i = 0; i < len; i++) {
- (asi + i)->slice_number = atoi(p[i]);
- }
- free(p);
+ if (asi == NULL) {
+ free(slice_names);
+ free(slice_actions);
+ return (NULL);
}
- p = get_manifest_element_array(AIM_SLICE_SIZE);
- if (p != NULL) {
- for (i = 0; i < len; i++) {
- /* if action is create, size is mandatory */
- if (p[i] == NULL) /* if size not provided */
- /* size required for create action */
- if (strcmp((asi + i)->slice_action, "create")
- != 0)
- continue;
- else {
- auto_debug_print(AUTO_DBGLVL_ERR,
- "Slice size for create action "
- "is missing from manifest.\n");
- *pstatus = 1;
- free(asi);
- return (NULL);
- }
- if (strcasecmp(p[i], "max_size") == 0) {
- (asi + i)->slice_size = OM_MAX_SIZE;
- /* zero will indicate maximum size */
- auto_log_print("Maximum size requested for "
- "new slice. (%d)\n", i);
+ for (i = 0; i < names_len; i++) {
+ /* Get the number for this slice */
+ (asi + i)->slice_number = atoi(slice_names[i]);
+
+ /* Get the action for this slice */
+ if (strlcpy((asi + i)->slice_action, slice_actions[i],
+ AUTO_MAX_ACTION_LEN) >= AUTO_MAX_ACTION_LEN) {
+ auto_debug_print(AUTO_DBGLVL_ERR,
+ "Slice action in manifest is too long (%s)\n", p);
+ *pstatus = 1;
+ free(asi);
+ free(slice_names);
+ free(slice_actions);
+ return (NULL);
+ }
+
+ /* Get the size (value + units) for this slice */
+ (void) snprintf(tag, sizeof (tag), AIM_SLICE_SIZE,
+ slice_names[i], slice_actions[i]);
+ p = ai_get_manifest_element_value(tag);
+ if (p == NULL) {
+ /*
+ * Default to 0mb. This is not strictly necessary,
+ * as both these values correspond to 0, which was
+ * the value they were already set to when the struct
+ * was calloc()ed.
+ */
+ (asi + i)->slice_size = (uint64_t) 0;
+ (asi + i)->slice_size_units = AI_SIZE_UNITS_MEGABYTES;
+ } else {
+ errno = 0;
+
+ /* Get the numerical portion of the size value */
+ (asi + i)->slice_size = strtoull(p, &endptr, 0);
+
+ if (errno == 0 && endptr != p) {
+ /* Get the units portion of the size value */
+ (asi + i)->slice_size_units =
+ get_size_units(endptr);
} else {
- char *endptr;
-
- errno = 0;
- (asi + i)->slice_size =
- strtoull(p[i], &endptr, 0);
- if (errno == 0 && endptr != p[i])
- continue;
auto_debug_print(AUTO_DBGLVL_ERR,
"Slice size in manifest (%s) is "
- "not a valid number or \"max_size\".\n",
- p[i]);
+ "not a valid number.\n",
+ p);
*pstatus = 1;
free(asi);
+ free(slice_names);
+ free(slice_actions);
errno = 0;
return (NULL);
}
}
- free(p);
+
+ /*
+ * Determine behavior for create action on existing slices.
+ */
+ (void) snprintf(tag, sizeof (tag),
+ AIM_SLICE_ON_EXISTING, slice_names[i], slice_actions[i]);
+ p = ai_get_manifest_element_value(tag);
+ if (p != NULL) {
+ /*
+ * Since the slice information array is initialized
+ * to zero, and the default enum value is also zero,
+ * the "error" case will also be the default in the
+ * slice information array.
+ *
+ * In the new schema, the slice attribute 'force'
+ * controls this. If force="false" (the default)
+ * then we leave on_existing=0, which equates to
+ * OM_ON_EXISTING_ERROR. If force="true", then we
+ * set it to OM_ON_EXISTING_OVERWRITE.
+ */
+ if (strcasecmp(p, "true") == 0)
+ (asi + i)->on_existing =
+ OM_ON_EXISTING_OVERWRITE;
+ }
}
- p = get_manifest_element_array(AIM_SLICE_SIZE_UNITS);
- /* slice size units can be sectors, GB, TB, or MB (default) */
- if (p != NULL) {
- for (i = 0; i < len; i++) {
- if (p[i] == NULL) { /* default to MB */
- (asi + i)->slice_size_units =
- AI_SIZE_UNITS_MEGABYTES;
- continue;
- }
- switch (p[i][0]) {
- case 's':
- case 'S':
- (asi + i)->slice_size_units =
- AI_SIZE_UNITS_SECTORS;
- break;
- case 'g':
- case 'G':
- (asi + i)->slice_size_units =
- AI_SIZE_UNITS_GIGABYTES;
- break;
- case 't':
- case 'T':
- (asi + i)->slice_size_units =
- AI_SIZE_UNITS_TERABYTES;
- break;
- case 'm':
- case 'M':
- default:
- (asi + i)->slice_size_units =
- AI_SIZE_UNITS_MEGABYTES;
- break;
- }
- }
- free(p);
+ free(slice_names);
+ free(slice_actions);
+
+ /* Debug - print slice info out to log */
+ tmp_asi = asi;
+ for (; tmp_asi->slice_action[0] != '\0'; tmp_asi++) {
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "Slice details from Manifest:\n");
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tslice_action\t\t: [%s]\n",
+ tmp_asi->slice_action);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tslice_number\t\t: [%d]\n",
+ tmp_asi->slice_number);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tslice_size\t\t\t: [%lld]\n",
+ tmp_asi->slice_size);
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\tslice_size_units\t: [%d] (= %s)\n",
+ (int)tmp_asi->slice_size_units,
+ CONVERT_UNITS_TO_TEXT(tmp_asi->slice_size_units));
+ auto_debug_print(AUTO_DBGLVL_INFO,
+ "\ton_existing\t: [%d] (= %s)\n",
+ (int)tmp_asi->on_existing,
+ tmp_asi->on_existing ? "OVERWRITE" : "ERROR");
}
- /*
- * Determine behavior for create action on existing slices.
- */
- p = get_manifest_element_array(AIM_SLICE_ON_EXISTING);
- if (p != NULL) {
- /*
- * Since the slice information array is initialized to zero,
- * and the default enum value is also zero, the "error" case
- * will also be the default in the slice information array.
- */
- for (i = 0; i < len; i++)
- if (p[i] != NULL && strcasecmp(p[i], "overwrite") == 0)
- (asi + i)->on_existing =
- OM_ON_EXISTING_OVERWRITE;
- free(p);
- }
return (asi);
}
@@ -823,15 +1246,7 @@
char **value;
char *url;
- value = ai_get_manifest_values(AIM_IPS_DEFAULT_PUBLISHER_URL, len);
-
- /*
- * If publisher is not supplied, check for authority
- */
- if (*len <= 0) {
- value = ai_get_manifest_values(
- AIM_IPS_DEFAULT_AUTH_URL, len);
- }
+ value = ai_get_manifest_values(AIM_IPS_PUBLISHER_URL, len);
if (*len > 0) {
url = value[0];
@@ -842,22 +1257,20 @@
}
/*
- * Retrieve the URL for the additional publisher
+ * Retrieve the URL(s) for the additional publisher(s)
+ *
+ * Default and additional (or primary and secondary) publishers
+ * now use the same nodepaths, so this function repeats the same
+ * search as ai_get_manifest_default_url() but the results are
+ * handled differently.
*/
char **
ai_get_manifest_addl_url(int *len)
{
char **value;
- value = ai_get_manifest_values(AIM_IPS_ADDL_PUBLISHER_URL, len);
+ value = ai_get_manifest_values(AIM_IPS_PUBLISHER_URL, len);
- /*
- * If publisher is not supplied, check for authority
- */
- if (*len <= 0) {
- value = ai_get_manifest_values(
- AIM_IPS_ADDL_AUTH_URL, len);
- }
if (*len > 0) {
return (value);
}
@@ -866,41 +1279,19 @@
/*
* Retrieve an publisher name from the manifest using url value
- * This is the common function for default publisher and
- * additional publisher. If the value of the flag is_default_publisher
- * is true, then the default publisher tag is used.
*/
char *
-ai_get_manifest_repo_publisher(boolean_t is_default_publisher, char *url)
+ai_get_manifest_repo_publisher(char *url)
{
char **value;
char *publisher;
int len;
char tag[MAXPATHLEN];
- if (is_default_publisher) {
- (void) snprintf(tag, sizeof (tag),
- AIM_ADD_DEFAULT_URL_PUBLISHER_NAME, url);
- } else {
- (void) snprintf(tag, sizeof (tag),
- AIM_ADD_ADDL_URL_PUBLISHER_NAME, url);
- }
+ (void) snprintf(tag, sizeof (tag),
+ AIM_ADD_URL_PUBLISHER_NAME, url);
value = ai_get_manifest_values(tag, &len);
- /*
- * If publisher is not supplied, check for authority
- */
- if (len <= 0) {
- if (is_default_publisher) {
- snprintf(tag, sizeof (tag),
- AIM_ADD_DEFAULT_URL_AUTH_NAME, url);
- } else {
- snprintf(tag, sizeof (tag),
- AIM_ADD_ADDL_URL_AUTH_NAME, url);
- }
- value = ai_get_manifest_values(tag, &len);
- }
-
if (len > 0) {
publisher = value[0];
free(value);
@@ -911,12 +1302,9 @@
/*
* Retrieve the URL for an IPS repo mirrors
- * This is the common function for default publisher and
- * additional publisher. If the value of the flag is_default_publisher
- * is true, then the default publisher tag is used.
*/
auto_mirror_repo_t *
-ai_get_manifest_repo_mirrors(boolean_t is_default_publisher, char *url)
+ai_get_manifest_repo_mirrors(char *url)
{
int i, len = 0;
char **value;
@@ -924,30 +1312,10 @@
auto_mirror_repo_t *ptr, *tmp_ptr;
auto_mirror_repo_t *mirror = NULL;
- if (is_default_publisher) {
- (void) snprintf(buf, sizeof (buf),
- AIM_ADD_DEFAULT_URL_PUBLISHER_MIRROR, url);
- } else {
- (void) snprintf(buf, sizeof (buf),
- AIM_ADD_ADDL_URL_PUBLISHER_MIRROR, url);
- }
-
+ (void) snprintf(buf, sizeof (buf),
+ AIM_ADD_URL_PUBLISHER_MIRROR, url);
value = ai_get_manifest_values(buf, &len);
- /*
- * If publisher is not supplied, check for authority
- */
- if (len <= 0) {
- if (is_default_publisher) {
- (void) snprintf(buf, sizeof (buf),
- AIM_ADD_DEFAULT_URL_AUTH_MIRROR, url);
- } else {
- (void) snprintf(buf, sizeof (buf),
- AIM_ADD_ADDL_URL_AUTH_MIRROR, url);
- }
- value = ai_get_manifest_values(buf, &len);
- }
-
if (len <= 0) {
return (NULL);
}
@@ -996,7 +1364,6 @@
char *current_url, *default_url;
int num_url;
auto_repo_info_t *repo, *default_repo;
- boolean_t is_default_publisher = B_TRUE;
default_repo = NULL;
@@ -1005,7 +1372,11 @@
*/
current_url = ai_get_manifest_default_url(&num_url);
if (current_url == NULL) {
- return (NULL);
+ /*
+ * If the publisher wasn't specified in the manifest,
+ * provide a default value.
+ */
+ current_url = AIM_FALLBACK_PUBLISHER_URL;
}
repo = calloc(sizeof (auto_repo_info_t), 1);
@@ -1017,9 +1388,18 @@
* Save the value before calling another ai_get_manifest_*()
*/
default_url = strdup(current_url);
- p = ai_get_manifest_repo_publisher(is_default_publisher, default_url);
+ p = ai_get_manifest_repo_publisher(default_url);
if (p == NULL) {
- goto get_out;
+ /*
+ * If the primary publisher URL is AIM_FALLBACK_PUBLISHER_URL
+ * and no name was specified, then provide a default value.
+ * For all other URLs, if a name is not specified for the
+ * publisher, then it is an error.
+ */
+ if (strcasecmp(current_url, AIM_FALLBACK_PUBLISHER_URL) == 0)
+ p = AIM_FALLBACK_PUBLISHER_NAME;
+ else
+ goto get_out;
}
repo->publisher = strdup(p);
repo->url = strdup(default_url);
@@ -1031,7 +1411,7 @@
* get the mirrors for this publishers
*/
repo->mirror_repo =
- ai_get_manifest_repo_mirrors(is_default_publisher, default_url);
+ ai_get_manifest_repo_mirrors(default_url);
repo->next_repo = NULL;
default_repo = repo;
@@ -1063,7 +1443,6 @@
char **urls;
int i, num_url;
auto_repo_info_t *repo, *tmp_repo, *addl_repo;
- boolean_t is_default_publisher = B_FALSE;
addl_repo = NULL;
tmp_repo = NULL;
@@ -1077,10 +1456,15 @@
return (NULL);
/*
+ * We start iterating through the urls at index 1
+ * instead of index 0, because the first url returned
+ * is the primary publisher. All subsequent urls are
+ * secondary, or additional, publishers, which is what
+ * we want here.
* Allocate space and save the urls because the next
* call to ai_get_manifest_*() will overwrite them
*/
- for (i = 0; i < num_url; i++) {
+ for (i = 1; i < num_url; i++) {
/*
* Ignore the empty string
*/
@@ -1112,8 +1496,7 @@
* mirrors (if any).
*/
for (repo = addl_repo; repo != NULL; repo = repo -> next_repo) {
- p = ai_get_manifest_repo_publisher(
- is_default_publisher, repo->url);
+ p = ai_get_manifest_repo_publisher(repo->url);
if (p == NULL) {
goto get_out;
}
@@ -1125,8 +1508,7 @@
/*
* get the mirrors for this publisher
*/
- repo->mirror_repo = ai_get_manifest_repo_mirrors(
- is_default_publisher, repo->url);
+ repo->mirror_repo = ai_get_manifest_repo_mirrors(repo->url);
}
free(urls);