The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/lib/libnvpair/libnvpair_json.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: f62ac4713f085a44b3068a73e1e9535d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.