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