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)
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 /*
  12  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  13  */
  14 
  15 #include <stdio.h>

  16 #include <strings.h>


  17 
  18 #include "libnvpair.h"
  19 






  20 /*
  21  * When formatting a string for JSON output we must escape certain characters,
  22  * as described in RFC4627.  This applies to both member names and
  23  * DATA_TYPE_STRING values.











  24  */
  25 static void
  26 nvlist_print_json_string(FILE *fp, const char *input)
  27 {
  28         char c;


  29 
  30         fprintf(fp, "\"");
  31         while ((c = *input++) != '\0') {


  32                 switch (c) {
  33                 case '"':
  34                         fprintf(fp, "\\\"");
  35                         break;
  36                 case '\n':
  37                         fprintf(fp, "\\n");
  38                         break;
  39                 case '\r':
  40                         fprintf(fp, "\\r");
  41                         break;
  42                 case '\\':
  43                         fprintf(fp, "\\\\");
  44                         break;
  45                 case '\f':
  46                         fprintf(fp, "\\f");
  47                         break;
  48                 case '\t':
  49                         fprintf(fp, "\\t");
  50                         break;
  51                 case '\b':
  52                         fprintf(fp, "\\b");
  53                         break;
  54                 default:
  55                         if (c >= 0x00 && c <= 0x1f) {
  56                                 fprintf(fp, "\\u00%02hhu", c);
  57                         } else {
  58                                 fprintf(fp, "%c", c);










  59                         }
  60                         break;
  61                 }

  62         }
  63         fprintf(fp, "\"");










  64 }
  65 
  66 void





  67 nvlist_print_json(FILE *fp, nvlist_t *nvl)
  68 {
  69         nvpair_t *curr;
  70         boolean_t first = B_TRUE;
  71 
  72         fprintf(fp, "{");
  73 
  74         for (curr = nvlist_next_nvpair(nvl, NULL); curr;
  75             curr = nvlist_next_nvpair(nvl, curr)) {
  76                 data_type_t type = nvpair_type(curr);
  77 
  78                 if (!first)
  79                         fprintf(fp, ",");
  80                 else
  81                         first = B_FALSE;
  82 
  83                 nvlist_print_json_string(fp, nvpair_name(curr));
  84                 fprintf(fp, ":");

  85 
  86                 switch (type) {
  87                 case DATA_TYPE_STRING: {
  88                         char *string;
  89                         nvpair_value_string(curr, &string);
  90                         nvlist_print_json_string(fp, string);
  91                         break;
  92                 }
  93 
  94                 case DATA_TYPE_BOOLEAN: {
  95                         fprintf(fp, "true");
  96                         break;
  97                 }
  98 
  99                 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");
 104                         break;
 105                 }
 106 
 107                 case DATA_TYPE_BYTE: {
 108                         uchar_t val;
 109                         nvpair_value_byte(curr, &val);
 110                         fprintf(fp, "%hhu", val);
 111                         break;
 112                 }
 113 
 114                 case DATA_TYPE_INT8: {
 115                         int8_t val;
 116                         nvpair_value_int8(curr, &val);
 117                         fprintf(fp, "%hhd", val);
 118                         break;
 119                 }
 120 
 121                 case DATA_TYPE_UINT8: {
 122                         uint8_t val;
 123                         nvpair_value_uint8(curr, &val);
 124                         fprintf(fp, "%hhu", val);
 125                         break;
 126                 }
 127 
 128                 case DATA_TYPE_INT16: {
 129                         int16_t val;
 130                         nvpair_value_int16(curr, &val);
 131                         fprintf(fp, "%hd", val);
 132                         break;
 133                 }
 134 
 135                 case DATA_TYPE_UINT16: {
 136                         uint16_t val;
 137                         nvpair_value_uint16(curr, &val);
 138                         fprintf(fp, "%hu", val);
 139                         break;
 140                 }
 141 
 142                 case DATA_TYPE_INT32: {
 143                         int32_t val;
 144                         nvpair_value_int32(curr, &val);
 145                         fprintf(fp, "%d", val);
 146                         break;
 147                 }
 148 
 149                 case DATA_TYPE_UINT32: {
 150                         uint32_t val;
 151                         nvpair_value_uint32(curr, &val);
 152                         fprintf(fp, "%u", val);
 153                         break;
 154                 }
 155 
 156                 case DATA_TYPE_INT64: {
 157                         int64_t val;
 158                         nvpair_value_int64(curr, &val);
 159                         fprintf(fp, "%lld", val);
 160                         break;
 161                 }
 162 
 163                 case DATA_TYPE_UINT64: {
 164                         uint64_t val;
 165                         nvpair_value_uint64(curr, &val);
 166                         fprintf(fp, "%llu", val);
 167                         break;
 168                 }
 169 
 170                 case DATA_TYPE_HRTIME: {
 171                         hrtime_t val;
 172                         nvpair_value_hrtime(curr, &val);
 173                         fprintf(fp, "%llu", val);
 174                         break;
 175                 }
 176 
 177                 case DATA_TYPE_DOUBLE: {
 178                         double val;
 179                         nvpair_value_double(curr, &val);
 180                         fprintf(fp, "%f", val);
 181                         break;
 182                 }
 183 
 184                 case DATA_TYPE_NVLIST: {
 185                         nvlist_t *val;
 186                         nvpair_value_nvlist(curr, &val);
 187                         nvlist_print_json(fp, val);
 188                         break;
 189                 }
 190 
 191                 case DATA_TYPE_STRING_ARRAY: {
 192                         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]);

 200                         }
 201                         fprintf(fp, "]");
 202                         break;
 203                 }
 204 
 205                 case DATA_TYPE_NVLIST_ARRAY: {
 206                         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]);

 214                         }
 215                         fprintf(fp, "]");
 216                         break;
 217                 }
 218 
 219                 case DATA_TYPE_BOOLEAN_ARRAY: {
 220                         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 ?
 228                                     "true" : "false");
 229                         }
 230                         fprintf(fp, "]");
 231                         break;
 232                 }
 233 
 234                 case DATA_TYPE_BYTE_ARRAY: {
 235                         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]);
 243                         }
 244                         fprintf(fp, "]");
 245                         break;
 246                 }
 247 
 248                 case DATA_TYPE_UINT8_ARRAY: {
 249                         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]);
 257                         }
 258                         fprintf(fp, "]");
 259                         break;
 260                 }
 261 
 262                 case DATA_TYPE_INT8_ARRAY: {
 263                         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]);
 271                         }
 272                         fprintf(fp, "]");
 273                         break;
 274                 }
 275 
 276                 case DATA_TYPE_UINT16_ARRAY: {
 277                         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]);
 285                         }
 286                         fprintf(fp, "]");
 287                         break;
 288                 }
 289 
 290                 case DATA_TYPE_INT16_ARRAY: {
 291                         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]);
 299                         }
 300                         fprintf(fp, "]");
 301                         break;
 302                 }
 303 
 304                 case DATA_TYPE_UINT32_ARRAY: {
 305                         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]);
 313                         }
 314                         fprintf(fp, "]");
 315                         break;
 316                 }
 317 
 318                 case DATA_TYPE_INT32_ARRAY: {
 319                         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]);
 327                         }
 328                         fprintf(fp, "]");
 329                         break;
 330                 }
 331 
 332                 case DATA_TYPE_UINT64_ARRAY: {
 333                         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]);
 341                         }
 342                         fprintf(fp, "]");
 343                         break;
 344                 }
 345 
 346                 case DATA_TYPE_INT64_ARRAY: {
 347                         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]);
 355                         }
 356                         fprintf(fp, "]");
 357                         break;
 358                 }
 359 
 360                 case DATA_TYPE_UNKNOWN:
 361                         fprintf(fp, "null");
 362                         break;
 363                 }
 364         }
 365 
 366         fprintf(fp, "}");

 367 }
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 /*
  12  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  13  */
  14 
  15 #include <stdio.h>
  16 #include <stdlib.h>
  17 #include <strings.h>
  18 #include <wchar.h>
  19 #include <sys/debug.h>
  20 
  21 #include "libnvpair.h"
  22 
  23 #define FPRINTF(fp, ...)                                \
  24         do {                                            \
  25                 if (fprintf(fp, __VA_ARGS__) < 0)    \
  26                         return (-1);                    \
  27         } while (0)
  28 
  29 /*
  30  * When formatting a string for JSON output we must escape certain characters,
  31  * as described in RFC4627.  This applies to both member names and
  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.
  44  */
  45 static int
  46 nvlist_print_json_string(FILE *fp, const char *input)
  47 {
  48         mbstate_t mbr;
  49         wchar_t c;
  50         size_t sz;
  51 
  52         bzero(&mbr, sizeof (mbr));
  53 
  54         FPRINTF(fp, "\"");
  55         while ((sz = mbrtowc(&c, input, MB_CUR_MAX, &mbr)) > 0) {
  56                 switch (c) {
  57                 case '"':
  58                         FPRINTF(fp, "\\\"");
  59                         break;
  60                 case '\n':
  61                         FPRINTF(fp, "\\n");
  62                         break;
  63                 case '\r':
  64                         FPRINTF(fp, "\\r");
  65                         break;
  66                 case '\\':
  67                         FPRINTF(fp, "\\\\");
  68                         break;
  69                 case '\f':
  70                         FPRINTF(fp, "\\f");
  71                         break;
  72                 case '\t':
  73                         FPRINTF(fp, "\\t");
  74                         break;
  75                 case '\b':
  76                         FPRINTF(fp, "\\b");
  77                         break;
  78                 default:
  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);
  93                         }
  94                         break;
  95                 }
  96                 input += sz;
  97         }
  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);
 109 }
 110 
 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
 117 nvlist_print_json(FILE *fp, nvlist_t *nvl)
 118 {
 119         nvpair_t *curr;
 120         boolean_t first = B_TRUE;
 121 
 122         FPRINTF(fp, "{");
 123 
 124         for (curr = nvlist_next_nvpair(nvl, NULL); curr;
 125             curr = nvlist_next_nvpair(nvl, curr)) {
 126                 data_type_t type = nvpair_type(curr);
 127 
 128                 if (!first)
 129                         FPRINTF(fp, ",");
 130                 else
 131                         first = B_FALSE;
 132 
 133                 if (nvlist_print_json_string(fp, nvpair_name(curr)) == -1)
 134                         return (-1);
 135                 FPRINTF(fp, ":");
 136 
 137                 switch (type) {
 138                 case DATA_TYPE_STRING: {
 139                         char *string = fnvpair_value_string(curr);
 140                         if (nvlist_print_json_string(fp, string) == -1)
 141                                 return (-1);
 142                         break;
 143                 }
 144 
 145                 case DATA_TYPE_BOOLEAN: {
 146                         FPRINTF(fp, "true");
 147                         break;
 148                 }
 149 
 150                 case DATA_TYPE_BOOLEAN_VALUE: {
 151                         FPRINTF(fp, "%s", fnvpair_value_boolean_value(curr) ==
 152                             B_TRUE ? "true" : "false");


 153                         break;
 154                 }
 155 
 156                 case DATA_TYPE_BYTE: {
 157                         FPRINTF(fp, "%hhu", fnvpair_value_byte(curr));


 158                         break;
 159                 }
 160 
 161                 case DATA_TYPE_INT8: {
 162                         FPRINTF(fp, "%hhd", fnvpair_value_int8(curr));


 163                         break;
 164                 }
 165 
 166                 case DATA_TYPE_UINT8: {
 167                         FPRINTF(fp, "%hhu", fnvpair_value_uint8(curr));


 168                         break;
 169                 }
 170 
 171                 case DATA_TYPE_INT16: {
 172                         FPRINTF(fp, "%hd", fnvpair_value_int16(curr));


 173                         break;
 174                 }
 175 
 176                 case DATA_TYPE_UINT16: {
 177                         FPRINTF(fp, "%hu", fnvpair_value_uint16(curr));


 178                         break;
 179                 }
 180 
 181                 case DATA_TYPE_INT32: {
 182                         FPRINTF(fp, "%d", fnvpair_value_int32(curr));


 183                         break;
 184                 }
 185 
 186                 case DATA_TYPE_UINT32: {
 187                         FPRINTF(fp, "%u", fnvpair_value_uint32(curr));


 188                         break;
 189                 }
 190 
 191                 case DATA_TYPE_INT64: {
 192                         FPRINTF(fp, "%lld", fnvpair_value_int64(curr));


 193                         break;
 194                 }
 195 
 196                 case DATA_TYPE_UINT64: {
 197                         FPRINTF(fp, "%llu", fnvpair_value_uint64(curr));


 198                         break;
 199                 }
 200 
 201                 case DATA_TYPE_HRTIME: {
 202                         FPRINTF(fp, "%llu", fnvpair_value_hrtime(curr));


 203                         break;
 204                 }
 205 
 206                 case DATA_TYPE_DOUBLE: {
 207                         FPRINTF(fp, "%f", fnvpair_value_double(curr));


 208                         break;
 209                 }
 210 
 211                 case DATA_TYPE_NVLIST: {
 212                         if (nvlist_print_json(fp,
 213                             fnvpair_value_nvlist(curr)) == -1)
 214                                 return (-1);
 215                         break;
 216                 }
 217 
 218                 case DATA_TYPE_STRING_ARRAY: {
 219                         char **val;
 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);
 228                         }
 229                         FPRINTF(fp, "]");
 230                         break;
 231                 }
 232 
 233                 case DATA_TYPE_NVLIST_ARRAY: {
 234                         nvlist_t **val;
 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);
 243                         }
 244                         FPRINTF(fp, "]");
 245                         break;
 246                 }
 247 
 248                 case DATA_TYPE_BOOLEAN_ARRAY: {
 249                         boolean_t *val;
 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 ?
 257                                     "true" : "false");
 258                         }
 259                         FPRINTF(fp, "]");
 260                         break;
 261                 }
 262 
 263                 case DATA_TYPE_BYTE_ARRAY: {
 264                         uchar_t *val;
 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]);
 272                         }
 273                         FPRINTF(fp, "]");
 274                         break;
 275                 }
 276 
 277                 case DATA_TYPE_UINT8_ARRAY: {
 278                         uint8_t *val;
 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]);
 286                         }
 287                         FPRINTF(fp, "]");
 288                         break;
 289                 }
 290 
 291                 case DATA_TYPE_INT8_ARRAY: {
 292                         int8_t *val;
 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]);
 300                         }
 301                         FPRINTF(fp, "]");
 302                         break;
 303                 }
 304 
 305                 case DATA_TYPE_UINT16_ARRAY: {
 306                         uint16_t *val;
 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]);
 314                         }
 315                         FPRINTF(fp, "]");
 316                         break;
 317                 }
 318 
 319                 case DATA_TYPE_INT16_ARRAY: {
 320                         int16_t *val;
 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]);
 328                         }
 329                         FPRINTF(fp, "]");
 330                         break;
 331                 }
 332 
 333                 case DATA_TYPE_UINT32_ARRAY: {
 334                         uint32_t *val;
 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]);
 342                         }
 343                         FPRINTF(fp, "]");
 344                         break;
 345                 }
 346 
 347                 case DATA_TYPE_INT32_ARRAY: {
 348                         int32_t *val;
 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]);
 356                         }
 357                         FPRINTF(fp, "]");
 358                         break;
 359                 }
 360 
 361                 case DATA_TYPE_UINT64_ARRAY: {
 362                         uint64_t *val;
 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]);
 370                         }
 371                         FPRINTF(fp, "]");
 372                         break;
 373                 }
 374 
 375                 case DATA_TYPE_INT64_ARRAY: {
 376                         int64_t *val;
 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]);
 384                         }
 385                         FPRINTF(fp, "]");
 386                         break;
 387                 }
 388 
 389                 case DATA_TYPE_UNKNOWN:
 390                         return (-1);

 391                 }
 392         }
 393 
 394         FPRINTF(fp, "}");
 395         return (0);
 396 }