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, " %lld", (longlong_t)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%llx", (u_longlong_t)val); 138 break; 139 } 140 case DATA_TYPE_DOUBLE: { 141 double val; 142 (void) nvpair_value_double(nvp, &val); 143 (void) fprintf(fp, " 0x%llf", 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, " %lld", (longlong_t)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%llx", 220 (u_longlong_t)val[i]); 221 break; 222 } 223 case DATA_TYPE_STRING_ARRAY: { 224 char **val; 225 (void) nvpair_value_string_array(nvp, &val, &nelem); 226 for (i = 0; i < nelem; i++) 227 (void) fprintf(fp, " %s", val[i]); 228 break; 229 } 230 case DATA_TYPE_HRTIME: { 231 hrtime_t val; 232 (void) nvpair_value_hrtime(nvp, &val); 233 (void) fprintf(fp, " 0x%llx", val); 234 break; 235 } 236 case DATA_TYPE_NVLIST: { 237 nvlist_t *val; 238 (void) nvpair_value_nvlist(nvp, &val); 239 (void) fprintf(fp, " (embedded nvlist)\n"); 240 nvlist_print_with_indent(fp, val, depth + 1); 241 indent(fp, depth + 1); 242 (void) fprintf(fp, "(end %s)\n", name); 243 break; 244 } 245 case DATA_TYPE_NVLIST_ARRAY: { 246 nvlist_t **val; 247 (void) nvpair_value_nvlist_array(nvp, &val, &nelem); 248 (void) fprintf(fp, " (array of embedded nvlists)\n"); 249 for (i = 0; i < nelem; i++) { 250 indent(fp, depth + 1); 251 (void) fprintf(fp, 252 "(start %s[%d])\n", name, i); 253 nvlist_print_with_indent(fp, val[i], depth + 1); 254 indent(fp, depth + 1); 255 (void) fprintf(fp, "(end %s[%d])\n", name, i); 256 } 257 break; 258 } 259 default: 260 (void) fprintf(fp, " unknown data type (%d)", type); 261 break; 262 } 263 (void) fprintf(fp, "\n"); 264 nvp = nvlist_next_nvpair(nvl, nvp); 265 } 266 } 267 268 void 269 nvlist_print(FILE *fp, nvlist_t *nvl) 270 { 271 nvlist_print_with_indent(fp, nvl, 0); 272 } 273 274 275 #define NVP(elem, type, vtype, ptype, format) { \ 276 vtype value; \ 277 \ 278 (void) nvpair_value_##type(elem, &value); \ 279 (void) printf("%*s%s: " format "\n", indent, "", \ 280 nvpair_name(elem), (ptype)value); \ 281 } 282 283 #define NVPA(elem, type, vtype, ptype, format) { \ 284 uint_t i, count; \ 285 vtype *value; \ 286 \ 287 (void) nvpair_value_##type(elem, &value, &count); \ 288 for (i = 0; i < count; i++) { \ 289 (void) printf("%*s%s[%d]: " format "\n", indent, "", \ 290 nvpair_name(elem), i, (ptype)value[i]); \ 291 } \ 292 } 293 294 /* 295 * Similar to nvlist_print() but handles arrays slightly differently. 296 */ 297 void 298 dump_nvlist(nvlist_t *list, int indent) 299 { 300 nvpair_t *elem = NULL; 301 boolean_t bool_value; 302 nvlist_t *nvlist_value; 303 nvlist_t **nvlist_array_value; 304 uint_t i, count; 305 306 if (list == NULL) { 307 return; 308 } 309 310 while ((elem = nvlist_next_nvpair(list, elem)) != NULL) { 311 switch (nvpair_type(elem)) { 312 case DATA_TYPE_BOOLEAN_VALUE: 313 (void) nvpair_value_boolean_value(elem, &bool_value); 314 (void) printf("%*s%s: %s\n", indent, "", 315 nvpair_name(elem), bool_value ? "true" : "false"); 316 break; 317 318 case DATA_TYPE_BYTE: 319 NVP(elem, byte, uchar_t, int, "%u"); 320 break; 321 322 case DATA_TYPE_INT8: 323 NVP(elem, int8, int8_t, int, "%d"); 324 break; 325 326 case DATA_TYPE_UINT8: 327 NVP(elem, uint8, uint8_t, int, "%u"); 328 break; 329 330 case DATA_TYPE_INT16: 331 NVP(elem, int16, int16_t, int, "%d"); 332 break; 333 334 case DATA_TYPE_UINT16: 335 NVP(elem, uint16, uint16_t, int, "%u"); 336 break; 337 338 case DATA_TYPE_INT32: 339 NVP(elem, int32, int32_t, long, "%ld"); 340 break; 341 342 case DATA_TYPE_UINT32: 343 NVP(elem, uint32, uint32_t, ulong_t, "%lu"); 344 break; 345 346 case DATA_TYPE_INT64: 347 NVP(elem, int64, int64_t, longlong_t, "%lld"); 348 break; 349 350 case DATA_TYPE_UINT64: 351 NVP(elem, uint64, uint64_t, u_longlong_t, "%llu"); 352 break; 353 354 case DATA_TYPE_STRING: 355 NVP(elem, string, char *, char *, "'%s'"); 356 break; 357 358 case DATA_TYPE_BYTE_ARRAY: 359 NVPA(elem, byte_array, uchar_t, int, "%u"); 360 break; 361 362 case DATA_TYPE_INT8_ARRAY: 363 NVPA(elem, int8_array, int8_t, int, "%d"); 364 break; 365 366 case DATA_TYPE_UINT8_ARRAY: 367 NVPA(elem, uint8_array, uint8_t, int, "%u"); 368 break; 369 370 case DATA_TYPE_INT16_ARRAY: 371 NVPA(elem, int16_array, int16_t, int, "%d"); 372 break; 373 374 case DATA_TYPE_UINT16_ARRAY: 375 NVPA(elem, uint16_array, uint16_t, int, "%u"); 376 break; 377 378 case DATA_TYPE_INT32_ARRAY: 379 NVPA(elem, int32_array, int32_t, long, "%ld"); 380 break; 381 382 case DATA_TYPE_UINT32_ARRAY: 383 NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu"); 384 break; 385 386 case DATA_TYPE_INT64_ARRAY: 387 NVPA(elem, int64_array, int64_t, longlong_t, "%lld"); 388 break; 389 390 case DATA_TYPE_UINT64_ARRAY: 391 NVPA(elem, uint64_array, uint64_t, u_longlong_t, 392 "%llu"); 393 break; 394 395 case DATA_TYPE_STRING_ARRAY: 396 NVPA(elem, string_array, char *, char *, "'%s'"); 397 break; 398 399 case DATA_TYPE_NVLIST: 400 (void) nvpair_value_nvlist(elem, &nvlist_value); 401 (void) printf("%*s%s:\n", indent, "", 402 nvpair_name(elem)); 403 dump_nvlist(nvlist_value, indent + 4); 404 break; 405 406 case DATA_TYPE_NVLIST_ARRAY: 407 (void) nvpair_value_nvlist_array(elem, 408 &nvlist_array_value, &count); 409 for (i = 0; i < count; i++) { 410 (void) printf("%*s%s[%u]:\n", indent, "", 411 nvpair_name(elem), i); 412 dump_nvlist(nvlist_array_value[i], indent + 4); 413 } 414 break; 415 416 default: 417 (void) printf(dgettext(TEXT_DOMAIN, "bad config type " 418 "%d for %s\n"), nvpair_type(elem), 419 nvpair_name(elem)); 420 } 421 } 422 } 423 424 /* 425 * Determine if string 'value' matches 'nvp' value. The 'value' string is 426 * converted, depending on the type of 'nvp', prior to match. For numeric 427 * types, a radix independent sscanf conversion of 'value' is used. If 'nvp' 428 * is an array type, 'ai' is the index into the array against which we are 429 * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass 430 * in a regex_t compilation of value in 'value_regex' to trigger regular 431 * expression string match instead of simple strcmp(). 432 * 433 * Return 1 on match, 0 on no-match, and -1 on error. If the error is 434 * related to value syntax error and 'ep' is non-NULL, *ep will point into 435 * the 'value' string at the location where the error exists. 436 * 437 * NOTE: It may be possible to move the non-regex_t version of this into 438 * common code used by library/kernel/boot. 439 */ 440 int 441 nvpair_value_match_regex(nvpair_t *nvp, int ai, 442 char *value, regex_t *value_regex, char **ep) 443 { 444 char *evalue; 445 uint_t a_len; 446 int sr; 447 448 if (ep) 449 *ep = NULL; 450 451 if ((nvp == NULL) || (value == NULL)) 452 return (-1); /* error fail match - invalid args */ 453 454 /* make sure array and index combination make sense */ 455 if ((nvpair_type_is_array(nvp) && (ai < 0)) || 456 (!nvpair_type_is_array(nvp) && (ai >= 0))) 457 return (-1); /* error fail match - bad index */ 458 459 /* non-string values should be single 'chunk' */ 460 if ((nvpair_type(nvp) != DATA_TYPE_STRING) && 461 (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) { 462 value += strspn(value, " \t"); 463 evalue = value + strcspn(value, " \t"); 464 if (*evalue) { 465 if (ep) 466 *ep = evalue; 467 return (-1); /* error fail match - syntax */ 468 } 469 } 470 471 sr = EOF; 472 switch (nvpair_type(nvp)) { 473 case DATA_TYPE_STRING: { 474 char *val; 475 476 /* check string value for match */ 477 if (nvpair_value_string(nvp, &val) == 0) { 478 if (value_regex) { 479 if (regexec(value_regex, val, 480 (size_t)0, NULL, 0) == 0) 481 return (1); /* match */ 482 } else { 483 if (strcmp(value, val) == 0) 484 return (1); /* match */ 485 } 486 } 487 break; 488 } 489 case DATA_TYPE_STRING_ARRAY: { 490 char **val_array; 491 492 /* check indexed string value of array for match */ 493 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) && 494 (ai < a_len)) { 495 if (value_regex) { 496 if (regexec(value_regex, val_array[ai], 497 (size_t)0, NULL, 0) == 0) 498 return (1); 499 } else { 500 if (strcmp(value, val_array[ai]) == 0) 501 return (1); 502 } 503 } 504 break; 505 } 506 case DATA_TYPE_BYTE: { 507 uchar_t val, val_arg; 508 509 /* scanf uchar_t from value and check for match */ 510 sr = sscanf(value, "%c", &val_arg); 511 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) && 512 (val == val_arg)) 513 return (1); 514 break; 515 } 516 case DATA_TYPE_BYTE_ARRAY: { 517 uchar_t *val_array, val_arg; 518 519 520 /* check indexed value of array for match */ 521 sr = sscanf(value, "%c", &val_arg); 522 if ((sr == 1) && 523 (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) && 524 (ai < a_len) && 525 (val_array[ai] == val_arg)) 526 return (1); 527 break; 528 } 529 case DATA_TYPE_INT8: { 530 int8_t val, val_arg; 531 532 /* scanf int8_t from value and check for match */ 533 sr = sscanf(value, "%"SCNi8, &val_arg); 534 if ((sr == 1) && 535 (nvpair_value_int8(nvp, &val) == 0) && 536 (val == val_arg)) 537 return (1); 538 break; 539 } 540 case DATA_TYPE_INT8_ARRAY: { 541 int8_t *val_array, val_arg; 542 543 /* check indexed value of array for match */ 544 sr = sscanf(value, "%"SCNi8, &val_arg); 545 if ((sr == 1) && 546 (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) && 547 (ai < a_len) && 548 (val_array[ai] == val_arg)) 549 return (1); 550 break; 551 } 552 case DATA_TYPE_UINT8: { 553 uint8_t val, val_arg; 554 555 /* scanf uint8_t from value and check for match */ 556 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 557 if ((sr == 1) && 558 (nvpair_value_uint8(nvp, &val) == 0) && 559 (val == val_arg)) 560 return (1); 561 break; 562 } 563 case DATA_TYPE_UINT8_ARRAY: { 564 uint8_t *val_array, val_arg; 565 566 /* check indexed value of array for match */ 567 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 568 if ((sr == 1) && 569 (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) && 570 (ai < a_len) && 571 (val_array[ai] == val_arg)) 572 return (1); 573 break; 574 } 575 case DATA_TYPE_INT16: { 576 int16_t val, val_arg; 577 578 /* scanf int16_t from value and check for match */ 579 sr = sscanf(value, "%"SCNi16, &val_arg); 580 if ((sr == 1) && 581 (nvpair_value_int16(nvp, &val) == 0) && 582 (val == val_arg)) 583 return (1); 584 break; 585 } 586 case DATA_TYPE_INT16_ARRAY: { 587 int16_t *val_array, val_arg; 588 589 /* check indexed value of array for match */ 590 sr = sscanf(value, "%"SCNi16, &val_arg); 591 if ((sr == 1) && 592 (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) && 593 (ai < a_len) && 594 (val_array[ai] == val_arg)) 595 return (1); 596 break; 597 } 598 case DATA_TYPE_UINT16: { 599 uint16_t val, val_arg; 600 601 /* scanf uint16_t from value and check for match */ 602 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 603 if ((sr == 1) && 604 (nvpair_value_uint16(nvp, &val) == 0) && 605 (val == val_arg)) 606 return (1); 607 break; 608 } 609 case DATA_TYPE_UINT16_ARRAY: { 610 uint16_t *val_array, val_arg; 611 612 /* check indexed value of array for match */ 613 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 614 if ((sr == 1) && 615 (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) && 616 (ai < a_len) && 617 (val_array[ai] == val_arg)) 618 return (1); 619 break; 620 } 621 case DATA_TYPE_INT32: { 622 int32_t val, val_arg; 623 624 /* scanf int32_t from value and check for match */ 625 sr = sscanf(value, "%"SCNi32, &val_arg); 626 if ((sr == 1) && 627 (nvpair_value_int32(nvp, &val) == 0) && 628 (val == val_arg)) 629 return (1); 630 break; 631 } 632 case DATA_TYPE_INT32_ARRAY: { 633 int32_t *val_array, val_arg; 634 635 /* check indexed value of array for match */ 636 sr = sscanf(value, "%"SCNi32, &val_arg); 637 if ((sr == 1) && 638 (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) && 639 (ai < a_len) && 640 (val_array[ai] == val_arg)) 641 return (1); 642 break; 643 } 644 case DATA_TYPE_UINT32: { 645 uint32_t val, val_arg; 646 647 /* scanf uint32_t from value and check for match */ 648 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 649 if ((sr == 1) && 650 (nvpair_value_uint32(nvp, &val) == 0) && 651 (val == val_arg)) 652 return (1); 653 break; 654 } 655 case DATA_TYPE_UINT32_ARRAY: { 656 uint32_t *val_array, val_arg; 657 658 /* check indexed value of array for match */ 659 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 660 if ((sr == 1) && 661 (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) && 662 (ai < a_len) && 663 (val_array[ai] == val_arg)) 664 return (1); 665 break; 666 } 667 case DATA_TYPE_INT64: { 668 int64_t val, val_arg; 669 670 /* scanf int64_t from value and check for match */ 671 sr = sscanf(value, "%"SCNi64, &val_arg); 672 if ((sr == 1) && 673 (nvpair_value_int64(nvp, &val) == 0) && 674 (val == val_arg)) 675 return (1); 676 break; 677 } 678 case DATA_TYPE_INT64_ARRAY: { 679 int64_t *val_array, val_arg; 680 681 /* check indexed value of array for match */ 682 sr = sscanf(value, "%"SCNi64, &val_arg); 683 if ((sr == 1) && 684 (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) && 685 (ai < a_len) && 686 (val_array[ai] == val_arg)) 687 return (1); 688 break; 689 } 690 case DATA_TYPE_UINT64: { 691 uint64_t val_arg, val; 692 693 /* scanf uint64_t from value and check for match */ 694 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 695 if ((sr == 1) && 696 (nvpair_value_uint64(nvp, &val) == 0) && 697 (val == val_arg)) 698 return (1); 699 break; 700 } 701 case DATA_TYPE_UINT64_ARRAY: { 702 uint64_t *val_array, val_arg; 703 704 /* check indexed value of array for match */ 705 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 706 if ((sr == 1) && 707 (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) && 708 (ai < a_len) && 709 (val_array[ai] == val_arg)) 710 return (1); 711 break; 712 } 713 case DATA_TYPE_BOOLEAN_VALUE: { 714 boolean_t val, val_arg; 715 716 /* scanf boolean_t from value and check for match */ 717 sr = sscanf(value, "%"SCNi32, &val_arg); 718 if ((sr == 1) && 719 (nvpair_value_boolean_value(nvp, &val) == 0) && 720 (val == val_arg)) 721 return (1); 722 break; 723 } 724 case DATA_TYPE_BOOLEAN_ARRAY: { 725 boolean_t *val_array, val_arg; 726 727 /* check indexed value of array for match */ 728 sr = sscanf(value, "%"SCNi32, &val_arg); 729 if ((sr == 1) && 730 (nvpair_value_boolean_array(nvp, 731 &val_array, &a_len) == 0) && 732 (ai < a_len) && 733 (val_array[ai] == val_arg)) 734 return (1); 735 break; 736 } 737 case DATA_TYPE_HRTIME: 738 case DATA_TYPE_NVLIST: 739 case DATA_TYPE_NVLIST_ARRAY: 740 case DATA_TYPE_BOOLEAN: 741 case DATA_TYPE_DOUBLE: 742 case DATA_TYPE_UNKNOWN: 743 default: 744 /* 745 * unknown/unsupported data type 746 */ 747 return (-1); /* error fail match */ 748 } 749 750 /* 751 * check to see if sscanf failed conversion, return approximate 752 * pointer to problem 753 */ 754 if (sr != 1) { 755 if (ep) 756 *ep = value; 757 return (-1); /* error fail match - syntax */ 758 } 759 760 return (0); /* fail match */ 761 } 762 763 int 764 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep) 765 { 766 return (nvpair_value_match_regex(nvp, ai, value, NULL, ep)); 767 } 768