libnvpair.c revision 185029
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 <inttypes.h> 29#include <unistd.h> 30#include <strings.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 41static void 42indent(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 */ 51static 52void 53nvlist_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 268void 269nvlist_print(FILE *fp, nvlist_t *nvl) 270{ 271 nvlist_print_with_indent(fp, nvl, 0); 272} 273 274/* 275 * Determine if string 'value' matches 'nvp' value. The 'value' string is 276 * converted, depending on the type of 'nvp', prior to match. For numeric 277 * types, a radix independent sscanf conversion of 'value' is used. If 'nvp' 278 * is an array type, 'ai' is the index into the array against which we are 279 * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass 280 * in a regex_t compilation of value in 'value_regex' to trigger regular 281 * expression string match instead of simple strcmp(). 282 * 283 * Return 1 on match, 0 on no-match, and -1 on error. If the error is 284 * related to value syntax error and 'ep' is non-NULL, *ep will point into 285 * the 'value' string at the location where the error exists. 286 * 287 * NOTE: It may be possible to move the non-regex_t version of this into 288 * common code used by library/kernel/boot. 289 */ 290int 291nvpair_value_match_regex(nvpair_t *nvp, int ai, 292 char *value, regex_t *value_regex, char **ep) 293{ 294 char *evalue; 295 uint_t a_len; 296 int sr; 297 298 if (ep) 299 *ep = NULL; 300 301 if ((nvp == NULL) || (value == NULL)) 302 return (-1); /* error fail match - invalid args */ 303 304 /* make sure array and index combination make sense */ 305 if ((nvpair_type_is_array(nvp) && (ai < 0)) || 306 (!nvpair_type_is_array(nvp) && (ai >= 0))) 307 return (-1); /* error fail match - bad index */ 308 309 /* non-string values should be single 'chunk' */ 310 if ((nvpair_type(nvp) != DATA_TYPE_STRING) && 311 (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) { 312 value += strspn(value, " \t"); 313 evalue = value + strcspn(value, " \t"); 314 if (*evalue) { 315 if (ep) 316 *ep = evalue; 317 return (-1); /* error fail match - syntax */ 318 } 319 } 320 321 sr = EOF; 322 switch (nvpair_type(nvp)) { 323 case DATA_TYPE_STRING: { 324 char *val; 325 326 /* check string value for match */ 327 if (nvpair_value_string(nvp, &val) == 0) { 328 if (value_regex) { 329 if (regexec(value_regex, val, 330 (size_t)0, NULL, 0) == 0) 331 return (1); /* match */ 332 } else { 333 if (strcmp(value, val) == 0) 334 return (1); /* match */ 335 } 336 } 337 break; 338 } 339 case DATA_TYPE_STRING_ARRAY: { 340 char **val_array; 341 342 /* check indexed string value of array for match */ 343 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) && 344 (ai < a_len)) { 345 if (value_regex) { 346 if (regexec(value_regex, val_array[ai], 347 (size_t)0, NULL, 0) == 0) 348 return (1); 349 } else { 350 if (strcmp(value, val_array[ai]) == 0) 351 return (1); 352 } 353 } 354 break; 355 } 356 case DATA_TYPE_BYTE: { 357 uchar_t val, val_arg; 358 359 /* scanf uchar_t from value and check for match */ 360 sr = sscanf(value, "%c", &val_arg); 361 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) && 362 (val == val_arg)) 363 return (1); 364 break; 365 } 366 case DATA_TYPE_BYTE_ARRAY: { 367 uchar_t *val_array, val_arg; 368 369 370 /* check indexed value of array for match */ 371 sr = sscanf(value, "%c", &val_arg); 372 if ((sr == 1) && 373 (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) && 374 (ai < a_len) && 375 (val_array[ai] == val_arg)) 376 return (1); 377 break; 378 } 379 case DATA_TYPE_INT8: { 380 int8_t val, val_arg; 381 382 /* scanf int8_t from value and check for match */ 383 sr = sscanf(value, "%"SCNi8, &val_arg); 384 if ((sr == 1) && 385 (nvpair_value_int8(nvp, &val) == 0) && 386 (val == val_arg)) 387 return (1); 388 break; 389 } 390 case DATA_TYPE_INT8_ARRAY: { 391 int8_t *val_array, val_arg; 392 393 /* check indexed value of array for match */ 394 sr = sscanf(value, "%"SCNi8, &val_arg); 395 if ((sr == 1) && 396 (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) && 397 (ai < a_len) && 398 (val_array[ai] == val_arg)) 399 return (1); 400 break; 401 } 402 case DATA_TYPE_UINT8: { 403 uint8_t val, val_arg; 404 405 /* scanf uint8_t from value and check for match */ 406 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 407 if ((sr == 1) && 408 (nvpair_value_uint8(nvp, &val) == 0) && 409 (val == val_arg)) 410 return (1); 411 break; 412 } 413 case DATA_TYPE_UINT8_ARRAY: { 414 uint8_t *val_array, val_arg; 415 416 /* check indexed value of array for match */ 417 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 418 if ((sr == 1) && 419 (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) && 420 (ai < a_len) && 421 (val_array[ai] == val_arg)) 422 return (1); 423 break; 424 } 425 case DATA_TYPE_INT16: { 426 int16_t val, val_arg; 427 428 /* scanf int16_t from value and check for match */ 429 sr = sscanf(value, "%"SCNi16, &val_arg); 430 if ((sr == 1) && 431 (nvpair_value_int16(nvp, &val) == 0) && 432 (val == val_arg)) 433 return (1); 434 break; 435 } 436 case DATA_TYPE_INT16_ARRAY: { 437 int16_t *val_array, val_arg; 438 439 /* check indexed value of array for match */ 440 sr = sscanf(value, "%"SCNi16, &val_arg); 441 if ((sr == 1) && 442 (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) && 443 (ai < a_len) && 444 (val_array[ai] == val_arg)) 445 return (1); 446 break; 447 } 448 case DATA_TYPE_UINT16: { 449 uint16_t val, val_arg; 450 451 /* scanf uint16_t from value and check for match */ 452 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 453 if ((sr == 1) && 454 (nvpair_value_uint16(nvp, &val) == 0) && 455 (val == val_arg)) 456 return (1); 457 break; 458 } 459 case DATA_TYPE_UINT16_ARRAY: { 460 uint16_t *val_array, val_arg; 461 462 /* check indexed value of array for match */ 463 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 464 if ((sr == 1) && 465 (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) && 466 (ai < a_len) && 467 (val_array[ai] == val_arg)) 468 return (1); 469 break; 470 } 471 case DATA_TYPE_INT32: { 472 int32_t val, val_arg; 473 474 /* scanf int32_t from value and check for match */ 475 sr = sscanf(value, "%"SCNi32, &val_arg); 476 if ((sr == 1) && 477 (nvpair_value_int32(nvp, &val) == 0) && 478 (val == val_arg)) 479 return (1); 480 break; 481 } 482 case DATA_TYPE_INT32_ARRAY: { 483 int32_t *val_array, val_arg; 484 485 /* check indexed value of array for match */ 486 sr = sscanf(value, "%"SCNi32, &val_arg); 487 if ((sr == 1) && 488 (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) && 489 (ai < a_len) && 490 (val_array[ai] == val_arg)) 491 return (1); 492 break; 493 } 494 case DATA_TYPE_UINT32: { 495 uint32_t val, val_arg; 496 497 /* scanf uint32_t from value and check for match */ 498 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 499 if ((sr == 1) && 500 (nvpair_value_uint32(nvp, &val) == 0) && 501 (val == val_arg)) 502 return (1); 503 break; 504 } 505 case DATA_TYPE_UINT32_ARRAY: { 506 uint32_t *val_array, val_arg; 507 508 /* check indexed value of array for match */ 509 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 510 if ((sr == 1) && 511 (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) && 512 (ai < a_len) && 513 (val_array[ai] == val_arg)) 514 return (1); 515 break; 516 } 517 case DATA_TYPE_INT64: { 518 int64_t val, val_arg; 519 520 /* scanf int64_t from value and check for match */ 521 sr = sscanf(value, "%"SCNi64, &val_arg); 522 if ((sr == 1) && 523 (nvpair_value_int64(nvp, &val) == 0) && 524 (val == val_arg)) 525 return (1); 526 break; 527 } 528 case DATA_TYPE_INT64_ARRAY: { 529 int64_t *val_array, val_arg; 530 531 /* check indexed value of array for match */ 532 sr = sscanf(value, "%"SCNi64, &val_arg); 533 if ((sr == 1) && 534 (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) && 535 (ai < a_len) && 536 (val_array[ai] == val_arg)) 537 return (1); 538 break; 539 } 540 case DATA_TYPE_UINT64: { 541 uint64_t val_arg, val; 542 543 /* scanf uint64_t from value and check for match */ 544 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 545 if ((sr == 1) && 546 (nvpair_value_uint64(nvp, &val) == 0) && 547 (val == val_arg)) 548 return (1); 549 break; 550 } 551 case DATA_TYPE_UINT64_ARRAY: { 552 uint64_t *val_array, val_arg; 553 554 /* check indexed value of array for match */ 555 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 556 if ((sr == 1) && 557 (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) && 558 (ai < a_len) && 559 (val_array[ai] == val_arg)) 560 return (1); 561 break; 562 } 563 case DATA_TYPE_BOOLEAN_VALUE: { 564 boolean_t val, val_arg; 565 566 /* scanf boolean_t from value and check for match */ 567 sr = sscanf(value, "%"SCNi32, &val_arg); 568 if ((sr == 1) && 569 (nvpair_value_boolean_value(nvp, &val) == 0) && 570 (val == val_arg)) 571 return (1); 572 break; 573 } 574 case DATA_TYPE_BOOLEAN_ARRAY: { 575 boolean_t *val_array, val_arg; 576 577 /* check indexed value of array for match */ 578 sr = sscanf(value, "%"SCNi32, &val_arg); 579 if ((sr == 1) && 580 (nvpair_value_boolean_array(nvp, 581 &val_array, &a_len) == 0) && 582 (ai < a_len) && 583 (val_array[ai] == val_arg)) 584 return (1); 585 break; 586 } 587 case DATA_TYPE_HRTIME: 588 case DATA_TYPE_NVLIST: 589 case DATA_TYPE_NVLIST_ARRAY: 590 case DATA_TYPE_BOOLEAN: 591 case DATA_TYPE_DOUBLE: 592 case DATA_TYPE_UNKNOWN: 593 default: 594 /* 595 * unknown/unsupported data type 596 */ 597 return (-1); /* error fail match */ 598 } 599 600 /* 601 * check to see if sscanf failed conversion, return approximate 602 * pointer to problem 603 */ 604 if (sr != 1) { 605 if (ep) 606 *ep = value; 607 return (-1); /* error fail match - syntax */ 608 } 609 610 return (0); /* fail match */ 611} 612 613int 614nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep) 615{ 616 return (nvpair_value_match_regex(nvp, ai, value, NULL, ep)); 617} 618