1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28 /*
29 * System includes
30 */
31
32 #include <stdio.h>
33 #include <limits.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <sys/types.h>
39 #include <locale.h>
40 #include <libintl.h>
41 #include <assert.h>
42
43 /*
44 * local pkg command library includes
45 */
46
47 #include "libinst.h"
48 #include "messages.h"
49
50 /*
51 * forward declarations
52 */
53
54 static int
55 collectError(int *r_numZones, char **r_zoneNames, char *a_packageName,
56 depckl_t *a_dck, int a_depIndex, depckErrorRecord_t *a_eir,
57 int a_errIndex);
58
59 /*
60 * *****************************************************************************
61 * global external (public) functions
62 * *****************************************************************************
63 */
64
65 int
depchkReportErrors(depckl_t * a_dck)66 depchkReportErrors(depckl_t *a_dck)
67 {
68 char *packageName;
69 char *zonenames;
70 char msgbuf[4096];
71 int err;
72 int i;
73 int numzones = 0;
74
75 /* entry assertions */
76
77 assert(a_dck != (depckl_t *)NULL);
78
79 /* entry debugging info */
80
81 echoDebug(DBG_DEPCHK_ENTRY);
82
83 zonenames = (char *)NULL;
84
85 /* go through dependency table, collect, collapse, report errors */
86
87 for (i = 0; a_dck[i].name != (char *)NULL; i++) {
88 int j;
89 depckError_t *erc;
90
91 if (zonenames != (char *)NULL) {
92 free(zonenames);
93 zonenames = (char *)NULL;
94 }
95
96 erc = a_dck[i].record;
97 if (erc->er_numEntries == 0) {
98 continue;
99 }
100
101 for (j = 0; j < erc->er_numEntries; j++) {
102 int k;
103 depckErrorRecord_t *eir;
104
105 if (zonenames != (char *)NULL) {
106 free(zonenames);
107 zonenames = (char *)NULL;
108 }
109
110 eir = &erc->er_theEntries[j];
111 packageName = eir->ier_packageName;
112 for (k = 0; k < eir->ier_numZones; k++) {
113 int err;
114
115 err = collectError(&numzones, &zonenames,
116 packageName, a_dck, i, eir, k);
117 if (err != 0) {
118 if (zonenames != (char *)NULL) {
119 free(zonenames);
120 zonenames = (char *)NULL;
121 }
122 return (err);
123 }
124 }
125
126 if (a_dck[i].ignore_values == (char *)NULL) {
127 continue;
128 }
129
130 if (a_dck[i].err_msg == (char **)NULL) {
131 (void) snprintf(msgbuf, sizeof (msgbuf),
132 ERR_DEPENDENCY_IGNORED, a_dck[i].name,
133 packageName,
134 numzones == 1 ? "zone" : "zones",
135 zonenames ? zonenames : "?");
136 } else {
137 /* LINTED variable format specifier to ... */
138 (void) snprintf(msgbuf, sizeof (msgbuf),
139 *a_dck[i].err_msg, "package",
140 packageName,
141 numzones == 1 ? "zone" : "zones",
142 zonenames ? zonenames : "??");
143 }
144
145 if (a_dck[i].depcklFunc != NULL) {
146 /* call check function */
147 err = (a_dck[i].depcklFunc)(msgbuf,
148 packageName);
149 echoDebug(DBG_DEPCHK_REPORT_ERROR,
150 a_dck[i].ignore_values, err,
151 packageName, msgbuf);
152 if (err != 0) {
153 if (zonenames != (char *)NULL) {
154 free(zonenames);
155 zonenames = (char *)NULL;
156 }
157 return (err);
158 }
159 } else {
160 /* no check function - just report message */
161 echoDebug(DBG_DEPCHK_IGNORE_ERROR,
162 a_dck[i].ignore_values, packageName,
163 msgbuf);
164 ptext(stderr, "\\n%s", msgbuf);
165 }
166 }
167 }
168
169 if (zonenames != (char *)NULL) {
170 free(zonenames);
171 zonenames = (char *)NULL;
172 }
173
174 return (0);
175 }
176
177 void
depchkRecordError(depckError_t * a_erc,char * a_pkginst,char * a_zoneName,char * a_value)178 depchkRecordError(depckError_t *a_erc, char *a_pkginst,
179 char *a_zoneName, char *a_value)
180 {
181 depckErrorRecord_t *erc;
182 int i;
183
184 /*
185 * create new error record and entry if first entry
186 * record will look like this:
187 * err->er_#entry=1
188 * err->entry[0]->record->ier_numZones=1
189 * err->entry[0]->record->ier_packageName=a_pkginst
190 * err->entry[0]->record->ier_zones[0]=a_zoneName
191 * err->entry[0]->record->ier_values[0]=a_value
192 */
193
194 if (a_erc->er_numEntries == 0) {
195 depckErrorRecord_t *eir;
196
197 eir = (depckErrorRecord_t *)calloc(1,
198 sizeof (depckErrorRecord_t));
199 eir->ier_packageName = strdup(a_pkginst);
200 eir->ier_numZones = 1;
201 eir->ier_zones = (char **)calloc(1, sizeof (char **));
202 (eir->ier_zones)[eir->ier_numZones-1] = strdup(a_zoneName);
203 eir->ier_values = (char **)calloc(1, sizeof (char *));
204 (eir->ier_values)[eir->ier_numZones-1] = strdup(a_value);
205
206 a_erc->er_numEntries = 1;
207 a_erc->er_theEntries = eir;
208
209 echoDebug(DBG_DEPCHK_RECORD_ERROR, (long)a_erc, a_pkginst,
210 a_zoneName, a_value);
211
212 return;
213 }
214
215 /* see if this package already has an entry if so add zone to list */
216
217 for (i = 0; i < a_erc->er_numEntries; i++) {
218 erc = &a_erc->er_theEntries[i];
219
220 if (strcmp(erc->ier_packageName, a_pkginst) != 0) {
221 continue;
222 }
223
224 echoDebug(DBG_DEPCHK_RECORD_ZERROR, (long)a_erc, a_zoneName,
225 a_value, erc->ier_packageName, erc->ier_numZones,
226 erc->ier_zones[0]);
227
228 /*
229 * this package already has an entry - add zone to
230 * existing package entry the modified records will
231 * look like this:
232 * err->er_#entry++;
233 * err->entry[0]->...
234 * err->entry[i]->
235 * -------------->record->
236 * ---------------------->ier_numZones++;
237 * ---------------------->ier_packageName=a_pkginst
238 * ---------------------->ier_zones[0]=...
239 * ---------------------->ier_zones[...]=...
240 * ---------------------->ier_zones[ier_numZones-1]=a_zoneName
241 * ---------------------->ier_values[0]=...
242 * ---------------------->ier_values[...]=...
243 * ---------------------->ier_values[ier_numZones-1]=a_value
244 * err->entry[i+1]->...
245 */
246 erc->ier_numZones++;
247 erc->ier_zones = (char **)realloc(erc->ier_zones,
248 sizeof (char **)*erc->ier_numZones);
249 (erc->ier_zones)[erc->ier_numZones-1] = strdup(a_zoneName);
250 erc->ier_values = (char **)realloc(erc->ier_values,
251 sizeof (char **)*erc->ier_numZones);
252 (erc->ier_values)[erc->ier_numZones-1] = strdup(a_value);
253 return;
254 }
255
256 /*
257 * this packages does not have an entry - add new package
258 * entry for this zone the modified records will look like this:
259 * err->er_#entry++;
260 * err->entry[0]->record->ier_numZones=...
261 * err->entry[0]->record->ier_packageName=...
262 * err->entry[0]->record->ier_zones[0]=...
263 * err->entry[0]->record->ier_values[0]=...
264 * err->entry[er_#entry-1]->record->ier_numZones=1
265 * err->entry[er_#entry-1]->record->ier_packageName=a_pkginst
266 * err->entry[er_#entry-1]->record->ier_zones[0]=a_zoneName
267 * err->entry[er_#entry-1]->record->ier_values[0]=a_value
268 */
269
270 echoDebug(DBG_DEPCHK_RECORD_PERROR, (long)a_erc,
271 a_erc->er_numEntries, a_pkginst, a_zoneName, a_value);
272
273 a_erc->er_numEntries++;
274
275 a_erc->er_theEntries = realloc(a_erc->er_theEntries,
276 sizeof (depckErrorRecord_t)*a_erc->er_numEntries);
277
278 erc = &a_erc->er_theEntries[a_erc->er_numEntries-1];
279
280 erc->ier_packageName = strdup(a_pkginst);
281 erc->ier_numZones = 1;
282 erc->ier_zones = (char **)calloc(1, sizeof (char *));
283 (erc->ier_zones)[erc->ier_numZones-1] = strdup(a_zoneName);
284 erc->ier_values = (char **)calloc(1, sizeof (char *));
285 (erc->ier_values)[erc->ier_numZones-1] = strdup(a_value);
286 }
287
288 /*
289 * *****************************************************************************
290 * static internal (private) functions
291 * *****************************************************************************
292 */
293
294 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)295 collectError(int *r_numZones, char **r_zoneNames, char *a_packageName,
296 depckl_t *a_dck, int a_depIndex, depckErrorRecord_t *a_eir,
297 int a_errIndex)
298 {
299 char msgbuf[4096];
300 char *zn = *r_zoneNames;
301
302 if (a_dck[a_depIndex].ignore_values == (char *)NULL) {
303 if (a_dck[a_depIndex].err_msg == (char **)NULL) {
304 (void) snprintf(msgbuf, sizeof (msgbuf),
305 ERR_DEPENDENCY_REPORT, a_eir->ier_values[a_errIndex],
306 "package", a_packageName,
307 "zone", a_eir->ier_zones[a_errIndex]);
308 } else {
309 /* LINTED variable format specifier to snprintf(); */
310 (void) snprintf(msgbuf, sizeof (msgbuf),
311 *a_dck[a_depIndex].err_msg,
312 a_eir->ier_values[a_errIndex],
313 "package", a_packageName,
314 "zone", a_eir->ier_zones[a_errIndex]);
315 }
316 if (a_dck[a_depIndex].depcklFunc != NULL) {
317 int err;
318
319 err = (a_dck[a_depIndex].depcklFunc)(msgbuf,
320 a_packageName);
321 echoDebug(DBG_DEPCHK_COLLECT_ERROR, err, a_packageName,
322 msgbuf);
323 if (err != 0) {
324 return (err);
325 }
326 } else {
327 echoDebug(DBG_DEPCHK_COLLECT_IGNORE, a_packageName,
328 msgbuf);
329 ptext(stderr, "\\n%s", msgbuf);
330 }
331 return (0);
332 }
333
334 *r_numZones = (*r_numZones)+1;
335 if (zn == (char *)NULL) {
336 zn = strdup(a_eir->ier_zones[a_errIndex]);
337 } else {
338 char *p;
339 int len = strlen(zn)+strlen(a_eir->ier_zones[a_errIndex])+3;
340 p = calloc(1, len);
341 (void) snprintf(p, len, "%s, %s", zn,
342 a_eir->ier_zones[a_errIndex]);
343 free(zn);
344 zn = p;
345
346 }
347 *r_zoneNames = zn;
348 return (0);
349 }
350