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>
18da5137abSMartin Matuska #include <string.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
nvlist_print_json_string(FILE * fp,const char * input)47eda14cbcSMatt Macy nvlist_print_json_string(FILE *fp, const char *input)
48eda14cbcSMatt Macy {
49da5137abSMartin Matuska 	mbstate_t mbr = {0};
50eda14cbcSMatt Macy 	wchar_t c;
51eda14cbcSMatt Macy 	size_t sz;
52eda14cbcSMatt Macy 
53eda14cbcSMatt Macy 	FPRINTF(fp, "\"");
54eda14cbcSMatt Macy 	while ((sz = mbrtowc(&c, input, MB_CUR_MAX, &mbr)) > 0) {
5516038816SMartin Matuska 		if (sz == (size_t)-1 || sz == (size_t)-2) {
5616038816SMartin Matuska 			/*
5716038816SMartin Matuska 			 * We last read an invalid multibyte character sequence,
5816038816SMartin Matuska 			 * so return an error.
5916038816SMartin Matuska 			 */
6016038816SMartin Matuska 			return (-1);
6116038816SMartin Matuska 		}
62eda14cbcSMatt Macy 		switch (c) {
63eda14cbcSMatt Macy 		case '"':
64eda14cbcSMatt Macy 			FPRINTF(fp, "\\\"");
65eda14cbcSMatt Macy 			break;
66eda14cbcSMatt Macy 		case '\n':
67eda14cbcSMatt Macy 			FPRINTF(fp, "\\n");
68eda14cbcSMatt Macy 			break;
69eda14cbcSMatt Macy 		case '\r':
70eda14cbcSMatt Macy 			FPRINTF(fp, "\\r");
71eda14cbcSMatt Macy 			break;
72eda14cbcSMatt Macy 		case '\\':
73eda14cbcSMatt Macy 			FPRINTF(fp, "\\\\");
74eda14cbcSMatt Macy 			break;
75eda14cbcSMatt Macy 		case '\f':
76eda14cbcSMatt Macy 			FPRINTF(fp, "\\f");
77eda14cbcSMatt Macy 			break;
78eda14cbcSMatt Macy 		case '\t':
79eda14cbcSMatt Macy 			FPRINTF(fp, "\\t");
80eda14cbcSMatt Macy 			break;
81eda14cbcSMatt Macy 		case '\b':
82eda14cbcSMatt Macy 			FPRINTF(fp, "\\b");
83eda14cbcSMatt Macy 			break;
84eda14cbcSMatt Macy 		default:
85eda14cbcSMatt Macy 			if ((c >= 0x00 && c <= 0x1f) ||
86eda14cbcSMatt Macy 			    (c > 0x7f && c <= 0xffff)) {
87eda14cbcSMatt Macy 				/*
88eda14cbcSMatt Macy 				 * Render both Control Characters and Unicode
89eda14cbcSMatt Macy 				 * characters in the Basic Multilingual Plane
90eda14cbcSMatt Macy 				 * as JSON-escaped multibyte characters.
91eda14cbcSMatt Macy 				 */
92eda14cbcSMatt Macy 				FPRINTF(fp, "\\u%04x", (int)(0xffff & c));
93eda14cbcSMatt Macy 			} else if (c >= 0x20 && c <= 0x7f) {
94eda14cbcSMatt Macy 				/*
95eda14cbcSMatt Macy 				 * Render other 7-bit ASCII characters directly
96eda14cbcSMatt Macy 				 * and drop other, unrepresentable characters.
97eda14cbcSMatt Macy 				 */
98eda14cbcSMatt Macy 				FPRINTF(fp, "%c", (int)(0xff & c));
99eda14cbcSMatt Macy 			}
100eda14cbcSMatt Macy 			break;
101eda14cbcSMatt Macy 		}
102eda14cbcSMatt Macy 		input += sz;
103eda14cbcSMatt Macy 	}
104eda14cbcSMatt Macy 
105eda14cbcSMatt Macy 	FPRINTF(fp, "\"");
106eda14cbcSMatt Macy 	return (0);
107eda14cbcSMatt Macy }
108eda14cbcSMatt Macy 
109eda14cbcSMatt Macy /*
110eda14cbcSMatt Macy  * Dump a JSON-formatted representation of an nvlist to the provided FILE *.
111eda14cbcSMatt Macy  * This routine does not output any new-lines or additional whitespace other
112eda14cbcSMatt Macy  * than that contained in strings, nor does it call fflush(3C).
113eda14cbcSMatt Macy  */
114eda14cbcSMatt Macy int
nvlist_print_json(FILE * fp,nvlist_t * nvl)115eda14cbcSMatt Macy nvlist_print_json(FILE *fp, nvlist_t *nvl)
116eda14cbcSMatt Macy {
117eda14cbcSMatt Macy 	nvpair_t *curr;
118eda14cbcSMatt Macy 	boolean_t first = B_TRUE;
119eda14cbcSMatt Macy 
120eda14cbcSMatt Macy 	FPRINTF(fp, "{");
121eda14cbcSMatt Macy 
122eda14cbcSMatt Macy 	for (curr = nvlist_next_nvpair(nvl, NULL); curr;
123eda14cbcSMatt Macy 	    curr = nvlist_next_nvpair(nvl, curr)) {
124eda14cbcSMatt Macy 		data_type_t type = nvpair_type(curr);
125eda14cbcSMatt Macy 
126eda14cbcSMatt Macy 		if (!first)
127eda14cbcSMatt Macy 			FPRINTF(fp, ",");
128eda14cbcSMatt Macy 		else
129eda14cbcSMatt Macy 			first = B_FALSE;
130eda14cbcSMatt Macy 
131eda14cbcSMatt Macy 		if (nvlist_print_json_string(fp, nvpair_name(curr)) == -1)
132eda14cbcSMatt Macy 			return (-1);
133eda14cbcSMatt Macy 		FPRINTF(fp, ":");
134eda14cbcSMatt Macy 
135eda14cbcSMatt Macy 		switch (type) {
136eda14cbcSMatt Macy 		case DATA_TYPE_STRING: {
137*2a58b312SMartin Matuska 			const char *string = fnvpair_value_string(curr);
138eda14cbcSMatt Macy 			if (nvlist_print_json_string(fp, string) == -1)
139eda14cbcSMatt Macy 				return (-1);
140eda14cbcSMatt Macy 			break;
141eda14cbcSMatt Macy 		}
142eda14cbcSMatt Macy 
143eda14cbcSMatt Macy 		case DATA_TYPE_BOOLEAN: {
144eda14cbcSMatt Macy 			FPRINTF(fp, "true");
145eda14cbcSMatt Macy 			break;
146eda14cbcSMatt Macy 		}
147eda14cbcSMatt Macy 
148eda14cbcSMatt Macy 		case DATA_TYPE_BOOLEAN_VALUE: {
149eda14cbcSMatt Macy 			FPRINTF(fp, "%s", fnvpair_value_boolean_value(curr) ==
150eda14cbcSMatt Macy 			    B_TRUE ? "true" : "false");
151eda14cbcSMatt Macy 			break;
152eda14cbcSMatt Macy 		}
153eda14cbcSMatt Macy 
154eda14cbcSMatt Macy 		case DATA_TYPE_BYTE: {
155eda14cbcSMatt Macy 			FPRINTF(fp, "%hhu", fnvpair_value_byte(curr));
156eda14cbcSMatt Macy 			break;
157eda14cbcSMatt Macy 		}
158eda14cbcSMatt Macy 
159eda14cbcSMatt Macy 		case DATA_TYPE_INT8: {
160eda14cbcSMatt Macy 			FPRINTF(fp, "%hhd", fnvpair_value_int8(curr));
161eda14cbcSMatt Macy 			break;
162eda14cbcSMatt Macy 		}
163eda14cbcSMatt Macy 
164eda14cbcSMatt Macy 		case DATA_TYPE_UINT8: {
165eda14cbcSMatt Macy 			FPRINTF(fp, "%hhu", fnvpair_value_uint8(curr));
166eda14cbcSMatt Macy 			break;
167eda14cbcSMatt Macy 		}
168eda14cbcSMatt Macy 
169eda14cbcSMatt Macy 		case DATA_TYPE_INT16: {
170eda14cbcSMatt Macy 			FPRINTF(fp, "%hd", fnvpair_value_int16(curr));
171eda14cbcSMatt Macy 			break;
172eda14cbcSMatt Macy 		}
173eda14cbcSMatt Macy 
174eda14cbcSMatt Macy 		case DATA_TYPE_UINT16: {
175eda14cbcSMatt Macy 			FPRINTF(fp, "%hu", fnvpair_value_uint16(curr));
176eda14cbcSMatt Macy 			break;
177eda14cbcSMatt Macy 		}
178eda14cbcSMatt Macy 
179eda14cbcSMatt Macy 		case DATA_TYPE_INT32: {
180eda14cbcSMatt Macy 			FPRINTF(fp, "%d", fnvpair_value_int32(curr));
181eda14cbcSMatt Macy 			break;
182eda14cbcSMatt Macy 		}
183eda14cbcSMatt Macy 
184eda14cbcSMatt Macy 		case DATA_TYPE_UINT32: {
185eda14cbcSMatt Macy 			FPRINTF(fp, "%u", fnvpair_value_uint32(curr));
186eda14cbcSMatt Macy 			break;
187eda14cbcSMatt Macy 		}
188eda14cbcSMatt Macy 
189eda14cbcSMatt Macy 		case DATA_TYPE_INT64: {
190eda14cbcSMatt Macy 			FPRINTF(fp, "%lld",
191eda14cbcSMatt Macy 			    (long long)fnvpair_value_int64(curr));
192eda14cbcSMatt Macy 			break;
193eda14cbcSMatt Macy 		}
194eda14cbcSMatt Macy 
195eda14cbcSMatt Macy 		case DATA_TYPE_UINT64: {
196eda14cbcSMatt Macy 			FPRINTF(fp, "%llu",
197eda14cbcSMatt Macy 			    (unsigned long long)fnvpair_value_uint64(curr));
198eda14cbcSMatt Macy 			break;
199eda14cbcSMatt Macy 		}
200eda14cbcSMatt Macy 
201eda14cbcSMatt Macy 		case DATA_TYPE_HRTIME: {
202eda14cbcSMatt Macy 			hrtime_t val;
203eda14cbcSMatt Macy 			VERIFY0(nvpair_value_hrtime(curr, &val));
204eda14cbcSMatt Macy 			FPRINTF(fp, "%llu", (unsigned long long)val);
205eda14cbcSMatt Macy 			break;
206eda14cbcSMatt Macy 		}
207eda14cbcSMatt Macy 
208eda14cbcSMatt Macy 		case DATA_TYPE_DOUBLE: {
209eda14cbcSMatt Macy 			double val;
210eda14cbcSMatt Macy 			VERIFY0(nvpair_value_double(curr, &val));
211eda14cbcSMatt Macy 			FPRINTF(fp, "%f", val);
212eda14cbcSMatt Macy 			break;
213eda14cbcSMatt Macy 		}
214eda14cbcSMatt Macy 
215eda14cbcSMatt Macy 		case DATA_TYPE_NVLIST: {
216eda14cbcSMatt Macy 			if (nvlist_print_json(fp,
217eda14cbcSMatt Macy 			    fnvpair_value_nvlist(curr)) == -1)
218eda14cbcSMatt Macy 				return (-1);
219eda14cbcSMatt Macy 			break;
220eda14cbcSMatt Macy 		}
221eda14cbcSMatt Macy 
222eda14cbcSMatt Macy 		case DATA_TYPE_STRING_ARRAY: {
223*2a58b312SMartin Matuska 			const char **val;
224eda14cbcSMatt Macy 			uint_t valsz, i;
225eda14cbcSMatt Macy 			VERIFY0(nvpair_value_string_array(curr, &val, &valsz));
226eda14cbcSMatt Macy 			FPRINTF(fp, "[");
227eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
228eda14cbcSMatt Macy 				if (i > 0)
229eda14cbcSMatt Macy 					FPRINTF(fp, ",");
230eda14cbcSMatt Macy 				if (nvlist_print_json_string(fp, val[i]) == -1)
231eda14cbcSMatt Macy 					return (-1);
232eda14cbcSMatt Macy 			}
233eda14cbcSMatt Macy 			FPRINTF(fp, "]");
234eda14cbcSMatt Macy 			break;
235eda14cbcSMatt Macy 		}
236eda14cbcSMatt Macy 
237eda14cbcSMatt Macy 		case DATA_TYPE_NVLIST_ARRAY: {
238eda14cbcSMatt Macy 			nvlist_t **val;
239eda14cbcSMatt Macy 			uint_t valsz, i;
240eda14cbcSMatt Macy 			VERIFY0(nvpair_value_nvlist_array(curr, &val, &valsz));
241eda14cbcSMatt Macy 			FPRINTF(fp, "[");
242eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
243eda14cbcSMatt Macy 				if (i > 0)
244eda14cbcSMatt Macy 					FPRINTF(fp, ",");
245eda14cbcSMatt Macy 				if (nvlist_print_json(fp, val[i]) == -1)
246eda14cbcSMatt Macy 					return (-1);
247eda14cbcSMatt Macy 			}
248eda14cbcSMatt Macy 			FPRINTF(fp, "]");
249eda14cbcSMatt Macy 			break;
250eda14cbcSMatt Macy 		}
251eda14cbcSMatt Macy 
252eda14cbcSMatt Macy 		case DATA_TYPE_BOOLEAN_ARRAY: {
253eda14cbcSMatt Macy 			boolean_t *val;
254eda14cbcSMatt Macy 			uint_t valsz, i;
255eda14cbcSMatt Macy 			VERIFY0(nvpair_value_boolean_array(curr, &val, &valsz));
256eda14cbcSMatt Macy 			FPRINTF(fp, "[");
257eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
258eda14cbcSMatt Macy 				if (i > 0)
259eda14cbcSMatt Macy 					FPRINTF(fp, ",");
260eda14cbcSMatt Macy 				FPRINTF(fp, val[i] == B_TRUE ?
261eda14cbcSMatt Macy 				    "true" : "false");
262eda14cbcSMatt Macy 			}
263eda14cbcSMatt Macy 			FPRINTF(fp, "]");
264eda14cbcSMatt Macy 			break;
265eda14cbcSMatt Macy 		}
266eda14cbcSMatt Macy 
267eda14cbcSMatt Macy 		case DATA_TYPE_BYTE_ARRAY: {
268eda14cbcSMatt Macy 			uchar_t *val;
269eda14cbcSMatt Macy 			uint_t valsz, i;
270eda14cbcSMatt Macy 			VERIFY0(nvpair_value_byte_array(curr, &val, &valsz));
271eda14cbcSMatt Macy 			FPRINTF(fp, "[");
272eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
273eda14cbcSMatt Macy 				if (i > 0)
274eda14cbcSMatt Macy 					FPRINTF(fp, ",");
275eda14cbcSMatt Macy 				FPRINTF(fp, "%hhu", val[i]);
276eda14cbcSMatt Macy 			}
277eda14cbcSMatt Macy 			FPRINTF(fp, "]");
278eda14cbcSMatt Macy 			break;
279eda14cbcSMatt Macy 		}
280eda14cbcSMatt Macy 
281eda14cbcSMatt Macy 		case DATA_TYPE_UINT8_ARRAY: {
282eda14cbcSMatt Macy 			uint8_t *val;
283eda14cbcSMatt Macy 			uint_t valsz, i;
284eda14cbcSMatt Macy 			VERIFY0(nvpair_value_uint8_array(curr, &val, &valsz));
285eda14cbcSMatt Macy 			FPRINTF(fp, "[");
286eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
287eda14cbcSMatt Macy 				if (i > 0)
288eda14cbcSMatt Macy 					FPRINTF(fp, ",");
289eda14cbcSMatt Macy 				FPRINTF(fp, "%hhu", val[i]);
290eda14cbcSMatt Macy 			}
291eda14cbcSMatt Macy 			FPRINTF(fp, "]");
292eda14cbcSMatt Macy 			break;
293eda14cbcSMatt Macy 		}
294eda14cbcSMatt Macy 
295eda14cbcSMatt Macy 		case DATA_TYPE_INT8_ARRAY: {
296eda14cbcSMatt Macy 			int8_t *val;
297eda14cbcSMatt Macy 			uint_t valsz, i;
298eda14cbcSMatt Macy 			VERIFY0(nvpair_value_int8_array(curr, &val, &valsz));
299eda14cbcSMatt Macy 			FPRINTF(fp, "[");
300eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
301eda14cbcSMatt Macy 				if (i > 0)
302eda14cbcSMatt Macy 					FPRINTF(fp, ",");
303eda14cbcSMatt Macy 				FPRINTF(fp, "%hhd", val[i]);
304eda14cbcSMatt Macy 			}
305eda14cbcSMatt Macy 			FPRINTF(fp, "]");
306eda14cbcSMatt Macy 			break;
307eda14cbcSMatt Macy 		}
308eda14cbcSMatt Macy 
309eda14cbcSMatt Macy 		case DATA_TYPE_UINT16_ARRAY: {
310eda14cbcSMatt Macy 			uint16_t *val;
311eda14cbcSMatt Macy 			uint_t valsz, i;
312eda14cbcSMatt Macy 			VERIFY0(nvpair_value_uint16_array(curr, &val, &valsz));
313eda14cbcSMatt Macy 			FPRINTF(fp, "[");
314eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
315eda14cbcSMatt Macy 				if (i > 0)
316eda14cbcSMatt Macy 					FPRINTF(fp, ",");
317eda14cbcSMatt Macy 				FPRINTF(fp, "%hu", val[i]);
318eda14cbcSMatt Macy 			}
319eda14cbcSMatt Macy 			FPRINTF(fp, "]");
320eda14cbcSMatt Macy 			break;
321eda14cbcSMatt Macy 		}
322eda14cbcSMatt Macy 
323eda14cbcSMatt Macy 		case DATA_TYPE_INT16_ARRAY: {
324eda14cbcSMatt Macy 			int16_t *val;
325eda14cbcSMatt Macy 			uint_t valsz, i;
326eda14cbcSMatt Macy 			VERIFY0(nvpair_value_int16_array(curr, &val, &valsz));
327eda14cbcSMatt Macy 			FPRINTF(fp, "[");
328eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
329eda14cbcSMatt Macy 				if (i > 0)
330eda14cbcSMatt Macy 					FPRINTF(fp, ",");
331eda14cbcSMatt Macy 				FPRINTF(fp, "%hd", val[i]);
332eda14cbcSMatt Macy 			}
333eda14cbcSMatt Macy 			FPRINTF(fp, "]");
334eda14cbcSMatt Macy 			break;
335eda14cbcSMatt Macy 		}
336eda14cbcSMatt Macy 
337eda14cbcSMatt Macy 		case DATA_TYPE_UINT32_ARRAY: {
338eda14cbcSMatt Macy 			uint32_t *val;
339eda14cbcSMatt Macy 			uint_t valsz, i;
340eda14cbcSMatt Macy 			VERIFY0(nvpair_value_uint32_array(curr, &val, &valsz));
341eda14cbcSMatt Macy 			FPRINTF(fp, "[");
342eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
343eda14cbcSMatt Macy 				if (i > 0)
344eda14cbcSMatt Macy 					FPRINTF(fp, ",");
345eda14cbcSMatt Macy 				FPRINTF(fp, "%u", val[i]);
346eda14cbcSMatt Macy 			}
347eda14cbcSMatt Macy 			FPRINTF(fp, "]");
348eda14cbcSMatt Macy 			break;
349eda14cbcSMatt Macy 		}
350eda14cbcSMatt Macy 
351eda14cbcSMatt Macy 		case DATA_TYPE_INT32_ARRAY: {
352eda14cbcSMatt Macy 			int32_t *val;
353eda14cbcSMatt Macy 			uint_t valsz, i;
354eda14cbcSMatt Macy 			VERIFY0(nvpair_value_int32_array(curr, &val, &valsz));
355eda14cbcSMatt Macy 			FPRINTF(fp, "[");
356eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
357eda14cbcSMatt Macy 				if (i > 0)
358eda14cbcSMatt Macy 					FPRINTF(fp, ",");
359eda14cbcSMatt Macy 				FPRINTF(fp, "%d", val[i]);
360eda14cbcSMatt Macy 			}
361eda14cbcSMatt Macy 			FPRINTF(fp, "]");
362eda14cbcSMatt Macy 			break;
363eda14cbcSMatt Macy 		}
364eda14cbcSMatt Macy 
365eda14cbcSMatt Macy 		case DATA_TYPE_UINT64_ARRAY: {
366eda14cbcSMatt Macy 			uint64_t *val;
367eda14cbcSMatt Macy 			uint_t valsz, i;
368eda14cbcSMatt Macy 			VERIFY0(nvpair_value_uint64_array(curr, &val, &valsz));
369eda14cbcSMatt Macy 			FPRINTF(fp, "[");
370eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
371eda14cbcSMatt Macy 				if (i > 0)
372eda14cbcSMatt Macy 					FPRINTF(fp, ",");
373eda14cbcSMatt Macy 				FPRINTF(fp, "%llu",
374eda14cbcSMatt Macy 				    (unsigned long long)val[i]);
375eda14cbcSMatt Macy 			}
376eda14cbcSMatt Macy 			FPRINTF(fp, "]");
377eda14cbcSMatt Macy 			break;
378eda14cbcSMatt Macy 		}
379eda14cbcSMatt Macy 
380eda14cbcSMatt Macy 		case DATA_TYPE_INT64_ARRAY: {
381eda14cbcSMatt Macy 			int64_t *val;
382eda14cbcSMatt Macy 			uint_t valsz, i;
383eda14cbcSMatt Macy 			VERIFY0(nvpair_value_int64_array(curr, &val, &valsz));
384eda14cbcSMatt Macy 			FPRINTF(fp, "[");
385eda14cbcSMatt Macy 			for (i = 0; i < valsz; i++) {
386eda14cbcSMatt Macy 				if (i > 0)
387eda14cbcSMatt Macy 					FPRINTF(fp, ",");
388eda14cbcSMatt Macy 				FPRINTF(fp, "%lld", (long long)val[i]);
389eda14cbcSMatt Macy 			}
390eda14cbcSMatt Macy 			FPRINTF(fp, "]");
391eda14cbcSMatt Macy 			break;
392eda14cbcSMatt Macy 		}
393eda14cbcSMatt Macy 
394eda14cbcSMatt Macy 		case DATA_TYPE_UNKNOWN:
395eda14cbcSMatt Macy 		case DATA_TYPE_DONTCARE:
396eda14cbcSMatt Macy 			return (-1);
397eda14cbcSMatt Macy 		}
398eda14cbcSMatt Macy 
399eda14cbcSMatt Macy 	}
400eda14cbcSMatt Macy 
401eda14cbcSMatt Macy 	FPRINTF(fp, "}");
402eda14cbcSMatt Macy 	return (0);
403eda14cbcSMatt Macy }
404