Print this page
patch tsoome-feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fm/fminject/common/inj_defn.c
+++ new/usr/src/cmd/fm/fminject/common/inj_defn.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 27 /*
30 28 * After having been declared, events, FMRIs and authorities must be defined
31 29 * (instantiated) before they can be used as the subjects of commands.
32 30 */
33 31
34 32 #include <sys/sysmacros.h>
35 33 #include <libnvpair.h>
36 34 #include <string.h>
37 35 #include <assert.h>
38 36
39 37 #include <inj_event.h>
40 38 #include <inj_err.h>
41 39 #include <inj_lex.h>
42 40 #include <inj_string.h>
43 41 #include <inj.h>
44 42
45 43 static inj_hash_t inj_defns[3];
46 44 static int inj_defns_initialized;
47 45
48 46 /* Intrinsics (signed and unsigned integer integer constants) */
49 47 typedef struct intr {
50 48 uchar_t ei_signed;
51 49 uchar_t ei_width;
52 50 } intr_t;
53 51
54 52 static inj_hash_t *
55 53 item2hash(inj_itemtype_t item)
56 54 {
57 55 int i;
58 56
59 57 assert(item >= 0 && item < sizeof (inj_defns) / sizeof (inj_hash_t));
60 58
61 59 if (!inj_defns_initialized) {
62 60 for (i = 0; i < sizeof (inj_defns) / sizeof (inj_hash_t); i++)
63 61 inj_strhash_create(&inj_defns[i]);
64 62 inj_defns_initialized = 1;
65 63 }
66 64
67 65 return (&inj_defns[item]);
68 66 }
69 67
70 68 inj_defn_t *
71 69 inj_defn_lookup(const char *name, inj_memtype_t type)
72 70 {
73 71 inj_hash_t *hash = item2hash(inj_mem2item(type));
74 72 inj_var_t *v;
75 73
76 74 if ((v = inj_strhash_lookup(hash, name)) == NULL)
77 75 return (NULL);
78 76
79 77 return (inj_hash_get_cookie(v));
80 78 }
81 79
82 80 static void
83 81 inj_defn_destroy_memlist(inj_defnmem_t *m)
84 82 {
85 83 inj_defnmem_t *n;
86 84
87 85 for (/* */; m != NULL; m = n) {
88 86 n = inj_list_next(m);
89 87
90 88 switch (m->dfm_type) {
91 89 case DEFNMEM_ARRAY:
92 90 case DEFNMEM_LIST:
93 91 inj_defn_destroy_memlist(inj_list_next(&m->dfm_list));
94 92 break;
95 93 default:
96 94 inj_strfree(m->dfm_str);
↓ open down ↓ |
58 lines elided |
↑ open up ↑ |
97 95 }
98 96 }
99 97 }
100 98
101 99 void
102 100 inj_defn_destroy(inj_defn_t *defn)
103 101 {
104 102 if (defn->defn_name != NULL)
105 103 inj_strfree(defn->defn_name);
106 104
107 - if (defn->defn_nvl != NULL)
108 - nvlist_free(defn->defn_nvl);
105 + nvlist_free(defn->defn_nvl);
109 106
110 107 inj_defn_destroy_memlist(inj_list_next(&defn->defn_members));
111 108 }
112 109
113 110 static inj_defnmem_t *
114 111 inj_defn_mem_create_common(inj_defnmemtype_t type)
115 112 {
116 113 inj_defnmem_t *dfm = inj_zalloc(sizeof (inj_defnmem_t));
117 114
118 115 dfm->dfm_type = type;
119 116 dfm->dfm_lineno = yylineno;
120 117
121 118 return (dfm);
122 119 }
123 120
124 121 inj_defnmem_t *
125 122 inj_defn_mem_create(const char *str, inj_defnmemtype_t type)
126 123 {
127 124 inj_defnmem_t *dfm = inj_defn_mem_create_common(type);
128 125
129 126 dfm->dfm_str = str;
130 127
131 128 return (dfm);
132 129 }
133 130
134 131 inj_defnmem_t *
135 132 inj_defn_mem_create_list(inj_defn_t *list, inj_defnmemtype_t type)
136 133 {
137 134 inj_defnmem_t *dfm = inj_defn_mem_create_common(type);
138 135
139 136 dfm->dfm_list = list->defn_members;
140 137
141 138 inj_free(list, sizeof (inj_defn_t));
142 139
143 140 return (dfm);
144 141 }
145 142
146 143 inj_defn_t *
147 144 inj_defn_create(inj_defnmem_t *dfm)
148 145 {
149 146 inj_defn_t *defn = inj_zalloc(sizeof (inj_defn_t));
150 147
151 148 defn->defn_lineno = yylineno;
152 149
153 150 inj_list_append(&defn->defn_members, dfm);
154 151
155 152 return (defn);
156 153 }
157 154
158 155 void
159 156 inj_defn_addmem(inj_defn_t *defn, inj_defnmem_t *dfm)
160 157 {
161 158 inj_list_append(&defn->defn_members, dfm);
162 159 }
163 160
164 161 /*
165 162 * Validate the dimensions of an array. If the declared array size was zero,
166 163 * accept (and return) whatever the definition used. If fewer cells were
167 164 * defined than were declared, return the declared size - the calling code will
168 165 * fill the remaining cells with zeros. The definition of more than the
169 166 * declared number of cells triggers an error. We print and error message in
170 167 * this case and return the declared number. This will allow processing to
171 168 * continue. The act of emitting the error will guarantee that we never
172 169 * pass from parsing to program execution.
173 170 */
174 171 static size_t
175 172 array_dim_check(inj_declmem_t *dlm, inj_defnmem_t *dfm)
176 173 {
177 174 inj_list_t *l;
178 175 size_t dfnelems;
179 176
180 177 for (dfnelems = 0, l = inj_list_next(&dfm->dfm_list); l != NULL;
181 178 l = inj_list_next(l), dfnelems++);
182 179
183 180 if (dlm->dlm_arrdim != 0 && dlm->dlm_arrdim != dfnelems) {
184 181 yyerror(" %d: defined array has %d elements, expected %d\n",
185 182 dfm->dfm_lineno, dfnelems, dlm->dlm_arrdim);
186 183 dfnelems = dlm->dlm_arrdim;
187 184 }
188 185
189 186 return (MAX(dfnelems, dlm->dlm_arrdim));
190 187 }
191 188
192 189 /*
193 190 * The inj_defn_memcmp_* routines serve two purposes. First, they compare a
194 191 * given defined member with the corresponding declared member, signalling an
195 192 * error if the two are incompatible.
196 193 *
197 194 * Assuming that validation succeeds, an entry is added to the passed nvlist
198 195 * for the defined member.
199 196 */
200 197
201 198 /* Used to ease signed and unsigned integer validation */
202 199 static const intr_t inj_intrinsics[] = {
203 200 { 0, 0 }, /* MEMTYPE_UNKNOWN */
204 201 { 1, 8 }, { 1, 16 }, { 1, 32 }, { 1, 64 },
205 202 { 0, 8 }, { 0, 16 }, { 0, 32 }, { 0, 64 }
206 203 };
207 204
208 205 static int
209 206 inj_defn_memcmp_signed(const intr_t *intr, inj_declmem_t *dlm,
210 207 inj_defnmem_t *dfm, nvlist_t *nvl)
211 208 {
212 209 longlong_t val;
213 210
214 211 if (dfm->dfm_type != DEFNMEM_IMM && dfm->dfm_type != DEFNMEM_IDENT)
215 212 return (inj_set_errno(EINVAL));
216 213
217 214 if (inj_strtoll(dfm->dfm_str, intr->ei_width, &val) < 0)
218 215 return (-1); /* errno is set for us */
219 216
220 217 switch (dlm->dlm_type) {
221 218 case MEMTYPE_INT8:
222 219 errno = nvlist_add_int8(nvl, (char *)dlm->dlm_name,
223 220 (int8_t)val);
224 221 break;
225 222 case MEMTYPE_INT16:
226 223 errno = nvlist_add_int16(nvl, (char *)dlm->dlm_name,
227 224 (int16_t)val);
228 225 break;
229 226 case MEMTYPE_INT32:
230 227 errno = nvlist_add_int32(nvl, (char *)dlm->dlm_name,
231 228 (int32_t)val);
232 229 break;
233 230 case MEMTYPE_INT64:
234 231 errno = nvlist_add_int64(nvl, (char *)dlm->dlm_name,
235 232 (int64_t)val);
236 233 }
237 234
238 235 if (errno != 0)
239 236 die("failed to add member %s\n", dlm->dlm_name);
240 237
241 238 return (0);
242 239 }
243 240
244 241 static int
245 242 inj_defn_memcmp_unsigned(const intr_t *intr, inj_declmem_t *dlm,
246 243 inj_defnmem_t *dfm, nvlist_t *nvl)
247 244 {
248 245 u_longlong_t val;
249 246
250 247 if (dfm->dfm_type != DEFNMEM_IMM && dfm->dfm_type != DEFNMEM_IDENT)
251 248 return (inj_set_errno(EINVAL));
252 249
253 250 if (inj_strtoull(dfm->dfm_str, intr->ei_width, &val) < 0)
254 251 return (-1); /* errno is set for us */
255 252
256 253 switch (dlm->dlm_type) {
257 254 case MEMTYPE_UINT8:
258 255 errno = nvlist_add_uint8(nvl, (char *)dlm->dlm_name,
259 256 (uint8_t)val);
260 257 break;
261 258 case MEMTYPE_UINT16:
262 259 errno = nvlist_add_uint16(nvl, (char *)dlm->dlm_name,
263 260 (uint16_t)val);
264 261 break;
265 262 case MEMTYPE_UINT32:
266 263 errno = nvlist_add_uint32(nvl, (char *)dlm->dlm_name,
267 264 (uint32_t)val);
268 265 break;
269 266 case MEMTYPE_UINT64:
270 267 errno = nvlist_add_uint64(nvl, (char *)dlm->dlm_name,
271 268 (uint64_t)val);
272 269 }
273 270
274 271 if (errno != 0)
275 272 die("failed to add member %s\n", dlm->dlm_name);
276 273
277 274 return (0);
278 275 }
279 276
280 277 /* Validate an array of (un)signed integers. */
281 278 static int
282 279 inj_defn_memcmp_intr_array(const intr_t *cont, inj_declmem_t *dlm,
283 280 inj_defnmem_t *dfm, nvlist_t *nvl)
284 281 {
285 282 typedef int (*adder_t)();
286 283 static const adder_t signed_adders[] = {
287 284 NULL, nvlist_add_int8_array, nvlist_add_int16_array,
288 285 NULL, nvlist_add_int32_array, NULL, NULL, NULL,
289 286 nvlist_add_int64_array
290 287 };
291 288 static const adder_t unsigned_adders[] = {
292 289 NULL,
293 290 nvlist_add_uint8_array, nvlist_add_uint16_array,
294 291 NULL, nvlist_add_uint32_array, NULL, NULL, NULL,
295 292 nvlist_add_uint64_array
296 293 };
297 294
298 295 union {
299 296 char *a;
300 297 int8_t *a8; uint8_t *au8;
301 298 int16_t *a16; uint16_t *au16;
302 299 int32_t *a32; uint32_t *au32;
303 300 int64_t *a64; uint64_t *au64;
304 301 } a;
305 302
306 303 int (*adder)(nvlist_t *, const char *, char *, uint_t);
307 304 size_t nelems;
308 305 inj_defnmem_t *elem;
309 306 char *arrbase, *arr;
310 307 size_t arrsz;
311 308 int err = 0;
312 309 int i;
313 310
314 311 if (dfm->dfm_type != DEFNMEM_ARRAY)
315 312 return (inj_set_errno(EINVAL));
316 313
317 314 /*
318 315 * Each nvlist array adder wants an array of its own type as input,
319 316 * which is reasonable, but it complicates our general implementation.
320 317 * We fight back with casting magic.
321 318 */
322 319
323 320 nelems = array_dim_check(dlm, dfm);
324 321 arrsz = (nelems + 1) * (cont->ei_width / NBBY);
325 322 arrbase = inj_zalloc(arrsz);
326 323 a.a = arr = (char *)P2ROUNDUP((uintptr_t)arrbase,
327 324 cont->ei_width / NBBY);
328 325
329 326 adder = (cont->ei_signed ? signed_adders :
330 327 unsigned_adders)[cont->ei_width / NBBY];
331 328 assert(adder != NULL);
332 329
333 330 for (i = 1, elem = inj_list_next(&dfm->dfm_list); elem != NULL;
334 331 elem = inj_list_next(elem), i++) {
335 332 if (elem->dfm_type != DEFNMEM_IMM &&
336 333 elem->dfm_type != DEFNMEM_IDENT) {
337 334 yyerror(" %d: array cell %d is invalid\n",
338 335 dfm->dfm_lineno, i);
339 336 err++;
340 337 continue;
341 338 }
342 339
343 340 if (cont->ei_signed) {
344 341 longlong_t val;
345 342
346 343 if (inj_strtoll(elem->dfm_str, cont->ei_width,
347 344 &val) < 0) {
348 345 yyerror(" %d: array cell %d %s\n",
349 346 dfm->dfm_lineno, i, (errno == ERANGE ?
350 347 "out of range for type" : "invalid"));
351 348 err++;
352 349 continue;
353 350 }
354 351
355 352 switch (cont->ei_width) {
356 353 case 8:
357 354 *a.a8++ = (int8_t)val;
358 355 break;
359 356 case 16:
360 357 *a.a16++ = (int16_t)val;
361 358 break;
362 359 case 32:
363 360 *a.a32++ = (int32_t)val;
364 361 break;
365 362 default:
366 363 *a.a64++ = (int64_t)val;
367 364 }
368 365
369 366 } else {
370 367 u_longlong_t val;
371 368
372 369 if (inj_strtoull(elem->dfm_str, cont->ei_width,
373 370 &val) < 0) {
374 371 yyerror(" %d: array cell %d %s\n",
375 372 dfm->dfm_lineno, i, (errno == ERANGE ?
376 373 "out of range for type" : "invalid"));
377 374 err++;
378 375 continue;
379 376 }
380 377
381 378 switch (cont->ei_width) {
382 379 case 8:
383 380 *a.au8++ = (uint8_t)val;
384 381 break;
385 382 case 16:
386 383 *a.au16++ = (uint16_t)val;
387 384 break;
388 385 case 32:
389 386 *a.au32++ = (uint32_t)val;
390 387 break;
391 388 default:
392 389 *a.au64++ = (uint64_t)val;
393 390 }
394 391 }
395 392 }
396 393
397 394 if (err == 0 && (errno = adder(nvl, dlm->dlm_name, arr, nelems)) != 0)
398 395 die("failed to add array member %s", dlm->dlm_name);
399 396
400 397 inj_free(arrbase, arrsz);
401 398
402 399 if (err != 0)
403 400 return (inj_set_errno(EINVAL));
404 401
405 402 return (0);
406 403 }
407 404
408 405 static int
409 406 bool2val(const char *str, boolean_t *valp)
410 407 {
411 408 if (strcasecmp(str, "true") == 0)
412 409 *valp = 1;
413 410 else if (strcasecmp(str, "false") == 0)
414 411 *valp = 0;
415 412 else
416 413 return (-1);
417 414
418 415 return (0);
419 416 }
420 417
421 418 static int
422 419 inj_defn_memcmp_bool(inj_declmem_t *dlm, inj_defnmem_t *dfm, nvlist_t *nvl)
423 420 {
424 421 boolean_t val;
425 422
426 423 if (dfm->dfm_type != DEFNMEM_IDENT)
427 424 return (inj_set_errno(EINVAL));
428 425
429 426 if (bool2val(dfm->dfm_str, &val) < 0)
430 427 return (inj_set_errno(EINVAL));
431 428
432 429 if ((errno = nvlist_add_boolean_value(nvl, (char *)dlm->dlm_name,
433 430 val)) != 0)
434 431 die("failed to add boolean member %s", dlm->dlm_name);
435 432
436 433 return (0);
437 434 }
438 435
439 436 static int
440 437 inj_defn_memcmp_bool_array(inj_declmem_t *dlm, inj_defnmem_t *dfm,
441 438 nvlist_t *nvl)
442 439 {
443 440 inj_defnmem_t *elem;
444 441 boolean_t *arr;
445 442 size_t nelems, arrsz;
446 443 int err = 0;
447 444 int i;
448 445
449 446 if (dfm->dfm_type != DEFNMEM_ARRAY)
450 447 return (inj_set_errno(EINVAL));
451 448
452 449 nelems = array_dim_check(dlm, dfm);
453 450 arrsz = nelems * sizeof (boolean_t);
454 451 arr = inj_zalloc(arrsz);
455 452
456 453 for (i = 0, elem = inj_list_next(&dfm->dfm_list); elem != NULL;
457 454 elem = inj_list_next(elem), i++) {
458 455 if (elem->dfm_type != DEFNMEM_IDENT) {
459 456 yyerror(" %d: array cell %d is invalid\n",
460 457 dfm->dfm_lineno, i + 1);
461 458 err++;
462 459 continue;
463 460 }
464 461
465 462 if (bool2val(elem->dfm_str, &arr[i]) < 0)
466 463 return (inj_set_errno(EINVAL));
467 464 }
468 465
469 466 if (err == 0 && (errno = nvlist_add_boolean_array(nvl,
470 467 (char *)dlm->dlm_name, arr, nelems)) != 0)
471 468 die("failed to add boolean array member %s", dlm->dlm_name);
472 469
473 470 inj_free(arr, arrsz);
474 471
475 472 return (0);
476 473 }
477 474
478 475 /* Used for both strings and enums */
479 476 static int
480 477 inj_defn_memcmp_strenum(inj_declmem_t *dlm, inj_defnmem_t *dfm, nvlist_t *nvl)
481 478 {
482 479 inj_defnmemtype_t defnmemtype = (dlm->dlm_type == MEMTYPE_ENUM ?
483 480 DEFNMEM_IDENT : DEFNMEM_QSTRING);
484 481 const char *strenum = (dlm->dlm_type == MEMTYPE_ENUM ? "enum" :
485 482 "string");
486 483
487 484 if (dfm->dfm_type != defnmemtype)
488 485 return (inj_set_errno(EINVAL));
489 486
490 487 if ((errno = nvlist_add_string(nvl, (char *)dlm->dlm_name,
491 488 (char *)dfm->dfm_str)) != 0)
492 489 die("failed to add %s member %s", strenum, dlm->dlm_name);
493 490
494 491 return (0);
495 492 }
496 493
497 494 static int
498 495 inj_defn_memcmp_strenum_array(inj_declmem_t *dlm, inj_defnmem_t *dfm,
499 496 nvlist_t *nvl)
500 497 {
501 498 inj_defnmemtype_t defnmemtype = (dlm->dlm_type == MEMTYPE_ENUM ?
502 499 DEFNMEM_IDENT : DEFNMEM_QSTRING);
503 500 const char *strenum = (dlm->dlm_type == MEMTYPE_ENUM ? "enum" :
504 501 "string");
505 502
506 503 inj_defnmem_t *elem;
507 504 size_t nelems, arrsz;
508 505 const char **arr;
509 506 int err = 0;
510 507 int i;
511 508
512 509 if (dfm->dfm_type != DEFNMEM_ARRAY)
513 510 return (inj_set_errno(EINVAL));
514 511
515 512 nelems = array_dim_check(dlm, dfm);
516 513 arrsz = nelems * sizeof (char *);
517 514 arr = inj_zalloc(arrsz);
518 515
519 516 for (i = 0, elem = inj_list_next(&dfm->dfm_list); elem != NULL;
520 517 elem = inj_list_next(elem), i++) {
521 518 if (elem->dfm_type != defnmemtype) {
522 519 yyerror(" %d: array cell %d is invalid\n",
523 520 dfm->dfm_lineno, i + 1);
524 521 err++;
525 522 continue;
526 523 }
527 524
528 525 if (dlm->dlm_type == MEMTYPE_ENUM &&
529 526 inj_strhash_lookup(dlm->dlm_enumvals, elem->dfm_str) ==
530 527 NULL) {
531 528 yyerror(" %d: invalid enum value %s\n",
532 529 dfm->dfm_lineno, elem->dfm_str);
533 530 err++;
534 531 continue;
535 532 }
536 533
537 534 arr[i] = elem->dfm_str;
538 535 }
539 536
540 537 if (err == 0 && (errno = nvlist_add_string_array(nvl,
541 538 dlm->dlm_name, (char **)arr, nelems)) != 0)
542 539 die("failed to add %s array member %s", strenum, dlm->dlm_name);
543 540
544 541 inj_free(arr, arrsz);
545 542 return (0);
546 543 }
547 544
548 545 /*
549 546 * Validator for embedded lists (events, fmris, authorities, lists, etc.).
550 547 * There are two cases to deal with here. The user could either have provided
551 548 * the name of a previously-defined list, in which case we just make a copy of
552 549 * said list for insertion into ours. Alternatively, the user could simply
553 550 * define a new list here. In that case, we recursively invoke the member
554 551 * comparator, but against the list type for the member being defined.
555 552 */
556 553 static nvlist_t *inj_defn_validate_memlist(inj_declmem_t *, inj_defnmem_t *);
557 554
558 555 /* Embedded definition */
559 556 static nvlist_t *
560 557 inj_defn_memcmp_sub_list(inj_declmem_t *dlm, inj_defnmem_t *dfm)
561 558 {
562 559 inj_declmem_t *subdlm = inj_list_next(&dlm->dlm_decl->decl_members);
563 560 inj_defnmem_t *subdfm = inj_list_next(&dfm->dfm_list);
564 561
565 562 return (inj_defn_validate_memlist(subdlm, subdfm));
566 563 }
567 564
568 565 /* Reference to previously-defined thing */
569 566 static nvlist_t *
570 567 inj_defn_memcmp_sub_defined(inj_declmem_t *dlm, inj_defnmem_t *dfm)
571 568 {
572 569 inj_defn_t *subdefn;
573 570 nvlist_t *new;
574 571
575 572 if ((subdefn = inj_defn_lookup(dfm->dfm_str, dlm->dlm_type)) == NULL) {
576 573 yyerror(" %d: reference to undefined %s %s\n", dfm->dfm_lineno,
577 574 inj_mem2str(dlm->dlm_type), dfm->dfm_str);
578 575 (void) inj_set_errno(EINVAL);
579 576 return (NULL);
580 577 }
581 578
582 579 if (subdefn->defn_decl != dlm->dlm_decl) {
583 580 yyerror(" %d: %s %s is not a(n) %s\n", dfm->dfm_lineno,
584 581 inj_mem2str(dlm->dlm_type), dfm->dfm_str,
585 582 subdefn->defn_decl->decl_name);
586 583 (void) inj_set_errno(EINVAL);
587 584 return (NULL);
588 585 }
589 586
590 587 assert(subdefn->defn_nvl != NULL);
591 588
592 589 if ((errno = nvlist_dup(subdefn->defn_nvl, &new, 0)) != 0) {
593 590 die("failed to duplicate %s list %s",
594 591 inj_item2str(subdefn->defn_decl->decl_type), dfm->dfm_str);
595 592 }
596 593
597 594 return (new);
598 595 }
599 596
600 597 static nvlist_t *
601 598 inj_defn_memcmp_sub_makenvl(inj_declmem_t *dlm, inj_defnmem_t *dfm)
602 599 {
603 600 inj_defnmemtype_t dftype = dfm->dfm_type;
604 601 inj_memtype_t dltype = dlm->dlm_type;
605 602 nvlist_t *new = NULL;
606 603
607 604 if (dftype == DEFNMEM_LIST)
608 605 new = inj_defn_memcmp_sub_list(dlm, dfm);
609 606 else if (dftype == DEFNMEM_IDENT && (dltype == MEMTYPE_EVENT ||
610 607 dltype == MEMTYPE_FMRI || dltype == MEMTYPE_AUTH))
611 608 new = inj_defn_memcmp_sub_defined(dlm, dfm);
612 609 else
613 610 (void) inj_set_errno(EINVAL);
614 611
615 612 return (new);
616 613 }
617 614
618 615 /* A single sub-list */
619 616 static int
620 617 inj_defn_memcmp_sub(inj_declmem_t *dlm, inj_defnmem_t *dfm, nvlist_t *nvl)
621 618 {
622 619 nvlist_t *new;
623 620
624 621 if ((new = inj_defn_memcmp_sub_makenvl(dlm, dfm)) == NULL)
625 622 return (-1); /* errno is set for us */
626 623
627 624 if ((errno = nvlist_add_nvlist(nvl, (char *)dlm->dlm_name,
628 625 new)) != 0)
629 626 die("failed to add list member %s", dlm->dlm_name);
630 627
631 628 return (0);
632 629 }
633 630
634 631 /* An array of sub-lists (for example, an array of events of a given type) */
635 632 static int
636 633 inj_defn_memcmp_sub_array(inj_declmem_t *dlm, inj_defnmem_t *dfm, nvlist_t *nvl)
637 634 {
638 635 size_t nelems, arrsz;
639 636 inj_defnmem_t *elem;
640 637 nvlist_t **arr;
641 638 int err = 0;
642 639 int i;
643 640
644 641 if (dfm->dfm_type != DEFNMEM_ARRAY)
645 642 return (inj_set_errno(EINVAL));
646 643
647 644 nelems = array_dim_check(dlm, dfm);
648 645 arrsz = nelems * sizeof (char *);
649 646 arr = inj_zalloc(arrsz);
650 647
651 648 for (i = 0, elem = inj_list_next(&dfm->dfm_list); elem != NULL;
652 649 elem = inj_list_next(elem), i++) {
653 650 if ((arr[i] = inj_defn_memcmp_sub_makenvl(dlm, elem)) == NULL) {
654 651 yyerror(" %d: array cell %d is invalid\n",
655 652 elem->dfm_lineno, i + 1);
656 653 err++;
657 654 continue;
658 655 }
659 656 }
660 657
661 658 if (err == 0 && (errno = nvlist_add_nvlist_array(nvl,
662 659 (char *)dlm->dlm_name, arr, nelems)) != 0)
663 660 die("failed to add nvlist list member %s", dlm->dlm_name);
664 661
665 662 inj_free(arr, arrsz);
666 663
667 664 return (0);
668 665 }
669 666
670 667 /*
671 668 * The declaration-definition member comparator. Designed to recursive
672 669 * invocation to allow for the validation of embedded/referenced lists.
673 670 */
674 671 nvlist_t *
675 672 inj_defn_validate_memlist(inj_declmem_t *dlm, inj_defnmem_t *dfm)
676 673 {
677 674 const intr_t *intr;
678 675 nvlist_t *nvl;
679 676 int rc, nmem, dlnmem, dfnmem;
680 677 int err = 0;
681 678
682 679 if ((errno = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
683 680 die("failed to allocate nvl for event");
684 681
685 682 for (nmem = 1; dlm != NULL && dfm != NULL;
686 683 dlm = inj_list_next(dlm), dfm = inj_list_next(dfm), nmem++) {
687 684
688 685 switch (dlm->dlm_type) {
689 686 case MEMTYPE_INT8:
690 687 case MEMTYPE_INT16:
691 688 case MEMTYPE_INT32:
692 689 case MEMTYPE_INT64:
693 690 intr = &inj_intrinsics[dlm->dlm_type];
694 691
695 692 if (dlm->dlm_flags & DECLMEM_F_ARRAY) {
696 693 rc = inj_defn_memcmp_intr_array(intr, dlm, dfm,
697 694 nvl);
698 695 } else {
699 696 rc = inj_defn_memcmp_signed(intr, dlm, dfm,
700 697 nvl);
701 698 }
702 699 break;
703 700
704 701 case MEMTYPE_UINT8:
705 702 case MEMTYPE_UINT16:
706 703 case MEMTYPE_UINT32:
707 704 case MEMTYPE_UINT64:
708 705 intr = &inj_intrinsics[dlm->dlm_type];
709 706
710 707 if (dlm->dlm_flags & DECLMEM_F_ARRAY) {
711 708 rc = inj_defn_memcmp_intr_array(intr, dlm, dfm,
712 709 nvl);
713 710 } else {
714 711 rc = inj_defn_memcmp_unsigned(intr, dlm, dfm,
715 712 nvl);
716 713 }
717 714 break;
718 715
719 716 case MEMTYPE_BOOL:
720 717 if (dlm->dlm_flags & DECLMEM_F_ARRAY)
721 718 rc = inj_defn_memcmp_bool_array(dlm, dfm, nvl);
722 719 else
723 720 rc = inj_defn_memcmp_bool(dlm, dfm, nvl);
724 721 break;
725 722
726 723 case MEMTYPE_STRING:
727 724 if (dlm->dlm_flags & DECLMEM_F_ARRAY) {
728 725 rc = inj_defn_memcmp_strenum_array(dlm, dfm,
729 726 nvl);
730 727 } else
731 728 rc = inj_defn_memcmp_strenum(dlm, dfm, nvl);
732 729 break;
733 730
734 731 case MEMTYPE_ENUM:
735 732 if (dlm->dlm_flags & DECLMEM_F_ARRAY) {
736 733 rc = inj_defn_memcmp_strenum_array(dlm, dfm,
737 734 nvl);
738 735 } else
739 736 rc = inj_defn_memcmp_strenum(dlm, dfm, nvl);
740 737 break;
741 738
742 739 case MEMTYPE_EVENT:
743 740 case MEMTYPE_FMRI:
744 741 case MEMTYPE_AUTH:
745 742 case MEMTYPE_LIST:
746 743 if (dlm->dlm_flags & DECLMEM_F_ARRAY)
747 744 rc = inj_defn_memcmp_sub_array(dlm, dfm, nvl);
748 745 else
749 746 rc = inj_defn_memcmp_sub(dlm, dfm, nvl);
750 747 break;
751 748
752 749 default:
753 750 die("unknown decl member type %d on member %s\n",
754 751 dlm->dlm_type, dlm->dlm_name);
755 752 }
756 753
757 754 if (rc < 0) {
758 755 yyerror(" %d: %s for member %s\n", dfm->dfm_lineno,
759 756 (errno == ERANGE ? "value out of range" :
760 757 "invalid value"), dlm->dlm_name);
761 758 err++;
762 759 }
763 760 }
764 761
765 762 dlnmem = dfnmem = nmem;
766 763
767 764 while (dlm != NULL) {
768 765 dlm = inj_list_next(dlm);
769 766 dlnmem++;
770 767 }
771 768
772 769 while (dfm != NULL) {
773 770 dfm = inj_list_next(dfm);
774 771 dfnmem++;
775 772 }
776 773
777 774 if (dlnmem != dfnmem) {
778 775 yyerror("%d members found, expected %d", dfnmem, dlnmem);
779 776 err++;
780 777 }
781 778
782 779 if (err > 0) {
783 780 nvlist_free(nvl);
784 781 return (NULL);
785 782 }
786 783
787 784 return (nvl);
788 785 }
789 786
790 787 /*
791 788 * The members have all been defined. Validate the members against the
792 789 * declaration, and add it to the appropriate "defined" list.
793 790 */
794 791 void
795 792 inj_defn_finish(inj_defn_t *defn, const char *declnm, const char *name,
796 793 inj_itemtype_t type)
797 794 {
798 795 inj_decl_t *decl = inj_decl_lookup(declnm, type);
799 796 inj_hash_t *hash = item2hash(type);
800 797 inj_declmem_t *dlm;
801 798 inj_defnmem_t *dfm;
802 799 inj_var_t *v;
803 800
804 801 defn->defn_name = name;
805 802 defn->defn_decl = decl;
806 803
807 804 if (decl == NULL) {
808 805 yyerror("unknown %s type %s\n", inj_item2str(type), declnm);
809 806 inj_defn_destroy(defn);
810 807 return;
811 808 }
812 809
813 810 dlm = inj_list_next(&decl->decl_members);
814 811 dfm = inj_list_next(&defn->defn_members);
815 812
816 813 if ((defn->defn_nvl = inj_defn_validate_memlist(dlm, dfm)) == NULL) {
817 814 inj_defn_destroy(defn);
818 815 return;
819 816 }
820 817
821 818 if (type == ITEMTYPE_EVENT) {
822 819 if ((errno = nvlist_add_string(defn->defn_nvl, "class",
823 820 (char *)defn->defn_decl->decl_name)) != 0)
824 821 die("failed to add class to %s", name);
825 822 }
826 823
827 824 if ((v = inj_strhash_lookup(hash, name)) != NULL) {
828 825 inj_defn_t *other = inj_hash_get_cookie(v);
829 826
830 827 yyerror("duplicate %s name %s (other on line %d)\n",
831 828 inj_item2str(type), name, other->defn_lineno);
832 829 inj_defn_destroy(defn);
833 830 return;
834 831 }
835 832
836 833 (void) inj_strhash_insert(hash, name, (uintptr_t)defn);
837 834 }
↓ open down ↓ |
719 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX