12311Sjkh/* 22311Sjkh * CDDL HEADER START 32311Sjkh * 42311Sjkh * The contents of this file are subject to the terms of the 52311Sjkh * Common Development and Distribution License (the "License"). 62311Sjkh * You may not use this file except in compliance with the License. 72311Sjkh * 82311Sjkh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92311Sjkh * or http://www.opensolaris.org/os/licensing. 102311Sjkh * See the License for the specific language governing permissions 112311Sjkh * and limitations under the License. 122311Sjkh * 132311Sjkh * When distributing Covered Code, include this CDDL HEADER in each 142311Sjkh * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152311Sjkh * If applicable, add the following below this CDDL HEADER, with the 162311Sjkh * fields enclosed by brackets "[]" replaced with your own identifying 172311Sjkh * information: Portions Copyright [yyyy] [name of copyright owner] 182311Sjkh * 192311Sjkh * CDDL HEADER END 202311Sjkh */ 212311Sjkh/* 222311Sjkh * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 232311Sjkh * Copyright (c) 2012 by Delphix. All rights reserved. 242311Sjkh */ 252311Sjkh 262311Sjkh#include <solaris.h> 272311Sjkh#include <inttypes.h> 282311Sjkh#include <unistd.h> 292311Sjkh#include <strings.h> 302311Sjkh#include <libintl.h> 312311Sjkh#include <stdarg.h> 322311Sjkh#include "libnvpair.h" 332311Sjkh 342311Sjkh/* 352311Sjkh * libnvpair - A tools library for manipulating <name, value> pairs. 362311Sjkh * 372311Sjkh * This library provides routines packing an unpacking nv pairs 382311Sjkh * for transporting data across process boundaries, transporting 392311Sjkh * between kernel and userland, and possibly saving onto disk files. 402311Sjkh */ 412311Sjkh 422311Sjkh/* 432311Sjkh * Print control structure. 442311Sjkh */ 452311Sjkh 462311Sjkh#define DEFINEOP(opname, vtype) \ 472311Sjkh struct { \ 482311Sjkh int (*op)(struct nvlist_prtctl *, void *, nvlist_t *, \ 492311Sjkh const char *, vtype); \ 502311Sjkh void *arg; \ 512311Sjkh } opname 522311Sjkh 532311Sjkh#define DEFINEARROP(opname, vtype) \ 542311Sjkh struct { \ 552311Sjkh int (*op)(struct nvlist_prtctl *, void *, nvlist_t *, \ 562311Sjkh const char *, vtype, uint_t); \ 572311Sjkh void *arg; \ 582311Sjkh } opname 592311Sjkh 602311Sjkhstruct nvlist_printops { 612311Sjkh DEFINEOP(print_boolean, int); 622311Sjkh DEFINEOP(print_boolean_value, boolean_t); 632311Sjkh DEFINEOP(print_byte, uchar_t); 642311Sjkh DEFINEOP(print_int8, int8_t); 652311Sjkh DEFINEOP(print_uint8, uint8_t); 662311Sjkh DEFINEOP(print_int16, int16_t); 672311Sjkh DEFINEOP(print_uint16, uint16_t); 682311Sjkh DEFINEOP(print_int32, int32_t); 692311Sjkh DEFINEOP(print_uint32, uint32_t); 702311Sjkh DEFINEOP(print_int64, int64_t); 712311Sjkh DEFINEOP(print_uint64, uint64_t); 7250479Speter 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 boolean_t *bool_array_value; 797 nvlist_t *nvlist_value; 798 nvlist_t **nvlist_array_value; 799 uint_t i, count; 800 801 if (list == NULL) { 802 return; 803 } 804 805 while ((elem = nvlist_next_nvpair(list, elem)) != NULL) { 806 switch (nvpair_type(elem)) { 807 case DATA_TYPE_BOOLEAN: 808 (void) printf("%*s%s\n", indent, "", nvpair_name(elem)); 809 break; 810 811 case DATA_TYPE_BOOLEAN_VALUE: 812 (void) nvpair_value_boolean_value(elem, &bool_value); 813 (void) printf("%*s%s: %s\n", indent, "", 814 nvpair_name(elem), bool_value ? "true" : "false"); 815 break; 816 817 case DATA_TYPE_BYTE: 818 NVP(elem, byte, uchar_t, int, "%u"); 819 break; 820 821 case DATA_TYPE_INT8: 822 NVP(elem, int8, int8_t, int, "%d"); 823 break; 824 825 case DATA_TYPE_UINT8: 826 NVP(elem, uint8, uint8_t, int, "%u"); 827 break; 828 829 case DATA_TYPE_INT16: 830 NVP(elem, int16, int16_t, int, "%d"); 831 break; 832 833 case DATA_TYPE_UINT16: 834 NVP(elem, uint16, uint16_t, int, "%u"); 835 break; 836 837 case DATA_TYPE_INT32: 838 NVP(elem, int32, int32_t, long, "%ld"); 839 break; 840 841 case DATA_TYPE_UINT32: 842 NVP(elem, uint32, uint32_t, ulong_t, "%lu"); 843 break; 844 845 case DATA_TYPE_INT64: 846 NVP(elem, int64, int64_t, longlong_t, "%lld"); 847 break; 848 849 case DATA_TYPE_UINT64: 850 NVP(elem, uint64, uint64_t, u_longlong_t, "%llu"); 851 break; 852 853 case DATA_TYPE_STRING: 854 NVP(elem, string, char *, char *, "'%s'"); 855 break; 856 857 case DATA_TYPE_BOOLEAN_ARRAY: 858 (void) nvpair_value_boolean_array(elem, 859 &bool_array_value, &count); 860 for (i = 0; i < count; i++) { 861 (void) printf("%*s%s[%d]: %s\n", indent, "", 862 nvpair_name(elem), i, 863 bool_array_value[i] ? "true" : "false"); 864 } 865 break; 866 867 case DATA_TYPE_BYTE_ARRAY: 868 NVPA(elem, byte_array, uchar_t, int, "%u"); 869 break; 870 871 case DATA_TYPE_INT8_ARRAY: 872 NVPA(elem, int8_array, int8_t, int, "%d"); 873 break; 874 875 case DATA_TYPE_UINT8_ARRAY: 876 NVPA(elem, uint8_array, uint8_t, int, "%u"); 877 break; 878 879 case DATA_TYPE_INT16_ARRAY: 880 NVPA(elem, int16_array, int16_t, int, "%d"); 881 break; 882 883 case DATA_TYPE_UINT16_ARRAY: 884 NVPA(elem, uint16_array, uint16_t, int, "%u"); 885 break; 886 887 case DATA_TYPE_INT32_ARRAY: 888 NVPA(elem, int32_array, int32_t, long, "%ld"); 889 break; 890 891 case DATA_TYPE_UINT32_ARRAY: 892 NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu"); 893 break; 894 895 case DATA_TYPE_INT64_ARRAY: 896 NVPA(elem, int64_array, int64_t, longlong_t, "%lld"); 897 break; 898 899 case DATA_TYPE_UINT64_ARRAY: 900 NVPA(elem, uint64_array, uint64_t, u_longlong_t, 901 "%llu"); 902 break; 903 904 case DATA_TYPE_STRING_ARRAY: 905 NVPA(elem, string_array, char *, char *, "'%s'"); 906 break; 907 908 case DATA_TYPE_NVLIST: 909 (void) nvpair_value_nvlist(elem, &nvlist_value); 910 (void) printf("%*s%s:\n", indent, "", 911 nvpair_name(elem)); 912 dump_nvlist(nvlist_value, indent + 4); 913 break; 914 915 case DATA_TYPE_NVLIST_ARRAY: 916 (void) nvpair_value_nvlist_array(elem, 917 &nvlist_array_value, &count); 918 for (i = 0; i < count; i++) { 919 (void) printf("%*s%s[%u]:\n", indent, "", 920 nvpair_name(elem), i); 921 dump_nvlist(nvlist_array_value[i], indent + 4); 922 } 923 break; 924 925 default: 926 (void) printf(dgettext(TEXT_DOMAIN, "bad config type " 927 "%d for %s\n"), nvpair_type(elem), 928 nvpair_name(elem)); 929 } 930 } 931} 932 933/* 934 * ====================================================================== 935 * | | 936 * | Misc private interface. | 937 * | | 938 * ====================================================================== 939 */ 940 941/* 942 * Determine if string 'value' matches 'nvp' value. The 'value' string is 943 * converted, depending on the type of 'nvp', prior to match. For numeric 944 * types, a radix independent sscanf conversion of 'value' is used. If 'nvp' 945 * is an array type, 'ai' is the index into the array against which we are 946 * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass 947 * in a regex_t compilation of value in 'value_regex' to trigger regular 948 * expression string match instead of simple strcmp(). 949 * 950 * Return 1 on match, 0 on no-match, and -1 on error. If the error is 951 * related to value syntax error and 'ep' is non-NULL, *ep will point into 952 * the 'value' string at the location where the error exists. 953 * 954 * NOTE: It may be possible to move the non-regex_t version of this into 955 * common code used by library/kernel/boot. 956 */ 957int 958nvpair_value_match_regex(nvpair_t *nvp, int ai, 959 char *value, regex_t *value_regex, char **ep) 960{ 961 char *evalue; 962 uint_t a_len; 963 int sr; 964 965 if (ep) 966 *ep = NULL; 967 968 if ((nvp == NULL) || (value == NULL)) 969 return (-1); /* error fail match - invalid args */ 970 971 /* make sure array and index combination make sense */ 972 if ((nvpair_type_is_array(nvp) && (ai < 0)) || 973 (!nvpair_type_is_array(nvp) && (ai >= 0))) 974 return (-1); /* error fail match - bad index */ 975 976 /* non-string values should be single 'chunk' */ 977 if ((nvpair_type(nvp) != DATA_TYPE_STRING) && 978 (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) { 979 value += strspn(value, " \t"); 980 evalue = value + strcspn(value, " \t"); 981 if (*evalue) { 982 if (ep) 983 *ep = evalue; 984 return (-1); /* error fail match - syntax */ 985 } 986 } 987 988 sr = EOF; 989 switch (nvpair_type(nvp)) { 990 case DATA_TYPE_STRING: { 991 char *val; 992 993 /* check string value for match */ 994 if (nvpair_value_string(nvp, &val) == 0) { 995 if (value_regex) { 996 if (regexec(value_regex, val, 997 (size_t)0, NULL, 0) == 0) 998 return (1); /* match */ 999 } else { 1000 if (strcmp(value, val) == 0) 1001 return (1); /* match */ 1002 } 1003 } 1004 break; 1005 } 1006 case DATA_TYPE_STRING_ARRAY: { 1007 char **val_array; 1008 1009 /* check indexed string value of array for match */ 1010 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) && 1011 (ai < a_len)) { 1012 if (value_regex) { 1013 if (regexec(value_regex, val_array[ai], 1014 (size_t)0, NULL, 0) == 0) 1015 return (1); 1016 } else { 1017 if (strcmp(value, val_array[ai]) == 0) 1018 return (1); 1019 } 1020 } 1021 break; 1022 } 1023 case DATA_TYPE_BYTE: { 1024 uchar_t val, val_arg; 1025 1026 /* scanf uchar_t from value and check for match */ 1027 sr = sscanf(value, "%c", &val_arg); 1028 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) && 1029 (val == val_arg)) 1030 return (1); 1031 break; 1032 } 1033 case DATA_TYPE_BYTE_ARRAY: { 1034 uchar_t *val_array, val_arg; 1035 1036 1037 /* check indexed value of array for match */ 1038 sr = sscanf(value, "%c", &val_arg); 1039 if ((sr == 1) && 1040 (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) && 1041 (ai < a_len) && 1042 (val_array[ai] == val_arg)) 1043 return (1); 1044 break; 1045 } 1046 case DATA_TYPE_INT8: { 1047 int8_t val, val_arg; 1048 1049 /* scanf int8_t from value and check for match */ 1050 sr = sscanf(value, "%"SCNi8, &val_arg); 1051 if ((sr == 1) && 1052 (nvpair_value_int8(nvp, &val) == 0) && 1053 (val == val_arg)) 1054 return (1); 1055 break; 1056 } 1057 case DATA_TYPE_INT8_ARRAY: { 1058 int8_t *val_array, val_arg; 1059 1060 /* check indexed value of array for match */ 1061 sr = sscanf(value, "%"SCNi8, &val_arg); 1062 if ((sr == 1) && 1063 (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) && 1064 (ai < a_len) && 1065 (val_array[ai] == val_arg)) 1066 return (1); 1067 break; 1068 } 1069 case DATA_TYPE_UINT8: { 1070 uint8_t val, val_arg; 1071 1072 /* scanf uint8_t from value and check for match */ 1073 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 1074 if ((sr == 1) && 1075 (nvpair_value_uint8(nvp, &val) == 0) && 1076 (val == val_arg)) 1077 return (1); 1078 break; 1079 } 1080 case DATA_TYPE_UINT8_ARRAY: { 1081 uint8_t *val_array, val_arg; 1082 1083 /* check indexed value of array for match */ 1084 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 1085 if ((sr == 1) && 1086 (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) && 1087 (ai < a_len) && 1088 (val_array[ai] == val_arg)) 1089 return (1); 1090 break; 1091 } 1092 case DATA_TYPE_INT16: { 1093 int16_t val, val_arg; 1094 1095 /* scanf int16_t from value and check for match */ 1096 sr = sscanf(value, "%"SCNi16, &val_arg); 1097 if ((sr == 1) && 1098 (nvpair_value_int16(nvp, &val) == 0) && 1099 (val == val_arg)) 1100 return (1); 1101 break; 1102 } 1103 case DATA_TYPE_INT16_ARRAY: { 1104 int16_t *val_array, val_arg; 1105 1106 /* check indexed value of array for match */ 1107 sr = sscanf(value, "%"SCNi16, &val_arg); 1108 if ((sr == 1) && 1109 (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) && 1110 (ai < a_len) && 1111 (val_array[ai] == val_arg)) 1112 return (1); 1113 break; 1114 } 1115 case DATA_TYPE_UINT16: { 1116 uint16_t val, val_arg; 1117 1118 /* scanf uint16_t from value and check for match */ 1119 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 1120 if ((sr == 1) && 1121 (nvpair_value_uint16(nvp, &val) == 0) && 1122 (val == val_arg)) 1123 return (1); 1124 break; 1125 } 1126 case DATA_TYPE_UINT16_ARRAY: { 1127 uint16_t *val_array, val_arg; 1128 1129 /* check indexed value of array for match */ 1130 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 1131 if ((sr == 1) && 1132 (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) && 1133 (ai < a_len) && 1134 (val_array[ai] == val_arg)) 1135 return (1); 1136 break; 1137 } 1138 case DATA_TYPE_INT32: { 1139 int32_t val, val_arg; 1140 1141 /* scanf int32_t from value and check for match */ 1142 sr = sscanf(value, "%"SCNi32, &val_arg); 1143 if ((sr == 1) && 1144 (nvpair_value_int32(nvp, &val) == 0) && 1145 (val == val_arg)) 1146 return (1); 1147 break; 1148 } 1149 case DATA_TYPE_INT32_ARRAY: { 1150 int32_t *val_array, val_arg; 1151 1152 /* check indexed value of array for match */ 1153 sr = sscanf(value, "%"SCNi32, &val_arg); 1154 if ((sr == 1) && 1155 (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) && 1156 (ai < a_len) && 1157 (val_array[ai] == val_arg)) 1158 return (1); 1159 break; 1160 } 1161 case DATA_TYPE_UINT32: { 1162 uint32_t val, val_arg; 1163 1164 /* scanf uint32_t from value and check for match */ 1165 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 1166 if ((sr == 1) && 1167 (nvpair_value_uint32(nvp, &val) == 0) && 1168 (val == val_arg)) 1169 return (1); 1170 break; 1171 } 1172 case DATA_TYPE_UINT32_ARRAY: { 1173 uint32_t *val_array, val_arg; 1174 1175 /* check indexed value of array for match */ 1176 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 1177 if ((sr == 1) && 1178 (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) && 1179 (ai < a_len) && 1180 (val_array[ai] == val_arg)) 1181 return (1); 1182 break; 1183 } 1184 case DATA_TYPE_INT64: { 1185 int64_t val, val_arg; 1186 1187 /* scanf int64_t from value and check for match */ 1188 sr = sscanf(value, "%"SCNi64, &val_arg); 1189 if ((sr == 1) && 1190 (nvpair_value_int64(nvp, &val) == 0) && 1191 (val == val_arg)) 1192 return (1); 1193 break; 1194 } 1195 case DATA_TYPE_INT64_ARRAY: { 1196 int64_t *val_array, val_arg; 1197 1198 /* check indexed value of array for match */ 1199 sr = sscanf(value, "%"SCNi64, &val_arg); 1200 if ((sr == 1) && 1201 (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) && 1202 (ai < a_len) && 1203 (val_array[ai] == val_arg)) 1204 return (1); 1205 break; 1206 } 1207 case DATA_TYPE_UINT64: { 1208 uint64_t val_arg, val; 1209 1210 /* scanf uint64_t from value and check for match */ 1211 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 1212 if ((sr == 1) && 1213 (nvpair_value_uint64(nvp, &val) == 0) && 1214 (val == val_arg)) 1215 return (1); 1216 break; 1217 } 1218 case DATA_TYPE_UINT64_ARRAY: { 1219 uint64_t *val_array, val_arg; 1220 1221 /* check indexed value of array for match */ 1222 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 1223 if ((sr == 1) && 1224 (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) && 1225 (ai < a_len) && 1226 (val_array[ai] == val_arg)) 1227 return (1); 1228 break; 1229 } 1230 case DATA_TYPE_BOOLEAN_VALUE: { 1231 boolean_t val, val_arg; 1232 1233 /* scanf boolean_t from value and check for match */ 1234 sr = sscanf(value, "%"SCNi32, &val_arg); 1235 if ((sr == 1) && 1236 (nvpair_value_boolean_value(nvp, &val) == 0) && 1237 (val == val_arg)) 1238 return (1); 1239 break; 1240 } 1241 case DATA_TYPE_BOOLEAN_ARRAY: { 1242 boolean_t *val_array, val_arg; 1243 1244 /* check indexed value of array for match */ 1245 sr = sscanf(value, "%"SCNi32, &val_arg); 1246 if ((sr == 1) && 1247 (nvpair_value_boolean_array(nvp, 1248 &val_array, &a_len) == 0) && 1249 (ai < a_len) && 1250 (val_array[ai] == val_arg)) 1251 return (1); 1252 break; 1253 } 1254 case DATA_TYPE_HRTIME: 1255 case DATA_TYPE_NVLIST: 1256 case DATA_TYPE_NVLIST_ARRAY: 1257 case DATA_TYPE_BOOLEAN: 1258 case DATA_TYPE_DOUBLE: 1259 case DATA_TYPE_UNKNOWN: 1260 default: 1261 /* 1262 * unknown/unsupported data type 1263 */ 1264 return (-1); /* error fail match */ 1265 } 1266 1267 /* 1268 * check to see if sscanf failed conversion, return approximate 1269 * pointer to problem 1270 */ 1271 if (sr != 1) { 1272 if (ep) 1273 *ep = value; 1274 return (-1); /* error fail match - syntax */ 1275 } 1276 1277 return (0); /* fail match */ 1278} 1279 1280int 1281nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep) 1282{ 1283 return (nvpair_value_match_regex(nvp, ai, value, NULL, ep)); 1284} 1285