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 (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright (c) 2012 by Delphix. All rights reserved. 24 */ 25 26 #include <unistd.h> 27 #include <string.h> 28 #include <libintl.h> 29 #include <sys/types.h> 30 #include <sys/inttypes.h> 31 #include <sys/note.h> 32 #include <stdarg.h> 33 #include "libnvpair.h" 34 35 /* 36 * libnvpair - A tools library for manipulating <name, value> pairs. 37 * 38 * This library provides routines packing an unpacking nv pairs 39 * for transporting data across process boundaries, transporting 40 * between kernel and userland, and possibly saving onto disk files. 41 */ 42 43 /* 44 * Print control structure. 45 */ 46 47 #define DEFINEOP(opname, vtype) \ 48 struct { \ 49 int (*op)(struct nvlist_prtctl *, void *, nvlist_t *, \ 50 const char *, vtype); \ 51 void *arg; \ 52 } opname 53 54 #define DEFINEARROP(opname, vtype) \ 55 struct { \ 56 int (*op)(struct nvlist_prtctl *, void *, nvlist_t *, \ 57 const char *, vtype, uint_t); \ 58 void *arg; \ 59 } opname 60 61 struct nvlist_printops { 62 DEFINEOP(print_boolean, int); 63 DEFINEOP(print_boolean_value, boolean_t); 64 DEFINEOP(print_byte, uchar_t); 65 DEFINEOP(print_int8, int8_t); 66 DEFINEOP(print_uint8, uint8_t); 67 DEFINEOP(print_int16, int16_t); 68 DEFINEOP(print_uint16, uint16_t); 69 DEFINEOP(print_int32, int32_t); 70 DEFINEOP(print_uint32, uint32_t); 71 DEFINEOP(print_int64, int64_t); 72 DEFINEOP(print_uint64, uint64_t); 73 DEFINEOP(print_double, double); 74 DEFINEOP(print_string, char *); 75 DEFINEOP(print_hrtime, hrtime_t); 76 DEFINEOP(print_nvlist, nvlist_t *); 77 DEFINEARROP(print_boolean_array, boolean_t *); 78 DEFINEARROP(print_byte_array, uchar_t *); 79 DEFINEARROP(print_int8_array, int8_t *); 80 DEFINEARROP(print_uint8_array, uint8_t *); 81 DEFINEARROP(print_int16_array, int16_t *); 82 DEFINEARROP(print_uint16_array, uint16_t *); 83 DEFINEARROP(print_int32_array, int32_t *); 84 DEFINEARROP(print_uint32_array, uint32_t *); 85 DEFINEARROP(print_int64_array, int64_t *); 86 DEFINEARROP(print_uint64_array, uint64_t *); 87 DEFINEARROP(print_string_array, char **); 88 DEFINEARROP(print_nvlist_array, nvlist_t **); 89 }; 90 91 struct nvlist_prtctl { 92 FILE *nvprt_fp; /* output destination */ 93 enum nvlist_indent_mode nvprt_indent_mode; /* see above */ 94 int nvprt_indent; /* absolute indent, or tab depth */ 95 int nvprt_indentinc; /* indent or tab increment */ 96 const char *nvprt_nmfmt; /* member name format, max one %s */ 97 const char *nvprt_eomfmt; /* after member format, e.g. "\n" */ 98 const char *nvprt_btwnarrfmt; /* between array members */ 99 int nvprt_btwnarrfmt_nl; /* nvprt_eoamfmt includes newline? */ 100 struct nvlist_printops *nvprt_dfltops; 101 struct nvlist_printops *nvprt_custops; 102 }; 103 104 #define DFLTPRTOP(pctl, type) \ 105 ((pctl)->nvprt_dfltops->print_##type.op) 106 107 #define DFLTPRTOPARG(pctl, type) \ 108 ((pctl)->nvprt_dfltops->print_##type.arg) 109 110 #define CUSTPRTOP(pctl, type) \ 111 ((pctl)->nvprt_custops->print_##type.op) 112 113 #define CUSTPRTOPARG(pctl, type) \ 114 ((pctl)->nvprt_custops->print_##type.arg) 115 116 #define RENDER(pctl, type, nvl, name, val) \ 117 { \ 118 int done = 0; \ 119 if ((pctl)->nvprt_custops && CUSTPRTOP(pctl, type)) { \ 120 done = CUSTPRTOP(pctl, type)(pctl, \ 121 CUSTPRTOPARG(pctl, type), nvl, name, val); \ 122 } \ 123 if (!done) { \ 124 (void) DFLTPRTOP(pctl, type)(pctl, \ 125 DFLTPRTOPARG(pctl, type), nvl, name, val); \ 126 } \ 127 (void) fprintf(pctl->nvprt_fp, "%s", pctl->nvprt_eomfmt); \ 128 } 129 130 #define ARENDER(pctl, type, nvl, name, arrp, count) \ 131 { \ 132 int done = 0; \ 133 if ((pctl)->nvprt_custops && CUSTPRTOP(pctl, type)) { \ 134 done = CUSTPRTOP(pctl, type)(pctl, \ 135 CUSTPRTOPARG(pctl, type), nvl, name, arrp, count); \ 136 } \ 137 if (!done) { \ 138 (void) DFLTPRTOP(pctl, type)(pctl, \ 139 DFLTPRTOPARG(pctl, type), nvl, name, arrp, count); \ 140 } \ 141 (void) fprintf(pctl->nvprt_fp, "%s", pctl->nvprt_eomfmt); \ 142 } 143 144 static void nvlist_print_with_indent(nvlist_t *, nvlist_prtctl_t); 145 146 /* 147 * ====================================================================== 148 * | | 149 * | Indentation | 150 * | | 151 * ====================================================================== 152 */ 153 154 static void 155 indent(nvlist_prtctl_t pctl, int onemore) 156 { 157 int depth; 158 159 switch (pctl->nvprt_indent_mode) { 160 case NVLIST_INDENT_ABS: 161 (void) fprintf(pctl->nvprt_fp, "%*s", 162 pctl->nvprt_indent + onemore * pctl->nvprt_indentinc, ""); 163 break; 164 165 case NVLIST_INDENT_TABBED: 166 depth = pctl->nvprt_indent + onemore; 167 while (depth-- > 0) 168 (void) fprintf(pctl->nvprt_fp, "\t"); 169 } 170 } 171 172 /* 173 * ====================================================================== 174 * | | 175 * | Default nvlist member rendering functions. | 176 * | | 177 * ====================================================================== 178 */ 179 180 /* 181 * Generate functions to print single-valued nvlist members. 182 * 183 * type_and_variant - suffix to form function name 184 * vtype - C type for the member value 185 * ptype - C type to cast value to for printing 186 * vfmt - format string for pair value, e.g "%d" or "0x%llx" 187 */ 188 189 #define NVLIST_PRTFUNC(type_and_variant, vtype, ptype, vfmt) \ 190 static int \ 191 nvprint_##type_and_variant(nvlist_prtctl_t pctl, void *private, \ 192 nvlist_t *nvl, const char *name, vtype value) \ 193 { \ 194 FILE *fp = pctl->nvprt_fp; \ 195 NOTE(ARGUNUSED(private)) \ 196 NOTE(ARGUNUSED(nvl)) \ 197 indent(pctl, 1); \ 198 (void) fprintf(fp, pctl->nvprt_nmfmt, name); \ 199 (void) fprintf(fp, vfmt, (ptype)value); \ 200 return (1); \ 201 } 202 203 NVLIST_PRTFUNC(boolean, int, int, "%d") 204 NVLIST_PRTFUNC(boolean_value, boolean_t, int, "%d") 205 NVLIST_PRTFUNC(byte, uchar_t, uchar_t, "0x%2.2x") 206 NVLIST_PRTFUNC(int8, int8_t, int, "%d") 207 NVLIST_PRTFUNC(uint8, uint8_t, uint8_t, "0x%x") 208 NVLIST_PRTFUNC(int16, int16_t, int16_t, "%d") 209 NVLIST_PRTFUNC(uint16, uint16_t, uint16_t, "0x%x") 210 NVLIST_PRTFUNC(int32, int32_t, int32_t, "%d") 211 NVLIST_PRTFUNC(uint32, uint32_t, uint32_t, "0x%x") 212 NVLIST_PRTFUNC(int64, int64_t, longlong_t, "%lld") 213 NVLIST_PRTFUNC(uint64, uint64_t, u_longlong_t, "0x%llx") 214 NVLIST_PRTFUNC(double, double, double, "0x%f") 215 NVLIST_PRTFUNC(string, char *, char *, "%s") 216 NVLIST_PRTFUNC(hrtime, hrtime_t, hrtime_t, "0x%llx") 217 218 /* 219 * Generate functions to print array-valued nvlist members. 220 */ 221 222 #define NVLIST_ARRPRTFUNC(type_and_variant, vtype, ptype, vfmt) \ 223 static int \ 224 nvaprint_##type_and_variant(nvlist_prtctl_t pctl, void *private, \ 225 nvlist_t *nvl, const char *name, vtype *valuep, uint_t count) \ 226 { \ 227 FILE *fp = pctl->nvprt_fp; \ 228 uint_t i; \ 229 NOTE(ARGUNUSED(private)) \ 230 NOTE(ARGUNUSED(nvl)) \ 231 for (i = 0; i < count; i++) { \ 232 if (i == 0 || pctl->nvprt_btwnarrfmt_nl) { \ 233 indent(pctl, 1); \ 234 (void) fprintf(fp, pctl->nvprt_nmfmt, name); \ 235 if (pctl->nvprt_btwnarrfmt_nl) \ 236 (void) fprintf(fp, "[%d]: ", i); \ 237 } \ 238 if (i != 0) \ 239 (void) fprintf(fp, "%s", pctl->nvprt_btwnarrfmt); \ 240 (void) fprintf(fp, vfmt, (ptype)valuep[i]); \ 241 } \ 242 return (1); \ 243 } 244 245 NVLIST_ARRPRTFUNC(boolean_array, boolean_t, boolean_t, "%d") 246 NVLIST_ARRPRTFUNC(byte_array, uchar_t, uchar_t, "0x%2.2x") 247 NVLIST_ARRPRTFUNC(int8_array, int8_t, int8_t, "%d") 248 NVLIST_ARRPRTFUNC(uint8_array, uint8_t, uint8_t, "0x%x") 249 NVLIST_ARRPRTFUNC(int16_array, int16_t, int16_t, "%d") 250 NVLIST_ARRPRTFUNC(uint16_array, uint16_t, uint16_t, "0x%x") 251 NVLIST_ARRPRTFUNC(int32_array, int32_t, int32_t, "%d") 252 NVLIST_ARRPRTFUNC(uint32_array, uint32_t, uint32_t, "0x%x") 253 NVLIST_ARRPRTFUNC(int64_array, int64_t, longlong_t, "%lld") 254 NVLIST_ARRPRTFUNC(uint64_array, uint64_t, u_longlong_t, "0x%llx") 255 NVLIST_ARRPRTFUNC(string_array, char *, char *, "%s") 256 257 /*ARGSUSED*/ 258 static int 259 nvprint_nvlist(nvlist_prtctl_t pctl, void *private, 260 nvlist_t *nvl, const char *name, nvlist_t *value) 261 { 262 FILE *fp = pctl->nvprt_fp; 263 264 indent(pctl, 1); 265 (void) fprintf(fp, "%s = (embedded nvlist)\n", name); 266 267 pctl->nvprt_indent += pctl->nvprt_indentinc; 268 nvlist_print_with_indent(value, pctl); 269 pctl->nvprt_indent -= pctl->nvprt_indentinc; 270 271 indent(pctl, 1); 272 (void) fprintf(fp, "(end %s)\n", name); 273 274 return (1); 275 } 276 277 /*ARGSUSED*/ 278 static int 279 nvaprint_nvlist_array(nvlist_prtctl_t pctl, void *private, 280 nvlist_t *nvl, const char *name, nvlist_t **valuep, uint_t count) 281 { 282 FILE *fp = pctl->nvprt_fp; 283 uint_t i; 284 285 indent(pctl, 1); 286 (void) fprintf(fp, "%s = (array of embedded nvlists)\n", name); 287 288 for (i = 0; i < count; i++) { 289 indent(pctl, 1); 290 (void) fprintf(fp, "(start %s[%d])\n", name, i); 291 292 pctl->nvprt_indent += pctl->nvprt_indentinc; 293 nvlist_print_with_indent(valuep[i], pctl); 294 pctl->nvprt_indent -= pctl->nvprt_indentinc; 295 296 indent(pctl, 1); 297 (void) fprintf(fp, "(end %s[%d])\n", name, i); 298 } 299 300 return (1); 301 } 302 303 /* 304 * ====================================================================== 305 * | | 306 * | Interfaces that allow control over formatting. | 307 * | | 308 * ====================================================================== 309 */ 310 311 void 312 nvlist_prtctl_setdest(nvlist_prtctl_t pctl, FILE *fp) 313 { 314 pctl->nvprt_fp = fp; 315 } 316 317 FILE * 318 nvlist_prtctl_getdest(nvlist_prtctl_t pctl) 319 { 320 return (pctl->nvprt_fp); 321 } 322 323 324 void 325 nvlist_prtctl_setindent(nvlist_prtctl_t pctl, enum nvlist_indent_mode mode, 326 int start, int inc) 327 { 328 if (mode < NVLIST_INDENT_ABS || mode > NVLIST_INDENT_TABBED) 329 mode = NVLIST_INDENT_TABBED; 330 331 if (start < 0) 332 start = 0; 333 334 if (inc < 0) 335 inc = 1; 336 337 pctl->nvprt_indent_mode = mode; 338 pctl->nvprt_indent = start; 339 pctl->nvprt_indentinc = inc; 340 } 341 342 void 343 nvlist_prtctl_doindent(nvlist_prtctl_t pctl, int onemore) 344 { 345 indent(pctl, onemore); 346 } 347 348 349 void 350 nvlist_prtctl_setfmt(nvlist_prtctl_t pctl, enum nvlist_prtctl_fmt which, 351 const char *fmt) 352 { 353 switch (which) { 354 case NVLIST_FMT_MEMBER_NAME: 355 if (fmt == NULL) 356 fmt = "%s = "; 357 pctl->nvprt_nmfmt = fmt; 358 break; 359 360 case NVLIST_FMT_MEMBER_POSTAMBLE: 361 if (fmt == NULL) 362 fmt = "\n"; 363 pctl->nvprt_eomfmt = fmt; 364 break; 365 366 case NVLIST_FMT_BTWN_ARRAY: 367 if (fmt == NULL) { 368 pctl->nvprt_btwnarrfmt = " "; 369 pctl->nvprt_btwnarrfmt_nl = 0; 370 } else { 371 pctl->nvprt_btwnarrfmt = fmt; 372 pctl->nvprt_btwnarrfmt_nl = (strstr(fmt, "\n") != NULL); 373 } 374 break; 375 376 default: 377 break; 378 } 379 } 380 381 382 void 383 nvlist_prtctl_dofmt(nvlist_prtctl_t pctl, enum nvlist_prtctl_fmt which, ...) 384 { 385 FILE *fp = pctl->nvprt_fp; 386 va_list ap; 387 char *name; 388 389 va_start(ap, which); 390 391 switch (which) { 392 case NVLIST_FMT_MEMBER_NAME: 393 name = va_arg(ap, char *); 394 (void) fprintf(fp, pctl->nvprt_nmfmt, name); 395 break; 396 397 case NVLIST_FMT_MEMBER_POSTAMBLE: 398 (void) fprintf(fp, "%s", pctl->nvprt_eomfmt); 399 break; 400 401 case NVLIST_FMT_BTWN_ARRAY: 402 (void) fprintf(fp, "%s", pctl->nvprt_btwnarrfmt); 403 break; 404 405 default: 406 break; 407 } 408 409 va_end(ap); 410 } 411 412 /* 413 * ====================================================================== 414 * | | 415 * | Interfaces to allow appointment of replacement rendering functions.| 416 * | | 417 * ====================================================================== 418 */ 419 420 #define NVLIST_PRINTCTL_REPLACE(type, vtype) \ 421 void \ 422 nvlist_prtctlop_##type(nvlist_prtctl_t pctl, \ 423 int (*func)(nvlist_prtctl_t, void *, nvlist_t *, const char *, vtype), \ 424 void *private) \ 425 { \ 426 CUSTPRTOP(pctl, type) = func; \ 427 CUSTPRTOPARG(pctl, type) = private; \ 428 } 429 430 NVLIST_PRINTCTL_REPLACE(boolean, int) 431 NVLIST_PRINTCTL_REPLACE(boolean_value, boolean_t) 432 NVLIST_PRINTCTL_REPLACE(byte, uchar_t) 433 NVLIST_PRINTCTL_REPLACE(int8, int8_t) 434 NVLIST_PRINTCTL_REPLACE(uint8, uint8_t) 435 NVLIST_PRINTCTL_REPLACE(int16, int16_t) 436 NVLIST_PRINTCTL_REPLACE(uint16, uint16_t) 437 NVLIST_PRINTCTL_REPLACE(int32, int32_t) 438 NVLIST_PRINTCTL_REPLACE(uint32, uint32_t) 439 NVLIST_PRINTCTL_REPLACE(int64, int64_t) 440 NVLIST_PRINTCTL_REPLACE(uint64, uint64_t) 441 NVLIST_PRINTCTL_REPLACE(double, double) 442 NVLIST_PRINTCTL_REPLACE(string, char *) 443 NVLIST_PRINTCTL_REPLACE(hrtime, hrtime_t) 444 NVLIST_PRINTCTL_REPLACE(nvlist, nvlist_t *) 445 446 #define NVLIST_PRINTCTL_AREPLACE(type, vtype) \ 447 void \ 448 nvlist_prtctlop_##type(nvlist_prtctl_t pctl, \ 449 int (*func)(nvlist_prtctl_t, void *, nvlist_t *, const char *, vtype, \ 450 uint_t), void *private) \ 451 { \ 452 CUSTPRTOP(pctl, type) = func; \ 453 CUSTPRTOPARG(pctl, type) = private; \ 454 } 455 456 NVLIST_PRINTCTL_AREPLACE(boolean_array, boolean_t *) 457 NVLIST_PRINTCTL_AREPLACE(byte_array, uchar_t *) 458 NVLIST_PRINTCTL_AREPLACE(int8_array, int8_t *) 459 NVLIST_PRINTCTL_AREPLACE(uint8_array, uint8_t *) 460 NVLIST_PRINTCTL_AREPLACE(int16_array, int16_t *) 461 NVLIST_PRINTCTL_AREPLACE(uint16_array, uint16_t *) 462 NVLIST_PRINTCTL_AREPLACE(int32_array, int32_t *) 463 NVLIST_PRINTCTL_AREPLACE(uint32_array, uint32_t *) 464 NVLIST_PRINTCTL_AREPLACE(int64_array, int64_t *) 465 NVLIST_PRINTCTL_AREPLACE(uint64_array, uint64_t *) 466 NVLIST_PRINTCTL_AREPLACE(string_array, char **) 467 NVLIST_PRINTCTL_AREPLACE(nvlist_array, nvlist_t **) 468 469 /* 470 * ====================================================================== 471 * | | 472 * | Interfaces to manage nvlist_prtctl_t cookies. | 473 * | | 474 * ====================================================================== 475 */ 476 477 478 static const struct nvlist_printops defprtops = 479 { 480 { nvprint_boolean, NULL }, 481 { nvprint_boolean_value, NULL }, 482 { nvprint_byte, NULL }, 483 { nvprint_int8, NULL }, 484 { nvprint_uint8, NULL }, 485 { nvprint_int16, NULL }, 486 { nvprint_uint16, NULL }, 487 { nvprint_int32, NULL }, 488 { nvprint_uint32, NULL }, 489 { nvprint_int64, NULL }, 490 { nvprint_uint64, NULL }, 491 { nvprint_double, NULL }, 492 { nvprint_string, NULL }, 493 { nvprint_hrtime, NULL }, 494 { nvprint_nvlist, NULL }, 495 { nvaprint_boolean_array, NULL }, 496 { nvaprint_byte_array, NULL }, 497 { nvaprint_int8_array, NULL }, 498 { nvaprint_uint8_array, NULL }, 499 { nvaprint_int16_array, NULL }, 500 { nvaprint_uint16_array, NULL }, 501 { nvaprint_int32_array, NULL }, 502 { nvaprint_uint32_array, NULL }, 503 { nvaprint_int64_array, NULL }, 504 { nvaprint_uint64_array, NULL }, 505 { nvaprint_string_array, NULL }, 506 { nvaprint_nvlist_array, NULL }, 507 }; 508 509 static void 510 prtctl_defaults(FILE *fp, struct nvlist_prtctl *pctl, 511 struct nvlist_printops *ops) 512 { 513 pctl->nvprt_fp = fp; 514 pctl->nvprt_indent_mode = NVLIST_INDENT_TABBED; 515 pctl->nvprt_indent = 0; 516 pctl->nvprt_indentinc = 1; 517 pctl->nvprt_nmfmt = "%s = "; 518 pctl->nvprt_eomfmt = "\n"; 519 pctl->nvprt_btwnarrfmt = " "; 520 pctl->nvprt_btwnarrfmt_nl = 0; 521 522 pctl->nvprt_dfltops = (struct nvlist_printops *)&defprtops; 523 pctl->nvprt_custops = ops; 524 } 525 526 nvlist_prtctl_t 527 nvlist_prtctl_alloc(void) 528 { 529 struct nvlist_prtctl *pctl; 530 struct nvlist_printops *ops; 531 532 if ((pctl = malloc(sizeof (*pctl))) == NULL) 533 return (NULL); 534 535 if ((ops = calloc(1, sizeof (*ops))) == NULL) { 536 free(pctl); 537 return (NULL); 538 } 539 540 prtctl_defaults(stdout, pctl, ops); 541 542 return (pctl); 543 } 544 545 void 546 nvlist_prtctl_free(nvlist_prtctl_t pctl) 547 { 548 if (pctl != NULL) { 549 free(pctl->nvprt_custops); 550 free(pctl); 551 } 552 } 553 554 /* 555 * ====================================================================== 556 * | | 557 * | Top-level print request interfaces. | 558 * | | 559 * ====================================================================== 560 */ 561 562 /* 563 * nvlist_print - Prints elements in an event buffer 564 */ 565 static void 566 nvlist_print_with_indent(nvlist_t *nvl, nvlist_prtctl_t pctl) 567 { 568 FILE *fp = pctl->nvprt_fp; 569 char *name; 570 uint_t nelem; 571 nvpair_t *nvp; 572 573 if (nvl == NULL) 574 return; 575 576 indent(pctl, 0); 577 (void) fprintf(fp, "nvlist version: %d\n", NVL_VERSION(nvl)); 578 579 nvp = nvlist_next_nvpair(nvl, NULL); 580 581 while (nvp) { 582 data_type_t type = nvpair_type(nvp); 583 584 name = nvpair_name(nvp); 585 nelem = 0; 586 587 switch (type) { 588 case DATA_TYPE_BOOLEAN: { 589 RENDER(pctl, boolean, nvl, name, 1); 590 break; 591 } 592 case DATA_TYPE_BOOLEAN_VALUE: { 593 boolean_t val; 594 (void) nvpair_value_boolean_value(nvp, &val); 595 RENDER(pctl, boolean_value, nvl, name, val); 596 break; 597 } 598 case DATA_TYPE_BYTE: { 599 uchar_t val; 600 (void) nvpair_value_byte(nvp, &val); 601 RENDER(pctl, byte, nvl, name, val); 602 break; 603 } 604 case DATA_TYPE_INT8: { 605 int8_t val; 606 (void) nvpair_value_int8(nvp, &val); 607 RENDER(pctl, int8, nvl, name, val); 608 break; 609 } 610 case DATA_TYPE_UINT8: { 611 uint8_t val; 612 (void) nvpair_value_uint8(nvp, &val); 613 RENDER(pctl, uint8, nvl, name, val); 614 break; 615 } 616 case DATA_TYPE_INT16: { 617 int16_t val; 618 (void) nvpair_value_int16(nvp, &val); 619 RENDER(pctl, int16, nvl, name, val); 620 break; 621 } 622 case DATA_TYPE_UINT16: { 623 uint16_t val; 624 (void) nvpair_value_uint16(nvp, &val); 625 RENDER(pctl, uint16, nvl, name, val); 626 break; 627 } 628 case DATA_TYPE_INT32: { 629 int32_t val; 630 (void) nvpair_value_int32(nvp, &val); 631 RENDER(pctl, int32, nvl, name, val); 632 break; 633 } 634 case DATA_TYPE_UINT32: { 635 uint32_t val; 636 (void) nvpair_value_uint32(nvp, &val); 637 RENDER(pctl, uint32, nvl, name, val); 638 break; 639 } 640 case DATA_TYPE_INT64: { 641 int64_t val; 642 (void) nvpair_value_int64(nvp, &val); 643 RENDER(pctl, int64, nvl, name, val); 644 break; 645 } 646 case DATA_TYPE_UINT64: { 647 uint64_t val; 648 (void) nvpair_value_uint64(nvp, &val); 649 RENDER(pctl, uint64, nvl, name, val); 650 break; 651 } 652 case DATA_TYPE_DOUBLE: { 653 double val; 654 (void) nvpair_value_double(nvp, &val); 655 RENDER(pctl, double, nvl, name, val); 656 break; 657 } 658 case DATA_TYPE_STRING: { 659 char *val; 660 (void) nvpair_value_string(nvp, &val); 661 RENDER(pctl, string, nvl, name, val); 662 break; 663 } 664 case DATA_TYPE_BOOLEAN_ARRAY: { 665 boolean_t *val; 666 (void) nvpair_value_boolean_array(nvp, &val, &nelem); 667 ARENDER(pctl, boolean_array, nvl, name, val, nelem); 668 break; 669 } 670 case DATA_TYPE_BYTE_ARRAY: { 671 uchar_t *val; 672 (void) nvpair_value_byte_array(nvp, &val, &nelem); 673 ARENDER(pctl, byte_array, nvl, name, val, nelem); 674 break; 675 } 676 case DATA_TYPE_INT8_ARRAY: { 677 int8_t *val; 678 (void) nvpair_value_int8_array(nvp, &val, &nelem); 679 ARENDER(pctl, int8_array, nvl, name, val, nelem); 680 break; 681 } 682 case DATA_TYPE_UINT8_ARRAY: { 683 uint8_t *val; 684 (void) nvpair_value_uint8_array(nvp, &val, &nelem); 685 ARENDER(pctl, uint8_array, nvl, name, val, nelem); 686 break; 687 } 688 case DATA_TYPE_INT16_ARRAY: { 689 int16_t *val; 690 (void) nvpair_value_int16_array(nvp, &val, &nelem); 691 ARENDER(pctl, int16_array, nvl, name, val, nelem); 692 break; 693 } 694 case DATA_TYPE_UINT16_ARRAY: { 695 uint16_t *val; 696 (void) nvpair_value_uint16_array(nvp, &val, &nelem); 697 ARENDER(pctl, uint16_array, nvl, name, val, nelem); 698 break; 699 } 700 case DATA_TYPE_INT32_ARRAY: { 701 int32_t *val; 702 (void) nvpair_value_int32_array(nvp, &val, &nelem); 703 ARENDER(pctl, int32_array, nvl, name, val, nelem); 704 break; 705 } 706 case DATA_TYPE_UINT32_ARRAY: { 707 uint32_t *val; 708 (void) nvpair_value_uint32_array(nvp, &val, &nelem); 709 ARENDER(pctl, uint32_array, nvl, name, val, nelem); 710 break; 711 } 712 case DATA_TYPE_INT64_ARRAY: { 713 int64_t *val; 714 (void) nvpair_value_int64_array(nvp, &val, &nelem); 715 ARENDER(pctl, int64_array, nvl, name, val, nelem); 716 break; 717 } 718 case DATA_TYPE_UINT64_ARRAY: { 719 uint64_t *val; 720 (void) nvpair_value_uint64_array(nvp, &val, &nelem); 721 ARENDER(pctl, uint64_array, nvl, name, val, nelem); 722 break; 723 } 724 case DATA_TYPE_STRING_ARRAY: { 725 char **val; 726 (void) nvpair_value_string_array(nvp, &val, &nelem); 727 ARENDER(pctl, string_array, nvl, name, val, nelem); 728 break; 729 } 730 case DATA_TYPE_HRTIME: { 731 hrtime_t val; 732 (void) nvpair_value_hrtime(nvp, &val); 733 RENDER(pctl, hrtime, nvl, name, val); 734 break; 735 } 736 case DATA_TYPE_NVLIST: { 737 nvlist_t *val; 738 (void) nvpair_value_nvlist(nvp, &val); 739 RENDER(pctl, nvlist, nvl, name, val); 740 break; 741 } 742 case DATA_TYPE_NVLIST_ARRAY: { 743 nvlist_t **val; 744 (void) nvpair_value_nvlist_array(nvp, &val, &nelem); 745 ARENDER(pctl, nvlist_array, nvl, name, val, nelem); 746 break; 747 } 748 default: 749 (void) fprintf(fp, " unknown data type (%d)", type); 750 break; 751 } 752 nvp = nvlist_next_nvpair(nvl, nvp); 753 } 754 } 755 756 void 757 nvlist_print(FILE *fp, nvlist_t *nvl) 758 { 759 struct nvlist_prtctl pc; 760 761 prtctl_defaults(fp, &pc, NULL); 762 nvlist_print_with_indent(nvl, &pc); 763 } 764 765 void 766 nvlist_prt(nvlist_t *nvl, nvlist_prtctl_t pctl) 767 { 768 nvlist_print_with_indent(nvl, pctl); 769 } 770 771 #define NVP(elem, type, vtype, ptype, format) { \ 772 vtype value; \ 773 \ 774 (void) nvpair_value_##type(elem, &value); \ 775 (void) printf("%*s%s: " format "\n", indent, "", \ 776 nvpair_name(elem), (ptype)value); \ 777 } 778 779 #define NVPA(elem, type, vtype, ptype, format) { \ 780 uint_t i, count; \ 781 vtype *value; \ 782 \ 783 (void) nvpair_value_##type(elem, &value, &count); \ 784 for (i = 0; i < count; i++) { \ 785 (void) printf("%*s%s[%d]: " format "\n", indent, "", \ 786 nvpair_name(elem), i, (ptype)value[i]); \ 787 } \ 788 } 789 790 /* 791 * Similar to nvlist_print() but handles arrays slightly differently. 792 */ 793 void 794 dump_nvlist(nvlist_t *list, int indent) 795 { 796 nvpair_t *elem = NULL; 797 boolean_t bool_value; 798 nvlist_t *nvlist_value; 799 nvlist_t **nvlist_array_value; 800 uint_t i, count; 801 802 if (list == NULL) { 803 return; 804 } 805 806 while ((elem = nvlist_next_nvpair(list, elem)) != NULL) { 807 switch (nvpair_type(elem)) { 808 case DATA_TYPE_BOOLEAN: 809 (void) printf("%*s%s\n", indent, "", nvpair_name(elem)); 810 break; 811 812 case DATA_TYPE_BOOLEAN_VALUE: 813 (void) nvpair_value_boolean_value(elem, &bool_value); 814 (void) printf("%*s%s: %s\n", indent, "", 815 nvpair_name(elem), bool_value ? "true" : "false"); 816 break; 817 818 case DATA_TYPE_BYTE: 819 NVP(elem, byte, uchar_t, int, "%u"); 820 break; 821 822 case DATA_TYPE_INT8: 823 NVP(elem, int8, int8_t, int, "%d"); 824 break; 825 826 case DATA_TYPE_UINT8: 827 NVP(elem, uint8, uint8_t, int, "%u"); 828 break; 829 830 case DATA_TYPE_INT16: 831 NVP(elem, int16, int16_t, int, "%d"); 832 break; 833 834 case DATA_TYPE_UINT16: 835 NVP(elem, uint16, uint16_t, int, "%u"); 836 break; 837 838 case DATA_TYPE_INT32: 839 NVP(elem, int32, int32_t, long, "%ld"); 840 break; 841 842 case DATA_TYPE_UINT32: 843 NVP(elem, uint32, uint32_t, ulong_t, "%lu"); 844 break; 845 846 case DATA_TYPE_INT64: 847 NVP(elem, int64, int64_t, longlong_t, "%lld"); 848 break; 849 850 case DATA_TYPE_UINT64: 851 NVP(elem, uint64, uint64_t, u_longlong_t, "%llu"); 852 break; 853 854 case DATA_TYPE_STRING: 855 NVP(elem, string, char *, char *, "'%s'"); 856 break; 857 858 case DATA_TYPE_BYTE_ARRAY: 859 NVPA(elem, byte_array, uchar_t, int, "%u"); 860 break; 861 862 case DATA_TYPE_INT8_ARRAY: 863 NVPA(elem, int8_array, int8_t, int, "%d"); 864 break; 865 866 case DATA_TYPE_UINT8_ARRAY: 867 NVPA(elem, uint8_array, uint8_t, int, "%u"); 868 break; 869 870 case DATA_TYPE_INT16_ARRAY: 871 NVPA(elem, int16_array, int16_t, int, "%d"); 872 break; 873 874 case DATA_TYPE_UINT16_ARRAY: 875 NVPA(elem, uint16_array, uint16_t, int, "%u"); 876 break; 877 878 case DATA_TYPE_INT32_ARRAY: 879 NVPA(elem, int32_array, int32_t, long, "%ld"); 880 break; 881 882 case DATA_TYPE_UINT32_ARRAY: 883 NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu"); 884 break; 885 886 case DATA_TYPE_INT64_ARRAY: 887 NVPA(elem, int64_array, int64_t, longlong_t, "%lld"); 888 break; 889 890 case DATA_TYPE_UINT64_ARRAY: 891 NVPA(elem, uint64_array, uint64_t, u_longlong_t, 892 "%llu"); 893 break; 894 895 case DATA_TYPE_STRING_ARRAY: 896 NVPA(elem, string_array, char *, char *, "'%s'"); 897 break; 898 899 case DATA_TYPE_NVLIST: 900 (void) nvpair_value_nvlist(elem, &nvlist_value); 901 (void) printf("%*s%s:\n", indent, "", 902 nvpair_name(elem)); 903 dump_nvlist(nvlist_value, indent + 4); 904 break; 905 906 case DATA_TYPE_NVLIST_ARRAY: 907 (void) nvpair_value_nvlist_array(elem, 908 &nvlist_array_value, &count); 909 for (i = 0; i < count; i++) { 910 (void) printf("%*s%s[%u]:\n", indent, "", 911 nvpair_name(elem), i); 912 dump_nvlist(nvlist_array_value[i], indent + 4); 913 } 914 break; 915 916 default: 917 (void) printf(dgettext(TEXT_DOMAIN, "bad config type " 918 "%d for %s\n"), nvpair_type(elem), 919 nvpair_name(elem)); 920 } 921 } 922 } 923 924 /* 925 * ====================================================================== 926 * | | 927 * | Misc private interface. | 928 * | | 929 * ====================================================================== 930 */ 931 932 /* 933 * Determine if string 'value' matches 'nvp' value. The 'value' string is 934 * converted, depending on the type of 'nvp', prior to match. For numeric 935 * types, a radix independent sscanf conversion of 'value' is used. If 'nvp' 936 * is an array type, 'ai' is the index into the array against which we are 937 * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass 938 * in a regex_t compilation of value in 'value_regex' to trigger regular 939 * expression string match instead of simple strcmp(). 940 * 941 * Return 1 on match, 0 on no-match, and -1 on error. If the error is 942 * related to value syntax error and 'ep' is non-NULL, *ep will point into 943 * the 'value' string at the location where the error exists. 944 * 945 * NOTE: It may be possible to move the non-regex_t version of this into 946 * common code used by library/kernel/boot. 947 */ 948 int 949 nvpair_value_match_regex(nvpair_t *nvp, int ai, 950 char *value, regex_t *value_regex, char **ep) 951 { 952 char *evalue; 953 uint_t a_len; 954 int sr; 955 956 if (ep) 957 *ep = NULL; 958 959 if ((nvp == NULL) || (value == NULL)) 960 return (-1); /* error fail match - invalid args */ 961 962 /* make sure array and index combination make sense */ 963 if ((nvpair_type_is_array(nvp) && (ai < 0)) || 964 (!nvpair_type_is_array(nvp) && (ai >= 0))) 965 return (-1); /* error fail match - bad index */ 966 967 /* non-string values should be single 'chunk' */ 968 if ((nvpair_type(nvp) != DATA_TYPE_STRING) && 969 (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) { 970 value += strspn(value, " \t"); 971 evalue = value + strcspn(value, " \t"); 972 if (*evalue) { 973 if (ep) 974 *ep = evalue; 975 return (-1); /* error fail match - syntax */ 976 } 977 } 978 979 sr = EOF; 980 switch (nvpair_type(nvp)) { 981 case DATA_TYPE_STRING: { 982 char *val; 983 984 /* check string value for match */ 985 if (nvpair_value_string(nvp, &val) == 0) { 986 if (value_regex) { 987 if (regexec(value_regex, val, 988 (size_t)0, NULL, 0) == 0) 989 return (1); /* match */ 990 } else { 991 if (strcmp(value, val) == 0) 992 return (1); /* match */ 993 } 994 } 995 break; 996 } 997 case DATA_TYPE_STRING_ARRAY: { 998 char **val_array; 999 1000 /* check indexed string value of array for match */ 1001 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) && 1002 (ai < a_len)) { 1003 if (value_regex) { 1004 if (regexec(value_regex, val_array[ai], 1005 (size_t)0, NULL, 0) == 0) 1006 return (1); 1007 } else { 1008 if (strcmp(value, val_array[ai]) == 0) 1009 return (1); 1010 } 1011 } 1012 break; 1013 } 1014 case DATA_TYPE_BYTE: { 1015 uchar_t val, val_arg; 1016 1017 /* scanf uchar_t from value and check for match */ 1018 sr = sscanf(value, "%c", &val_arg); 1019 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) && 1020 (val == val_arg)) 1021 return (1); 1022 break; 1023 } 1024 case DATA_TYPE_BYTE_ARRAY: { 1025 uchar_t *val_array, val_arg; 1026 1027 1028 /* check indexed value of array for match */ 1029 sr = sscanf(value, "%c", &val_arg); 1030 if ((sr == 1) && 1031 (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) && 1032 (ai < a_len) && 1033 (val_array[ai] == val_arg)) 1034 return (1); 1035 break; 1036 } 1037 case DATA_TYPE_INT8: { 1038 int8_t val, val_arg; 1039 1040 /* scanf int8_t from value and check for match */ 1041 sr = sscanf(value, "%"SCNi8, &val_arg); 1042 if ((sr == 1) && 1043 (nvpair_value_int8(nvp, &val) == 0) && 1044 (val == val_arg)) 1045 return (1); 1046 break; 1047 } 1048 case DATA_TYPE_INT8_ARRAY: { 1049 int8_t *val_array, val_arg; 1050 1051 /* check indexed value of array for match */ 1052 sr = sscanf(value, "%"SCNi8, &val_arg); 1053 if ((sr == 1) && 1054 (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) && 1055 (ai < a_len) && 1056 (val_array[ai] == val_arg)) 1057 return (1); 1058 break; 1059 } 1060 case DATA_TYPE_UINT8: { 1061 uint8_t val, val_arg; 1062 1063 /* scanf uint8_t from value and check for match */ 1064 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 1065 if ((sr == 1) && 1066 (nvpair_value_uint8(nvp, &val) == 0) && 1067 (val == val_arg)) 1068 return (1); 1069 break; 1070 } 1071 case DATA_TYPE_UINT8_ARRAY: { 1072 uint8_t *val_array, val_arg; 1073 1074 /* check indexed value of array for match */ 1075 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 1076 if ((sr == 1) && 1077 (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) && 1078 (ai < a_len) && 1079 (val_array[ai] == val_arg)) 1080 return (1); 1081 break; 1082 } 1083 case DATA_TYPE_INT16: { 1084 int16_t val, val_arg; 1085 1086 /* scanf int16_t from value and check for match */ 1087 sr = sscanf(value, "%"SCNi16, &val_arg); 1088 if ((sr == 1) && 1089 (nvpair_value_int16(nvp, &val) == 0) && 1090 (val == val_arg)) 1091 return (1); 1092 break; 1093 } 1094 case DATA_TYPE_INT16_ARRAY: { 1095 int16_t *val_array, val_arg; 1096 1097 /* check indexed value of array for match */ 1098 sr = sscanf(value, "%"SCNi16, &val_arg); 1099 if ((sr == 1) && 1100 (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) && 1101 (ai < a_len) && 1102 (val_array[ai] == val_arg)) 1103 return (1); 1104 break; 1105 } 1106 case DATA_TYPE_UINT16: { 1107 uint16_t val, val_arg; 1108 1109 /* scanf uint16_t from value and check for match */ 1110 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 1111 if ((sr == 1) && 1112 (nvpair_value_uint16(nvp, &val) == 0) && 1113 (val == val_arg)) 1114 return (1); 1115 break; 1116 } 1117 case DATA_TYPE_UINT16_ARRAY: { 1118 uint16_t *val_array, val_arg; 1119 1120 /* check indexed value of array for match */ 1121 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 1122 if ((sr == 1) && 1123 (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) && 1124 (ai < a_len) && 1125 (val_array[ai] == val_arg)) 1126 return (1); 1127 break; 1128 } 1129 case DATA_TYPE_INT32: { 1130 int32_t val, val_arg; 1131 1132 /* scanf int32_t from value and check for match */ 1133 sr = sscanf(value, "%"SCNi32, &val_arg); 1134 if ((sr == 1) && 1135 (nvpair_value_int32(nvp, &val) == 0) && 1136 (val == val_arg)) 1137 return (1); 1138 break; 1139 } 1140 case DATA_TYPE_INT32_ARRAY: { 1141 int32_t *val_array, val_arg; 1142 1143 /* check indexed value of array for match */ 1144 sr = sscanf(value, "%"SCNi32, &val_arg); 1145 if ((sr == 1) && 1146 (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) && 1147 (ai < a_len) && 1148 (val_array[ai] == val_arg)) 1149 return (1); 1150 break; 1151 } 1152 case DATA_TYPE_UINT32: { 1153 uint32_t val, val_arg; 1154 1155 /* scanf uint32_t from value and check for match */ 1156 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 1157 if ((sr == 1) && 1158 (nvpair_value_uint32(nvp, &val) == 0) && 1159 (val == val_arg)) 1160 return (1); 1161 break; 1162 } 1163 case DATA_TYPE_UINT32_ARRAY: { 1164 uint32_t *val_array, val_arg; 1165 1166 /* check indexed value of array for match */ 1167 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 1168 if ((sr == 1) && 1169 (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) && 1170 (ai < a_len) && 1171 (val_array[ai] == val_arg)) 1172 return (1); 1173 break; 1174 } 1175 case DATA_TYPE_INT64: { 1176 int64_t val, val_arg; 1177 1178 /* scanf int64_t from value and check for match */ 1179 sr = sscanf(value, "%"SCNi64, &val_arg); 1180 if ((sr == 1) && 1181 (nvpair_value_int64(nvp, &val) == 0) && 1182 (val == val_arg)) 1183 return (1); 1184 break; 1185 } 1186 case DATA_TYPE_INT64_ARRAY: { 1187 int64_t *val_array, val_arg; 1188 1189 /* check indexed value of array for match */ 1190 sr = sscanf(value, "%"SCNi64, &val_arg); 1191 if ((sr == 1) && 1192 (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) && 1193 (ai < a_len) && 1194 (val_array[ai] == val_arg)) 1195 return (1); 1196 break; 1197 } 1198 case DATA_TYPE_UINT64: { 1199 uint64_t val_arg, val; 1200 1201 /* scanf uint64_t from value and check for match */ 1202 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 1203 if ((sr == 1) && 1204 (nvpair_value_uint64(nvp, &val) == 0) && 1205 (val == val_arg)) 1206 return (1); 1207 break; 1208 } 1209 case DATA_TYPE_UINT64_ARRAY: { 1210 uint64_t *val_array, val_arg; 1211 1212 /* check indexed value of array for match */ 1213 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 1214 if ((sr == 1) && 1215 (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) && 1216 (ai < a_len) && 1217 (val_array[ai] == val_arg)) 1218 return (1); 1219 break; 1220 } 1221 case DATA_TYPE_BOOLEAN_VALUE: { 1222 int32_t val_arg; 1223 boolean_t val; 1224 1225 /* scanf boolean_t from value and check for match */ 1226 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 1227 if ((sr == 1) && 1228 (nvpair_value_boolean_value(nvp, &val) == 0) && 1229 (val == val_arg)) 1230 return (1); 1231 break; 1232 } 1233 case DATA_TYPE_BOOLEAN_ARRAY: { 1234 boolean_t *val_array; 1235 int32_t val_arg; 1236 1237 /* check indexed value of array for match */ 1238 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 1239 if ((sr == 1) && 1240 (nvpair_value_boolean_array(nvp, 1241 &val_array, &a_len) == 0) && 1242 (ai < a_len) && 1243 (val_array[ai] == val_arg)) 1244 return (1); 1245 break; 1246 } 1247 case DATA_TYPE_HRTIME: 1248 case DATA_TYPE_NVLIST: 1249 case DATA_TYPE_NVLIST_ARRAY: 1250 case DATA_TYPE_BOOLEAN: 1251 case DATA_TYPE_DOUBLE: 1252 case DATA_TYPE_UNKNOWN: 1253 default: 1254 /* 1255 * unknown/unsupported data type 1256 */ 1257 return (-1); /* error fail match */ 1258 } 1259 1260 /* 1261 * check to see if sscanf failed conversion, return approximate 1262 * pointer to problem 1263 */ 1264 if (sr != 1) { 1265 if (ep) 1266 *ep = value; 1267 return (-1); /* error fail match - syntax */ 1268 } 1269 1270 return (0); /* fail match */ 1271 } 1272 1273 int 1274 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep) 1275 { 1276 return (nvpair_value_match_regex(nvp, ai, value, NULL, ep)); 1277 } 1278