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  */
  24 
  25 #include <unistd.h>
  26 #include <strings.h>
  27 #include <libintl.h>
  28 #include <sys/types.h>
  29 #include <sys/inttypes.h>
  30 #include <stdarg.h>
  31 #include <note.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 
  60 struct 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 
  90 struct 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 
 143 static void nvlist_print_with_indent(nvlist_t *, nvlist_prtctl_t);
 144 
 145 /*
 146  * ======================================================================
 147  * |                                                                    |
 148  * | Indentation                                                        |
 149  * |                                                                    |
 150  * ======================================================================
 151  */
 152 
 153 static void
 154 indent(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) \
 189 static int \
 190 nvprint_##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 
 202 NVLIST_PRTFUNC(boolean, int, int, "%d")
 203 NVLIST_PRTFUNC(boolean_value, boolean_t, int, "%d")
 204 NVLIST_PRTFUNC(byte, uchar_t, uchar_t, "0x%2.2x")
 205 NVLIST_PRTFUNC(int8, int8_t, int, "%d")
 206 NVLIST_PRTFUNC(uint8, uint8_t, uint8_t, "0x%x")
 207 NVLIST_PRTFUNC(int16, int16_t, int16_t, "%d")
 208 NVLIST_PRTFUNC(uint16, uint16_t, uint16_t, "0x%x")
 209 NVLIST_PRTFUNC(int32, int32_t, int32_t, "%d")
 210 NVLIST_PRTFUNC(uint32, uint32_t, uint32_t, "0x%x")
 211 NVLIST_PRTFUNC(int64, int64_t, longlong_t, "%lld")
 212 NVLIST_PRTFUNC(uint64, uint64_t, u_longlong_t, "0x%llx")
 213 NVLIST_PRTFUNC(double, double, double, "0x%llf")
 214 NVLIST_PRTFUNC(string, char *, char *, "%s")
 215 NVLIST_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) \
 222 static int \
 223 nvaprint_##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 
 244 NVLIST_ARRPRTFUNC(boolean_array, boolean_t, boolean_t, "%d")
 245 NVLIST_ARRPRTFUNC(byte_array, uchar_t, uchar_t, "0x%2.2x")
 246 NVLIST_ARRPRTFUNC(int8_array, int8_t, int8_t, "%d")
 247 NVLIST_ARRPRTFUNC(uint8_array, uint8_t, uint8_t, "0x%x")
 248 NVLIST_ARRPRTFUNC(int16_array, int16_t, int16_t, "%d")
 249 NVLIST_ARRPRTFUNC(uint16_array, uint16_t, uint16_t, "0x%x")
 250 NVLIST_ARRPRTFUNC(int32_array, int32_t, int32_t, "%d")
 251 NVLIST_ARRPRTFUNC(uint32_array, uint32_t, uint32_t, "0x%x")
 252 NVLIST_ARRPRTFUNC(int64_array, int64_t, longlong_t, "%lld")
 253 NVLIST_ARRPRTFUNC(uint64_array, uint64_t, u_longlong_t, "0x%llx")
 254 NVLIST_ARRPRTFUNC(string_array, char *, char *, "%s")
 255 
 256 /*ARGSUSED*/
 257 static int
 258 nvprint_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*/
 277 static int
 278 nvaprint_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 
 310 void
 311 nvlist_prtctl_setdest(nvlist_prtctl_t pctl, FILE *fp)
 312 {
 313         pctl->nvprt_fp = fp;
 314 }
 315 
 316 FILE *
 317 nvlist_prtctl_getdest(nvlist_prtctl_t pctl)
 318 {
 319         return (pctl->nvprt_fp);
 320 }
 321 
 322 
 323 void
 324 nvlist_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 
 341 void
 342 nvlist_prtctl_doindent(nvlist_prtctl_t pctl, int onemore)
 343 {
 344         indent(pctl, onemore);
 345 }
 346 
 347 
 348 void
 349 nvlist_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 
 381 void
 382 nvlist_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) \
 420 void \
 421 nvlist_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 
 429 NVLIST_PRINTCTL_REPLACE(boolean, int)
 430 NVLIST_PRINTCTL_REPLACE(boolean_value, boolean_t)
 431 NVLIST_PRINTCTL_REPLACE(byte, uchar_t)
 432 NVLIST_PRINTCTL_REPLACE(int8, int8_t)
 433 NVLIST_PRINTCTL_REPLACE(uint8, uint8_t)
 434 NVLIST_PRINTCTL_REPLACE(int16, int16_t)
 435 NVLIST_PRINTCTL_REPLACE(uint16, uint16_t)
 436 NVLIST_PRINTCTL_REPLACE(int32, int32_t)
 437 NVLIST_PRINTCTL_REPLACE(uint32, uint32_t)
 438 NVLIST_PRINTCTL_REPLACE(int64, int64_t)
 439 NVLIST_PRINTCTL_REPLACE(uint64, uint64_t)
 440 NVLIST_PRINTCTL_REPLACE(double, double)
 441 NVLIST_PRINTCTL_REPLACE(string, char *)
 442 NVLIST_PRINTCTL_REPLACE(hrtime, hrtime_t)
 443 NVLIST_PRINTCTL_REPLACE(nvlist, nvlist_t *)
 444 
 445 #define NVLIST_PRINTCTL_AREPLACE(type, vtype) \
 446 void \
 447 nvlist_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 
 455 NVLIST_PRINTCTL_AREPLACE(boolean_array, boolean_t *)
 456 NVLIST_PRINTCTL_AREPLACE(byte_array, uchar_t *)
 457 NVLIST_PRINTCTL_AREPLACE(int8_array, int8_t *)
 458 NVLIST_PRINTCTL_AREPLACE(uint8_array, uint8_t *)
 459 NVLIST_PRINTCTL_AREPLACE(int16_array, int16_t *)
 460 NVLIST_PRINTCTL_AREPLACE(uint16_array, uint16_t *)
 461 NVLIST_PRINTCTL_AREPLACE(int32_array, int32_t *)
 462 NVLIST_PRINTCTL_AREPLACE(uint32_array, uint32_t *)
 463 NVLIST_PRINTCTL_AREPLACE(int64_array, int64_t *)
 464 NVLIST_PRINTCTL_AREPLACE(uint64_array, uint64_t *)
 465 NVLIST_PRINTCTL_AREPLACE(string_array, char **)
 466 NVLIST_PRINTCTL_AREPLACE(nvlist_array, nvlist_t **)
 467 
 468 /*
 469  * ======================================================================
 470  * |                                                                    |
 471  * | Interfaces to manage nvlist_prtctl_t cookies.                      |
 472  * |                                                                    |
 473  * ======================================================================
 474  */
 475 
 476 
 477 static 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 
 507 static void
 508 prtctl_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 
 524 nvlist_prtctl_t
 525 nvlist_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 
 543 void
 544 nvlist_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  */
 563 static void
 564 nvlist_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 
 754 void
 755 nvlist_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 
 763 void
 764 nvlist_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  */
 791 void
 792 dump_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_VALUE:
 807                         (void) nvpair_value_boolean_value(elem, &bool_value);
 808                         (void) printf("%*s%s: %s\n", indent, "",
 809                             nvpair_name(elem), bool_value ? "true" : "false");
 810                         break;
 811 
 812                 case DATA_TYPE_BYTE:
 813                         NVP(elem, byte, uchar_t, int, "%u");
 814                         break;
 815 
 816                 case DATA_TYPE_INT8:
 817                         NVP(elem, int8, int8_t, int, "%d");
 818                         break;
 819 
 820                 case DATA_TYPE_UINT8:
 821                         NVP(elem, uint8, uint8_t, int, "%u");
 822                         break;
 823 
 824                 case DATA_TYPE_INT16:
 825                         NVP(elem, int16, int16_t, int, "%d");
 826                         break;
 827 
 828                 case DATA_TYPE_UINT16:
 829                         NVP(elem, uint16, uint16_t, int, "%u");
 830                         break;
 831 
 832                 case DATA_TYPE_INT32:
 833                         NVP(elem, int32, int32_t, long, "%ld");
 834                         break;
 835 
 836                 case DATA_TYPE_UINT32:
 837                         NVP(elem, uint32, uint32_t, ulong_t, "%lu");
 838                         break;
 839 
 840                 case DATA_TYPE_INT64:
 841                         NVP(elem, int64, int64_t, longlong_t, "%lld");
 842                         break;
 843 
 844                 case DATA_TYPE_UINT64:
 845                         NVP(elem, uint64, uint64_t, u_longlong_t, "%llu");
 846                         break;
 847 
 848                 case DATA_TYPE_STRING:
 849                         NVP(elem, string, char *, char *, "'%s'");
 850                         break;
 851 
 852                 case DATA_TYPE_BYTE_ARRAY:
 853                         NVPA(elem, byte_array, uchar_t, int, "%u");
 854                         break;
 855 
 856                 case DATA_TYPE_INT8_ARRAY:
 857                         NVPA(elem, int8_array, int8_t, int, "%d");
 858                         break;
 859 
 860                 case DATA_TYPE_UINT8_ARRAY:
 861                         NVPA(elem, uint8_array, uint8_t, int, "%u");
 862                         break;
 863 
 864                 case DATA_TYPE_INT16_ARRAY:
 865                         NVPA(elem, int16_array, int16_t, int, "%d");
 866                         break;
 867 
 868                 case DATA_TYPE_UINT16_ARRAY:
 869                         NVPA(elem, uint16_array, uint16_t, int, "%u");
 870                         break;
 871 
 872                 case DATA_TYPE_INT32_ARRAY:
 873                         NVPA(elem, int32_array, int32_t, long, "%ld");
 874                         break;
 875 
 876                 case DATA_TYPE_UINT32_ARRAY:
 877                         NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu");
 878                         break;
 879 
 880                 case DATA_TYPE_INT64_ARRAY:
 881                         NVPA(elem, int64_array, int64_t, longlong_t, "%lld");
 882                         break;
 883 
 884                 case DATA_TYPE_UINT64_ARRAY:
 885                         NVPA(elem, uint64_array, uint64_t, u_longlong_t,
 886                             "%llu");
 887                         break;
 888 
 889                 case DATA_TYPE_STRING_ARRAY:
 890                         NVPA(elem, string_array, char *, char *, "'%s'");
 891                         break;
 892 
 893                 case DATA_TYPE_NVLIST:
 894                         (void) nvpair_value_nvlist(elem, &nvlist_value);
 895                         (void) printf("%*s%s:\n", indent, "",
 896                             nvpair_name(elem));
 897                         dump_nvlist(nvlist_value, indent + 4);
 898                         break;
 899 
 900                 case DATA_TYPE_NVLIST_ARRAY:
 901                         (void) nvpair_value_nvlist_array(elem,
 902                             &nvlist_array_value, &count);
 903                         for (i = 0; i < count; i++) {
 904                                 (void) printf("%*s%s[%u]:\n", indent, "",
 905                                     nvpair_name(elem), i);
 906                                 dump_nvlist(nvlist_array_value[i], indent + 4);
 907                         }
 908                         break;
 909 
 910                 default:
 911                         (void) printf(dgettext(TEXT_DOMAIN, "bad config type "
 912                             "%d for %s\n"), nvpair_type(elem),
 913                             nvpair_name(elem));
 914                 }
 915         }
 916 }
 917 
 918 /*
 919  * ======================================================================
 920  * |                                                                    |
 921  * | Misc private interface.                                            |
 922  * |                                                                    |
 923  * ======================================================================
 924  */
 925 
 926 /*
 927  * Determine if string 'value' matches 'nvp' value.  The 'value' string is
 928  * converted, depending on the type of 'nvp', prior to match.  For numeric
 929  * types, a radix independent sscanf conversion of 'value' is used. If 'nvp'
 930  * is an array type, 'ai' is the index into the array against which we are
 931  * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass
 932  * in a regex_t compilation of value in 'value_regex' to trigger regular
 933  * expression string match instead of simple strcmp().
 934  *
 935  * Return 1 on match, 0 on no-match, and -1 on error.  If the error is
 936  * related to value syntax error and 'ep' is non-NULL, *ep will point into
 937  * the 'value' string at the location where the error exists.
 938  *
 939  * NOTE: It may be possible to move the non-regex_t version of this into
 940  * common code used by library/kernel/boot.
 941  */
 942 int
 943 nvpair_value_match_regex(nvpair_t *nvp, int ai,
 944     char *value, regex_t *value_regex, char **ep)
 945 {
 946         char    *evalue;
 947         uint_t  a_len;
 948         int     sr;
 949 
 950         if (ep)
 951                 *ep = NULL;
 952 
 953         if ((nvp == NULL) || (value == NULL))
 954                 return (-1);            /* error fail match - invalid args */
 955 
 956         /* make sure array and index combination make sense */
 957         if ((nvpair_type_is_array(nvp) && (ai < 0)) ||
 958             (!nvpair_type_is_array(nvp) && (ai >= 0)))
 959                 return (-1);            /* error fail match - bad index */
 960 
 961         /* non-string values should be single 'chunk' */
 962         if ((nvpair_type(nvp) != DATA_TYPE_STRING) &&
 963             (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) {
 964                 value += strspn(value, " \t");
 965                 evalue = value + strcspn(value, " \t");
 966                 if (*evalue) {
 967                         if (ep)
 968                                 *ep = evalue;
 969                         return (-1);    /* error fail match - syntax */
 970                 }
 971         }
 972 
 973         sr = EOF;
 974         switch (nvpair_type(nvp)) {
 975         case DATA_TYPE_STRING: {
 976                 char    *val;
 977 
 978                 /* check string value for match */
 979                 if (nvpair_value_string(nvp, &val) == 0) {
 980                         if (value_regex) {
 981                                 if (regexec(value_regex, val,
 982                                     (size_t)0, NULL, 0) == 0)
 983                                         return (1);     /* match */
 984                         } else {
 985                                 if (strcmp(value, val) == 0)
 986                                         return (1);     /* match */
 987                         }
 988                 }
 989                 break;
 990         }
 991         case DATA_TYPE_STRING_ARRAY: {
 992                 char **val_array;
 993 
 994                 /* check indexed string value of array for match */
 995                 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
 996                     (ai < a_len)) {
 997                         if (value_regex) {
 998                                 if (regexec(value_regex, val_array[ai],
 999                                     (size_t)0, NULL, 0) == 0)
1000                                         return (1);
1001                         } else {
1002                                 if (strcmp(value, val_array[ai]) == 0)
1003                                         return (1);
1004                         }
1005                 }
1006                 break;
1007         }
1008         case DATA_TYPE_BYTE: {
1009                 uchar_t val, val_arg;
1010 
1011                 /* scanf uchar_t from value and check for match */
1012                 sr = sscanf(value, "%c", &val_arg);
1013                 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) &&
1014                     (val == val_arg))
1015                         return (1);
1016                 break;
1017         }
1018         case DATA_TYPE_BYTE_ARRAY: {
1019                 uchar_t *val_array, val_arg;
1020 
1021 
1022                 /* check indexed value of array for match */
1023                 sr = sscanf(value, "%c", &val_arg);
1024                 if ((sr == 1) &&
1025                     (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
1026                     (ai < a_len) &&
1027                     (val_array[ai] == val_arg))
1028                         return (1);
1029                 break;
1030         }
1031         case DATA_TYPE_INT8: {
1032                 int8_t val, val_arg;
1033 
1034                 /* scanf int8_t from value and check for match */
1035                 sr = sscanf(value, "%"SCNi8, &val_arg);
1036                 if ((sr == 1) &&
1037                     (nvpair_value_int8(nvp, &val) == 0) &&
1038                     (val == val_arg))
1039                         return (1);
1040                 break;
1041         }
1042         case DATA_TYPE_INT8_ARRAY: {
1043                 int8_t *val_array, val_arg;
1044 
1045                 /* check indexed value of array for match */
1046                 sr = sscanf(value, "%"SCNi8, &val_arg);
1047                 if ((sr == 1) &&
1048                     (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
1049                     (ai < a_len) &&
1050                     (val_array[ai] == val_arg))
1051                         return (1);
1052                 break;
1053         }
1054         case DATA_TYPE_UINT8: {
1055                 uint8_t val, val_arg;
1056 
1057                 /* scanf uint8_t from value and check for match */
1058                 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
1059                 if ((sr == 1) &&
1060                     (nvpair_value_uint8(nvp, &val) == 0) &&
1061                     (val == val_arg))
1062                         return (1);
1063                 break;
1064         }
1065         case DATA_TYPE_UINT8_ARRAY: {
1066                 uint8_t *val_array, val_arg;
1067 
1068                 /* check indexed value of array for match */
1069                 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
1070                 if ((sr == 1) &&
1071                     (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
1072                     (ai < a_len) &&
1073                     (val_array[ai] == val_arg))
1074                         return (1);
1075                 break;
1076         }
1077         case DATA_TYPE_INT16: {
1078                 int16_t val, val_arg;
1079 
1080                 /* scanf int16_t from value and check for match */
1081                 sr = sscanf(value, "%"SCNi16, &val_arg);
1082                 if ((sr == 1) &&
1083                     (nvpair_value_int16(nvp, &val) == 0) &&
1084                     (val == val_arg))
1085                         return (1);
1086                 break;
1087         }
1088         case DATA_TYPE_INT16_ARRAY: {
1089                 int16_t *val_array, val_arg;
1090 
1091                 /* check indexed value of array for match */
1092                 sr = sscanf(value, "%"SCNi16, &val_arg);
1093                 if ((sr == 1) &&
1094                     (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
1095                     (ai < a_len) &&
1096                     (val_array[ai] == val_arg))
1097                         return (1);
1098                 break;
1099         }
1100         case DATA_TYPE_UINT16: {
1101                 uint16_t val, val_arg;
1102 
1103                 /* scanf uint16_t from value and check for match */
1104                 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
1105                 if ((sr == 1) &&
1106                     (nvpair_value_uint16(nvp, &val) == 0) &&
1107                     (val == val_arg))
1108                         return (1);
1109                 break;
1110         }
1111         case DATA_TYPE_UINT16_ARRAY: {
1112                 uint16_t *val_array, val_arg;
1113 
1114                 /* check indexed value of array for match */
1115                 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
1116                 if ((sr == 1) &&
1117                     (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
1118                     (ai < a_len) &&
1119                     (val_array[ai] == val_arg))
1120                         return (1);
1121                 break;
1122         }
1123         case DATA_TYPE_INT32: {
1124                 int32_t val, val_arg;
1125 
1126                 /* scanf int32_t from value and check for match */
1127                 sr = sscanf(value, "%"SCNi32, &val_arg);
1128                 if ((sr == 1) &&
1129                     (nvpair_value_int32(nvp, &val) == 0) &&
1130                     (val == val_arg))
1131                         return (1);
1132                 break;
1133         }
1134         case DATA_TYPE_INT32_ARRAY: {
1135                 int32_t *val_array, val_arg;
1136 
1137                 /* check indexed value of array for match */
1138                 sr = sscanf(value, "%"SCNi32, &val_arg);
1139                 if ((sr == 1) &&
1140                     (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
1141                     (ai < a_len) &&
1142                     (val_array[ai] == val_arg))
1143                         return (1);
1144                 break;
1145         }
1146         case DATA_TYPE_UINT32: {
1147                 uint32_t val, val_arg;
1148 
1149                 /* scanf uint32_t from value and check for match */
1150                 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
1151                 if ((sr == 1) &&
1152                     (nvpair_value_uint32(nvp, &val) == 0) &&
1153                     (val == val_arg))
1154                         return (1);
1155                 break;
1156         }
1157         case DATA_TYPE_UINT32_ARRAY: {
1158                 uint32_t *val_array, val_arg;
1159 
1160                 /* check indexed value of array for match */
1161                 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
1162                 if ((sr == 1) &&
1163                     (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
1164                     (ai < a_len) &&
1165                     (val_array[ai] == val_arg))
1166                         return (1);
1167                 break;
1168         }
1169         case DATA_TYPE_INT64: {
1170                 int64_t val, val_arg;
1171 
1172                 /* scanf int64_t from value and check for match */
1173                 sr = sscanf(value, "%"SCNi64, &val_arg);
1174                 if ((sr == 1) &&
1175                     (nvpair_value_int64(nvp, &val) == 0) &&
1176                     (val == val_arg))
1177                         return (1);
1178                 break;
1179         }
1180         case DATA_TYPE_INT64_ARRAY: {
1181                 int64_t *val_array, val_arg;
1182 
1183                 /* check indexed value of array for match */
1184                 sr = sscanf(value, "%"SCNi64, &val_arg);
1185                 if ((sr == 1) &&
1186                     (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
1187                     (ai < a_len) &&
1188                     (val_array[ai] == val_arg))
1189                                 return (1);
1190                 break;
1191         }
1192         case DATA_TYPE_UINT64: {
1193                 uint64_t val_arg, val;
1194 
1195                 /* scanf uint64_t from value and check for match */
1196                 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
1197                 if ((sr == 1) &&
1198                     (nvpair_value_uint64(nvp, &val) == 0) &&
1199                     (val == val_arg))
1200                         return (1);
1201                 break;
1202         }
1203         case DATA_TYPE_UINT64_ARRAY: {
1204                 uint64_t *val_array, val_arg;
1205 
1206                 /* check indexed value of array for match */
1207                 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
1208                 if ((sr == 1) &&
1209                     (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
1210                     (ai < a_len) &&
1211                     (val_array[ai] == val_arg))
1212                         return (1);
1213                 break;
1214         }
1215         case DATA_TYPE_BOOLEAN_VALUE: {
1216                 boolean_t val, val_arg;
1217 
1218                 /* scanf boolean_t from value and check for match */
1219                 sr = sscanf(value, "%"SCNi32, &val_arg);
1220                 if ((sr == 1) &&
1221                     (nvpair_value_boolean_value(nvp, &val) == 0) &&
1222                     (val == val_arg))
1223                         return (1);
1224                 break;
1225         }
1226         case DATA_TYPE_BOOLEAN_ARRAY: {
1227                 boolean_t *val_array, val_arg;
1228 
1229                 /* check indexed value of array for match */
1230                 sr = sscanf(value, "%"SCNi32, &val_arg);
1231                 if ((sr == 1) &&
1232                     (nvpair_value_boolean_array(nvp,
1233                     &val_array, &a_len) == 0) &&
1234                     (ai < a_len) &&
1235                     (val_array[ai] == val_arg))
1236                         return (1);
1237                 break;
1238         }
1239         case DATA_TYPE_HRTIME:
1240         case DATA_TYPE_NVLIST:
1241         case DATA_TYPE_NVLIST_ARRAY:
1242         case DATA_TYPE_BOOLEAN:
1243         case DATA_TYPE_DOUBLE:
1244         case DATA_TYPE_UNKNOWN:
1245         default:
1246                 /*
1247                  * unknown/unsupported data type
1248                  */
1249                 return (-1);            /* error fail match */
1250         }
1251 
1252         /*
1253          * check to see if sscanf failed conversion, return approximate
1254          * pointer to problem
1255          */
1256         if (sr != 1) {
1257                 if (ep)
1258                         *ep = value;
1259                 return (-1);            /* error fail match  - syntax */
1260         }
1261 
1262         return (0);                     /* fail match */
1263 }
1264 
1265 int
1266 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
1267 {
1268         return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
1269 }