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