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