Home | History | Annotate | Line # | Download | only in libnvpair
      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 <solaris.h>
     27 #include <inttypes.h>
     28 #include <unistd.h>
     29 #include <string.h>
     30 #include <libintl.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%f")
    215 NVLIST_PRTFUNC(string, char *, char *, "%s")
    216 NVLIST_PRTFUNC(hrtime, hrtime_t, hrtime_t, "0x%llx")
    217 
    218 /*
    219  * Generate functions to print array-valued nvlist members.
    220  */
    221 
    222 #define	NVLIST_ARRPRTFUNC(type_and_variant, vtype, ptype, vfmt) \
    223 static int \
    224 nvaprint_##type_and_variant(nvlist_prtctl_t pctl, void *private, \
    225     nvlist_t *nvl, const char *name, vtype *valuep, uint_t count) \
    226 { \
    227 	FILE *fp = pctl->nvprt_fp; \
    228 	uint_t i; \
    229 	NOTE(ARGUNUSED(private)) \
    230 	NOTE(ARGUNUSED(nvl)) \
    231 	for (i = 0; i < count; i++) { \
    232 		if (i == 0 || pctl->nvprt_btwnarrfmt_nl) { \
    233 			indent(pctl, 1); \
    234 			(void) fprintf(fp, pctl->nvprt_nmfmt, name); \
    235 			if (pctl->nvprt_btwnarrfmt_nl) \
    236 				(void) fprintf(fp, "[%d]: ", i); \
    237 		} \
    238 		if (i != 0) \
    239 			(void) fprintf(fp, 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 		int32_t val_arg;
   1233 		boolean_t val;
   1234 
   1235 		/* scanf boolean_t from value and check for match */
   1236 		sr = sscanf(value, "%"SCNi32, &val_arg);
   1237 		if ((sr == 1) &&
   1238 		    (nvpair_value_boolean_value(nvp, &val) == 0) &&
   1239 		    (val == val_arg))
   1240 			return (1);
   1241 		break;
   1242 	}
   1243 	case DATA_TYPE_BOOLEAN_ARRAY: {
   1244 		boolean_t *val_array;
   1245 		int32_t val_arg;
   1246 
   1247 		/* check indexed value of array for match */
   1248 		sr = sscanf(value, "%"SCNi32, &val_arg);
   1249 		if ((sr == 1) &&
   1250 		    (nvpair_value_boolean_array(nvp,
   1251 		    &val_array, &a_len) == 0) &&
   1252 		    (ai < a_len) &&
   1253 		    (val_array[ai] == val_arg))
   1254 			return (1);
   1255 		break;
   1256 	}
   1257 	case DATA_TYPE_HRTIME:
   1258 	case DATA_TYPE_NVLIST:
   1259 	case DATA_TYPE_NVLIST_ARRAY:
   1260 	case DATA_TYPE_BOOLEAN:
   1261 	case DATA_TYPE_DOUBLE:
   1262 	case DATA_TYPE_UNKNOWN:
   1263 	default:
   1264 		/*
   1265 		 * unknown/unsupported data type
   1266 		 */
   1267 		return (-1);		/* error fail match */
   1268 	}
   1269 
   1270 	/*
   1271 	 * check to see if sscanf failed conversion, return approximate
   1272 	 * pointer to problem
   1273 	 */
   1274 	if (sr != 1) {
   1275 		if (ep)
   1276 			*ep = value;
   1277 		return (-1);		/* error fail match  - syntax */
   1278 	}
   1279 
   1280 	return (0);			/* fail match */
   1281 }
   1282 
   1283 int
   1284 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
   1285 {
   1286 	return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
   1287 }
   1288