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/kern/subr_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  * Copyright (c) 2009-2013 The FreeBSD Foundation
    3  * All rights reserved.
    4  *
    5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
    6  * the FreeBSD Foundation.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/10.4/sys/kern/subr_nvlist.c 292973 2015-12-31 03:28:14Z ngie $");
   32 
   33 #include <sys/param.h>
   34 #include <sys/endian.h>
   35 #include <sys/queue.h>
   36 
   37 #ifdef _KERNEL
   38 
   39 #include <sys/errno.h>
   40 #include <sys/kernel.h>
   41 #include <sys/lock.h>
   42 #include <sys/malloc.h>
   43 #include <sys/systm.h>
   44 
   45 #include <machine/stdarg.h>
   46 
   47 #else
   48 #include <sys/socket.h>
   49 
   50 #include <errno.h>
   51 #include <stdarg.h>
   52 #include <stdbool.h>
   53 #include <stdint.h>
   54 #define _WITH_DPRINTF
   55 #include <stdio.h>
   56 #include <stdlib.h>
   57 #include <string.h>
   58 #include <unistd.h>
   59 
   60 #include "msgio.h"
   61 #endif
   62 
   63 #ifdef HAVE_PJDLOG
   64 #include <pjdlog.h>
   65 #endif
   66 
   67 #include <sys/nv.h>
   68 #include <sys/nv_impl.h>
   69 #include <sys/nvlist_impl.h>
   70 #include <sys/nvpair_impl.h>
   71 
   72 #ifndef HAVE_PJDLOG
   73 #ifdef _KERNEL
   74 #define PJDLOG_ASSERT(...)              MPASS(__VA_ARGS__)
   75 #define PJDLOG_RASSERT(expr, ...)       KASSERT(expr, (__VA_ARGS__))
   76 #define PJDLOG_ABORT(...)               panic(__VA_ARGS__)
   77 #else
   78 #include <assert.h>
   79 #define PJDLOG_ASSERT(...)              assert(__VA_ARGS__)
   80 #define PJDLOG_RASSERT(expr, ...)       assert(expr)
   81 #define PJDLOG_ABORT(...)               do {                            \
   82         fprintf(stderr, "%s:%u: ", __FILE__, __LINE__);                 \
   83         fprintf(stderr, __VA_ARGS__);                                   \
   84         fprintf(stderr, "\n");                                          \
   85         abort();                                                        \
   86 } while (0)
   87 #endif
   88 #endif
   89 
   90 #define NV_FLAG_PRIVATE_MASK    (NV_FLAG_BIG_ENDIAN)
   91 #define NV_FLAG_PUBLIC_MASK     (NV_FLAG_IGNORE_CASE)
   92 #define NV_FLAG_ALL_MASK        (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
   93 
   94 #define NVLIST_MAGIC    0x6e766c        /* "nvl" */
   95 struct nvlist {
   96         int              nvl_magic;
   97         int              nvl_error;
   98         int              nvl_flags;
   99         nvpair_t        *nvl_parent;
  100         struct nvl_head  nvl_head;
  101 };
  102 
  103 #define NVLIST_ASSERT(nvl)      do {                                    \
  104         PJDLOG_ASSERT((nvl) != NULL);                                   \
  105         PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);                \
  106 } while (0)
  107 
  108 #ifdef _KERNEL
  109 MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
  110 #endif
  111 
  112 #define NVPAIR_ASSERT(nvp)      nvpair_assert(nvp)
  113 
  114 #define NVLIST_HEADER_MAGIC     0x6c
  115 #define NVLIST_HEADER_VERSION   0x00
  116 struct nvlist_header {
  117         uint8_t         nvlh_magic;
  118         uint8_t         nvlh_version;
  119         uint8_t         nvlh_flags;
  120         uint64_t        nvlh_descriptors;
  121         uint64_t        nvlh_size;
  122 } __packed;
  123 
  124 nvlist_t *
  125 nvlist_create(int flags)
  126 {
  127         nvlist_t *nvl;
  128 
  129         PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
  130 
  131         nvl = nv_malloc(sizeof(*nvl));
  132         nvl->nvl_error = 0;
  133         nvl->nvl_flags = flags;
  134         nvl->nvl_parent = NULL;
  135         TAILQ_INIT(&nvl->nvl_head);
  136         nvl->nvl_magic = NVLIST_MAGIC;
  137 
  138         return (nvl);
  139 }
  140 
  141 void
  142 nvlist_destroy(nvlist_t *nvl)
  143 {
  144         nvpair_t *nvp;
  145         int serrno;
  146 
  147         if (nvl == NULL)
  148                 return;
  149 
  150         SAVE_ERRNO(serrno);
  151 
  152         NVLIST_ASSERT(nvl);
  153 
  154         while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
  155                 nvlist_remove_nvpair(nvl, nvp);
  156                 nvpair_free(nvp);
  157         }
  158         nvl->nvl_magic = 0;
  159         nv_free(nvl);
  160 
  161         RESTORE_ERRNO(serrno);
  162 }
  163 
  164 void
  165 nvlist_set_error(nvlist_t *nvl, int error)
  166 {
  167 
  168         PJDLOG_ASSERT(error != 0);
  169 
  170         /*
  171          * Check for error != 0 so that we don't do the wrong thing if somebody
  172          * tries to abuse this API when asserts are disabled.
  173          */
  174         if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
  175                 nvl->nvl_error = error;
  176 }
  177 
  178 int
  179 nvlist_error(const nvlist_t *nvl)
  180 {
  181 
  182         if (nvl == NULL)
  183                 return (ENOMEM);
  184 
  185         NVLIST_ASSERT(nvl);
  186 
  187         return (nvl->nvl_error);
  188 }
  189 
  190 nvpair_t *
  191 nvlist_get_nvpair_parent(const nvlist_t *nvl)
  192 {
  193 
  194         NVLIST_ASSERT(nvl);
  195 
  196         return (nvl->nvl_parent);
  197 }
  198 
  199 const nvlist_t *
  200 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
  201 {
  202         nvpair_t *nvp;
  203 
  204         NVLIST_ASSERT(nvl);
  205 
  206         nvp = nvl->nvl_parent;
  207         if (cookiep != NULL)
  208                 *cookiep = nvp;
  209         if (nvp == NULL)
  210                 return (NULL);
  211 
  212         return (nvpair_nvlist(nvp));
  213 }
  214 
  215 void
  216 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
  217 {
  218 
  219         NVLIST_ASSERT(nvl);
  220 
  221         nvl->nvl_parent = parent;
  222 }
  223 
  224 bool
  225 nvlist_empty(const nvlist_t *nvl)
  226 {
  227 
  228         NVLIST_ASSERT(nvl);
  229         PJDLOG_ASSERT(nvl->nvl_error == 0);
  230 
  231         return (nvlist_first_nvpair(nvl) == NULL);
  232 }
  233 
  234 int
  235 nvlist_flags(const nvlist_t *nvl)
  236 {
  237 
  238         NVLIST_ASSERT(nvl);
  239         PJDLOG_ASSERT(nvl->nvl_error == 0);
  240         PJDLOG_ASSERT((nvl->nvl_flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
  241 
  242         return (nvl->nvl_flags);
  243 }
  244 
  245 static void
  246 nvlist_report_missing(int type, const char *name)
  247 {
  248 
  249         PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
  250             name, nvpair_type_string(type));
  251 }
  252 
  253 static nvpair_t *
  254 nvlist_find(const nvlist_t *nvl, int type, const char *name)
  255 {
  256         nvpair_t *nvp;
  257 
  258         NVLIST_ASSERT(nvl);
  259         PJDLOG_ASSERT(nvl->nvl_error == 0);
  260         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
  261             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
  262 
  263         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
  264             nvp = nvlist_next_nvpair(nvl, nvp)) {
  265                 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
  266                         continue;
  267                 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
  268                         if (strcasecmp(nvpair_name(nvp), name) != 0)
  269                                 continue;
  270                 } else {
  271                         if (strcmp(nvpair_name(nvp), name) != 0)
  272                                 continue;
  273                 }
  274                 break;
  275         }
  276 
  277         if (nvp == NULL)
  278                 RESTORE_ERRNO(ENOENT);
  279 
  280         return (nvp);
  281 }
  282 
  283 bool
  284 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
  285 {
  286 
  287         NVLIST_ASSERT(nvl);
  288         PJDLOG_ASSERT(nvl->nvl_error == 0);
  289         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
  290             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
  291 
  292         return (nvlist_find(nvl, type, name) != NULL);
  293 }
  294 
  295 void
  296 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
  297 {
  298         nvpair_t *nvp;
  299 
  300         NVLIST_ASSERT(nvl);
  301         PJDLOG_ASSERT(nvl->nvl_error == 0);
  302         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
  303             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
  304 
  305         nvp = nvlist_find(nvl, type, name);
  306         if (nvp != NULL)
  307                 nvlist_free_nvpair(nvl, nvp);
  308         else
  309                 nvlist_report_missing(type, name);
  310 }
  311 
  312 nvlist_t *
  313 nvlist_clone(const nvlist_t *nvl)
  314 {
  315         nvlist_t *newnvl;
  316         nvpair_t *nvp, *newnvp;
  317 
  318         NVLIST_ASSERT(nvl);
  319 
  320         if (nvl->nvl_error != 0) {
  321                 RESTORE_ERRNO(nvl->nvl_error);
  322                 return (NULL);
  323         }
  324 
  325         newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
  326         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
  327             nvp = nvlist_next_nvpair(nvl, nvp)) {
  328                 newnvp = nvpair_clone(nvp);
  329                 if (newnvp == NULL)
  330                         break;
  331                 nvlist_move_nvpair(newnvl, newnvp);
  332         }
  333         if (nvp != NULL) {
  334                 nvlist_destroy(newnvl);
  335                 return (NULL);
  336         }
  337         return (newnvl);
  338 }
  339 
  340 #ifndef _KERNEL
  341 static bool
  342 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
  343 {
  344 
  345         if (nvlist_error(nvl) != 0) {
  346                 dprintf(fd, "%*serror: %d\n", level * 4, "",
  347                     nvlist_error(nvl));
  348                 return (true);
  349         }
  350 
  351         return (false);
  352 }
  353 
  354 /*
  355  * Dump content of nvlist.
  356  */
  357 void
  358 nvlist_dump(const nvlist_t *nvl, int fd)
  359 {
  360         const nvlist_t *tmpnvl;
  361         nvpair_t *nvp, *tmpnvp;
  362         void *cookie;
  363         int level;
  364 
  365         level = 0;
  366         if (nvlist_dump_error_check(nvl, fd, level))
  367                 return;
  368 
  369         nvp = nvlist_first_nvpair(nvl);
  370         while (nvp != NULL) {
  371                 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
  372                     nvpair_type_string(nvpair_type(nvp)));
  373                 switch (nvpair_type(nvp)) {
  374                 case NV_TYPE_NULL:
  375                         dprintf(fd, " null\n");
  376                         break;
  377                 case NV_TYPE_BOOL:
  378                         dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
  379                             "TRUE" : "FALSE");
  380                         break;
  381                 case NV_TYPE_NUMBER:
  382                         dprintf(fd, " %ju (%jd) (0x%jx)\n",
  383                             (uintmax_t)nvpair_get_number(nvp),
  384                             (intmax_t)nvpair_get_number(nvp),
  385                             (uintmax_t)nvpair_get_number(nvp));
  386                         break;
  387                 case NV_TYPE_STRING:
  388                         dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
  389                         break;
  390                 case NV_TYPE_NVLIST:
  391                         dprintf(fd, "\n");
  392                         tmpnvl = nvpair_get_nvlist(nvp);
  393                         if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
  394                                 break;
  395                         tmpnvp = nvlist_first_nvpair(tmpnvl);
  396                         if (tmpnvp != NULL) {
  397                                 nvl = tmpnvl;
  398                                 nvp = tmpnvp;
  399                                 level++;
  400                                 continue;
  401                         }
  402                         break;
  403                 case NV_TYPE_DESCRIPTOR:
  404                         dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
  405                         break;
  406                 case NV_TYPE_BINARY:
  407                     {
  408                         const unsigned char *binary;
  409                         unsigned int ii;
  410                         size_t size;
  411 
  412                         binary = nvpair_get_binary(nvp, &size);
  413                         dprintf(fd, " %zu ", size);
  414                         for (ii = 0; ii < size; ii++)
  415                                 dprintf(fd, "%02hhx", binary[ii]);
  416                         dprintf(fd, "\n");
  417                         break;
  418                     }
  419                 default:
  420                         PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
  421                 }
  422 
  423                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
  424                         cookie = NULL;
  425                         nvl = nvlist_get_parent(nvl, &cookie);
  426                         if (nvl == NULL)
  427                                 return;
  428                         nvp = cookie;
  429                         level--;
  430                 }
  431         }
  432 }
  433 
  434 void
  435 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
  436 {
  437 
  438         fflush(fp);
  439         nvlist_dump(nvl, fileno(fp));
  440 }
  441 #endif
  442 
  443 /*
  444  * The function obtains size of the nvlist after nvlist_pack().
  445  */
  446 size_t
  447 nvlist_size(const nvlist_t *nvl)
  448 {
  449         const nvlist_t *tmpnvl;
  450         const nvpair_t *nvp, *tmpnvp;
  451         void *cookie;
  452         size_t size;
  453 
  454         NVLIST_ASSERT(nvl);
  455         PJDLOG_ASSERT(nvl->nvl_error == 0);
  456 
  457         size = sizeof(struct nvlist_header);
  458         nvp = nvlist_first_nvpair(nvl);
  459         while (nvp != NULL) {
  460                 size += nvpair_header_size();
  461                 size += strlen(nvpair_name(nvp)) + 1;
  462                 if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
  463                         size += sizeof(struct nvlist_header);
  464                         size += nvpair_header_size() + 1;
  465                         tmpnvl = nvpair_get_nvlist(nvp);
  466                         PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
  467                         tmpnvp = nvlist_first_nvpair(tmpnvl);
  468                         if (tmpnvp != NULL) {
  469                                 nvl = tmpnvl;
  470                                 nvp = tmpnvp;
  471                                 continue;
  472                         }
  473                 } else {
  474                         size += nvpair_size(nvp);
  475                 }
  476 
  477                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
  478                         cookie = NULL;
  479                         nvl = nvlist_get_parent(nvl, &cookie);
  480                         if (nvl == NULL)
  481                                 goto out;
  482                         nvp = cookie;
  483                 }
  484         }
  485 
  486 out:
  487         return (size);
  488 }
  489 
  490 #ifndef _KERNEL
  491 static int *
  492 nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
  493 {
  494         const nvpair_t *nvp;
  495 
  496         NVLIST_ASSERT(nvl);
  497         PJDLOG_ASSERT(nvl->nvl_error == 0);
  498         PJDLOG_ASSERT(level < 3);
  499 
  500         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
  501             nvp = nvlist_next_nvpair(nvl, nvp)) {
  502                 switch (nvpair_type(nvp)) {
  503                 case NV_TYPE_DESCRIPTOR:
  504                         *descs = nvpair_get_descriptor(nvp);
  505                         descs++;
  506                         break;
  507                 case NV_TYPE_NVLIST:
  508                         descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
  509                             descs, level + 1);
  510                         break;
  511                 }
  512         }
  513 
  514         return (descs);
  515 }
  516 #endif
  517 
  518 #ifndef _KERNEL
  519 int *
  520 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
  521 {
  522         size_t nitems;
  523         int *fds;
  524 
  525         nitems = nvlist_ndescriptors(nvl);
  526         fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
  527         if (fds == NULL)
  528                 return (NULL);
  529         if (nitems > 0)
  530                 nvlist_xdescriptors(nvl, fds, 0);
  531         fds[nitems] = -1;
  532         if (nitemsp != NULL)
  533                 *nitemsp = nitems;
  534         return (fds);
  535 }
  536 #endif
  537 
  538 static size_t
  539 nvlist_xndescriptors(const nvlist_t *nvl, int level)
  540 {
  541 #ifndef _KERNEL
  542         const nvpair_t *nvp;
  543         size_t ndescs;
  544 
  545         NVLIST_ASSERT(nvl);
  546         PJDLOG_ASSERT(nvl->nvl_error == 0);
  547         PJDLOG_ASSERT(level < 3);
  548 
  549         ndescs = 0;
  550         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
  551             nvp = nvlist_next_nvpair(nvl, nvp)) {
  552                 switch (nvpair_type(nvp)) {
  553                 case NV_TYPE_DESCRIPTOR:
  554                         ndescs++;
  555                         break;
  556                 case NV_TYPE_NVLIST:
  557                         ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
  558                             level + 1);
  559                         break;
  560                 }
  561         }
  562 
  563         return (ndescs);
  564 #else
  565         return (0);
  566 #endif
  567 }
  568 
  569 size_t
  570 nvlist_ndescriptors(const nvlist_t *nvl)
  571 {
  572 
  573         return (nvlist_xndescriptors(nvl, 0));
  574 }
  575 
  576 static unsigned char *
  577 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
  578 {
  579         struct nvlist_header nvlhdr;
  580 
  581         NVLIST_ASSERT(nvl);
  582 
  583         nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
  584         nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
  585         nvlhdr.nvlh_flags = nvl->nvl_flags;
  586 #if BYTE_ORDER == BIG_ENDIAN
  587         nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
  588 #endif
  589         nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
  590         nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
  591         PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
  592         memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
  593         ptr += sizeof(nvlhdr);
  594         *leftp -= sizeof(nvlhdr);
  595 
  596         return (ptr);
  597 }
  598 
  599 void *
  600 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
  601 {
  602         unsigned char *buf, *ptr;
  603         size_t left, size;
  604         const nvlist_t *tmpnvl;
  605         nvpair_t *nvp, *tmpnvp;
  606         void *cookie;
  607 
  608         NVLIST_ASSERT(nvl);
  609 
  610         if (nvl->nvl_error != 0) {
  611                 RESTORE_ERRNO(nvl->nvl_error);
  612                 return (NULL);
  613         }
  614 
  615         size = nvlist_size(nvl);
  616         buf = nv_malloc(size);
  617         if (buf == NULL)
  618                 return (NULL);
  619 
  620         ptr = buf;
  621         left = size;
  622 
  623         ptr = nvlist_pack_header(nvl, ptr, &left);
  624 
  625         nvp = nvlist_first_nvpair(nvl);
  626         while (nvp != NULL) {
  627                 NVPAIR_ASSERT(nvp);
  628 
  629                 nvpair_init_datasize(nvp);
  630                 ptr = nvpair_pack_header(nvp, ptr, &left);
  631                 if (ptr == NULL) {
  632                         nv_free(buf);
  633                         return (NULL);
  634                 }
  635                 switch (nvpair_type(nvp)) {
  636                 case NV_TYPE_NULL:
  637                         ptr = nvpair_pack_null(nvp, ptr, &left);
  638                         break;
  639                 case NV_TYPE_BOOL:
  640                         ptr = nvpair_pack_bool(nvp, ptr, &left);
  641                         break;
  642                 case NV_TYPE_NUMBER:
  643                         ptr = nvpair_pack_number(nvp, ptr, &left);
  644                         break;
  645                 case NV_TYPE_STRING:
  646                         ptr = nvpair_pack_string(nvp, ptr, &left);
  647                         break;
  648                 case NV_TYPE_NVLIST:
  649                         tmpnvl = nvpair_get_nvlist(nvp);
  650                         ptr = nvlist_pack_header(tmpnvl, ptr, &left);
  651                         if (ptr == NULL)
  652                                 goto out;
  653                         tmpnvp = nvlist_first_nvpair(tmpnvl);
  654                         if (tmpnvp != NULL) {
  655                                 nvl = tmpnvl;
  656                                 nvp = tmpnvp;
  657                                 continue;
  658                         }
  659                         ptr = nvpair_pack_nvlist_up(ptr, &left);
  660                         break;
  661 #ifndef _KERNEL
  662                 case NV_TYPE_DESCRIPTOR:
  663                         ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
  664                         break;
  665 #endif
  666                 case NV_TYPE_BINARY:
  667                         ptr = nvpair_pack_binary(nvp, ptr, &left);
  668                         break;
  669                 default:
  670                         PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
  671                 }
  672                 if (ptr == NULL) {
  673                         nv_free(buf);
  674                         return (NULL);
  675                 }
  676                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
  677                         cookie = NULL;
  678                         nvl = nvlist_get_parent(nvl, &cookie);
  679                         if (nvl == NULL)
  680                                 goto out;
  681                         nvp = cookie;
  682                         ptr = nvpair_pack_nvlist_up(ptr, &left);
  683                         if (ptr == NULL)
  684                                 goto out;
  685                 }
  686         }
  687 
  688 out:
  689         if (sizep != NULL)
  690                 *sizep = size;
  691         return (buf);
  692 }
  693 
  694 void *
  695 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
  696 {
  697 
  698         NVLIST_ASSERT(nvl);
  699 
  700         if (nvl->nvl_error != 0) {
  701                 RESTORE_ERRNO(nvl->nvl_error);
  702                 return (NULL);
  703         }
  704 
  705         if (nvlist_ndescriptors(nvl) > 0) {
  706                 RESTORE_ERRNO(EOPNOTSUPP);
  707                 return (NULL);
  708         }
  709 
  710         return (nvlist_xpack(nvl, NULL, sizep));
  711 }
  712 
  713 static bool
  714 nvlist_check_header(struct nvlist_header *nvlhdrp)
  715 {
  716 
  717         if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
  718                 RESTORE_ERRNO(EINVAL);
  719                 return (false);
  720         }
  721         if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
  722                 RESTORE_ERRNO(EINVAL);
  723                 return (false);
  724         }
  725 #if BYTE_ORDER == BIG_ENDIAN
  726         if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
  727                 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
  728                 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
  729         }
  730 #else
  731         if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
  732                 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
  733                 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
  734         }
  735 #endif
  736         return (true);
  737 }
  738 
  739 const unsigned char *
  740 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
  741     bool *isbep, size_t *leftp)
  742 {
  743         struct nvlist_header nvlhdr;
  744 
  745         if (*leftp < sizeof(nvlhdr))
  746                 goto failed;
  747 
  748         memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
  749 
  750         if (!nvlist_check_header(&nvlhdr))
  751                 goto failed;
  752 
  753         if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
  754                 goto failed;
  755 
  756         /*
  757          * nvlh_descriptors might be smaller than nfds in embedded nvlists.
  758          */
  759         if (nvlhdr.nvlh_descriptors > nfds)
  760                 goto failed;
  761 
  762         if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
  763                 goto failed;
  764 
  765         nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
  766 
  767         ptr += sizeof(nvlhdr);
  768         if (isbep != NULL)
  769                 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
  770         *leftp -= sizeof(nvlhdr);
  771 
  772         return (ptr);
  773 failed:
  774         RESTORE_ERRNO(EINVAL);
  775         return (NULL);
  776 }
  777 
  778 nvlist_t *
  779 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
  780 {
  781         const unsigned char *ptr;
  782         nvlist_t *nvl, *retnvl, *tmpnvl;
  783         nvpair_t *nvp;
  784         size_t left;
  785         bool isbe;
  786 
  787         left = size;
  788         ptr = buf;
  789 
  790         tmpnvl = NULL;
  791         nvl = retnvl = nvlist_create(0);
  792         if (nvl == NULL)
  793                 goto failed;
  794 
  795         ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
  796         if (ptr == NULL)
  797                 goto failed;
  798 
  799         while (left > 0) {
  800                 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
  801                 if (ptr == NULL)
  802                         goto failed;
  803                 switch (nvpair_type(nvp)) {
  804                 case NV_TYPE_NULL:
  805                         ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
  806                         break;
  807                 case NV_TYPE_BOOL:
  808                         ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
  809                         break;
  810                 case NV_TYPE_NUMBER:
  811                         ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
  812                         break;
  813                 case NV_TYPE_STRING:
  814                         ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
  815                         break;
  816                 case NV_TYPE_NVLIST:
  817                         ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
  818                             &tmpnvl);
  819                         nvlist_set_parent(tmpnvl, nvp);
  820                         break;
  821 #ifndef _KERNEL
  822                 case NV_TYPE_DESCRIPTOR:
  823                         ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
  824                             fds, nfds);
  825                         break;
  826 #endif
  827                 case NV_TYPE_BINARY:
  828                         ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
  829                         break;
  830                 case NV_TYPE_NVLIST_UP:
  831                         if (nvl->nvl_parent == NULL)
  832                                 goto failed;
  833                         nvl = nvpair_nvlist(nvl->nvl_parent);
  834                         continue;
  835                 default:
  836                         PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
  837                 }
  838                 if (ptr == NULL)
  839                         goto failed;
  840                 nvlist_move_nvpair(nvl, nvp);
  841                 if (tmpnvl != NULL) {
  842                         nvl = tmpnvl;
  843                         tmpnvl = NULL;
  844                 }
  845         }
  846 
  847         return (retnvl);
  848 failed:
  849         nvlist_destroy(retnvl);
  850         return (NULL);
  851 }
  852 
  853 nvlist_t *
  854 nvlist_unpack(const void *buf, size_t size)
  855 {
  856 
  857         return (nvlist_xunpack(buf, size, NULL, 0));
  858 }
  859 
  860 #ifndef _KERNEL
  861 int
  862 nvlist_send(int sock, const nvlist_t *nvl)
  863 {
  864         size_t datasize, nfds;
  865         int *fds;
  866         void *data;
  867         int64_t fdidx;
  868         int serrno, ret;
  869 
  870         if (nvlist_error(nvl) != 0) {
  871                 errno = nvlist_error(nvl);
  872                 return (-1);
  873         }
  874 
  875         fds = nvlist_descriptors(nvl, &nfds);
  876         if (fds == NULL)
  877                 return (-1);
  878 
  879         ret = -1;
  880         data = NULL;
  881         fdidx = 0;
  882 
  883         data = nvlist_xpack(nvl, &fdidx, &datasize);
  884         if (data == NULL)
  885                 goto out;
  886 
  887         if (buf_send(sock, data, datasize) == -1)
  888                 goto out;
  889 
  890         if (nfds > 0) {
  891                 if (fd_send(sock, fds, nfds) == -1)
  892                         goto out;
  893         }
  894 
  895         ret = 0;
  896 out:
  897         serrno = errno;
  898         free(fds);
  899         free(data);
  900         errno = serrno;
  901         return (ret);
  902 }
  903 
  904 nvlist_t *
  905 nvlist_recv(int sock)
  906 {
  907         struct nvlist_header nvlhdr;
  908         nvlist_t *nvl, *ret;
  909         unsigned char *buf;
  910         size_t nfds, size, i;
  911         int serrno, *fds;
  912 
  913         if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
  914                 return (NULL);
  915 
  916         if (!nvlist_check_header(&nvlhdr))
  917                 return (NULL);
  918 
  919         nfds = (size_t)nvlhdr.nvlh_descriptors;
  920         size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
  921 
  922         buf = malloc(size);
  923         if (buf == NULL)
  924                 return (NULL);
  925 
  926         memcpy(buf, &nvlhdr, sizeof(nvlhdr));
  927 
  928         ret = NULL;
  929         fds = NULL;
  930 
  931         if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
  932                 goto out;
  933 
  934         if (nfds > 0) {
  935                 fds = malloc(nfds * sizeof(fds[0]));
  936                 if (fds == NULL)
  937                         goto out;
  938                 if (fd_recv(sock, fds, nfds) == -1)
  939                         goto out;
  940         }
  941 
  942         nvl = nvlist_xunpack(buf, size, fds, nfds);
  943         if (nvl == NULL) {
  944                 for (i = 0; i < nfds; i++)
  945                         close(fds[i]);
  946                 goto out;
  947         }
  948 
  949         ret = nvl;
  950 out:
  951         serrno = errno;
  952         free(buf);
  953         free(fds);
  954         errno = serrno;
  955 
  956         return (ret);
  957 }
  958 
  959 nvlist_t *
  960 nvlist_xfer(int sock, nvlist_t *nvl)
  961 {
  962 
  963         if (nvlist_send(sock, nvl) < 0) {
  964                 nvlist_destroy(nvl);
  965                 return (NULL);
  966         }
  967         nvlist_destroy(nvl);
  968         return (nvlist_recv(sock));
  969 }
  970 #endif
  971 
  972 nvpair_t *
  973 nvlist_first_nvpair(const nvlist_t *nvl)
  974 {
  975 
  976         NVLIST_ASSERT(nvl);
  977 
  978         return (TAILQ_FIRST(&nvl->nvl_head));
  979 }
  980 
  981 nvpair_t *
  982 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
  983 {
  984         nvpair_t *retnvp;
  985 
  986         NVLIST_ASSERT(nvl);
  987         NVPAIR_ASSERT(nvp);
  988         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
  989 
  990         retnvp = nvpair_next(nvp);
  991         PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
  992 
  993         return (retnvp);
  994 
  995 }
  996 
  997 nvpair_t *
  998 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
  999 {
 1000         nvpair_t *retnvp;
 1001 
 1002         NVLIST_ASSERT(nvl);
 1003         NVPAIR_ASSERT(nvp);
 1004         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
 1005 
 1006         retnvp = nvpair_prev(nvp);
 1007         PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
 1008 
 1009         return (retnvp);
 1010 }
 1011 
 1012 const char *
 1013 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
 1014 {
 1015         nvpair_t *nvp;
 1016 
 1017         NVLIST_ASSERT(nvl);
 1018         PJDLOG_ASSERT(cookiep != NULL);
 1019 
 1020         if (*cookiep == NULL)
 1021                 nvp = nvlist_first_nvpair(nvl);
 1022         else
 1023                 nvp = nvlist_next_nvpair(nvl, *cookiep);
 1024         if (nvp == NULL)
 1025                 return (NULL);
 1026         if (typep != NULL)
 1027                 *typep = nvpair_type(nvp);
 1028         *cookiep = nvp;
 1029         return (nvpair_name(nvp));
 1030 }
 1031 
 1032 bool
 1033 nvlist_exists(const nvlist_t *nvl, const char *name)
 1034 {
 1035 
 1036         return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
 1037 }
 1038 
 1039 #define NVLIST_EXISTS(type, TYPE)                                       \
 1040 bool                                                                    \
 1041 nvlist_exists_##type(const nvlist_t *nvl, const char *name)             \
 1042 {                                                                       \
 1043                                                                         \
 1044         return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL);        \
 1045 }
 1046 
 1047 NVLIST_EXISTS(null, NULL)
 1048 NVLIST_EXISTS(bool, BOOL)
 1049 NVLIST_EXISTS(number, NUMBER)
 1050 NVLIST_EXISTS(string, STRING)
 1051 NVLIST_EXISTS(nvlist, NVLIST)
 1052 #ifndef _KERNEL
 1053 NVLIST_EXISTS(descriptor, DESCRIPTOR)
 1054 #endif
 1055 NVLIST_EXISTS(binary, BINARY)
 1056 
 1057 #undef  NVLIST_EXISTS
 1058 
 1059 void
 1060 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
 1061 {
 1062         nvpair_t *newnvp;
 1063 
 1064         NVPAIR_ASSERT(nvp);
 1065 
 1066         if (nvlist_error(nvl) != 0) {
 1067                 RESTORE_ERRNO(nvlist_error(nvl));
 1068                 return;
 1069         }
 1070         if (nvlist_exists(nvl, nvpair_name(nvp))) {
 1071                 nvl->nvl_error = EEXIST;
 1072                 RESTORE_ERRNO(nvlist_error(nvl));
 1073                 return;
 1074         }
 1075 
 1076         newnvp = nvpair_clone(nvp);
 1077         if (newnvp == NULL) {
 1078                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1079                 RESTORE_ERRNO(nvlist_error(nvl));
 1080                 return;
 1081         }
 1082 
 1083         nvpair_insert(&nvl->nvl_head, newnvp, nvl);
 1084 }
 1085 
 1086 void
 1087 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
 1088 {
 1089         va_list valueap;
 1090 
 1091         va_start(valueap, valuefmt);
 1092         nvlist_add_stringv(nvl, name, valuefmt, valueap);
 1093         va_end(valueap);
 1094 }
 1095 
 1096 void
 1097 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
 1098     va_list valueap)
 1099 {
 1100         nvpair_t *nvp;
 1101 
 1102         if (nvlist_error(nvl) != 0) {
 1103                 RESTORE_ERRNO(nvlist_error(nvl));
 1104                 return;
 1105         }
 1106 
 1107         nvp = nvpair_create_stringv(name, valuefmt, valueap);
 1108         if (nvp == NULL) {
 1109                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1110                 RESTORE_ERRNO(nvl->nvl_error);
 1111         } else
 1112                 nvlist_move_nvpair(nvl, nvp);
 1113 }
 1114 
 1115 void
 1116 nvlist_add_null(nvlist_t *nvl, const char *name)
 1117 {
 1118         nvpair_t *nvp;
 1119 
 1120         if (nvlist_error(nvl) != 0) {
 1121                 RESTORE_ERRNO(nvlist_error(nvl));
 1122                 return;
 1123         }
 1124 
 1125         nvp = nvpair_create_null(name);
 1126         if (nvp == NULL) {
 1127                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1128                 RESTORE_ERRNO(nvl->nvl_error);
 1129         } else
 1130                 nvlist_move_nvpair(nvl, nvp);
 1131 }
 1132 
 1133 void
 1134 nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
 1135 {
 1136         nvpair_t *nvp;
 1137 
 1138         if (nvlist_error(nvl) != 0) {
 1139                 RESTORE_ERRNO(nvlist_error(nvl));
 1140                 return;
 1141         }
 1142 
 1143         nvp = nvpair_create_bool(name, value);
 1144         if (nvp == NULL) {
 1145                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1146                 RESTORE_ERRNO(nvl->nvl_error);
 1147         } else
 1148                 nvlist_move_nvpair(nvl, nvp);
 1149 }
 1150 
 1151 void
 1152 nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
 1153 {
 1154         nvpair_t *nvp;
 1155 
 1156         if (nvlist_error(nvl) != 0) {
 1157                 RESTORE_ERRNO(nvlist_error(nvl));
 1158                 return;
 1159         }
 1160 
 1161         nvp = nvpair_create_number(name, value);
 1162         if (nvp == NULL) {
 1163                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1164                 RESTORE_ERRNO(nvl->nvl_error);
 1165         } else
 1166                 nvlist_move_nvpair(nvl, nvp);
 1167 }
 1168 
 1169 void
 1170 nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
 1171 {
 1172         nvpair_t *nvp;
 1173 
 1174         if (nvlist_error(nvl) != 0) {
 1175                 RESTORE_ERRNO(nvlist_error(nvl));
 1176                 return;
 1177         }
 1178 
 1179         nvp = nvpair_create_string(name, value);
 1180         if (nvp == NULL) {
 1181                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1182                 RESTORE_ERRNO(nvl->nvl_error);
 1183         } else
 1184                 nvlist_move_nvpair(nvl, nvp);
 1185 }
 1186 
 1187 void
 1188 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
 1189 {
 1190         nvpair_t *nvp;
 1191 
 1192         if (nvlist_error(nvl) != 0) {
 1193                 RESTORE_ERRNO(nvlist_error(nvl));
 1194                 return;
 1195         }
 1196 
 1197         nvp = nvpair_create_nvlist(name, value);
 1198         if (nvp == NULL) {
 1199                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1200                 RESTORE_ERRNO(nvl->nvl_error);
 1201         } else
 1202                 nvlist_move_nvpair(nvl, nvp);
 1203 }
 1204 
 1205 #ifndef _KERNEL
 1206 void
 1207 nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
 1208 {
 1209         nvpair_t *nvp;
 1210 
 1211         if (nvlist_error(nvl) != 0) {
 1212                 errno = nvlist_error(nvl);
 1213                 return;
 1214         }
 1215 
 1216         nvp = nvpair_create_descriptor(name, value);
 1217         if (nvp == NULL)
 1218                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
 1219         else
 1220                 nvlist_move_nvpair(nvl, nvp);
 1221 }
 1222 #endif
 1223 
 1224 void
 1225 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
 1226     size_t size)
 1227 {
 1228         nvpair_t *nvp;
 1229 
 1230         if (nvlist_error(nvl) != 0) {
 1231                 RESTORE_ERRNO(nvlist_error(nvl));
 1232                 return;
 1233         }
 1234 
 1235         nvp = nvpair_create_binary(name, value, size);
 1236         if (nvp == NULL) {
 1237                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1238                 RESTORE_ERRNO(nvl->nvl_error);
 1239         } else
 1240                 nvlist_move_nvpair(nvl, nvp);
 1241 }
 1242 
 1243 void
 1244 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
 1245 {
 1246 
 1247         NVPAIR_ASSERT(nvp);
 1248         PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
 1249 
 1250         if (nvlist_error(nvl) != 0) {
 1251                 nvpair_free(nvp);
 1252                 RESTORE_ERRNO(nvlist_error(nvl));
 1253                 return;
 1254         }
 1255         if (nvlist_exists(nvl, nvpair_name(nvp))) {
 1256                 nvpair_free(nvp);
 1257                 nvl->nvl_error = EEXIST;
 1258                 RESTORE_ERRNO(nvl->nvl_error);
 1259                 return;
 1260         }
 1261 
 1262         nvpair_insert(&nvl->nvl_head, nvp, nvl);
 1263 }
 1264 
 1265 void
 1266 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
 1267 {
 1268         nvpair_t *nvp;
 1269 
 1270         if (nvlist_error(nvl) != 0) {
 1271                 nv_free(value);
 1272                 RESTORE_ERRNO(nvlist_error(nvl));
 1273                 return;
 1274         }
 1275 
 1276         nvp = nvpair_move_string(name, value);
 1277         if (nvp == NULL) {
 1278                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1279                 RESTORE_ERRNO(nvl->nvl_error);
 1280         } else
 1281                 nvlist_move_nvpair(nvl, nvp);
 1282 }
 1283 
 1284 void
 1285 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
 1286 {
 1287         nvpair_t *nvp;
 1288 
 1289         if (nvlist_error(nvl) != 0) {
 1290                 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
 1291                         nvlist_destroy(value);
 1292                 RESTORE_ERRNO(nvlist_error(nvl));
 1293                 return;
 1294         }
 1295 
 1296         nvp = nvpair_move_nvlist(name, value);
 1297         if (nvp == NULL) {
 1298                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1299                 RESTORE_ERRNO(nvl->nvl_error);
 1300         } else
 1301                 nvlist_move_nvpair(nvl, nvp);
 1302 }
 1303 
 1304 #ifndef _KERNEL
 1305 void
 1306 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
 1307 {
 1308         nvpair_t *nvp;
 1309 
 1310         if (nvlist_error(nvl) != 0) {
 1311                 close(value);
 1312                 errno = nvlist_error(nvl);
 1313                 return;
 1314         }
 1315 
 1316         nvp = nvpair_move_descriptor(name, value);
 1317         if (nvp == NULL)
 1318                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
 1319         else
 1320                 nvlist_move_nvpair(nvl, nvp);
 1321 }
 1322 #endif
 1323 
 1324 void
 1325 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
 1326 {
 1327         nvpair_t *nvp;
 1328 
 1329         if (nvlist_error(nvl) != 0) {
 1330                 nv_free(value);
 1331                 RESTORE_ERRNO(nvlist_error(nvl));
 1332                 return;
 1333         }
 1334 
 1335         nvp = nvpair_move_binary(name, value, size);
 1336         if (nvp == NULL) {
 1337                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
 1338                 RESTORE_ERRNO(nvl->nvl_error);
 1339         } else
 1340                 nvlist_move_nvpair(nvl, nvp);
 1341 }
 1342 
 1343 const nvpair_t *
 1344 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
 1345 {
 1346 
 1347         return (nvlist_find(nvl, NV_TYPE_NONE, name));
 1348 }
 1349 
 1350 #define NVLIST_GET(ftype, type, TYPE)                                   \
 1351 ftype                                                                   \
 1352 nvlist_get_##type(const nvlist_t *nvl, const char *name)                \
 1353 {                                                                       \
 1354         const nvpair_t *nvp;                                            \
 1355                                                                         \
 1356         nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);                   \
 1357         if (nvp == NULL)                                                \
 1358                 nvlist_report_missing(NV_TYPE_##TYPE, name);            \
 1359         return (nvpair_get_##type(nvp));                                \
 1360 }
 1361 
 1362 NVLIST_GET(bool, bool, BOOL)
 1363 NVLIST_GET(uint64_t, number, NUMBER)
 1364 NVLIST_GET(const char *, string, STRING)
 1365 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
 1366 #ifndef _KERNEL
 1367 NVLIST_GET(int, descriptor, DESCRIPTOR)
 1368 #endif
 1369 
 1370 #undef  NVLIST_GET
 1371 
 1372 const void *
 1373 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
 1374 {
 1375         nvpair_t *nvp;
 1376 
 1377         nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
 1378         if (nvp == NULL)
 1379                 nvlist_report_missing(NV_TYPE_BINARY, name);
 1380 
 1381         return (nvpair_get_binary(nvp, sizep));
 1382 }
 1383 
 1384 #define NVLIST_TAKE(ftype, type, TYPE)                                  \
 1385 ftype                                                                   \
 1386 nvlist_take_##type(nvlist_t *nvl, const char *name)                     \
 1387 {                                                                       \
 1388         nvpair_t *nvp;                                                  \
 1389         ftype value;                                                    \
 1390                                                                         \
 1391         nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);                   \
 1392         if (nvp == NULL)                                                \
 1393                 nvlist_report_missing(NV_TYPE_##TYPE, name);            \
 1394         value = (ftype)(intptr_t)nvpair_get_##type(nvp);                \
 1395         nvlist_remove_nvpair(nvl, nvp);                                 \
 1396         nvpair_free_structure(nvp);                                     \
 1397         return (value);                                                 \
 1398 }
 1399 
 1400 NVLIST_TAKE(bool, bool, BOOL)
 1401 NVLIST_TAKE(uint64_t, number, NUMBER)
 1402 NVLIST_TAKE(char *, string, STRING)
 1403 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
 1404 #ifndef _KERNEL
 1405 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
 1406 #endif
 1407 
 1408 #undef  NVLIST_TAKE
 1409 
 1410 void *
 1411 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
 1412 {
 1413         nvpair_t *nvp;
 1414         void *value;
 1415 
 1416         nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
 1417         if (nvp == NULL)
 1418                 nvlist_report_missing(NV_TYPE_BINARY, name);
 1419 
 1420         value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
 1421         nvlist_remove_nvpair(nvl, nvp);
 1422         nvpair_free_structure(nvp);
 1423         return (value);
 1424 }
 1425 
 1426 void
 1427 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
 1428 {
 1429 
 1430         NVLIST_ASSERT(nvl);
 1431         NVPAIR_ASSERT(nvp);
 1432         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
 1433 
 1434         nvpair_remove(&nvl->nvl_head, nvp, nvl);
 1435 }
 1436 
 1437 void
 1438 nvlist_free(nvlist_t *nvl, const char *name)
 1439 {
 1440 
 1441         nvlist_free_type(nvl, name, NV_TYPE_NONE);
 1442 }
 1443 
 1444 #define NVLIST_FREE(type, TYPE)                                         \
 1445 void                                                                    \
 1446 nvlist_free_##type(nvlist_t *nvl, const char *name)                     \
 1447 {                                                                       \
 1448                                                                         \
 1449         nvlist_free_type(nvl, name, NV_TYPE_##TYPE);                    \
 1450 }
 1451 
 1452 NVLIST_FREE(null, NULL)
 1453 NVLIST_FREE(bool, BOOL)
 1454 NVLIST_FREE(number, NUMBER)
 1455 NVLIST_FREE(string, STRING)
 1456 NVLIST_FREE(nvlist, NVLIST)
 1457 #ifndef _KERNEL
 1458 NVLIST_FREE(descriptor, DESCRIPTOR)
 1459 #endif
 1460 NVLIST_FREE(binary, BINARY)
 1461 
 1462 #undef  NVLIST_FREE
 1463 
 1464 void
 1465 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
 1466 {
 1467 
 1468         NVLIST_ASSERT(nvl);
 1469         NVPAIR_ASSERT(nvp);
 1470         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
 1471 
 1472         nvlist_remove_nvpair(nvl, nvp);
 1473         nvpair_free(nvp);
 1474 }
 1475 

Cache object: 31024be4a2e26fc5eb7ee93ad9440d97


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