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/libnv/nvlist.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2009-2013 The FreeBSD Foundation
    5  * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
    6  * All rights reserved.
    7  *
    8  * This software was developed by Pawel Jakub Dawidek under sponsorship from
    9  * the FreeBSD Foundation.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <sys/param.h>
   37 #include <sys/endian.h>
   38 #include <sys/queue.h>
   39 
   40 #ifdef _KERNEL
   41 
   42 #include <sys/errno.h>
   43 #include <sys/kernel.h>
   44 #include <sys/lock.h>
   45 #include <sys/malloc.h>
   46 #include <sys/systm.h>
   47 
   48 #include <machine/stdarg.h>
   49 
   50 #else
   51 #include <sys/socket.h>
   52 
   53 #include <errno.h>
   54 #include <stdarg.h>
   55 #include <stdbool.h>
   56 #include <stdint.h>
   57 #include <stdio.h>
   58 #include <stdlib.h>
   59 #include <string.h>
   60 #include <unistd.h>
   61 
   62 #include "msgio.h"
   63 #endif
   64 
   65 #ifdef HAVE_PJDLOG
   66 #include <pjdlog.h>
   67 #endif
   68 
   69 #include <sys/nv.h>
   70 
   71 #include "nv_impl.h"
   72 #include "nvlist_impl.h"
   73 #include "nvpair_impl.h"
   74 
   75 #ifndef HAVE_PJDLOG
   76 #ifdef _KERNEL
   77 #define PJDLOG_ASSERT(...)              MPASS(__VA_ARGS__)
   78 #define PJDLOG_RASSERT(expr, ...)       KASSERT(expr, (__VA_ARGS__))
   79 #define PJDLOG_ABORT(...)               panic(__VA_ARGS__)
   80 #else
   81 #include <assert.h>
   82 #define PJDLOG_ASSERT(...)              assert(__VA_ARGS__)
   83 #define PJDLOG_RASSERT(expr, ...)       assert(expr)
   84 #define PJDLOG_ABORT(...)               do {                            \
   85         fprintf(stderr, "%s:%u: ", __FILE__, __LINE__);                 \
   86         fprintf(stderr, __VA_ARGS__);                                   \
   87         fprintf(stderr, "\n");                                          \
   88         abort();                                                        \
   89 } while (0)
   90 #endif
   91 #endif
   92 
   93 #define NV_FLAG_PRIVATE_MASK    (NV_FLAG_BIG_ENDIAN | NV_FLAG_IN_ARRAY)
   94 #define NV_FLAG_PUBLIC_MASK     (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE)
   95 #define NV_FLAG_ALL_MASK        (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
   96 
   97 #define NVLIST_MAGIC    0x6e766c        /* "nvl" */
   98 struct nvlist {
   99         int              nvl_magic;
  100         int              nvl_error;
  101         int              nvl_flags;
  102         size_t           nvl_datasize;
  103         nvpair_t        *nvl_parent;
  104         nvpair_t        *nvl_array_next;
  105         struct nvl_head  nvl_head;
  106 };
  107 
  108 #define NVLIST_ASSERT(nvl)      do {                                    \
  109         PJDLOG_ASSERT((nvl) != NULL);                                   \
  110         PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);                \
  111 } while (0)
  112 
  113 #ifdef _KERNEL
  114 MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
  115 #endif
  116 
  117 #define NVPAIR_ASSERT(nvp)      nvpair_assert(nvp)
  118 
  119 #define NVLIST_HEADER_MAGIC     0x6c
  120 #define NVLIST_HEADER_VERSION   0x00
  121 struct nvlist_header {
  122         uint8_t         nvlh_magic;
  123         uint8_t         nvlh_version;
  124         uint8_t         nvlh_flags;
  125         uint64_t        nvlh_descriptors;
  126         uint64_t        nvlh_size;
  127 } __packed;
  128 
  129 nvlist_t *
  130 nvlist_create(int flags)
  131 {
  132         nvlist_t *nvl;
  133 
  134         PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
  135 
  136         nvl = nv_malloc(sizeof(*nvl));
  137         if (nvl == NULL)
  138                 return (NULL);
  139         nvl->nvl_error = 0;
  140         nvl->nvl_flags = flags;
  141         nvl->nvl_parent = NULL;
  142         nvl->nvl_array_next = NULL;
  143         nvl->nvl_datasize = sizeof(struct nvlist_header);
  144         TAILQ_INIT(&nvl->nvl_head);
  145         nvl->nvl_magic = NVLIST_MAGIC;
  146 
  147         return (nvl);
  148 }
  149 
  150 void
  151 nvlist_destroy(nvlist_t *nvl)
  152 {
  153         nvpair_t *nvp;
  154 
  155         if (nvl == NULL)
  156                 return;
  157 
  158         ERRNO_SAVE();
  159 
  160         NVLIST_ASSERT(nvl);
  161 
  162         while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
  163                 nvlist_remove_nvpair(nvl, nvp);
  164                 nvpair_free(nvp);
  165         }
  166         if (nvl->nvl_array_next != NULL)
  167                 nvpair_free_structure(nvl->nvl_array_next);
  168         nvl->nvl_array_next = NULL;
  169         nvl->nvl_parent = NULL;
  170         nvl->nvl_magic = 0;
  171         nv_free(nvl);
  172 
  173         ERRNO_RESTORE();
  174 }
  175 
  176 void
  177 nvlist_set_error(nvlist_t *nvl, int error)
  178 {
  179 
  180         PJDLOG_ASSERT(error != 0);
  181 
  182         /*
  183          * Check for error != 0 so that we don't do the wrong thing if somebody
  184          * tries to abuse this API when asserts are disabled.
  185          */
  186         if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
  187                 nvl->nvl_error = error;
  188 }
  189 
  190 int
  191 nvlist_error(const nvlist_t *nvl)
  192 {
  193 
  194         if (nvl == NULL)
  195                 return (ENOMEM);
  196 
  197         NVLIST_ASSERT(nvl);
  198 
  199         return (nvl->nvl_error);
  200 }
  201 
  202 nvpair_t *
  203 nvlist_get_nvpair_parent(const nvlist_t *nvl)
  204 {
  205 
  206         NVLIST_ASSERT(nvl);
  207 
  208         return (nvl->nvl_parent);
  209 }
  210 
  211 const nvlist_t *
  212 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
  213 {
  214         nvpair_t *nvp;
  215 
  216         NVLIST_ASSERT(nvl);
  217 
  218         nvp = nvl->nvl_parent;
  219         if (cookiep != NULL)
  220                 *cookiep = nvp;
  221         if (nvp == NULL)
  222                 return (NULL);
  223 
  224         return (nvpair_nvlist(nvp));
  225 }
  226 
  227 void
  228 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
  229 {
  230 
  231         NVLIST_ASSERT(nvl);
  232 
  233         nvl->nvl_parent = parent;
  234 }
  235 
  236 void
  237 nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele)
  238 {
  239 
  240         NVLIST_ASSERT(nvl);
  241 
  242         if (ele != NULL) {
  243                 nvl->nvl_flags |= NV_FLAG_IN_ARRAY;
  244         } else {
  245                 nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY;
  246                 nv_free(nvl->nvl_array_next);
  247         }
  248 
  249         nvl->nvl_array_next = ele;
  250 }
  251 
  252 static void
  253 nvlist_update_size(nvlist_t *nvl, nvpair_t *new, ssize_t mul)
  254 {
  255         ssize_t size;
  256         size_t nitems;
  257         const nvlist_t *nvlistnew;
  258         const nvlist_t * const *nvlarray;
  259         nvlist_t *parent;
  260         unsigned int ii;
  261 
  262         NVLIST_ASSERT(nvl);
  263         NVPAIR_ASSERT(new);
  264         PJDLOG_ASSERT(mul == 1 || mul == -1);
  265 
  266         size = nvpair_header_size();
  267         size += strlen(nvpair_name(new)) + 1;
  268 
  269         if (nvpair_type(new) == NV_TYPE_NVLIST) {
  270                 nvlistnew = nvpair_get_nvlist(new);
  271                 size += nvlistnew->nvl_datasize;
  272                 size += nvpair_header_size() + 1;
  273         } else if (nvpair_type(new) == NV_TYPE_NVLIST_ARRAY) {
  274                 nvlarray = nvpair_get_nvlist_array(new, &nitems);
  275                 PJDLOG_ASSERT(nitems > 0);
  276 
  277                 size += (nvpair_header_size() + 1) * nitems;
  278                 for (ii = 0; ii < nitems; ii++) {
  279                         PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0);
  280                         size += nvlarray[ii]->nvl_datasize;
  281                 }
  282         } else {
  283                 size += nvpair_size(new);
  284         }
  285 
  286         size *= mul;
  287 
  288         nvl->nvl_datasize += size;
  289 
  290         parent = nvl;
  291         while ((parent = __DECONST(nvlist_t *,
  292             nvlist_get_parent(parent, NULL))) != NULL) {
  293                 parent->nvl_datasize += size;
  294         }
  295 }
  296 
  297 nvpair_t *
  298 nvlist_get_array_next_nvpair(nvlist_t *nvl)
  299 {
  300 
  301         NVLIST_ASSERT(nvl);
  302 
  303         return (nvl->nvl_array_next);
  304 }
  305 
  306 bool
  307 nvlist_in_array(const nvlist_t *nvl)
  308 {
  309 
  310         NVLIST_ASSERT(nvl);
  311 
  312         return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0);
  313 }
  314 
  315 const nvlist_t *
  316 nvlist_get_array_next(const nvlist_t *nvl)
  317 {
  318         nvpair_t *nvp;
  319 
  320         NVLIST_ASSERT(nvl);
  321 
  322         nvp = nvl->nvl_array_next;
  323         if (nvp == NULL)
  324                 return (NULL);
  325 
  326         return (nvpair_get_nvlist(nvp));
  327 }
  328 
  329 const nvlist_t *
  330 nvlist_get_pararr(const nvlist_t *nvl, void **cookiep)
  331 {
  332         const nvlist_t *ret;
  333 
  334         ret = nvlist_get_array_next(nvl);
  335         if (ret != NULL) {
  336                 if (cookiep != NULL)
  337                         *cookiep = NULL;
  338                 return (ret);
  339         }
  340 
  341         return (nvlist_get_parent(nvl, cookiep));
  342 }
  343 
  344 bool
  345 nvlist_empty(const nvlist_t *nvl)
  346 {
  347 
  348         NVLIST_ASSERT(nvl);
  349         PJDLOG_ASSERT(nvl->nvl_error == 0);
  350 
  351         return (nvlist_first_nvpair(nvl) == NULL);
  352 }
  353 
  354 int
  355 nvlist_flags(const nvlist_t *nvl)
  356 {
  357 
  358         NVLIST_ASSERT(nvl);
  359         PJDLOG_ASSERT(nvl->nvl_error == 0);
  360 
  361         return (nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
  362 }
  363 
  364 void
  365 nvlist_set_flags(nvlist_t *nvl, int flags)
  366 {
  367 
  368         NVLIST_ASSERT(nvl);
  369         PJDLOG_ASSERT(nvl->nvl_error == 0);
  370 
  371         nvl->nvl_flags = flags;
  372 }
  373 
  374 void
  375 nvlist_report_missing(int type, const char *name)
  376 {
  377 
  378         PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
  379             name, nvpair_type_string(type));
  380 }
  381 
  382 static nvpair_t *
  383 nvlist_find(const nvlist_t *nvl, int type, const char *name)
  384 {
  385         nvpair_t *nvp;
  386 
  387         NVLIST_ASSERT(nvl);
  388         PJDLOG_ASSERT(nvl->nvl_error == 0);
  389         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
  390             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
  391 
  392         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
  393             nvp = nvlist_next_nvpair(nvl, nvp)) {
  394                 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
  395                         continue;
  396                 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
  397                         if (strcasecmp(nvpair_name(nvp), name) != 0)
  398                                 continue;
  399                 } else {
  400                         if (strcmp(nvpair_name(nvp), name) != 0)
  401                                 continue;
  402                 }
  403                 break;
  404         }
  405 
  406         if (nvp == NULL)
  407                 ERRNO_SET(ENOENT);
  408 
  409         return (nvp);
  410 }
  411 
  412 bool
  413 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
  414 {
  415 
  416         NVLIST_ASSERT(nvl);
  417         PJDLOG_ASSERT(nvl->nvl_error == 0);
  418         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
  419             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
  420 
  421         return (nvlist_find(nvl, type, name) != NULL);
  422 }
  423 
  424 void
  425 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
  426 {
  427         nvpair_t *nvp;
  428 
  429         NVLIST_ASSERT(nvl);
  430         PJDLOG_ASSERT(nvl->nvl_error == 0);
  431         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
  432             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
  433 
  434         nvp = nvlist_find(nvl, type, name);
  435         if (nvp != NULL)
  436                 nvlist_free_nvpair(nvl, nvp);
  437         else
  438                 nvlist_report_missing(type, name);
  439 }
  440 
  441 nvlist_t *
  442 nvlist_clone(const nvlist_t *nvl)
  443 {
  444         nvlist_t *newnvl;
  445         nvpair_t *nvp, *newnvp;
  446 
  447         NVLIST_ASSERT(nvl);
  448 
  449         if (nvl->nvl_error != 0) {
  450                 ERRNO_SET(nvl->nvl_error);
  451                 return (NULL);
  452         }
  453 
  454         newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
  455         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
  456             nvp = nvlist_next_nvpair(nvl, nvp)) {
  457                 newnvp = nvpair_clone(nvp);
  458                 if (newnvp == NULL)
  459                         break;
  460                 (void)nvlist_move_nvpair(newnvl, newnvp);
  461         }
  462         if (nvp != NULL) {
  463                 nvlist_destroy(newnvl);
  464                 return (NULL);
  465         }
  466         return (newnvl);
  467 }
  468 
  469 #ifndef _KERNEL
  470 static bool
  471 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
  472 {
  473 
  474         if (nvlist_error(nvl) != 0) {
  475                 dprintf(fd, "%*serror: %d\n", level * 4, "",
  476                     nvlist_error(nvl));
  477                 return (true);
  478         }
  479 
  480         return (false);
  481 }
  482 
  483 /*
  484  * Dump content of nvlist.
  485  */
  486 void
  487 nvlist_dump(const nvlist_t *nvl, int fd)
  488 {
  489         const nvlist_t *tmpnvl;
  490         nvpair_t *nvp, *tmpnvp;
  491         void *cookie;
  492         int level;
  493 
  494         level = 0;
  495         if (nvlist_dump_error_check(nvl, fd, level))
  496                 return;
  497 
  498         nvp = nvlist_first_nvpair(nvl);
  499         while (nvp != NULL) {
  500                 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
  501                     nvpair_type_string(nvpair_type(nvp)));
  502                 switch (nvpair_type(nvp)) {
  503                 case NV_TYPE_NULL:
  504                         dprintf(fd, " null\n");
  505                         break;
  506                 case NV_TYPE_BOOL:
  507                         dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
  508                             "TRUE" : "FALSE");
  509                         break;
  510                 case NV_TYPE_NUMBER:
  511                         dprintf(fd, " %ju (%jd) (0x%jx)\n",
  512                             (uintmax_t)nvpair_get_number(nvp),
  513                             (intmax_t)nvpair_get_number(nvp),
  514                             (uintmax_t)nvpair_get_number(nvp));
  515                         break;
  516                 case NV_TYPE_STRING:
  517                         dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
  518                         break;
  519                 case NV_TYPE_NVLIST:
  520                         dprintf(fd, "\n");
  521                         tmpnvl = nvpair_get_nvlist(nvp);
  522                         if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
  523                                 break;
  524                         tmpnvp = nvlist_first_nvpair(tmpnvl);
  525                         if (tmpnvp != NULL) {
  526                                 nvl = tmpnvl;
  527                                 nvp = tmpnvp;
  528                                 level++;
  529                                 continue;
  530                         }
  531                         break;
  532                 case NV_TYPE_DESCRIPTOR:
  533                         dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
  534                         break;
  535                 case NV_TYPE_BINARY:
  536                     {
  537                         const unsigned char *binary;
  538                         unsigned int ii;
  539                         size_t size;
  540 
  541                         binary = nvpair_get_binary(nvp, &size);
  542                         dprintf(fd, " %zu ", size);
  543                         for (ii = 0; ii < size; ii++)
  544                                 dprintf(fd, "%02hhx", binary[ii]);
  545                         dprintf(fd, "\n");
  546                         break;
  547                     }
  548                 case NV_TYPE_BOOL_ARRAY:
  549                     {
  550                         const bool *value;
  551                         unsigned int ii;
  552                         size_t nitems;
  553 
  554                         value = nvpair_get_bool_array(nvp, &nitems);
  555                         dprintf(fd, " [ ");
  556                         for (ii = 0; ii < nitems; ii++) {
  557                                 dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE");
  558                                 if (ii != nitems - 1)
  559                                         dprintf(fd, ", ");
  560                         }
  561                         dprintf(fd, " ]\n");
  562                         break;
  563                     }
  564                 case NV_TYPE_STRING_ARRAY:
  565                     {
  566                         const char * const *value;
  567                         unsigned int ii;
  568                         size_t nitems;
  569 
  570                         value = nvpair_get_string_array(nvp, &nitems);
  571                         dprintf(fd, " [ ");
  572                         for (ii = 0; ii < nitems; ii++) {
  573                                 if (value[ii] == NULL)
  574                                         dprintf(fd, "NULL");
  575                                 else
  576                                         dprintf(fd, "\"%s\"", value[ii]);
  577                                 if (ii != nitems - 1)
  578                                         dprintf(fd, ", ");
  579                         }
  580                         dprintf(fd, " ]\n");
  581                         break;
  582                     }
  583                 case NV_TYPE_NUMBER_ARRAY:
  584                     {
  585                         const uint64_t *value;
  586                         unsigned int ii;
  587                         size_t nitems;
  588 
  589                         value = nvpair_get_number_array(nvp, &nitems);
  590                         dprintf(fd, " [ ");
  591                         for (ii = 0; ii < nitems; ii++) {
  592                                 dprintf(fd, "%ju (%jd) (0x%jx)",
  593                                     value[ii], value[ii], value[ii]);
  594                                 if (ii != nitems - 1)
  595                                         dprintf(fd, ", ");
  596                         }
  597                         dprintf(fd, " ]\n");
  598                         break;
  599                     }
  600                 case NV_TYPE_DESCRIPTOR_ARRAY:
  601                     {
  602                         const int *value;
  603                         unsigned int ii;
  604                         size_t nitems;
  605 
  606                         value = nvpair_get_descriptor_array(nvp, &nitems);
  607                         dprintf(fd, " [ ");
  608                         for (ii = 0; ii < nitems; ii++) {
  609                                 dprintf(fd, "%d", value[ii]);
  610                                 if (ii != nitems - 1)
  611                                         dprintf(fd, ", ");
  612                         }
  613                         dprintf(fd, " ]\n");
  614                         break;
  615                     }
  616                 case NV_TYPE_NVLIST_ARRAY:
  617                     {
  618                         const nvlist_t * const *value;
  619                         unsigned int ii;
  620                         size_t nitems;
  621 
  622                         value = nvpair_get_nvlist_array(nvp, &nitems);
  623                         dprintf(fd, " %zu\n", nitems);
  624                         tmpnvl = NULL;
  625                         tmpnvp = NULL;
  626                         for (ii = 0; ii < nitems; ii++) {
  627                                 if (nvlist_dump_error_check(value[ii], fd,
  628                                     level + 1)) {
  629                                         break;
  630                                 }
  631 
  632                                 if (tmpnvl == NULL) {
  633                                         tmpnvp = nvlist_first_nvpair(value[ii]);
  634                                         if (tmpnvp != NULL) {
  635                                                 tmpnvl = value[ii];
  636                                         } else {
  637                                                 dprintf(fd, "%*s,\n",
  638                                                     (level + 1) * 4, "");
  639                                         }
  640                                 }
  641                         }
  642                         if (tmpnvp != NULL) {
  643                                 nvl = tmpnvl;
  644                                 nvp = tmpnvp;
  645                                 level++;
  646                                 continue;
  647                         }
  648                         break;
  649                     }
  650                 default:
  651                         PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
  652                 }
  653 
  654                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
  655                         do {
  656                                 cookie = NULL;
  657                                 if (nvlist_in_array(nvl))
  658                                         dprintf(fd, "%*s,\n", level * 4, "");
  659                                 nvl = nvlist_get_pararr(nvl, &cookie);
  660                                 if (nvl == NULL)
  661                                         return;
  662                                 if (nvlist_in_array(nvl) && cookie == NULL) {
  663                                         nvp = nvlist_first_nvpair(nvl);
  664                                 } else {
  665                                         nvp = cookie;
  666                                         level--;
  667                                 }
  668                         } while (nvp == NULL);
  669                         if (nvlist_in_array(nvl) && cookie == NULL)
  670                                 break;
  671                 }
  672         }
  673 }
  674 
  675 void
  676 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
  677 {
  678 
  679         fflush(fp);
  680         nvlist_dump(nvl, fileno(fp));
  681 }
  682 #endif
  683 
  684 /*
  685  * The function obtains size of the nvlist after nvlist_pack().
  686  */
  687 size_t
  688 nvlist_size(const nvlist_t *nvl)
  689 {
  690 
  691         return (nvl->nvl_datasize);
  692 }
  693 
  694 #ifndef _KERNEL
  695 static int *
  696 nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
  697 {
  698         void *cookie;
  699         nvpair_t *nvp;
  700         int type;
  701 
  702         NVLIST_ASSERT(nvl);
  703         PJDLOG_ASSERT(nvl->nvl_error == 0);
  704 
  705         cookie = NULL;
  706         do {
  707                 while (nvlist_next(nvl, &type, &cookie) != NULL) {
  708                         nvp = cookie;
  709                         switch (type) {
  710                         case NV_TYPE_DESCRIPTOR:
  711                                 *descs = nvpair_get_descriptor(nvp);
  712                                 descs++;
  713                                 break;
  714                         case NV_TYPE_DESCRIPTOR_ARRAY:
  715                             {
  716                                 const int *value;
  717                                 size_t nitems;
  718                                 unsigned int ii;
  719 
  720                                 value = nvpair_get_descriptor_array(nvp,
  721                                     &nitems);
  722                                 for (ii = 0; ii < nitems; ii++) {
  723                                         *descs = value[ii];
  724                                         descs++;
  725                                 }
  726                                 break;
  727                             }
  728                         case NV_TYPE_NVLIST:
  729                                 nvl = nvpair_get_nvlist(nvp);
  730                                 cookie = NULL;
  731                                 break;
  732                         case NV_TYPE_NVLIST_ARRAY:
  733                             {
  734                                 const nvlist_t * const *value;
  735                                 size_t nitems;
  736 
  737                                 value = nvpair_get_nvlist_array(nvp, &nitems);
  738                                 PJDLOG_ASSERT(value != NULL);
  739                                 PJDLOG_ASSERT(nitems > 0);
  740 
  741                                 nvl = value[0];
  742                                 cookie = NULL;
  743                                 break;
  744                             }
  745                         }
  746                 }
  747         } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
  748 
  749         return (descs);
  750 }
  751 #endif
  752 
  753 #ifndef _KERNEL
  754 int *
  755 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
  756 {
  757         size_t nitems;
  758         int *fds;
  759 
  760         nitems = nvlist_ndescriptors(nvl);
  761         fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
  762         if (fds == NULL)
  763                 return (NULL);
  764         if (nitems > 0)
  765                 nvlist_xdescriptors(nvl, fds);
  766         fds[nitems] = -1;
  767         if (nitemsp != NULL)
  768                 *nitemsp = nitems;
  769         return (fds);
  770 }
  771 #endif
  772 
  773 size_t
  774 nvlist_ndescriptors(const nvlist_t *nvl)
  775 {
  776 #ifndef _KERNEL
  777         void *cookie;
  778         nvpair_t *nvp;
  779         size_t ndescs;
  780         int type;
  781 
  782         NVLIST_ASSERT(nvl);
  783         PJDLOG_ASSERT(nvl->nvl_error == 0);
  784 
  785         ndescs = 0;
  786         cookie = NULL;
  787         do {
  788                 while (nvlist_next(nvl, &type, &cookie) != NULL) {
  789                         nvp = cookie;
  790                         switch (type) {
  791                         case NV_TYPE_DESCRIPTOR:
  792                                 ndescs++;
  793                                 break;
  794                         case NV_TYPE_NVLIST:
  795                                 nvl = nvpair_get_nvlist(nvp);
  796                                 cookie = NULL;
  797                                 break;
  798                         case NV_TYPE_NVLIST_ARRAY:
  799                             {
  800                                 const nvlist_t * const *value;
  801                                 size_t nitems;
  802 
  803                                 value = nvpair_get_nvlist_array(nvp, &nitems);
  804                                 PJDLOG_ASSERT(value != NULL);
  805                                 PJDLOG_ASSERT(nitems > 0);
  806 
  807                                 nvl = value[0];
  808                                 cookie = NULL;
  809                                 break;
  810                             }
  811                         case NV_TYPE_DESCRIPTOR_ARRAY:
  812                             {
  813                                 size_t nitems;
  814 
  815                                 (void)nvpair_get_descriptor_array(nvp,
  816                                     &nitems);
  817                                 ndescs += nitems;
  818                                 break;
  819                             }
  820                         }
  821                 }
  822         } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
  823 
  824         return (ndescs);
  825 #else
  826         return (0);
  827 #endif
  828 }
  829 
  830 static unsigned char *
  831 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
  832 {
  833         struct nvlist_header nvlhdr;
  834 
  835         NVLIST_ASSERT(nvl);
  836 
  837         nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
  838         nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
  839         nvlhdr.nvlh_flags = nvl->nvl_flags;
  840 #if BYTE_ORDER == BIG_ENDIAN
  841         nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
  842 #endif
  843         nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
  844         nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
  845         PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
  846         memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
  847         ptr += sizeof(nvlhdr);
  848         *leftp -= sizeof(nvlhdr);
  849 
  850         return (ptr);
  851 }
  852 
  853 static void *
  854 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
  855 {
  856         unsigned char *buf, *ptr;
  857         size_t left, size;
  858         const nvlist_t *tmpnvl;
  859         nvpair_t *nvp, *tmpnvp;
  860         void *cookie;
  861 
  862         NVLIST_ASSERT(nvl);
  863 
  864         if (nvl->nvl_error != 0) {
  865                 ERRNO_SET(nvl->nvl_error);
  866                 return (NULL);
  867         }
  868 
  869         size = nvlist_size(nvl);
  870         buf = nv_malloc(size);
  871         if (buf == NULL)
  872                 return (NULL);
  873 
  874         ptr = buf;
  875         left = size;
  876 
  877         ptr = nvlist_pack_header(nvl, ptr, &left);
  878 
  879         nvp = nvlist_first_nvpair(nvl);
  880         while (nvp != NULL) {
  881                 NVPAIR_ASSERT(nvp);
  882 
  883                 nvpair_init_datasize(nvp);
  884                 ptr = nvpair_pack_header(nvp, ptr, &left);
  885                 if (ptr == NULL)
  886                         goto fail;
  887                 switch (nvpair_type(nvp)) {
  888                 case NV_TYPE_NULL:
  889                         ptr = nvpair_pack_null(nvp, ptr, &left);
  890                         break;
  891                 case NV_TYPE_BOOL:
  892                         ptr = nvpair_pack_bool(nvp, ptr, &left);
  893                         break;
  894                 case NV_TYPE_NUMBER:
  895                         ptr = nvpair_pack_number(nvp, ptr, &left);
  896                         break;
  897                 case NV_TYPE_STRING:
  898                         ptr = nvpair_pack_string(nvp, ptr, &left);
  899                         break;
  900                 case NV_TYPE_NVLIST:
  901                         tmpnvl = nvpair_get_nvlist(nvp);
  902                         ptr = nvlist_pack_header(tmpnvl, ptr, &left);
  903                         if (ptr == NULL)
  904                                 goto fail;
  905                         tmpnvp = nvlist_first_nvpair(tmpnvl);
  906                         if (tmpnvp != NULL) {
  907                                 nvl = tmpnvl;
  908                                 nvp = tmpnvp;
  909                                 continue;
  910                         }
  911                         ptr = nvpair_pack_nvlist_up(ptr, &left);
  912                         break;
  913 #ifndef _KERNEL
  914                 case NV_TYPE_DESCRIPTOR:
  915                         ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
  916                         break;
  917                 case NV_TYPE_DESCRIPTOR_ARRAY:
  918                         ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp,
  919                             &left);
  920                         break;
  921 #endif
  922                 case NV_TYPE_BINARY:
  923                         ptr = nvpair_pack_binary(nvp, ptr, &left);
  924                         break;
  925                 case NV_TYPE_BOOL_ARRAY:
  926                         ptr = nvpair_pack_bool_array(nvp, ptr, &left);
  927                         break;
  928                 case NV_TYPE_NUMBER_ARRAY:
  929                         ptr = nvpair_pack_number_array(nvp, ptr, &left);
  930                         break;
  931                 case NV_TYPE_STRING_ARRAY:
  932                         ptr = nvpair_pack_string_array(nvp, ptr, &left);
  933                         break;
  934                 case NV_TYPE_NVLIST_ARRAY:
  935                     {
  936                         const nvlist_t * const * value;
  937                         size_t nitems;
  938                         unsigned int ii;
  939 
  940                         tmpnvl = NULL;
  941                         value = nvpair_get_nvlist_array(nvp, &nitems);
  942                         for (ii = 0; ii < nitems; ii++) {
  943                                 ptr = nvlist_pack_header(value[ii], ptr, &left);
  944                                 if (ptr == NULL)
  945                                         goto out;
  946                                 tmpnvp = nvlist_first_nvpair(value[ii]);
  947                                 if (tmpnvp != NULL) {
  948                                         tmpnvl = value[ii];
  949                                         break;
  950                                 }
  951                                 ptr = nvpair_pack_nvlist_array_next(ptr, &left);
  952                                 if (ptr == NULL)
  953                                         goto out;
  954                         }
  955                         if (tmpnvl != NULL) {
  956                                 nvl = tmpnvl;
  957                                 nvp = tmpnvp;
  958                                 continue;
  959                         }
  960                         break;
  961                     }
  962                 default:
  963                         PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
  964                 }
  965                 if (ptr == NULL)
  966                         goto fail;
  967                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
  968                         do {
  969                                 cookie = NULL;
  970                                 if (nvlist_in_array(nvl)) {
  971                                         ptr = nvpair_pack_nvlist_array_next(ptr,
  972                                             &left);
  973                                         if (ptr == NULL)
  974                                                 goto fail;
  975                                 }
  976                                 nvl = nvlist_get_pararr(nvl, &cookie);
  977                                 if (nvl == NULL)
  978                                         goto out;
  979                                 if (nvlist_in_array(nvl) && cookie == NULL) {
  980                                         nvp = nvlist_first_nvpair(nvl);
  981                                         ptr = nvlist_pack_header(nvl, ptr,
  982                                             &left);
  983                                         if (ptr == NULL)
  984                                                 goto fail;
  985                                 } else if (nvpair_type((nvpair_t *)cookie) !=
  986                                     NV_TYPE_NVLIST_ARRAY) {
  987                                         ptr = nvpair_pack_nvlist_up(ptr, &left);
  988                                         if (ptr == NULL)
  989                                                 goto fail;
  990                                         nvp = cookie;
  991                                 } else {
  992                                         nvp = cookie;
  993                                 }
  994                         } while (nvp == NULL);
  995                         if (nvlist_in_array(nvl) && cookie == NULL)
  996                                 break;
  997                 }
  998         }
  999 
 1000 out:
 1001         if (sizep != NULL)
 1002                 *sizep = size;
 1003         return (buf);
 1004 fail:
 1005         nv_free(buf);
 1006         return (NULL);
 1007 }
 1008 
 1009 void *
 1010 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
 1011 {
 1012 
 1013         NVLIST_ASSERT(nvl);
 1014 
 1015         if (nvl->nvl_error != 0) {
 1016                 ERRNO_SET(nvl->nvl_error);
 1017                 return (NULL);
 1018         }
 1019 
 1020         if (nvlist_ndescriptors(nvl) > 0) {
 1021                 ERRNO_SET(EOPNOTSUPP);
 1022                 return (NULL);
 1023         }
 1024 
 1025         return (nvlist_xpack(nvl, NULL, sizep));
 1026 }
 1027 
 1028 static bool
 1029 nvlist_check_header(struct nvlist_header *nvlhdrp)
 1030 {
 1031 
 1032         if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
 1033                 ERRNO_SET(EINVAL);
 1034                 return (false);
 1035         }
 1036         if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
 1037                 ERRNO_SET(EINVAL);
 1038                 return (false);
 1039         }
 1040 #if BYTE_ORDER == BIG_ENDIAN
 1041         if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
 1042                 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
 1043                 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
 1044         }
 1045 #else
 1046         if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
 1047                 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
 1048                 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
 1049         }
 1050 #endif
 1051         return (true);
 1052 }
 1053 
 1054 const unsigned char *
 1055 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
 1056     bool *isbep, size_t *leftp)
 1057 {
 1058         struct nvlist_header nvlhdr;
 1059         int inarrayf;
 1060 
 1061         if (*leftp < sizeof(nvlhdr))
 1062                 goto fail;
 1063 
 1064         memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
 1065 
 1066         if (!nvlist_check_header(&nvlhdr))
 1067                 goto fail;
 1068 
 1069         if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
 1070                 goto fail;
 1071 
 1072         /*
 1073          * nvlh_descriptors might be smaller than nfds in embedded nvlists.
 1074          */
 1075         if (nvlhdr.nvlh_descriptors > nfds)
 1076                 goto fail;
 1077 
 1078         if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
 1079                 goto fail;
 1080 
 1081         inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY);
 1082         nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf;
 1083 
 1084         ptr += sizeof(nvlhdr);
 1085         if (isbep != NULL)
 1086                 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
 1087         *leftp -= sizeof(nvlhdr);
 1088 
 1089         return (ptr);
 1090 fail:
 1091         ERRNO_SET(EINVAL);
 1092         return (NULL);
 1093 }
 1094 
 1095 static nvlist_t *
 1096 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
 1097     int flags)
 1098 {
 1099         const unsigned char *ptr;
 1100         nvlist_t *nvl, *retnvl, *tmpnvl, *array;
 1101         nvpair_t *nvp;
 1102         size_t left;
 1103         bool isbe;
 1104 
 1105         PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
 1106 
 1107         left = size;
 1108         ptr = buf;
 1109 
 1110         tmpnvl = array = NULL;
 1111         nvl = retnvl = nvlist_create(0);
 1112         if (nvl == NULL)
 1113                 goto fail;
 1114 
 1115         ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
 1116         if (ptr == NULL)
 1117                 goto fail;
 1118         if (nvl->nvl_flags != flags) {
 1119                 ERRNO_SET(EILSEQ);
 1120                 goto fail;
 1121         }
 1122 
 1123         while (left > 0) {
 1124                 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
 1125                 if (ptr == NULL)
 1126                         goto fail;
 1127                 switch (nvpair_type(nvp)) {
 1128                 case NV_TYPE_NULL:
 1129                         ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
 1130                         break;
 1131                 case NV_TYPE_BOOL:
 1132                         ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
 1133                         break;
 1134                 case NV_TYPE_NUMBER:
 1135                         ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
 1136                         break;
 1137                 case NV_TYPE_STRING:
 1138                         ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
 1139                         break;
 1140                 case NV_TYPE_NVLIST:
 1141                         ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
 1142                             &tmpnvl);
 1143                         if (tmpnvl == NULL || ptr == NULL)
 1144                                 goto fail;
 1145                         nvlist_set_parent(tmpnvl, nvp);
 1146                         break;
 1147 #ifndef _KERNEL
 1148                 case NV_TYPE_DESCRIPTOR:
 1149                         ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
 1150                             fds, nfds);
 1151                         break;
 1152                 case NV_TYPE_DESCRIPTOR_ARRAY:
 1153                         ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr,
 1154                             &left, fds, nfds);
 1155                         break;
 1156 #endif
 1157                 case NV_TYPE_BINARY:
 1158                         ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
 1159                         break;
 1160                 case NV_TYPE_NVLIST_UP:
 1161                         if (nvl->nvl_parent == NULL)
 1162                                 goto fail;
 1163                         nvl = nvpair_nvlist(nvl->nvl_parent);
 1164                         nvpair_free_structure(nvp);
 1165                         continue;
 1166                 case NV_TYPE_NVLIST_ARRAY_NEXT:
 1167                         if (nvl->nvl_array_next == NULL) {
 1168                                 if (nvl->nvl_parent == NULL)
 1169                                         goto fail;
 1170                                 nvl = nvpair_nvlist(nvl->nvl_parent);
 1171                         } else {
 1172                                 nvl = __DECONST(nvlist_t *,
 1173                                     nvlist_get_array_next(nvl));
 1174                                 ptr = nvlist_unpack_header(nvl, ptr, nfds,
 1175                                     &isbe, &left);
 1176                                 if (ptr == NULL)
 1177                                         goto fail;
 1178                         }
 1179                         nvpair_free_structure(nvp);
 1180                         continue;
 1181                 case NV_TYPE_BOOL_ARRAY:
 1182                         ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left);
 1183                         break;
 1184                 case NV_TYPE_NUMBER_ARRAY:
 1185                         ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left);
 1186                         break;
 1187                 case NV_TYPE_STRING_ARRAY:
 1188                         ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left);
 1189                         break;
 1190                 case NV_TYPE_NVLIST_ARRAY:
 1191                         ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left,
 1192                             &array);
 1193                         if (ptr == NULL)
 1194                                 goto fail;
 1195                         PJDLOG_ASSERT(array != NULL);
 1196                         tmpnvl = array;
 1197                         do {
 1198                                 nvlist_set_parent(array, nvp);
 1199                                 array = __DECONST(nvlist_t *,
 1200                                     nvlist_get_array_next(array));
 1201                         } while (array != NULL);
 1202                         ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe,
 1203                             &left);
 1204                         break;
 1205                 default:
 1206                         PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
 1207                 }
 1208                 if (ptr == NULL)
 1209                         goto fail;
 1210                 if (!nvlist_move_nvpair(nvl, nvp))
 1211                         goto fail;
 1212                 if (tmpnvl != NULL) {
 1213                         nvl = tmpnvl;
 1214                         tmpnvl = NULL;
 1215                 }
 1216         }
 1217 
 1218         return (retnvl);
 1219 fail:
 1220         nvlist_destroy(retnvl);
 1221         return (NULL);
 1222 }
 1223 
 1224 nvlist_t *
 1225 nvlist_unpack(const void *buf, size_t size, int flags)
 1226 {
 1227 
 1228         return (nvlist_xunpack(buf, size, NULL, 0, flags));
 1229 }
 1230 
 1231 #ifndef _KERNEL
 1232 int
 1233 nvlist_send(int sock, const nvlist_t *nvl)
 1234 {
 1235         size_t datasize, nfds;
 1236         int *fds;
 1237         void *data;
 1238         int64_t fdidx;
 1239         int ret;
 1240 
 1241         if (nvlist_error(nvl) != 0) {
 1242                 ERRNO_SET(nvlist_error(nvl));
 1243                 return (-1);
 1244         }
 1245 
 1246         fds = nvlist_descriptors(nvl, &nfds);
 1247         if (fds == NULL)
 1248                 return (-1);
 1249 
 1250         ret = -1;
 1251         fdidx = 0;
 1252 
 1253         data = nvlist_xpack(nvl, &fdidx, &datasize);
 1254         if (data == NULL)
 1255                 goto out;
 1256 
 1257         if (buf_send(sock, data, datasize) == -1)
 1258                 goto out;
 1259 
 1260         if (nfds > 0) {
 1261                 if (fd_send(sock, fds, nfds) == -1)
 1262                         goto out;
 1263         }
 1264 
 1265         ret = 0;
 1266 out:
 1267         ERRNO_SAVE();
 1268         nv_free(fds);
 1269         nv_free(data);
 1270         ERRNO_RESTORE();
 1271         return (ret);
 1272 }
 1273 
 1274 nvlist_t *
 1275 nvlist_recv(int sock, int flags)
 1276 {
 1277         struct nvlist_header nvlhdr;
 1278         nvlist_t *nvl, *ret;
 1279         unsigned char *buf;
 1280         size_t nfds, size, i, offset;
 1281         int *fds, soflags, sotype;
 1282         socklen_t solen;
 1283 
 1284         solen = sizeof(sotype);
 1285         if (getsockopt(sock, SOL_SOCKET, SO_TYPE, &sotype, &solen) != 0)
 1286                 return (NULL);
 1287 
 1288         soflags = sotype == SOCK_DGRAM ? MSG_PEEK : 0;
 1289         if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr), soflags) == -1)
 1290                 return (NULL);
 1291 
 1292         if (!nvlist_check_header(&nvlhdr))
 1293                 return (NULL);
 1294 
 1295         nfds = (size_t)nvlhdr.nvlh_descriptors;
 1296         size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
 1297 
 1298         buf = nv_malloc(size);
 1299         if (buf == NULL)
 1300                 return (NULL);
 1301 
 1302         ret = NULL;
 1303         fds = NULL;
 1304 
 1305         if (sotype == SOCK_DGRAM)
 1306                 offset = 0;
 1307         else {
 1308                 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
 1309                 offset = sizeof(nvlhdr);
 1310         }
 1311 
 1312         if (buf_recv(sock, buf + offset, size - offset, 0) == -1)
 1313                 goto out;
 1314 
 1315         if (nfds > 0) {
 1316                 fds = nv_malloc(nfds * sizeof(fds[0]));
 1317                 if (fds == NULL)
 1318                         goto out;
 1319                 if (fd_recv(sock, fds, nfds) == -1)
 1320                         goto out;
 1321         }
 1322 
 1323         nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
 1324         if (nvl == NULL) {
 1325                 ERRNO_SAVE();
 1326                 for (i = 0; i < nfds; i++)
 1327                         close(fds[i]);
 1328                 ERRNO_RESTORE();
 1329                 goto out;
 1330         }
 1331 
 1332         ret = nvl;
 1333 out:
 1334         ERRNO_SAVE();
 1335         nv_free(buf);
 1336         nv_free(fds);
 1337         ERRNO_RESTORE();
 1338 
 1339         return (ret);
 1340 }
 1341 
 1342 nvlist_t *
 1343 nvlist_xfer(int sock, nvlist_t *nvl, int flags)
 1344 {
 1345 
 1346         if (nvlist_send(sock, nvl) < 0) {
 1347                 nvlist_destroy(nvl);
 1348                 return (NULL);
 1349         }
 1350         nvlist_destroy(nvl);
 1351         return (nvlist_recv(sock, flags));
 1352 }
 1353 #endif
 1354 
 1355 nvpair_t *
 1356 nvlist_first_nvpair(const nvlist_t *nvl)
 1357 {
 1358 
 1359         NVLIST_ASSERT(nvl);
 1360 
 1361         return (TAILQ_FIRST(&nvl->nvl_head));
 1362 }
 1363 
 1364 nvpair_t *
 1365 nvlist_next_nvpair(const nvlist_t *nvl __unused, const nvpair_t *nvp)
 1366 {
 1367         nvpair_t *retnvp;
 1368 
 1369         NVLIST_ASSERT(nvl);
 1370         NVPAIR_ASSERT(nvp);
 1371         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
 1372 
 1373         retnvp = nvpair_next(nvp);
 1374         PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
 1375 
 1376         return (retnvp);
 1377 
 1378 }
 1379 
 1380 nvpair_t *
 1381 nvlist_prev_nvpair(const nvlist_t *nvl __unused, const nvpair_t *nvp)
 1382 {
 1383         nvpair_t *retnvp;
 1384 
 1385         NVLIST_ASSERT(nvl);
 1386         NVPAIR_ASSERT(nvp);
 1387         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
 1388 
 1389         retnvp = nvpair_prev(nvp);
 1390         PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
 1391 
 1392         return (retnvp);
 1393 }
 1394 
 1395 const char *
 1396 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
 1397 {
 1398         nvpair_t *nvp;
 1399 
 1400         NVLIST_ASSERT(nvl);
 1401 
 1402         if (cookiep == NULL || *cookiep == NULL)
 1403                 nvp = nvlist_first_nvpair(nvl);
 1404         else
 1405                 nvp = nvlist_next_nvpair(nvl, *cookiep);
 1406         if (nvp == NULL)
 1407                 return (NULL);
 1408         if (typep != NULL)
 1409                 *typep = nvpair_type(nvp);
 1410         if (cookiep != NULL)
 1411                 *cookiep = nvp;
 1412         return (nvpair_name(nvp));
 1413 }
 1414 
 1415 bool
 1416 nvlist_exists(const nvlist_t *nvl, const char *name)
 1417 {
 1418 
 1419         return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
 1420 }
 1421 
 1422 #define NVLIST_EXISTS(type, TYPE)                                       \
 1423 bool                                                                    \
 1424 nvlist_exists_##type(const nvlist_t *nvl, const char *name)             \
 1425 {                                                                       \
 1426                                                                         \
 1427         return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL);        \
 1428 }
 1429 
 1430 NVLIST_EXISTS(null, NULL)
 1431 NVLIST_EXISTS(bool, BOOL)
 1432 NVLIST_EXISTS(number, NUMBER)
 1433 NVLIST_EXISTS(string, STRING)
 1434 NVLIST_EXISTS(nvlist, NVLIST)
 1435 NVLIST_EXISTS(binary, BINARY)
 1436 NVLIST_EXISTS(bool_array, BOOL_ARRAY)
 1437 NVLIST_EXISTS(number_array, NUMBER_ARRAY)
 1438 NVLIST_EXISTS(string_array, STRING_ARRAY)
 1439 NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY)
 1440 #ifndef _KERNEL
 1441 NVLIST_EXISTS(descriptor, DESCRIPTOR)
 1442 NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY)
 1443 #endif
 1444 
 1445 #undef  NVLIST_EXISTS
 1446 
 1447 void
 1448 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
 1449 {
 1450         nvpair_t *newnvp;
 1451 
 1452         NVPAIR_ASSERT(nvp);
 1453 
 1454         if (nvlist_error(nvl) != 0) {
 1455                 ERRNO_SET(nvlist_error(nvl));
 1456                 return;
 1457         }
 1458         if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
 1459                 if (nvlist_exists(nvl, nvpair_name(nvp))) {
 1460                         nvl->nvl_error = EEXIST;
 1461                         ERRNO_SET(nvlist_error(nvl));
 1462                         return;
 1463                 }
 1464         }
 1465 
 1466         newnvp = nvpair_clone(nvp);
 1467         if (newnvp == NULL) {
 1468                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1469                 ERRNO_SET(nvlist_error(nvl));
 1470                 return;
 1471         }
 1472 
 1473         nvpair_insert(&nvl->nvl_head, newnvp, nvl);
 1474         nvlist_update_size(nvl, newnvp, 1);
 1475 }
 1476 
 1477 void
 1478 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
 1479 {
 1480         va_list valueap;
 1481 
 1482         va_start(valueap, valuefmt);
 1483         nvlist_add_stringv(nvl, name, valuefmt, valueap);
 1484         va_end(valueap);
 1485 }
 1486 
 1487 void
 1488 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
 1489     va_list valueap)
 1490 {
 1491         nvpair_t *nvp;
 1492 
 1493         if (nvlist_error(nvl) != 0) {
 1494                 ERRNO_SET(nvlist_error(nvl));
 1495                 return;
 1496         }
 1497 
 1498         nvp = nvpair_create_stringv(name, valuefmt, valueap);
 1499         if (nvp == NULL) {
 1500                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1501                 ERRNO_SET(nvl->nvl_error);
 1502         } else {
 1503                 (void)nvlist_move_nvpair(nvl, nvp);
 1504         }
 1505 }
 1506 
 1507 void
 1508 nvlist_add_null(nvlist_t *nvl, const char *name)
 1509 {
 1510         nvpair_t *nvp;
 1511 
 1512         if (nvlist_error(nvl) != 0) {
 1513                 ERRNO_SET(nvlist_error(nvl));
 1514                 return;
 1515         }
 1516 
 1517         nvp = nvpair_create_null(name);
 1518         if (nvp == NULL) {
 1519                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1520                 ERRNO_SET(nvl->nvl_error);
 1521         } else {
 1522                 (void)nvlist_move_nvpair(nvl, nvp);
 1523         }
 1524 }
 1525 
 1526 void
 1527 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
 1528     size_t size)
 1529 {
 1530         nvpair_t *nvp;
 1531 
 1532         if (nvlist_error(nvl) != 0) {
 1533                 ERRNO_SET(nvlist_error(nvl));
 1534                 return;
 1535         }
 1536 
 1537         nvp = nvpair_create_binary(name, value, size);
 1538         if (nvp == NULL) {
 1539                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1540                 ERRNO_SET(nvl->nvl_error);
 1541         } else {
 1542                 (void)nvlist_move_nvpair(nvl, nvp);
 1543         }
 1544 }
 1545 
 1546 
 1547 #define NVLIST_ADD(vtype, type)                                         \
 1548 void                                                                    \
 1549 nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value)         \
 1550 {                                                                       \
 1551         nvpair_t *nvp;                                                  \
 1552                                                                         \
 1553         if (nvlist_error(nvl) != 0) {                                   \
 1554                 ERRNO_SET(nvlist_error(nvl));                           \
 1555                 return;                                                 \
 1556         }                                                               \
 1557                                                                         \
 1558         nvp = nvpair_create_##type(name, value);                        \
 1559         if (nvp == NULL) {                                              \
 1560                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);              \
 1561                 ERRNO_SET(nvl->nvl_error);                              \
 1562         } else {                                                        \
 1563                 (void)nvlist_move_nvpair(nvl, nvp);                     \
 1564         }                                                               \
 1565 }
 1566 
 1567 NVLIST_ADD(bool, bool)
 1568 NVLIST_ADD(uint64_t, number)
 1569 NVLIST_ADD(const char *, string)
 1570 NVLIST_ADD(const nvlist_t *, nvlist)
 1571 #ifndef _KERNEL
 1572 NVLIST_ADD(int, descriptor);
 1573 #endif
 1574 
 1575 #undef  NVLIST_ADD
 1576 
 1577 #define NVLIST_ADD_ARRAY(vtype, type)                                   \
 1578 void                                                                    \
 1579 nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value, \
 1580     size_t nitems)                                                      \
 1581 {                                                                       \
 1582         nvpair_t *nvp;                                                  \
 1583                                                                         \
 1584         if (nvlist_error(nvl) != 0) {                                   \
 1585                 ERRNO_SET(nvlist_error(nvl));                           \
 1586                 return;                                                 \
 1587         }                                                               \
 1588                                                                         \
 1589         nvp = nvpair_create_##type##_array(name, value, nitems);        \
 1590         if (nvp == NULL) {                                              \
 1591                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);              \
 1592                 ERRNO_SET(nvl->nvl_error);                              \
 1593         } else {                                                        \
 1594                 (void)nvlist_move_nvpair(nvl, nvp);                     \
 1595         }                                                               \
 1596 }
 1597 
 1598 NVLIST_ADD_ARRAY(const bool *, bool)
 1599 NVLIST_ADD_ARRAY(const uint64_t *, number)
 1600 NVLIST_ADD_ARRAY(const char * const *, string)
 1601 NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist)
 1602 #ifndef _KERNEL
 1603 NVLIST_ADD_ARRAY(const int *, descriptor)
 1604 #endif
 1605 
 1606 #undef  NVLIST_ADD_ARRAY
 1607 
 1608 #define NVLIST_APPEND_ARRAY(vtype, type, TYPE)                          \
 1609 void                                                                    \
 1610 nvlist_append_##type##_array(nvlist_t *nvl, const char *name, vtype value)\
 1611 {                                                                       \
 1612         nvpair_t *nvp;                                                  \
 1613                                                                         \
 1614         if (nvlist_error(nvl) != 0) {                                   \
 1615                 ERRNO_SET(nvlist_error(nvl));                           \
 1616                 return;                                                 \
 1617         }                                                               \
 1618         nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);           \
 1619         if (nvp == NULL) {                                              \
 1620                 nvlist_add_##type##_array(nvl, name, &value, 1);        \
 1621                 return;                                                 \
 1622         }                                                               \
 1623         nvlist_update_size(nvl, nvp, -1);                               \
 1624         if (nvpair_append_##type##_array(nvp, value) == -1) {           \
 1625                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);              \
 1626                 ERRNO_SET(nvl->nvl_error);                              \
 1627         }                                                               \
 1628         nvlist_update_size(nvl, nvp, 1);                                \
 1629 }
 1630 
 1631 NVLIST_APPEND_ARRAY(const bool, bool, BOOL)
 1632 NVLIST_APPEND_ARRAY(const uint64_t, number, NUMBER)
 1633 NVLIST_APPEND_ARRAY(const char *, string, STRING)
 1634 NVLIST_APPEND_ARRAY(const nvlist_t *, nvlist, NVLIST)
 1635 #ifndef _KERNEL
 1636 NVLIST_APPEND_ARRAY(const int, descriptor, DESCRIPTOR)
 1637 #endif
 1638 
 1639 #undef  NVLIST_APPEND_ARRAY
 1640 
 1641 bool
 1642 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
 1643 {
 1644 
 1645         NVPAIR_ASSERT(nvp);
 1646         PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
 1647 
 1648         if (nvlist_error(nvl) != 0) {
 1649                 nvpair_free(nvp);
 1650                 ERRNO_SET(nvlist_error(nvl));
 1651                 return (false);
 1652         }
 1653         if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
 1654                 if (nvlist_exists(nvl, nvpair_name(nvp))) {
 1655                         nvpair_free(nvp);
 1656                         nvl->nvl_error = EEXIST;
 1657                         ERRNO_SET(nvl->nvl_error);
 1658                         return (false);
 1659                 }
 1660         }
 1661 
 1662         nvpair_insert(&nvl->nvl_head, nvp, nvl);
 1663         nvlist_update_size(nvl, nvp, 1);
 1664         return (true);
 1665 }
 1666 
 1667 void
 1668 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
 1669 {
 1670         nvpair_t *nvp;
 1671 
 1672         if (nvlist_error(nvl) != 0) {
 1673                 nv_free(value);
 1674                 ERRNO_SET(nvlist_error(nvl));
 1675                 return;
 1676         }
 1677 
 1678         nvp = nvpair_move_string(name, value);
 1679         if (nvp == NULL) {
 1680                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1681                 ERRNO_SET(nvl->nvl_error);
 1682         } else {
 1683                 (void)nvlist_move_nvpair(nvl, nvp);
 1684         }
 1685 }
 1686 
 1687 void
 1688 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
 1689 {
 1690         nvpair_t *nvp;
 1691 
 1692         if (nvlist_error(nvl) != 0) {
 1693                 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
 1694                         nvlist_destroy(value);
 1695                 ERRNO_SET(nvlist_error(nvl));
 1696                 return;
 1697         }
 1698 
 1699         nvp = nvpair_move_nvlist(name, value);
 1700         if (nvp == NULL) {
 1701                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1702                 ERRNO_SET(nvl->nvl_error);
 1703         } else {
 1704                 (void)nvlist_move_nvpair(nvl, nvp);
 1705         }
 1706 }
 1707 
 1708 #ifndef _KERNEL
 1709 void
 1710 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
 1711 {
 1712         nvpair_t *nvp;
 1713 
 1714         if (nvlist_error(nvl) != 0) {
 1715                 close(value);
 1716                 ERRNO_SET(nvlist_error(nvl));
 1717                 return;
 1718         }
 1719 
 1720         nvp = nvpair_move_descriptor(name, value);
 1721         if (nvp == NULL) {
 1722                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1723                 ERRNO_SET(nvl->nvl_error);
 1724         } else {
 1725                 (void)nvlist_move_nvpair(nvl, nvp);
 1726         }
 1727 }
 1728 #endif
 1729 
 1730 void
 1731 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
 1732 {
 1733         nvpair_t *nvp;
 1734 
 1735         if (nvlist_error(nvl) != 0) {
 1736                 nv_free(value);
 1737                 ERRNO_SET(nvlist_error(nvl));
 1738                 return;
 1739         }
 1740 
 1741         nvp = nvpair_move_binary(name, value, size);
 1742         if (nvp == NULL) {
 1743                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1744                 ERRNO_SET(nvl->nvl_error);
 1745         } else {
 1746                 (void)nvlist_move_nvpair(nvl, nvp);
 1747         }
 1748 }
 1749 
 1750 void
 1751 nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value,
 1752     size_t nitems)
 1753 {
 1754         nvpair_t *nvp;
 1755 
 1756         if (nvlist_error(nvl) != 0) {
 1757                 nv_free(value);
 1758                 ERRNO_SET(nvlist_error(nvl));
 1759                 return;
 1760         }
 1761 
 1762         nvp = nvpair_move_bool_array(name, value, nitems);
 1763         if (nvp == NULL) {
 1764                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1765                 ERRNO_SET(nvl->nvl_error);
 1766         } else {
 1767                 (void)nvlist_move_nvpair(nvl, nvp);
 1768         }
 1769 }
 1770 
 1771 void
 1772 nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value,
 1773     size_t nitems)
 1774 {
 1775         nvpair_t *nvp;
 1776         size_t i;
 1777 
 1778         if (nvlist_error(nvl) != 0) {
 1779                 if (value != NULL) {
 1780                         for (i = 0; i < nitems; i++)
 1781                                 nv_free(value[i]);
 1782                         nv_free(value);
 1783                 }
 1784                 ERRNO_SET(nvlist_error(nvl));
 1785                 return;
 1786         }
 1787 
 1788         nvp = nvpair_move_string_array(name, value, nitems);
 1789         if (nvp == NULL) {
 1790                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1791                 ERRNO_SET(nvl->nvl_error);
 1792         } else {
 1793                 (void)nvlist_move_nvpair(nvl, nvp);
 1794         }
 1795 }
 1796 
 1797 void
 1798 nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value,
 1799     size_t nitems)
 1800 {
 1801         nvpair_t *nvp;
 1802         size_t i;
 1803 
 1804         if (nvlist_error(nvl) != 0) {
 1805                 if (value != NULL) {
 1806                         for (i = 0; i < nitems; i++) {
 1807                                 if (nvlist_get_pararr(value[i], NULL) == NULL)
 1808                                         nvlist_destroy(value[i]);
 1809                         }
 1810                 }
 1811                 nv_free(value);
 1812                 ERRNO_SET(nvlist_error(nvl));
 1813                 return;
 1814         }
 1815 
 1816         nvp = nvpair_move_nvlist_array(name, value, nitems);
 1817         if (nvp == NULL) {
 1818                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1819                 ERRNO_SET(nvl->nvl_error);
 1820         } else {
 1821                 (void)nvlist_move_nvpair(nvl, nvp);
 1822         }
 1823 }
 1824 
 1825 void
 1826 nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value,
 1827     size_t nitems)
 1828 {
 1829         nvpair_t *nvp;
 1830 
 1831         if (nvlist_error(nvl) != 0) {
 1832                 nv_free(value);
 1833                 ERRNO_SET(nvlist_error(nvl));
 1834                 return;
 1835         }
 1836 
 1837         nvp = nvpair_move_number_array(name, value, nitems);
 1838         if (nvp == NULL) {
 1839                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1840                 ERRNO_SET(nvl->nvl_error);
 1841         } else {
 1842                 (void)nvlist_move_nvpair(nvl, nvp);
 1843         }
 1844 }
 1845 
 1846 #ifndef _KERNEL
 1847 void
 1848 nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value,
 1849     size_t nitems)
 1850 {
 1851         nvpair_t *nvp;
 1852         size_t i;
 1853 
 1854         if (nvlist_error(nvl) != 0) {
 1855                 if (value != 0) {
 1856                         for (i = 0; i < nitems; i++)
 1857                                 close(value[i]);
 1858                         nv_free(value);
 1859                 }
 1860 
 1861                 ERRNO_SET(nvlist_error(nvl));
 1862                 return;
 1863         }
 1864 
 1865         nvp = nvpair_move_descriptor_array(name, value, nitems);
 1866         if (nvp == NULL) {
 1867                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1868                 ERRNO_SET(nvl->nvl_error);
 1869         } else {
 1870                 (void)nvlist_move_nvpair(nvl, nvp);
 1871         }
 1872 }
 1873 #endif
 1874 
 1875 const nvpair_t *
 1876 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
 1877 {
 1878 
 1879         return (nvlist_find(nvl, NV_TYPE_NONE, name));
 1880 }
 1881 
 1882 #define NVLIST_GET(ftype, type, TYPE)                                   \
 1883 ftype                                                                   \
 1884 nvlist_get_##type(const nvlist_t *nvl, const char *name)                \
 1885 {                                                                       \
 1886         const nvpair_t *nvp;                                            \
 1887                                                                         \
 1888         nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);                   \
 1889         if (nvp == NULL)                                                \
 1890                 nvlist_report_missing(NV_TYPE_##TYPE, name);            \
 1891         return (nvpair_get_##type(nvp));                                \
 1892 }
 1893 
 1894 NVLIST_GET(bool, bool, BOOL)
 1895 NVLIST_GET(uint64_t, number, NUMBER)
 1896 NVLIST_GET(const char *, string, STRING)
 1897 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
 1898 #ifndef _KERNEL
 1899 NVLIST_GET(int, descriptor, DESCRIPTOR)
 1900 #endif
 1901 
 1902 #undef  NVLIST_GET
 1903 
 1904 const void *
 1905 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
 1906 {
 1907         nvpair_t *nvp;
 1908 
 1909         nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
 1910         if (nvp == NULL)
 1911                 nvlist_report_missing(NV_TYPE_BINARY, name);
 1912 
 1913         return (nvpair_get_binary(nvp, sizep));
 1914 }
 1915 
 1916 #define NVLIST_GET_ARRAY(ftype, type, TYPE)                             \
 1917 ftype                                                                   \
 1918 nvlist_get_##type##_array(const nvlist_t *nvl, const char *name,        \
 1919     size_t *nitems)                                                     \
 1920 {                                                                       \
 1921         const nvpair_t *nvp;                                            \
 1922                                                                         \
 1923         nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);           \
 1924         if (nvp == NULL)                                                \
 1925                 nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name);    \
 1926         return (nvpair_get_##type##_array(nvp, nitems));                \
 1927 }
 1928 
 1929 NVLIST_GET_ARRAY(const bool *, bool, BOOL)
 1930 NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER)
 1931 NVLIST_GET_ARRAY(const char * const *, string, STRING)
 1932 NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST)
 1933 #ifndef _KERNEL
 1934 NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR)
 1935 #endif
 1936 
 1937 #undef  NVLIST_GET_ARRAY
 1938 
 1939 #define NVLIST_TAKE(ftype, type, TYPE)                                  \
 1940 ftype                                                                   \
 1941 nvlist_take_##type(nvlist_t *nvl, const char *name)                     \
 1942 {                                                                       \
 1943         nvpair_t *nvp;                                                  \
 1944         ftype value;                                                    \
 1945                                                                         \
 1946         nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);                   \
 1947         if (nvp == NULL)                                                \
 1948                 nvlist_report_missing(NV_TYPE_##TYPE, name);            \
 1949         value = (ftype)(intptr_t)nvpair_get_##type(nvp);                \
 1950         nvlist_remove_nvpair(nvl, nvp);                                 \
 1951         nvpair_free_structure(nvp);                                     \
 1952         return (value);                                                 \
 1953 }
 1954 
 1955 NVLIST_TAKE(bool, bool, BOOL)
 1956 NVLIST_TAKE(uint64_t, number, NUMBER)
 1957 NVLIST_TAKE(char *, string, STRING)
 1958 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
 1959 #ifndef _KERNEL
 1960 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
 1961 #endif
 1962 
 1963 #undef  NVLIST_TAKE
 1964 
 1965 void *
 1966 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
 1967 {
 1968         nvpair_t *nvp;
 1969         void *value;
 1970 
 1971         nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
 1972         if (nvp == NULL)
 1973                 nvlist_report_missing(NV_TYPE_BINARY, name);
 1974 
 1975         value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
 1976         nvlist_remove_nvpair(nvl, nvp);
 1977         nvpair_free_structure(nvp);
 1978         return (value);
 1979 }
 1980 
 1981 #define NVLIST_TAKE_ARRAY(ftype, type, TYPE)                            \
 1982 ftype                                                                   \
 1983 nvlist_take_##type##_array(nvlist_t *nvl, const char *name,             \
 1984     size_t *nitems)                                                     \
 1985 {                                                                       \
 1986         nvpair_t *nvp;                                                  \
 1987         ftype value;                                                    \
 1988                                                                         \
 1989         nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);           \
 1990         if (nvp == NULL)                                                \
 1991                 nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name);    \
 1992         value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\
 1993         nvlist_remove_nvpair(nvl, nvp);                                 \
 1994         nvpair_free_structure(nvp);                                     \
 1995         return (value);                                                 \
 1996 }
 1997 
 1998 NVLIST_TAKE_ARRAY(bool *, bool, BOOL)
 1999 NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER)
 2000 NVLIST_TAKE_ARRAY(char **, string, STRING)
 2001 NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST)
 2002 #ifndef _KERNEL
 2003 NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR)
 2004 #endif
 2005 
 2006 void
 2007 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
 2008 {
 2009 
 2010         NVLIST_ASSERT(nvl);
 2011         NVPAIR_ASSERT(nvp);
 2012         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
 2013 
 2014         nvpair_remove(&nvl->nvl_head, nvp, nvl);
 2015         nvlist_update_size(nvl, nvp, -1);
 2016 }
 2017 
 2018 void
 2019 nvlist_free(nvlist_t *nvl, const char *name)
 2020 {
 2021 
 2022         nvlist_free_type(nvl, name, NV_TYPE_NONE);
 2023 }
 2024 
 2025 #define NVLIST_FREE(type, TYPE)                                         \
 2026 void                                                                    \
 2027 nvlist_free_##type(nvlist_t *nvl, const char *name)                     \
 2028 {                                                                       \
 2029                                                                         \
 2030         nvlist_free_type(nvl, name, NV_TYPE_##TYPE);                    \
 2031 }
 2032 
 2033 NVLIST_FREE(null, NULL)
 2034 NVLIST_FREE(bool, BOOL)
 2035 NVLIST_FREE(number, NUMBER)
 2036 NVLIST_FREE(string, STRING)
 2037 NVLIST_FREE(nvlist, NVLIST)
 2038 NVLIST_FREE(binary, BINARY)
 2039 NVLIST_FREE(bool_array, BOOL_ARRAY)
 2040 NVLIST_FREE(number_array, NUMBER_ARRAY)
 2041 NVLIST_FREE(string_array, STRING_ARRAY)
 2042 NVLIST_FREE(nvlist_array, NVLIST_ARRAY)
 2043 #ifndef _KERNEL
 2044 NVLIST_FREE(descriptor, DESCRIPTOR)
 2045 NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY)
 2046 #endif
 2047 
 2048 #undef  NVLIST_FREE
 2049 
 2050 void
 2051 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
 2052 {
 2053 
 2054         NVLIST_ASSERT(nvl);
 2055         NVPAIR_ASSERT(nvp);
 2056         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
 2057 
 2058         nvlist_remove_nvpair(nvl, nvp);
 2059         nvpair_free(nvp);
 2060 }
 2061 

Cache object: 0dd05935a53d4aa8eae8ecfd41af6785


[ 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.