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