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