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