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