xref: /freebsd/sys/contrib/openzfs/lib/libnvpair/libnvpair_json.c (revision eda14cbc264d6969b02f2b1994cef11148e914f1)
1*eda14cbcSMatt Macy /*
2*eda14cbcSMatt Macy  * This file and its contents are supplied under the terms of the
3*eda14cbcSMatt Macy  * Common Development and Distribution License ("CDDL"), version 1.0.
4*eda14cbcSMatt Macy  * You may only use this file in accordance with the terms of version
5*eda14cbcSMatt Macy  * 1.0 of the CDDL.
6*eda14cbcSMatt Macy  *
7*eda14cbcSMatt Macy  * A full copy of the text of the CDDL should have accompanied this
8*eda14cbcSMatt Macy  * source.  A copy of the CDDL is also available via the Internet at
9*eda14cbcSMatt Macy  * http://www.illumos.org/license/CDDL.
10*eda14cbcSMatt Macy  */
11*eda14cbcSMatt Macy /*
12*eda14cbcSMatt Macy  * Copyright (c) 2014, Joyent, Inc.
13*eda14cbcSMatt Macy  * Copyright (c) 2017 by Delphix. All rights reserved.
14*eda14cbcSMatt Macy  */
15*eda14cbcSMatt Macy 
16*eda14cbcSMatt Macy #include <stdio.h>
17*eda14cbcSMatt Macy #include <stdlib.h>
18*eda14cbcSMatt Macy #include <strings.h>
19*eda14cbcSMatt Macy #include <wchar.h>
20*eda14cbcSMatt Macy #include <sys/debug.h>
21*eda14cbcSMatt Macy 
22*eda14cbcSMatt Macy #include "libnvpair.h"
23*eda14cbcSMatt Macy 
24*eda14cbcSMatt Macy #define	FPRINTF(fp, ...)				\
25*eda14cbcSMatt Macy 	do {						\
26*eda14cbcSMatt Macy 		if (fprintf(fp, __VA_ARGS__) < 0)	\
27*eda14cbcSMatt Macy 			return (-1);			\
28*eda14cbcSMatt Macy 	} while (0)
29*eda14cbcSMatt Macy 
30*eda14cbcSMatt Macy /*
31*eda14cbcSMatt Macy  * When formatting a string for JSON output we must escape certain characters,
32*eda14cbcSMatt Macy  * as described in RFC4627.  This applies to both member names and
33*eda14cbcSMatt Macy  * DATA_TYPE_STRING values.
34*eda14cbcSMatt Macy  *
35*eda14cbcSMatt Macy  * This function will only operate correctly if the following conditions are
36*eda14cbcSMatt Macy  * met:
37*eda14cbcSMatt Macy  *
38*eda14cbcSMatt Macy  *       1. The input String is encoded in the current locale.
39*eda14cbcSMatt Macy  *
40*eda14cbcSMatt Macy  *       2. The current locale includes the Basic Multilingual Plane (plane 0)
41*eda14cbcSMatt Macy  *          as defined in the Unicode standard.
42*eda14cbcSMatt Macy  *
43*eda14cbcSMatt Macy  * The output will be entirely 7-bit ASCII (as a subset of UTF-8) with all
44*eda14cbcSMatt Macy  * representable Unicode characters included in their escaped numeric form.
45*eda14cbcSMatt Macy  */
46*eda14cbcSMatt Macy static int
47*eda14cbcSMatt Macy nvlist_print_json_string(FILE *fp, const char *input)
48*eda14cbcSMatt Macy {
49*eda14cbcSMatt Macy 	mbstate_t mbr;
50*eda14cbcSMatt Macy 	wchar_t c;
51*eda14cbcSMatt Macy 	size_t sz;
52*eda14cbcSMatt Macy 
53*eda14cbcSMatt Macy 	bzero(&mbr, sizeof (mbr));
54*eda14cbcSMatt Macy 
55*eda14cbcSMatt Macy 	FPRINTF(fp, "\"");
56*eda14cbcSMatt Macy 	while ((sz = mbrtowc(&c, input, MB_CUR_MAX, &mbr)) > 0) {
57*eda14cbcSMatt Macy 		switch (c) {
58*eda14cbcSMatt Macy 		case '"':
59*eda14cbcSMatt Macy 			FPRINTF(fp, "\\\"");
60*eda14cbcSMatt Macy 			break;
61*eda14cbcSMatt Macy 		case '\n':
62*eda14cbcSMatt Macy 			FPRINTF(fp, "\\n");
63*eda14cbcSMatt Macy 			break;
64*eda14cbcSMatt Macy 		case '\r':
65*eda14cbcSMatt Macy 			FPRINTF(fp, "\\r");
66*eda14cbcSMatt Macy 			break;
67*eda14cbcSMatt Macy 		case '\\':
68*eda14cbcSMatt Macy 			FPRINTF(fp, "\\\\");
69*eda14cbcSMatt Macy 			break;
70*eda14cbcSMatt Macy 		case '\f':
71*eda14cbcSMatt Macy 			FPRINTF(fp, "\\f");
72*eda14cbcSMatt Macy 			break;
73*eda14cbcSMatt Macy 		case '\t':
74*eda14cbcSMatt Macy 			FPRINTF(fp, "\\t");
75*eda14cbcSMatt Macy 			break;
76*eda14cbcSMatt Macy 		case '\b':
77*eda14cbcSMatt Macy 			FPRINTF(fp, "\\b");
78*eda14cbcSMatt Macy 			break;
79*eda14cbcSMatt Macy 		default:
80*eda14cbcSMatt Macy 			if ((c >= 0x00 && c <= 0x1f) ||
81*eda14cbcSMatt Macy 			    (c > 0x7f && c <= 0xffff)) {
82*eda14cbcSMatt Macy 				/*
83*eda14cbcSMatt Macy 				 * Render both Control Characters and Unicode
84*eda14cbcSMatt Macy 				 * characters in the Basic Multilingual Plane
85*eda14cbcSMatt Macy 				 * as JSON-escaped multibyte characters.
86*eda14cbcSMatt Macy 				 */
87*eda14cbcSMatt Macy 				FPRINTF(fp, "\\u%04x", (int)(0xffff & c));
88*eda14cbcSMatt Macy 			} else if (c >= 0x20 && c <= 0x7f) {
89*eda14cbcSMatt Macy 				/*
90*eda14cbcSMatt Macy 				 * Render other 7-bit ASCII characters directly
91*eda14cbcSMatt Macy 				 * and drop other, unrepresentable characters.
92*eda14cbcSMatt Macy 				 */
93*eda14cbcSMatt Macy 				FPRINTF(fp, "%c", (int)(0xff & c));
94*eda14cbcSMatt Macy 			}
95*eda14cbcSMatt Macy 			break;
96*eda14cbcSMatt Macy 		}
97*eda14cbcSMatt Macy 		input += sz;
98*eda14cbcSMatt Macy 	}
99*eda14cbcSMatt Macy 
100*eda14cbcSMatt Macy 	if (sz == (size_t)-1 || sz == (size_t)-2) {
101*eda14cbcSMatt Macy 		/*
102*eda14cbcSMatt Macy 		 * We last read an invalid multibyte character sequence,
103*eda14cbcSMatt Macy 		 * so return an error.
104*eda14cbcSMatt Macy 		 */
105*eda14cbcSMatt Macy 		return (-1);
106*eda14cbcSMatt Macy 	}
107*eda14cbcSMatt Macy 
108*eda14cbcSMatt Macy 	FPRINTF(fp, "\"");
109*eda14cbcSMatt Macy 	return (0);
110*eda14cbcSMatt Macy }
111*eda14cbcSMatt Macy 
112*eda14cbcSMatt Macy /*
113*eda14cbcSMatt Macy  * Dump a JSON-formatted representation of an nvlist to the provided FILE *.
114*eda14cbcSMatt Macy  * This routine does not output any new-lines or additional whitespace other
115*eda14cbcSMatt Macy  * than that contained in strings, nor does it call fflush(3C).
116*eda14cbcSMatt Macy  */
117*eda14cbcSMatt Macy int
118*eda14cbcSMatt Macy nvlist_print_json(FILE *fp, nvlist_t *nvl)
119*eda14cbcSMatt Macy {
120*eda14cbcSMatt Macy 	nvpair_t *curr;
121*eda14cbcSMatt Macy 	boolean_t first = B_TRUE;
122*eda14cbcSMatt Macy 
123*eda14cbcSMatt Macy 	FPRINTF(fp, "{");
124*eda14cbcSMatt Macy 
125*eda14cbcSMatt Macy 	for (curr = nvlist_next_nvpair(nvl, NULL); curr;
126*eda14cbcSMatt Macy 	    curr = nvlist_next_nvpair(nvl, curr)) {
127*eda14cbcSMatt Macy 		data_type_t type = nvpair_type(curr);
128*eda14cbcSMatt Macy 
129*eda14cbcSMatt Macy 		if (!first)
130*eda14cbcSMatt Macy 			FPRINTF(fp, ",");
131*eda14cbcSMatt Macy 		else
132*eda14cbcSMatt Macy 			first = B_FALSE;
133*eda14cbcSMatt Macy 
134*eda14cbcSMatt Macy 		if (nvlist_print_json_string(fp, nvpair_name(curr)) == -1)
135*eda14cbcSMatt Macy 			return (-1);
136*eda14cbcSMatt Macy 		FPRINTF(fp, ":");
137*eda14cbcSMatt Macy 
138*eda14cbcSMatt Macy 		switch (type) {
139*eda14cbcSMatt Macy 		case DATA_TYPE_STRING: {
140*eda14cbcSMatt Macy 			char *string = fnvpair_value_string(curr);
141*eda14cbcSMatt Macy 			if (nvlist_print_json_string(fp, string) == -1)
142*eda14cbcSMatt Macy 				return (-1);
143*eda14cbcSMatt Macy 			break;
144*eda14cbcSMatt Macy 		}
145*eda14cbcSMatt Macy 
146*eda14cbcSMatt Macy 		case DATA_TYPE_BOOLEAN: {
147*eda14cbcSMatt Macy 			FPRINTF(fp, "true");
148*eda14cbcSMatt Macy 			break;
149*eda14cbcSMatt Macy 		}
150*eda14cbcSMatt Macy 
151*eda14cbcSMatt Macy 		case DATA_TYPE_BOOLEAN_VALUE: {
152*eda14cbcSMatt Macy 			FPRINTF(fp, "%s", fnvpair_value_boolean_value(curr) ==
153*eda14cbcSMatt Macy 			    B_TRUE ? "true" : "false");
154*eda14cbcSMatt Macy 			break;
155*eda14cbcSMatt Macy 		}
156*eda14cbcSMatt Macy 
157*eda14cbcSMatt Macy 		case DATA_TYPE_BYTE: {
158*eda14cbcSMatt Macy 			FPRINTF(fp, "%hhu", fnvpair_value_byte(curr));
159*eda14cbcSMatt Macy 			break;
160*eda14cbcSMatt Macy 		}
161*eda14cbcSMatt Macy 
162*eda14cbcSMatt Macy 		case DATA_TYPE_INT8: {
163*eda14cbcSMatt Macy 			FPRINTF(fp, "%hhd", fnvpair_value_int8(curr));
164*eda14cbcSMatt Macy 			break;
165*eda14cbcSMatt Macy 		}
166*eda14cbcSMatt Macy 
167*eda14cbcSMatt Macy 		case DATA_TYPE_UINT8: {
168*eda14cbcSMatt Macy 			FPRINTF(fp, "%hhu", fnvpair_value_uint8(curr));
169*eda14cbcSMatt Macy 			break;
170*eda14cbcSMatt Macy 		}
171*eda14cbcSMatt Macy 
172*eda14cbcSMatt Macy 		case DATA_TYPE_INT16: {
173*eda14cbcSMatt Macy 			FPRINTF(fp, "%hd", fnvpair_value_int16(curr));
174*eda14cbcSMatt Macy 			break;
175*eda14cbcSMatt Macy 		}
176*eda14cbcSMatt Macy 
177*eda14cbcSMatt Macy 		case DATA_TYPE_UINT16: {
178*eda14cbcSMatt Macy 			FPRINTF(fp, "%hu", fnvpair_value_uint16(curr));
179*eda14cbcSMatt Macy 			break;
180*eda14cbcSMatt Macy 		}
181*eda14cbcSMatt Macy 
182*eda14cbcSMatt Macy 		case DATA_TYPE_INT32: {
183*eda14cbcSMatt Macy 			FPRINTF(fp, "%d", fnvpair_value_int32(curr));
184*eda14cbcSMatt Macy 			break;
185*eda14cbcSMatt Macy 		}
186*eda14cbcSMatt Macy 
187*eda14cbcSMatt Macy 		case DATA_TYPE_UINT32: {
188*eda14cbcSMatt Macy 			FPRINTF(fp, "%u", fnvpair_value_uint32(curr));
189*eda14cbcSMatt Macy 			break;
190*eda14cbcSMatt Macy 		}
191*eda14cbcSMatt Macy 
192*eda14cbcSMatt Macy 		case DATA_TYPE_INT64: {
193*eda14cbcSMatt Macy 			FPRINTF(fp, "%lld",
194*eda14cbcSMatt Macy 			    (long long)fnvpair_value_int64(curr));
195*eda14cbcSMatt Macy 			break;
196*eda14cbcSMatt Macy 		}
197*eda14cbcSMatt Macy 
198*eda14cbcSMatt Macy 		case DATA_TYPE_UINT64: {
199*eda14cbcSMatt Macy 			FPRINTF(fp, "%llu",
200*eda14cbcSMatt Macy 			    (unsigned long long)fnvpair_value_uint64(curr));
201*eda14cbcSMatt Macy 			break;
202*eda14cbcSMatt Macy 		}
203*eda14cbcSMatt Macy 
204*eda14cbcSMatt Macy 		case DATA_TYPE_HRTIME: {
205*eda14cbcSMatt Macy 			hrtime_t val;
206*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_hrtime(curr, &val));
207*eda14cbcSMatt Macy 			FPRINTF(fp, "%llu", (unsigned long long)val);
208*eda14cbcSMatt Macy 			break;
209*eda14cbcSMatt Macy 		}
210*eda14cbcSMatt Macy 
211*eda14cbcSMatt Macy 		case DATA_TYPE_DOUBLE: {
212*eda14cbcSMatt Macy 			double val;
213*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_double(curr, &val));
214*eda14cbcSMatt Macy 			FPRINTF(fp, "%f", val);
215*eda14cbcSMatt Macy 			break;
216*eda14cbcSMatt Macy 		}
217*eda14cbcSMatt Macy 
218*eda14cbcSMatt Macy 		case DATA_TYPE_NVLIST: {
219*eda14cbcSMatt Macy 			if (nvlist_print_json(fp,
220*eda14cbcSMatt Macy 			    fnvpair_value_nvlist(curr)) == -1)
221*eda14cbcSMatt Macy 				return (-1);
222*eda14cbcSMatt Macy 			break;
223*eda14cbcSMatt Macy 		}
224*eda14cbcSMatt Macy 
225*eda14cbcSMatt Macy 		case DATA_TYPE_STRING_ARRAY: {
226*eda14cbcSMatt Macy 			char **val;
227*eda14cbcSMatt Macy 			uint_t valsz, i;
228*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_string_array(curr, &val, &valsz));
229*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
230*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
231*eda14cbcSMatt Macy 				if (i > 0)
232*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
233*eda14cbcSMatt Macy 				if (nvlist_print_json_string(fp, val[i]) == -1)
234*eda14cbcSMatt Macy 					return (-1);
235*eda14cbcSMatt Macy 			}
236*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
237*eda14cbcSMatt Macy 			break;
238*eda14cbcSMatt Macy 		}
239*eda14cbcSMatt Macy 
240*eda14cbcSMatt Macy 		case DATA_TYPE_NVLIST_ARRAY: {
241*eda14cbcSMatt Macy 			nvlist_t **val;
242*eda14cbcSMatt Macy 			uint_t valsz, i;
243*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_nvlist_array(curr, &val, &valsz));
244*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
245*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
246*eda14cbcSMatt Macy 				if (i > 0)
247*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
248*eda14cbcSMatt Macy 				if (nvlist_print_json(fp, val[i]) == -1)
249*eda14cbcSMatt Macy 					return (-1);
250*eda14cbcSMatt Macy 			}
251*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
252*eda14cbcSMatt Macy 			break;
253*eda14cbcSMatt Macy 		}
254*eda14cbcSMatt Macy 
255*eda14cbcSMatt Macy 		case DATA_TYPE_BOOLEAN_ARRAY: {
256*eda14cbcSMatt Macy 			boolean_t *val;
257*eda14cbcSMatt Macy 			uint_t valsz, i;
258*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_boolean_array(curr, &val, &valsz));
259*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
260*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
261*eda14cbcSMatt Macy 				if (i > 0)
262*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
263*eda14cbcSMatt Macy 				FPRINTF(fp, val[i] == B_TRUE ?
264*eda14cbcSMatt Macy 				    "true" : "false");
265*eda14cbcSMatt Macy 			}
266*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
267*eda14cbcSMatt Macy 			break;
268*eda14cbcSMatt Macy 		}
269*eda14cbcSMatt Macy 
270*eda14cbcSMatt Macy 		case DATA_TYPE_BYTE_ARRAY: {
271*eda14cbcSMatt Macy 			uchar_t *val;
272*eda14cbcSMatt Macy 			uint_t valsz, i;
273*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_byte_array(curr, &val, &valsz));
274*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
275*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
276*eda14cbcSMatt Macy 				if (i > 0)
277*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
278*eda14cbcSMatt Macy 				FPRINTF(fp, "%hhu", val[i]);
279*eda14cbcSMatt Macy 			}
280*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
281*eda14cbcSMatt Macy 			break;
282*eda14cbcSMatt Macy 		}
283*eda14cbcSMatt Macy 
284*eda14cbcSMatt Macy 		case DATA_TYPE_UINT8_ARRAY: {
285*eda14cbcSMatt Macy 			uint8_t *val;
286*eda14cbcSMatt Macy 			uint_t valsz, i;
287*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_uint8_array(curr, &val, &valsz));
288*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
289*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
290*eda14cbcSMatt Macy 				if (i > 0)
291*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
292*eda14cbcSMatt Macy 				FPRINTF(fp, "%hhu", val[i]);
293*eda14cbcSMatt Macy 			}
294*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
295*eda14cbcSMatt Macy 			break;
296*eda14cbcSMatt Macy 		}
297*eda14cbcSMatt Macy 
298*eda14cbcSMatt Macy 		case DATA_TYPE_INT8_ARRAY: {
299*eda14cbcSMatt Macy 			int8_t *val;
300*eda14cbcSMatt Macy 			uint_t valsz, i;
301*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_int8_array(curr, &val, &valsz));
302*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
303*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
304*eda14cbcSMatt Macy 				if (i > 0)
305*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
306*eda14cbcSMatt Macy 				FPRINTF(fp, "%hhd", val[i]);
307*eda14cbcSMatt Macy 			}
308*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
309*eda14cbcSMatt Macy 			break;
310*eda14cbcSMatt Macy 		}
311*eda14cbcSMatt Macy 
312*eda14cbcSMatt Macy 		case DATA_TYPE_UINT16_ARRAY: {
313*eda14cbcSMatt Macy 			uint16_t *val;
314*eda14cbcSMatt Macy 			uint_t valsz, i;
315*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_uint16_array(curr, &val, &valsz));
316*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
317*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
318*eda14cbcSMatt Macy 				if (i > 0)
319*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
320*eda14cbcSMatt Macy 				FPRINTF(fp, "%hu", val[i]);
321*eda14cbcSMatt Macy 			}
322*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
323*eda14cbcSMatt Macy 			break;
324*eda14cbcSMatt Macy 		}
325*eda14cbcSMatt Macy 
326*eda14cbcSMatt Macy 		case DATA_TYPE_INT16_ARRAY: {
327*eda14cbcSMatt Macy 			int16_t *val;
328*eda14cbcSMatt Macy 			uint_t valsz, i;
329*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_int16_array(curr, &val, &valsz));
330*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
331*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
332*eda14cbcSMatt Macy 				if (i > 0)
333*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
334*eda14cbcSMatt Macy 				FPRINTF(fp, "%hd", val[i]);
335*eda14cbcSMatt Macy 			}
336*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
337*eda14cbcSMatt Macy 			break;
338*eda14cbcSMatt Macy 		}
339*eda14cbcSMatt Macy 
340*eda14cbcSMatt Macy 		case DATA_TYPE_UINT32_ARRAY: {
341*eda14cbcSMatt Macy 			uint32_t *val;
342*eda14cbcSMatt Macy 			uint_t valsz, i;
343*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_uint32_array(curr, &val, &valsz));
344*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
345*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
346*eda14cbcSMatt Macy 				if (i > 0)
347*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
348*eda14cbcSMatt Macy 				FPRINTF(fp, "%u", val[i]);
349*eda14cbcSMatt Macy 			}
350*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
351*eda14cbcSMatt Macy 			break;
352*eda14cbcSMatt Macy 		}
353*eda14cbcSMatt Macy 
354*eda14cbcSMatt Macy 		case DATA_TYPE_INT32_ARRAY: {
355*eda14cbcSMatt Macy 			int32_t *val;
356*eda14cbcSMatt Macy 			uint_t valsz, i;
357*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_int32_array(curr, &val, &valsz));
358*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
359*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
360*eda14cbcSMatt Macy 				if (i > 0)
361*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
362*eda14cbcSMatt Macy 				FPRINTF(fp, "%d", val[i]);
363*eda14cbcSMatt Macy 			}
364*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
365*eda14cbcSMatt Macy 			break;
366*eda14cbcSMatt Macy 		}
367*eda14cbcSMatt Macy 
368*eda14cbcSMatt Macy 		case DATA_TYPE_UINT64_ARRAY: {
369*eda14cbcSMatt Macy 			uint64_t *val;
370*eda14cbcSMatt Macy 			uint_t valsz, i;
371*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_uint64_array(curr, &val, &valsz));
372*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
373*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
374*eda14cbcSMatt Macy 				if (i > 0)
375*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
376*eda14cbcSMatt Macy 				FPRINTF(fp, "%llu",
377*eda14cbcSMatt Macy 				    (unsigned long long)val[i]);
378*eda14cbcSMatt Macy 			}
379*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
380*eda14cbcSMatt Macy 			break;
381*eda14cbcSMatt Macy 		}
382*eda14cbcSMatt Macy 
383*eda14cbcSMatt Macy 		case DATA_TYPE_INT64_ARRAY: {
384*eda14cbcSMatt Macy 			int64_t *val;
385*eda14cbcSMatt Macy 			uint_t valsz, i;
386*eda14cbcSMatt Macy 			VERIFY0(nvpair_value_int64_array(curr, &val, &valsz));
387*eda14cbcSMatt Macy 			FPRINTF(fp, "[");
388*eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
389*eda14cbcSMatt Macy 				if (i > 0)
390*eda14cbcSMatt Macy 					FPRINTF(fp, ",");
391*eda14cbcSMatt Macy 				FPRINTF(fp, "%lld", (long long)val[i]);
392*eda14cbcSMatt Macy 			}
393*eda14cbcSMatt Macy 			FPRINTF(fp, "]");
394*eda14cbcSMatt Macy 			break;
395*eda14cbcSMatt Macy 		}
396*eda14cbcSMatt Macy 
397*eda14cbcSMatt Macy 		case DATA_TYPE_UNKNOWN:
398*eda14cbcSMatt Macy 		case DATA_TYPE_DONTCARE:
399*eda14cbcSMatt Macy 			return (-1);
400*eda14cbcSMatt Macy 		}
401*eda14cbcSMatt Macy 
402*eda14cbcSMatt Macy 	}
403*eda14cbcSMatt Macy 
404*eda14cbcSMatt Macy 	FPRINTF(fp, "}");
405*eda14cbcSMatt Macy 	return (0);
406*eda14cbcSMatt Macy }
407