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