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