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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <unistd.h> 29 #include <strings.h> 30 #include <sys/types.h> 31 #include <sys/inttypes.h> 32 #include "libnvpair.h" 33 34 /* 35 * libnvpair - A tools library for manipulating <name, value> pairs. 36 * 37 * This library provides routines packing an unpacking nv pairs 38 * for transporting data across process boundaries, transporting 39 * between kernel and userland, and possibly saving onto disk files. 40 */ 41 42 static void 43 indent(FILE *fp, int depth) 44 { 45 while (depth-- > 0) 46 (void) fprintf(fp, "\t"); 47 } 48 49 /* 50 * nvlist_print - Prints elements in an event buffer 51 */ 52 static 53 void 54 nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth) 55 { 56 int i; 57 char *name; 58 uint_t nelem; 59 nvpair_t *nvp; 60 61 if (nvl == NULL) 62 return; 63 64 indent(fp, depth); 65 (void) fprintf(fp, "nvlist version: %d\n", NVL_VERSION(nvl)); 66 67 nvp = nvlist_next_nvpair(nvl, NULL); 68 69 while (nvp) { 70 data_type_t type = nvpair_type(nvp); 71 72 indent(fp, depth); 73 name = nvpair_name(nvp); 74 (void) fprintf(fp, "\t%s =", name); 75 nelem = 0; 76 switch (type) { 77 case DATA_TYPE_BOOLEAN: { 78 (void) fprintf(fp, " 1"); 79 break; 80 } 81 case DATA_TYPE_BOOLEAN_VALUE: { 82 boolean_t val; 83 (void) nvpair_value_boolean_value(nvp, &val); 84 (void) fprintf(fp, " %d", val); 85 break; 86 } 87 case DATA_TYPE_BYTE: { 88 uchar_t val; 89 (void) nvpair_value_byte(nvp, &val); 90 (void) fprintf(fp, " 0x%2.2x", val); 91 break; 92 } 93 case DATA_TYPE_INT8: { 94 int8_t val; 95 (void) nvpair_value_int8(nvp, &val); 96 (void) fprintf(fp, " %d", val); 97 break; 98 } 99 case DATA_TYPE_UINT8: { 100 uint8_t val; 101 (void) nvpair_value_uint8(nvp, &val); 102 (void) fprintf(fp, " 0x%x", val); 103 break; 104 } 105 case DATA_TYPE_INT16: { 106 int16_t val; 107 (void) nvpair_value_int16(nvp, &val); 108 (void) fprintf(fp, " %d", val); 109 break; 110 } 111 case DATA_TYPE_UINT16: { 112 uint16_t val; 113 (void) nvpair_value_uint16(nvp, &val); 114 (void) fprintf(fp, " 0x%x", val); 115 break; 116 } 117 case DATA_TYPE_INT32: { 118 int32_t val; 119 (void) nvpair_value_int32(nvp, &val); 120 (void) fprintf(fp, " %d", val); 121 break; 122 } 123 case DATA_TYPE_UINT32: { 124 uint32_t val; 125 (void) nvpair_value_uint32(nvp, &val); 126 (void) fprintf(fp, " 0x%x", val); 127 break; 128 } 129 case DATA_TYPE_INT64: { 130 int64_t val; 131 (void) nvpair_value_int64(nvp, &val); 132 (void) fprintf(fp, " %lld", (longlong_t)val); 133 break; 134 } 135 case DATA_TYPE_UINT64: { 136 uint64_t val; 137 (void) nvpair_value_uint64(nvp, &val); 138 (void) fprintf(fp, " 0x%llx", (u_longlong_t)val); 139 break; 140 } 141 case DATA_TYPE_DOUBLE: { 142 double val; 143 (void) nvpair_value_double(nvp, &val); 144 (void) fprintf(fp, " 0x%llf", val); 145 break; 146 } 147 case DATA_TYPE_STRING: { 148 char *val; 149 (void) nvpair_value_string(nvp, &val); 150 (void) fprintf(fp, " %s", val); 151 break; 152 } 153 case DATA_TYPE_BOOLEAN_ARRAY: { 154 boolean_t *val; 155 (void) nvpair_value_boolean_array(nvp, &val, &nelem); 156 for (i = 0; i < nelem; i++) 157 (void) fprintf(fp, " %d", val[i]); 158 break; 159 } 160 case DATA_TYPE_BYTE_ARRAY: { 161 uchar_t *val; 162 (void) nvpair_value_byte_array(nvp, &val, &nelem); 163 for (i = 0; i < nelem; i++) 164 (void) fprintf(fp, " 0x%2.2x", val[i]); 165 break; 166 } 167 case DATA_TYPE_INT8_ARRAY: { 168 int8_t *val; 169 (void) nvpair_value_int8_array(nvp, &val, &nelem); 170 for (i = 0; i < nelem; i++) 171 (void) fprintf(fp, " %d", val[i]); 172 break; 173 } 174 case DATA_TYPE_UINT8_ARRAY: { 175 uint8_t *val; 176 (void) nvpair_value_uint8_array(nvp, &val, &nelem); 177 for (i = 0; i < nelem; i++) 178 (void) fprintf(fp, " 0x%x", val[i]); 179 break; 180 } 181 case DATA_TYPE_INT16_ARRAY: { 182 int16_t *val; 183 (void) nvpair_value_int16_array(nvp, &val, &nelem); 184 for (i = 0; i < nelem; i++) 185 (void) fprintf(fp, " %d", val[i]); 186 break; 187 } 188 case DATA_TYPE_UINT16_ARRAY: { 189 uint16_t *val; 190 (void) nvpair_value_uint16_array(nvp, &val, &nelem); 191 for (i = 0; i < nelem; i++) 192 (void) fprintf(fp, " 0x%x", val[i]); 193 break; 194 } 195 case DATA_TYPE_INT32_ARRAY: { 196 int32_t *val; 197 (void) nvpair_value_int32_array(nvp, &val, &nelem); 198 for (i = 0; i < nelem; i++) 199 (void) fprintf(fp, " %d", val[i]); 200 break; 201 } 202 case DATA_TYPE_UINT32_ARRAY: { 203 uint32_t *val; 204 (void) nvpair_value_uint32_array(nvp, &val, &nelem); 205 for (i = 0; i < nelem; i++) 206 (void) fprintf(fp, " 0x%x", val[i]); 207 break; 208 } 209 case DATA_TYPE_INT64_ARRAY: { 210 int64_t *val; 211 (void) nvpair_value_int64_array(nvp, &val, &nelem); 212 for (i = 0; i < nelem; i++) 213 (void) fprintf(fp, " %lld", (longlong_t)val[i]); 214 break; 215 } 216 case DATA_TYPE_UINT64_ARRAY: { 217 uint64_t *val; 218 (void) nvpair_value_uint64_array(nvp, &val, &nelem); 219 for (i = 0; i < nelem; i++) 220 (void) fprintf(fp, " 0x%llx", 221 (u_longlong_t)val[i]); 222 break; 223 } 224 case DATA_TYPE_STRING_ARRAY: { 225 char **val; 226 (void) nvpair_value_string_array(nvp, &val, &nelem); 227 for (i = 0; i < nelem; i++) 228 (void) fprintf(fp, " %s", val[i]); 229 break; 230 } 231 case DATA_TYPE_HRTIME: { 232 hrtime_t val; 233 (void) nvpair_value_hrtime(nvp, &val); 234 (void) fprintf(fp, " 0x%llx", val); 235 break; 236 } 237 case DATA_TYPE_NVLIST: { 238 nvlist_t *val; 239 (void) nvpair_value_nvlist(nvp, &val); 240 (void) fprintf(fp, " (embedded nvlist)\n"); 241 nvlist_print_with_indent(fp, val, depth + 1); 242 indent(fp, depth + 1); 243 (void) fprintf(fp, "(end %s)\n", name); 244 break; 245 } 246 case DATA_TYPE_NVLIST_ARRAY: { 247 nvlist_t **val; 248 (void) nvpair_value_nvlist_array(nvp, &val, &nelem); 249 (void) fprintf(fp, " (array of embedded nvlists)\n"); 250 for (i = 0; i < nelem; i++) { 251 indent(fp, depth + 1); 252 (void) fprintf(fp, 253 "(start %s[%d])\n", name, i); 254 nvlist_print_with_indent(fp, val[i], depth + 1); 255 indent(fp, depth + 1); 256 (void) fprintf(fp, "(end %s[%d])\n", name, i); 257 } 258 break; 259 } 260 default: 261 (void) fprintf(fp, " unknown data type (%d)", type); 262 break; 263 } 264 (void) fprintf(fp, "\n"); 265 nvp = nvlist_next_nvpair(nvl, nvp); 266 } 267 } 268 269 void 270 nvlist_print(FILE *fp, nvlist_t *nvl) 271 { 272 nvlist_print_with_indent(fp, nvl, 0); 273 } 274 275 /* 276 * Determine if string 'value' matches 'nvp' value. The 'value' string is 277 * converted, depending on the type of 'nvp', prior to match. For numeric 278 * types, a radix independent sscanf conversion of 'value' is used. If 'nvp' 279 * is an array type, 'ai' is the index into the array against which we are 280 * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass 281 * in a regex_t compilation of value in 'value_regex' to trigger regular 282 * expression string match instead of simple strcmp(). 283 * 284 * Return 1 on match, 0 on no-match, and -1 on error. If the error is 285 * related to value syntax error and 'ep' is non-NULL, *ep will point into 286 * the 'value' string at the location where the error exists. 287 * 288 * NOTE: It may be possible to move the non-regex_t version of this into 289 * common code used by library/kernel/boot. 290 */ 291 int 292 nvpair_value_match_regex(nvpair_t *nvp, int ai, 293 char *value, regex_t *value_regex, char **ep) 294 { 295 char *evalue; 296 uint_t a_len; 297 int sr; 298 299 if (ep) 300 *ep = NULL; 301 302 if ((nvp == NULL) || (value == NULL)) 303 return (-1); /* error fail match - invalid args */ 304 305 /* make sure array and index combination make sense */ 306 if ((nvpair_type_is_array(nvp) && (ai < 0)) || 307 (!nvpair_type_is_array(nvp) && (ai >= 0))) 308 return (-1); /* error fail match - bad index */ 309 310 /* non-string values should be single 'chunk' */ 311 if ((nvpair_type(nvp) != DATA_TYPE_STRING) && 312 (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) { 313 value += strspn(value, " \t"); 314 evalue = value + strcspn(value, " \t"); 315 if (*evalue) { 316 if (ep) 317 *ep = evalue; 318 return (-1); /* error fail match - syntax */ 319 } 320 } 321 322 sr = EOF; 323 switch (nvpair_type(nvp)) { 324 case DATA_TYPE_STRING: { 325 char *val; 326 327 /* check string value for match */ 328 if (nvpair_value_string(nvp, &val) == 0) { 329 if (value_regex) { 330 if (regexec(value_regex, val, 331 (size_t)0, NULL, 0) == 0) 332 return (1); /* match */ 333 } else { 334 if (strcmp(value, val) == 0) 335 return (1); /* match */ 336 } 337 } 338 break; 339 } 340 case DATA_TYPE_STRING_ARRAY: { 341 char **val_array; 342 343 /* check indexed string value of array for match */ 344 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) && 345 (ai < a_len)) { 346 if (value_regex) { 347 if (regexec(value_regex, val_array[ai], 348 (size_t)0, NULL, 0) == 0) 349 return (1); 350 } else { 351 if (strcmp(value, val_array[ai]) == 0) 352 return (1); 353 } 354 } 355 break; 356 } 357 case DATA_TYPE_BYTE: { 358 uchar_t val, val_arg; 359 360 /* scanf uchar_t from value and check for match */ 361 sr = sscanf(value, "%c", &val_arg); 362 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) && 363 (val == val_arg)) 364 return (1); 365 break; 366 } 367 case DATA_TYPE_BYTE_ARRAY: { 368 uchar_t *val_array, val_arg; 369 370 371 /* check indexed value of array for match */ 372 sr = sscanf(value, "%c", &val_arg); 373 if ((sr == 1) && 374 (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) && 375 (ai < a_len) && 376 (val_array[ai] == val_arg)) 377 return (1); 378 break; 379 } 380 case DATA_TYPE_INT8: { 381 int8_t val, val_arg; 382 383 /* scanf int8_t from value and check for match */ 384 sr = sscanf(value, "%"SCNi8, &val_arg); 385 if ((sr == 1) && 386 (nvpair_value_int8(nvp, &val) == 0) && 387 (val == val_arg)) 388 return (1); 389 break; 390 } 391 case DATA_TYPE_INT8_ARRAY: { 392 int8_t *val_array, val_arg; 393 394 /* check indexed value of array for match */ 395 sr = sscanf(value, "%"SCNi8, &val_arg); 396 if ((sr == 1) && 397 (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) && 398 (ai < a_len) && 399 (val_array[ai] == val_arg)) 400 return (1); 401 break; 402 } 403 case DATA_TYPE_UINT8: { 404 uint8_t val, val_arg; 405 406 /* scanf uint8_t from value and check for match */ 407 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 408 if ((sr == 1) && 409 (nvpair_value_uint8(nvp, &val) == 0) && 410 (val == val_arg)) 411 return (1); 412 break; 413 } 414 case DATA_TYPE_UINT8_ARRAY: { 415 uint8_t *val_array, val_arg; 416 417 /* check indexed value of array for match */ 418 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 419 if ((sr == 1) && 420 (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) && 421 (ai < a_len) && 422 (val_array[ai] == val_arg)) 423 return (1); 424 break; 425 } 426 case DATA_TYPE_INT16: { 427 int16_t val, val_arg; 428 429 /* scanf int16_t from value and check for match */ 430 sr = sscanf(value, "%"SCNi16, &val_arg); 431 if ((sr == 1) && 432 (nvpair_value_int16(nvp, &val) == 0) && 433 (val == val_arg)) 434 return (1); 435 break; 436 } 437 case DATA_TYPE_INT16_ARRAY: { 438 int16_t *val_array, val_arg; 439 440 /* check indexed value of array for match */ 441 sr = sscanf(value, "%"SCNi16, &val_arg); 442 if ((sr == 1) && 443 (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) && 444 (ai < a_len) && 445 (val_array[ai] == val_arg)) 446 return (1); 447 break; 448 } 449 case DATA_TYPE_UINT16: { 450 uint16_t val, val_arg; 451 452 /* scanf uint16_t from value and check for match */ 453 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 454 if ((sr == 1) && 455 (nvpair_value_uint16(nvp, &val) == 0) && 456 (val == val_arg)) 457 return (1); 458 break; 459 } 460 case DATA_TYPE_UINT16_ARRAY: { 461 uint16_t *val_array, val_arg; 462 463 /* check indexed value of array for match */ 464 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 465 if ((sr == 1) && 466 (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) && 467 (ai < a_len) && 468 (val_array[ai] == val_arg)) 469 return (1); 470 break; 471 } 472 case DATA_TYPE_INT32: { 473 int32_t val, val_arg; 474 475 /* scanf int32_t from value and check for match */ 476 sr = sscanf(value, "%"SCNi32, &val_arg); 477 if ((sr == 1) && 478 (nvpair_value_int32(nvp, &val) == 0) && 479 (val == val_arg)) 480 return (1); 481 break; 482 } 483 case DATA_TYPE_INT32_ARRAY: { 484 int32_t *val_array, val_arg; 485 486 /* check indexed value of array for match */ 487 sr = sscanf(value, "%"SCNi32, &val_arg); 488 if ((sr == 1) && 489 (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) && 490 (ai < a_len) && 491 (val_array[ai] == val_arg)) 492 return (1); 493 break; 494 } 495 case DATA_TYPE_UINT32: { 496 uint32_t val, val_arg; 497 498 /* scanf uint32_t from value and check for match */ 499 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 500 if ((sr == 1) && 501 (nvpair_value_uint32(nvp, &val) == 0) && 502 (val == val_arg)) 503 return (1); 504 break; 505 } 506 case DATA_TYPE_UINT32_ARRAY: { 507 uint32_t *val_array, val_arg; 508 509 /* check indexed value of array for match */ 510 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 511 if ((sr == 1) && 512 (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) && 513 (ai < a_len) && 514 (val_array[ai] == val_arg)) 515 return (1); 516 break; 517 } 518 case DATA_TYPE_INT64: { 519 int64_t val, val_arg; 520 521 /* scanf int64_t from value and check for match */ 522 sr = sscanf(value, "%"SCNi64, &val_arg); 523 if ((sr == 1) && 524 (nvpair_value_int64(nvp, &val) == 0) && 525 (val == val_arg)) 526 return (1); 527 break; 528 } 529 case DATA_TYPE_INT64_ARRAY: { 530 int64_t *val_array, val_arg; 531 532 /* check indexed value of array for match */ 533 sr = sscanf(value, "%"SCNi64, &val_arg); 534 if ((sr == 1) && 535 (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) && 536 (ai < a_len) && 537 (val_array[ai] == val_arg)) 538 return (1); 539 break; 540 } 541 case DATA_TYPE_UINT64: { 542 uint64_t val_arg, val; 543 544 /* scanf uint64_t from value and check for match */ 545 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 546 if ((sr == 1) && 547 (nvpair_value_uint64(nvp, &val) == 0) && 548 (val == val_arg)) 549 return (1); 550 break; 551 } 552 case DATA_TYPE_UINT64_ARRAY: { 553 uint64_t *val_array, val_arg; 554 555 /* check indexed value of array for match */ 556 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 557 if ((sr == 1) && 558 (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) && 559 (ai < a_len) && 560 (val_array[ai] == val_arg)) 561 return (1); 562 break; 563 } 564 case DATA_TYPE_BOOLEAN_VALUE: { 565 boolean_t val, val_arg; 566 567 /* scanf boolean_t from value and check for match */ 568 sr = sscanf(value, "%"SCNi32, &val_arg); 569 if ((sr == 1) && 570 (nvpair_value_boolean_value(nvp, &val) == 0) && 571 (val == val_arg)) 572 return (1); 573 break; 574 } 575 case DATA_TYPE_BOOLEAN_ARRAY: { 576 boolean_t *val_array, val_arg; 577 578 /* check indexed value of array for match */ 579 sr = sscanf(value, "%"SCNi32, &val_arg); 580 if ((sr == 1) && 581 (nvpair_value_boolean_array(nvp, 582 &val_array, &a_len) == 0) && 583 (ai < a_len) && 584 (val_array[ai] == val_arg)) 585 return (1); 586 break; 587 } 588 case DATA_TYPE_HRTIME: 589 case DATA_TYPE_NVLIST: 590 case DATA_TYPE_NVLIST_ARRAY: 591 case DATA_TYPE_BOOLEAN: 592 case DATA_TYPE_DOUBLE: 593 case DATA_TYPE_UNKNOWN: 594 default: 595 /* 596 * unknown/unsupported data type 597 */ 598 return (-1); /* error fail match */ 599 } 600 601 /* 602 * check to see if sscanf failed conversion, return approximate 603 * pointer to problem 604 */ 605 if (sr != 1) { 606 if (ep) 607 *ep = value; 608 return (-1); /* error fail match - syntax */ 609 } 610 611 return (0); /* fail match */ 612 } 613 614 int 615 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep) 616 { 617 return (nvpair_value_match_regex(nvp, ai, value, NULL, ep)); 618 } 619