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 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 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 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