/*
* 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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* System includes
*/
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <locale.h>
#include <libintl.h>
#include <assert.h>
/*
* local pkg command library includes
*/
#include "libinst.h"
#include "messages.h"
/*
* forward declarations
*/
static int
collectError(int *r_numZones, char **r_zoneNames, char *a_packageName,
depckl_t *a_dck, int a_depIndex, depckErrorRecord_t *a_eir,
int a_errIndex);
/*
* *****************************************************************************
* global external (public) functions
* *****************************************************************************
*/
int
depchkReportErrors(depckl_t *a_dck)
{
char *packageName;
char *zonenames;
char msgbuf[4096];
int err;
int i;
int numzones = 0;
/* entry assertions */
assert(a_dck != (depckl_t *)NULL);
/* entry debugging info */
echoDebug(DBG_DEPCHK_ENTRY);
zonenames = (char *)NULL;
/* go through dependency table, collect, collapse, report errors */
for (i = 0; a_dck[i].name != (char *)NULL; i++) {
int j;
depckError_t *erc;
if (zonenames != (char *)NULL) {
free(zonenames);
zonenames = (char *)NULL;
}
erc = a_dck[i].record;
if (erc->er_numEntries == 0) {
continue;
}
for (j = 0; j < erc->er_numEntries; j++) {
int k;
depckErrorRecord_t *eir;
if (zonenames != (char *)NULL) {
free(zonenames);
zonenames = (char *)NULL;
}
eir = &erc->er_theEntries[j];
packageName = eir->ier_packageName;
for (k = 0; k < eir->ier_numZones; k++) {
int err;
err = collectError(&numzones, &zonenames,
packageName, a_dck, i, eir, k);
if (err != 0) {
if (zonenames != (char *)NULL) {
free(zonenames);
zonenames = (char *)NULL;
}
return (err);
}
}
if (a_dck[i].ignore_values == (char *)NULL) {
continue;
}
if (a_dck[i].err_msg == (char **)NULL) {
(void) snprintf(msgbuf, sizeof (msgbuf),
ERR_DEPENDENCY_IGNORED, a_dck[i].name,
packageName,
numzones == 1 ? "zone" : "zones",
zonenames ? zonenames : "?");
} else {
/* LINTED variable format specifier to ... */
(void) snprintf(msgbuf, sizeof (msgbuf),
*a_dck[i].err_msg, "package",
packageName,
numzones == 1 ? "zone" : "zones",
zonenames ? zonenames : "??");
}
if (a_dck[i].depcklFunc != NULL) {
/* call check function */
err = (a_dck[i].depcklFunc)(msgbuf,
packageName);
echoDebug(DBG_DEPCHK_REPORT_ERROR,
a_dck[i].ignore_values, err,
packageName, msgbuf);
if (err != 0) {
if (zonenames != (char *)NULL) {
free(zonenames);
zonenames = (char *)NULL;
}
return (err);
}
} else {
/* no check function - just report message */
echoDebug(DBG_DEPCHK_IGNORE_ERROR,
a_dck[i].ignore_values, packageName,
msgbuf);
ptext(stderr, "\\n%s", msgbuf);
}
}
}
if (zonenames != (char *)NULL) {
free(zonenames);
zonenames = (char *)NULL;
}
return (0);
}
void
depchkRecordError(depckError_t *a_erc, char *a_pkginst,
char *a_zoneName, char *a_value)
{
depckErrorRecord_t *erc;
int i;
/*
* create new error record and entry if first entry
* record will look like this:
* err->er_#entry=1
* err->entry[0]->record->ier_numZones=1
* err->entry[0]->record->ier_packageName=a_pkginst
* err->entry[0]->record->ier_zones[0]=a_zoneName
* err->entry[0]->record->ier_values[0]=a_value
*/
if (a_erc->er_numEntries == 0) {
depckErrorRecord_t *eir;
eir = (depckErrorRecord_t *)calloc(1,
sizeof (depckErrorRecord_t));
eir->ier_packageName = strdup(a_pkginst);
eir->ier_numZones = 1;
eir->ier_zones = (char **)calloc(1, sizeof (char **));
(eir->ier_zones)[eir->ier_numZones-1] = strdup(a_zoneName);
eir->ier_values = (char **)calloc(1, sizeof (char *));
(eir->ier_values)[eir->ier_numZones-1] = strdup(a_value);
a_erc->er_numEntries = 1;
a_erc->er_theEntries = eir;
echoDebug(DBG_DEPCHK_RECORD_ERROR, (long)a_erc, a_pkginst,
a_zoneName, a_value);
return;
}
/* see if this package already has an entry if so add zone to list */
for (i = 0; i < a_erc->er_numEntries; i++) {
erc = &a_erc->er_theEntries[i];
if (strcmp(erc->ier_packageName, a_pkginst) != 0) {
continue;
}
echoDebug(DBG_DEPCHK_RECORD_ZERROR, (long)a_erc, a_zoneName,
a_value, erc->ier_packageName, erc->ier_numZones,
erc->ier_zones[0]);
/*
* this package already has an entry - add zone to
* existing package entry the modified records will
* look like this:
* err->er_#entry++;
* err->entry[0]->...
* err->entry[i]->
* -------------->record->
* ---------------------->ier_numZones++;
* ---------------------->ier_packageName=a_pkginst
* ---------------------->ier_zones[0]=...
* ---------------------->ier_zones[...]=...
* ---------------------->ier_zones[ier_numZones-1]=a_zoneName
* ---------------------->ier_values[0]=...
* ---------------------->ier_values[...]=...
* ---------------------->ier_values[ier_numZones-1]=a_value
* err->entry[i+1]->...
*/
erc->ier_numZones++;
erc->ier_zones = (char **)realloc(erc->ier_zones,
sizeof (char **)*erc->ier_numZones);
(erc->ier_zones)[erc->ier_numZones-1] = strdup(a_zoneName);
erc->ier_values = (char **)realloc(erc->ier_values,
sizeof (char **)*erc->ier_numZones);
(erc->ier_values)[erc->ier_numZones-1] = strdup(a_value);
return;
}
/*
* this packages does not have an entry - add new package
* entry for this zone the modified records will look like this:
* err->er_#entry++;
* err->entry[0]->record->ier_numZones=...
* err->entry[0]->record->ier_packageName=...
* err->entry[0]->record->ier_zones[0]=...
* err->entry[0]->record->ier_values[0]=...
* err->entry[er_#entry-1]->record->ier_numZones=1
* err->entry[er_#entry-1]->record->ier_packageName=a_pkginst
* err->entry[er_#entry-1]->record->ier_zones[0]=a_zoneName
* err->entry[er_#entry-1]->record->ier_values[0]=a_value
*/
echoDebug(DBG_DEPCHK_RECORD_PERROR, (long)a_erc,
a_erc->er_numEntries, a_pkginst, a_zoneName, a_value);
a_erc->er_numEntries++;
a_erc->er_theEntries = realloc(a_erc->er_theEntries,
sizeof (depckErrorRecord_t)*a_erc->er_numEntries);
erc = &a_erc->er_theEntries[a_erc->er_numEntries-1];
erc->ier_packageName = strdup(a_pkginst);
erc->ier_numZones = 1;
erc->ier_zones = (char **)calloc(1, sizeof (char *));
(erc->ier_zones)[erc->ier_numZones-1] = strdup(a_zoneName);
erc->ier_values = (char **)calloc(1, sizeof (char *));
(erc->ier_values)[erc->ier_numZones-1] = strdup(a_value);
}
/*
* *****************************************************************************
* static internal (private) functions
* *****************************************************************************
*/
static int
collectError(int *r_numZones, char **r_zoneNames, char *a_packageName,
depckl_t *a_dck, int a_depIndex, depckErrorRecord_t *a_eir,
int a_errIndex)
{
char msgbuf[4096];
char *zn = *r_zoneNames;
if (a_dck[a_depIndex].ignore_values == (char *)NULL) {
if (a_dck[a_depIndex].err_msg == (char **)NULL) {
(void) snprintf(msgbuf, sizeof (msgbuf),
ERR_DEPENDENCY_REPORT, a_eir->ier_values[a_errIndex],
"package", a_packageName,
"zone", a_eir->ier_zones[a_errIndex]);
} else {
/* LINTED variable format specifier to snprintf(); */
(void) snprintf(msgbuf, sizeof (msgbuf),
*a_dck[a_depIndex].err_msg,
a_eir->ier_values[a_errIndex],
"package", a_packageName,
"zone", a_eir->ier_zones[a_errIndex]);
}
if (a_dck[a_depIndex].depcklFunc != NULL) {
int err;
err = (a_dck[a_depIndex].depcklFunc)(msgbuf,
a_packageName);
echoDebug(DBG_DEPCHK_COLLECT_ERROR, err, a_packageName,
msgbuf);
if (err != 0) {
return (err);
}
} else {
echoDebug(DBG_DEPCHK_COLLECT_IGNORE, a_packageName,
msgbuf);
ptext(stderr, "\\n%s", msgbuf);
}
return (0);
}
*r_numZones = (*r_numZones)+1;
if (zn == (char *)NULL) {
zn = strdup(a_eir->ier_zones[a_errIndex]);
} else {
char *p;
int len = strlen(zn)+strlen(a_eir->ier_zones[a_errIndex])+3;
p = calloc(1, len);
(void) snprintf(p, len, "%s, %s", zn,
a_eir->ier_zones[a_errIndex]);
free(zn);
zn = p;
}
*r_zoneNames = zn;
return (0);
}