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/bsd_nvpair.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/lock.h>
   44 #include <sys/malloc.h>
   45 #include <sys/systm.h>
   46 
   47 #include <machine/stdarg.h>
   48 
   49 #else
   50 #include <errno.h>
   51 #include <fcntl.h>
   52 #include <stdarg.h>
   53 #include <stdbool.h>
   54 #include <stdint.h>
   55 #include <stdlib.h>
   56 #include <string.h>
   57 #include <unistd.h>
   58 
   59 #include "common_impl.h"
   60 #endif
   61 
   62 #ifdef HAVE_PJDLOG
   63 #include <pjdlog.h>
   64 #endif
   65 
   66 #include <sys/nv.h>
   67 
   68 #include "nv_impl.h"
   69 #include "nvlist_impl.h"
   70 #include "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(...)               abort()
   82 #endif
   83 #endif
   84 
   85 #define NVPAIR_MAGIC    0x6e7670        /* "nvp" */
   86 struct nvpair {
   87         int              nvp_magic;
   88         char            *nvp_name;
   89         int              nvp_type;
   90         uint64_t         nvp_data;
   91         size_t           nvp_datasize;
   92         size_t           nvp_nitems;    /* Used only for array types. */
   93         nvlist_t        *nvp_list;
   94         TAILQ_ENTRY(nvpair) nvp_next;
   95 };
   96 
   97 #define NVPAIR_ASSERT(nvp)      do {                                    \
   98         PJDLOG_ASSERT((nvp) != NULL);                                   \
   99         PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC);                \
  100 } while (0)
  101 
  102 struct nvpair_header {
  103         uint8_t         nvph_type;
  104         uint16_t        nvph_namesize;
  105         uint64_t        nvph_datasize;
  106         uint64_t        nvph_nitems;
  107 } __packed;
  108 
  109 
  110 void
  111 nvpair_assert(const nvpair_t *nvp __unused)
  112 {
  113 
  114         NVPAIR_ASSERT(nvp);
  115 }
  116 
  117 static nvpair_t *
  118 nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize,
  119     size_t nitems)
  120 {
  121         nvpair_t *nvp;
  122         size_t namelen;
  123 
  124         PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
  125 
  126         namelen = strlen(name);
  127         if (namelen >= NV_NAME_MAX) {
  128                 ERRNO_SET(ENAMETOOLONG);
  129                 return (NULL);
  130         }
  131 
  132         nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
  133         if (nvp != NULL) {
  134                 nvp->nvp_name = (char *)(nvp + 1);
  135                 memcpy(nvp->nvp_name, name, namelen);
  136                 nvp->nvp_name[namelen] = '\0';
  137                 nvp->nvp_type = type;
  138                 nvp->nvp_data = data;
  139                 nvp->nvp_datasize = datasize;
  140                 nvp->nvp_nitems = nitems;
  141                 nvp->nvp_magic = NVPAIR_MAGIC;
  142         }
  143 
  144         return (nvp);
  145 }
  146 
  147 static int
  148 nvpair_append(nvpair_t *nvp, const void *value, size_t valsize, size_t datasize)
  149 {
  150         void *olddata, *data, *valp;
  151         size_t oldlen;
  152 
  153         oldlen = nvp->nvp_nitems * valsize;
  154         olddata = (void *)(uintptr_t)nvp->nvp_data;
  155         data = nv_realloc(olddata, oldlen + valsize);
  156         if (data == NULL) {
  157                 ERRNO_SET(ENOMEM);
  158                 return (-1);
  159         }
  160         valp = (unsigned char *)data + oldlen;
  161         memcpy(valp, value, valsize);
  162 
  163         nvp->nvp_data = (uint64_t)(uintptr_t)data;
  164         nvp->nvp_datasize += datasize;
  165         nvp->nvp_nitems++;
  166         return (0);
  167 }
  168 
  169 nvlist_t *
  170 nvpair_nvlist(const nvpair_t *nvp)
  171 {
  172 
  173         NVPAIR_ASSERT(nvp);
  174 
  175         return (nvp->nvp_list);
  176 }
  177 
  178 nvpair_t *
  179 nvpair_next(const nvpair_t *nvp)
  180 {
  181 
  182         NVPAIR_ASSERT(nvp);
  183         PJDLOG_ASSERT(nvp->nvp_list != NULL);
  184 
  185         return (TAILQ_NEXT(nvp, nvp_next));
  186 }
  187 
  188 nvpair_t *
  189 nvpair_prev(const nvpair_t *nvp)
  190 {
  191 
  192         NVPAIR_ASSERT(nvp);
  193         PJDLOG_ASSERT(nvp->nvp_list != NULL);
  194 
  195         return (TAILQ_PREV(nvp, nvl_head, nvp_next));
  196 }
  197 
  198 void
  199 nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
  200 {
  201 
  202         NVPAIR_ASSERT(nvp);
  203         PJDLOG_ASSERT(nvp->nvp_list == NULL);
  204         PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 ||
  205             !nvlist_exists(nvl, nvpair_name(nvp)));
  206 
  207         TAILQ_INSERT_TAIL(head, nvp, nvp_next);
  208         nvp->nvp_list = nvl;
  209 }
  210 
  211 static void
  212 nvpair_remove_nvlist(nvpair_t *nvp)
  213 {
  214         nvlist_t *nvl;
  215 
  216         /* XXX: DECONST is bad, mkay? */
  217         nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
  218         PJDLOG_ASSERT(nvl != NULL);
  219         nvlist_set_parent(nvl, NULL);
  220 }
  221 
  222 static void
  223 nvpair_remove_nvlist_array(nvpair_t *nvp)
  224 {
  225         nvlist_t **nvlarray;
  226         size_t count, i;
  227 
  228         /* XXX: DECONST is bad, mkay? */
  229         nvlarray = __DECONST(nvlist_t **,
  230             nvpair_get_nvlist_array(nvp, &count));
  231         for (i = 0; i < count; i++) {
  232                 nvlist_set_array_next(nvlarray[i], NULL);
  233                 nvlist_set_parent(nvlarray[i], NULL);
  234         }
  235 }
  236 
  237 void
  238 nvpair_remove(struct nvl_head *head, nvpair_t *nvp,
  239     const nvlist_t *nvl __unused)
  240 {
  241 
  242         NVPAIR_ASSERT(nvp);
  243         PJDLOG_ASSERT(nvp->nvp_list == nvl);
  244 
  245         if (nvpair_type(nvp) == NV_TYPE_NVLIST)
  246                 nvpair_remove_nvlist(nvp);
  247         else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY)
  248                 nvpair_remove_nvlist_array(nvp);
  249 
  250         TAILQ_REMOVE(head, nvp, nvp_next);
  251         nvp->nvp_list = NULL;
  252 }
  253 
  254 nvpair_t *
  255 nvpair_clone(const nvpair_t *nvp)
  256 {
  257         nvpair_t *newnvp;
  258         const char *name;
  259         const void *data;
  260         size_t datasize;
  261 
  262         NVPAIR_ASSERT(nvp);
  263 
  264         name = nvpair_name(nvp);
  265 
  266         switch (nvpair_type(nvp)) {
  267         case NV_TYPE_NULL:
  268                 newnvp = nvpair_create_null(name);
  269                 break;
  270         case NV_TYPE_BOOL:
  271                 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
  272                 break;
  273         case NV_TYPE_NUMBER:
  274                 newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
  275                 break;
  276         case NV_TYPE_STRING:
  277                 newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
  278                 break;
  279         case NV_TYPE_NVLIST:
  280                 newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
  281                 break;
  282         case NV_TYPE_BINARY:
  283                 data = nvpair_get_binary(nvp, &datasize);
  284                 newnvp = nvpair_create_binary(name, data, datasize);
  285                 break;
  286         case NV_TYPE_BOOL_ARRAY:
  287                 data = nvpair_get_bool_array(nvp, &datasize);
  288                 newnvp = nvpair_create_bool_array(name, data, datasize);
  289                 break;
  290         case NV_TYPE_NUMBER_ARRAY:
  291                 data = nvpair_get_number_array(nvp, &datasize);
  292                 newnvp = nvpair_create_number_array(name, data, datasize);
  293                 break;
  294         case NV_TYPE_STRING_ARRAY:
  295                 data = nvpair_get_string_array(nvp, &datasize);
  296                 newnvp = nvpair_create_string_array(name, data, datasize);
  297                 break;
  298         case NV_TYPE_NVLIST_ARRAY:
  299                 data = nvpair_get_nvlist_array(nvp, &datasize);
  300                 newnvp = nvpair_create_nvlist_array(name, data, datasize);
  301                 break;
  302 #ifndef _KERNEL
  303         case NV_TYPE_DESCRIPTOR:
  304                 newnvp = nvpair_create_descriptor(name,
  305                     nvpair_get_descriptor(nvp));
  306                 break;
  307         case NV_TYPE_DESCRIPTOR_ARRAY:
  308                 data = nvpair_get_descriptor_array(nvp, &datasize);
  309                 newnvp = nvpair_create_descriptor_array(name, data, datasize);
  310                 break;
  311 #endif
  312         default:
  313                 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
  314         }
  315 
  316         return (newnvp);
  317 }
  318 
  319 size_t
  320 nvpair_header_size(void)
  321 {
  322 
  323         return (sizeof(struct nvpair_header));
  324 }
  325 
  326 size_t
  327 nvpair_size(const nvpair_t *nvp)
  328 {
  329 
  330         NVPAIR_ASSERT(nvp);
  331 
  332         return (nvp->nvp_datasize);
  333 }
  334 
  335 unsigned char *
  336 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  337 {
  338         struct nvpair_header nvphdr;
  339         size_t namesize;
  340 
  341         NVPAIR_ASSERT(nvp);
  342 
  343         nvphdr.nvph_type = nvp->nvp_type;
  344         namesize = strlen(nvp->nvp_name) + 1;
  345         PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
  346         nvphdr.nvph_namesize = namesize;
  347         nvphdr.nvph_datasize = nvp->nvp_datasize;
  348         nvphdr.nvph_nitems = nvp->nvp_nitems;
  349         PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
  350         memcpy(ptr, &nvphdr, sizeof(nvphdr));
  351         ptr += sizeof(nvphdr);
  352         *leftp -= sizeof(nvphdr);
  353 
  354         PJDLOG_ASSERT(*leftp >= namesize);
  355         memcpy(ptr, nvp->nvp_name, namesize);
  356         ptr += namesize;
  357         *leftp -= namesize;
  358 
  359         return (ptr);
  360 }
  361 
  362 unsigned char *
  363 nvpair_pack_null(const nvpair_t *nvp __unused, unsigned char *ptr,
  364     size_t *leftp __unused)
  365 {
  366 
  367         NVPAIR_ASSERT(nvp);
  368         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
  369 
  370         return (ptr);
  371 }
  372 
  373 unsigned char *
  374 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  375 {
  376         uint8_t value;
  377 
  378         NVPAIR_ASSERT(nvp);
  379         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
  380 
  381         value = (uint8_t)nvp->nvp_data;
  382 
  383         PJDLOG_ASSERT(*leftp >= sizeof(value));
  384         memcpy(ptr, &value, sizeof(value));
  385         ptr += sizeof(value);
  386         *leftp -= sizeof(value);
  387 
  388         return (ptr);
  389 }
  390 
  391 unsigned char *
  392 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  393 {
  394         uint64_t value;
  395 
  396         NVPAIR_ASSERT(nvp);
  397         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
  398 
  399         value = (uint64_t)nvp->nvp_data;
  400 
  401         PJDLOG_ASSERT(*leftp >= sizeof(value));
  402         memcpy(ptr, &value, sizeof(value));
  403         ptr += sizeof(value);
  404         *leftp -= sizeof(value);
  405 
  406         return (ptr);
  407 }
  408 
  409 unsigned char *
  410 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  411 {
  412 
  413         NVPAIR_ASSERT(nvp);
  414         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
  415 
  416         PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
  417         memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
  418         ptr += nvp->nvp_datasize;
  419         *leftp -= nvp->nvp_datasize;
  420 
  421         return (ptr);
  422 }
  423 
  424 unsigned char *
  425 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
  426 {
  427         struct nvpair_header nvphdr;
  428         size_t namesize;
  429         const char *name = "";
  430 
  431         namesize = 1;
  432         nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
  433         nvphdr.nvph_namesize = namesize;
  434         nvphdr.nvph_datasize = 0;
  435         nvphdr.nvph_nitems = 0;
  436         PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
  437         memcpy(ptr, &nvphdr, sizeof(nvphdr));
  438         ptr += sizeof(nvphdr);
  439         *leftp -= sizeof(nvphdr);
  440 
  441         PJDLOG_ASSERT(*leftp >= namesize);
  442         memcpy(ptr, name, namesize);
  443         ptr += namesize;
  444         *leftp -= namesize;
  445 
  446         return (ptr);
  447 }
  448 
  449 unsigned char *
  450 nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp)
  451 {
  452         struct nvpair_header nvphdr;
  453         size_t namesize;
  454         const char *name = "";
  455 
  456         namesize = 1;
  457         nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT;
  458         nvphdr.nvph_namesize = namesize;
  459         nvphdr.nvph_datasize = 0;
  460         nvphdr.nvph_nitems = 0;
  461         PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
  462         memcpy(ptr, &nvphdr, sizeof(nvphdr));
  463         ptr += sizeof(nvphdr);
  464         *leftp -= sizeof(nvphdr);
  465 
  466         PJDLOG_ASSERT(*leftp >= namesize);
  467         memcpy(ptr, name, namesize);
  468         ptr += namesize;
  469         *leftp -= namesize;
  470 
  471         return (ptr);
  472 }
  473 
  474 #ifndef _KERNEL
  475 unsigned char *
  476 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
  477     size_t *leftp)
  478 {
  479         int64_t value;
  480 
  481         NVPAIR_ASSERT(nvp);
  482         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
  483 
  484         value = (int64_t)nvp->nvp_data;
  485         if (value != -1) {
  486                 /*
  487                  * If there is a real descriptor here, we change its number
  488                  * to position in the array of descriptors send via control
  489                  * message.
  490                  */
  491                 PJDLOG_ASSERT(fdidxp != NULL);
  492 
  493                 value = *fdidxp;
  494                 (*fdidxp)++;
  495         }
  496 
  497         PJDLOG_ASSERT(*leftp >= sizeof(value));
  498         memcpy(ptr, &value, sizeof(value));
  499         ptr += sizeof(value);
  500         *leftp -= sizeof(value);
  501 
  502         return (ptr);
  503 }
  504 #endif
  505 
  506 unsigned char *
  507 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  508 {
  509 
  510         NVPAIR_ASSERT(nvp);
  511         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
  512 
  513         PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
  514         memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
  515         ptr += nvp->nvp_datasize;
  516         *leftp -= nvp->nvp_datasize;
  517 
  518         return (ptr);
  519 }
  520 
  521 unsigned char *
  522 nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  523 {
  524 
  525         NVPAIR_ASSERT(nvp);
  526         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
  527         PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
  528 
  529         memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
  530         ptr += nvp->nvp_datasize;
  531         *leftp -= nvp->nvp_datasize;
  532 
  533         return (ptr);
  534 }
  535 
  536 unsigned char *
  537 nvpair_pack_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  538 {
  539 
  540         NVPAIR_ASSERT(nvp);
  541         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
  542         PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
  543 
  544         memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
  545         ptr += nvp->nvp_datasize;
  546         *leftp -= nvp->nvp_datasize;
  547 
  548         return (ptr);
  549 }
  550 
  551 unsigned char *
  552 nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  553 {
  554         unsigned int ii;
  555         size_t size __unused, len;
  556         const char * const *array;
  557 
  558         NVPAIR_ASSERT(nvp);
  559         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
  560         PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
  561 
  562         size = 0;
  563         array = nvpair_get_string_array(nvp, NULL);
  564         PJDLOG_ASSERT(array != NULL);
  565 
  566         for (ii = 0; ii < nvp->nvp_nitems; ii++) {
  567                 len = strlen(array[ii]) + 1;
  568                 PJDLOG_ASSERT(*leftp >= len);
  569 
  570                 memcpy(ptr, (const void *)array[ii], len);
  571                 size += len;
  572                 ptr += len;
  573                 *leftp -= len;
  574         }
  575 
  576         PJDLOG_ASSERT(size == nvp->nvp_datasize);
  577 
  578         return (ptr);
  579 }
  580 
  581 #ifndef _KERNEL
  582 unsigned char *
  583 nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr,
  584     int64_t *fdidxp, size_t *leftp)
  585 {
  586         int64_t value;
  587         const int *array;
  588         unsigned int ii;
  589 
  590         NVPAIR_ASSERT(nvp);
  591         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
  592         PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
  593 
  594         array = nvpair_get_descriptor_array(nvp, NULL);
  595         PJDLOG_ASSERT(array != NULL);
  596 
  597         for (ii = 0; ii < nvp->nvp_nitems; ii++) {
  598                 PJDLOG_ASSERT(*leftp >= sizeof(value));
  599 
  600                 value = array[ii];
  601                 if (value != -1) {
  602                         /*
  603                          * If there is a real descriptor here, we change its
  604                          * number to position in the array of descriptors send
  605                          * via control message.
  606                          */
  607                         PJDLOG_ASSERT(fdidxp != NULL);
  608 
  609                         value = *fdidxp;
  610                         (*fdidxp)++;
  611                 }
  612                 memcpy(ptr, &value, sizeof(value));
  613                 ptr += sizeof(value);
  614                 *leftp -= sizeof(value);
  615         }
  616 
  617         return (ptr);
  618 }
  619 #endif
  620 
  621 void
  622 nvpair_init_datasize(nvpair_t *nvp)
  623 {
  624 
  625         NVPAIR_ASSERT(nvp);
  626 
  627         if (nvp->nvp_type == NV_TYPE_NVLIST) {
  628                 if (nvp->nvp_data == 0) {
  629                         nvp->nvp_datasize = 0;
  630                 } else {
  631                         nvp->nvp_datasize =
  632                             nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
  633                 }
  634         }
  635 }
  636 
  637 const unsigned char *
  638 nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
  639     size_t *leftp)
  640 {
  641         struct nvpair_header nvphdr;
  642 
  643         if (*leftp < sizeof(nvphdr))
  644                 goto fail;
  645 
  646         memcpy(&nvphdr, ptr, sizeof(nvphdr));
  647         ptr += sizeof(nvphdr);
  648         *leftp -= sizeof(nvphdr);
  649 
  650 #if NV_TYPE_FIRST > 0
  651         if (nvphdr.nvph_type < NV_TYPE_FIRST)
  652                 goto fail;
  653 #endif
  654         if (nvphdr.nvph_type > NV_TYPE_LAST &&
  655             nvphdr.nvph_type != NV_TYPE_NVLIST_UP &&
  656             nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) {
  657                 goto fail;
  658         }
  659 
  660 #if BYTE_ORDER == BIG_ENDIAN
  661         if (!isbe) {
  662                 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
  663                 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
  664                 nvphdr.nvph_nitems = le64toh(nvphdr.nvph_nitems);
  665         }
  666 #else
  667         if (isbe) {
  668                 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
  669                 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
  670                 nvphdr.nvph_nitems = be64toh(nvphdr.nvph_nitems);
  671         }
  672 #endif
  673 
  674         if (nvphdr.nvph_namesize > NV_NAME_MAX)
  675                 goto fail;
  676         if (*leftp < nvphdr.nvph_namesize)
  677                 goto fail;
  678         if (nvphdr.nvph_namesize < 1)
  679                 goto fail;
  680         if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
  681             (size_t)(nvphdr.nvph_namesize - 1)) {
  682                 goto fail;
  683         }
  684 
  685         memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
  686         ptr += nvphdr.nvph_namesize;
  687         *leftp -= nvphdr.nvph_namesize;
  688 
  689         if (*leftp < nvphdr.nvph_datasize)
  690                 goto fail;
  691 
  692         nvp->nvp_type = nvphdr.nvph_type;
  693         nvp->nvp_data = 0;
  694         nvp->nvp_datasize = nvphdr.nvph_datasize;
  695         nvp->nvp_nitems = nvphdr.nvph_nitems;
  696 
  697         return (ptr);
  698 fail:
  699         ERRNO_SET(EINVAL);
  700         return (NULL);
  701 }
  702 
  703 const unsigned char *
  704 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
  705     size_t *leftp __unused)
  706 {
  707 
  708         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
  709 
  710         if (nvp->nvp_datasize != 0) {
  711                 ERRNO_SET(EINVAL);
  712                 return (NULL);
  713         }
  714 
  715         return (ptr);
  716 }
  717 
  718 const unsigned char *
  719 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
  720     size_t *leftp)
  721 {
  722         uint8_t value;
  723 
  724         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
  725 
  726         if (nvp->nvp_datasize != sizeof(value)) {
  727                 ERRNO_SET(EINVAL);
  728                 return (NULL);
  729         }
  730         if (*leftp < sizeof(value)) {
  731                 ERRNO_SET(EINVAL);
  732                 return (NULL);
  733         }
  734 
  735         memcpy(&value, ptr, sizeof(value));
  736         ptr += sizeof(value);
  737         *leftp -= sizeof(value);
  738 
  739         if (value != 0 && value != 1) {
  740                 ERRNO_SET(EINVAL);
  741                 return (NULL);
  742         }
  743 
  744         nvp->nvp_data = (uint64_t)value;
  745 
  746         return (ptr);
  747 }
  748 
  749 const unsigned char *
  750 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
  751      size_t *leftp)
  752 {
  753 
  754         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
  755 
  756         if (nvp->nvp_datasize != sizeof(uint64_t)) {
  757                 ERRNO_SET(EINVAL);
  758                 return (NULL);
  759         }
  760         if (*leftp < sizeof(uint64_t)) {
  761                 ERRNO_SET(EINVAL);
  762                 return (NULL);
  763         }
  764 
  765         if (isbe)
  766                 nvp->nvp_data = be64dec(ptr);
  767         else
  768                 nvp->nvp_data = le64dec(ptr);
  769 
  770         ptr += sizeof(uint64_t);
  771         *leftp -= sizeof(uint64_t);
  772 
  773         return (ptr);
  774 }
  775 
  776 const unsigned char *
  777 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
  778     const unsigned char *ptr, size_t *leftp)
  779 {
  780 
  781         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
  782 
  783         if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
  784                 ERRNO_SET(EINVAL);
  785                 return (NULL);
  786         }
  787 
  788         if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
  789             nvp->nvp_datasize - 1) {
  790                 ERRNO_SET(EINVAL);
  791                 return (NULL);
  792         }
  793 
  794         nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
  795         if (nvp->nvp_data == 0)
  796                 return (NULL);
  797 
  798         ptr += nvp->nvp_datasize;
  799         *leftp -= nvp->nvp_datasize;
  800 
  801         return (ptr);
  802 }
  803 
  804 const unsigned char *
  805 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
  806     const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
  807 {
  808         nvlist_t *value;
  809 
  810         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
  811 
  812         if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
  813                 ERRNO_SET(EINVAL);
  814                 return (NULL);
  815         }
  816 
  817         value = nvlist_create(0);
  818         if (value == NULL)
  819                 return (NULL);
  820 
  821         ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
  822         if (ptr == NULL)
  823                 return (NULL);
  824 
  825         nvp->nvp_data = (uint64_t)(uintptr_t)value;
  826         *child = value;
  827 
  828         return (ptr);
  829 }
  830 
  831 #ifndef _KERNEL
  832 const unsigned char *
  833 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
  834     size_t *leftp, const int *fds, size_t nfds)
  835 {
  836         int64_t idx;
  837 
  838         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
  839 
  840         if (nvp->nvp_datasize != sizeof(idx)) {
  841                 ERRNO_SET(EINVAL);
  842                 return (NULL);
  843         }
  844         if (*leftp < sizeof(idx)) {
  845                 ERRNO_SET(EINVAL);
  846                 return (NULL);
  847         }
  848 
  849         if (isbe)
  850                 idx = be64dec(ptr);
  851         else
  852                 idx = le64dec(ptr);
  853 
  854         if (idx < 0) {
  855                 ERRNO_SET(EINVAL);
  856                 return (NULL);
  857         }
  858 
  859         if ((size_t)idx >= nfds) {
  860                 ERRNO_SET(EINVAL);
  861                 return (NULL);
  862         }
  863 
  864         nvp->nvp_data = (uint64_t)fds[idx];
  865 
  866         ptr += sizeof(idx);
  867         *leftp -= sizeof(idx);
  868 
  869         return (ptr);
  870 }
  871 #endif
  872 
  873 const unsigned char *
  874 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
  875     const unsigned char *ptr, size_t *leftp)
  876 {
  877         void *value;
  878 
  879         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
  880 
  881         if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
  882                 ERRNO_SET(EINVAL);
  883                 return (NULL);
  884         }
  885 
  886         value = nv_malloc(nvp->nvp_datasize);
  887         if (value == NULL)
  888                 return (NULL);
  889 
  890         memcpy(value, ptr, nvp->nvp_datasize);
  891         ptr += nvp->nvp_datasize;
  892         *leftp -= nvp->nvp_datasize;
  893 
  894         nvp->nvp_data = (uint64_t)(uintptr_t)value;
  895 
  896         return (ptr);
  897 }
  898 
  899 const unsigned char *
  900 nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp,
  901     const unsigned char *ptr, size_t *leftp)
  902 {
  903         uint8_t *value;
  904         size_t size;
  905         unsigned int i;
  906 
  907         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
  908 
  909         size = sizeof(*value) * nvp->nvp_nitems;
  910         if (nvp->nvp_datasize != size || *leftp < size ||
  911             nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
  912                 ERRNO_SET(EINVAL);
  913                 return (NULL);
  914         }
  915 
  916         value = nv_malloc(size);
  917         if (value == NULL)
  918                 return (NULL);
  919 
  920         for (i = 0; i < nvp->nvp_nitems; i++) {
  921                 value[i] = *(const uint8_t *)ptr;
  922 
  923                 ptr += sizeof(*value);
  924                 *leftp -= sizeof(*value);
  925         }
  926 
  927         nvp->nvp_data = (uint64_t)(uintptr_t)value;
  928 
  929         return (ptr);
  930 }
  931 
  932 const unsigned char *
  933 nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
  934      size_t *leftp)
  935 {
  936         uint64_t *value;
  937         size_t size;
  938         unsigned int i;
  939 
  940         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
  941 
  942         size = sizeof(*value) * nvp->nvp_nitems;
  943         if (nvp->nvp_datasize != size || *leftp < size ||
  944             nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
  945                 ERRNO_SET(EINVAL);
  946                 return (NULL);
  947         }
  948 
  949         value = nv_malloc(size);
  950         if (value == NULL)
  951                 return (NULL);
  952 
  953         for (i = 0; i < nvp->nvp_nitems; i++) {
  954                 if (isbe)
  955                         value[i] = be64dec(ptr);
  956                 else
  957                         value[i] = le64dec(ptr);
  958 
  959                 ptr += sizeof(*value);
  960                 *leftp -= sizeof(*value);
  961         }
  962 
  963         nvp->nvp_data = (uint64_t)(uintptr_t)value;
  964 
  965         return (ptr);
  966 }
  967 
  968 const unsigned char *
  969 nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp,
  970     const unsigned char *ptr, size_t *leftp)
  971 {
  972         ssize_t size;
  973         size_t len;
  974         const char *tmp;
  975         char **value;
  976         unsigned int ii, j;
  977 
  978         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
  979 
  980         if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 ||
  981             nvp->nvp_nitems == 0) {
  982                 ERRNO_SET(EINVAL);
  983                 return (NULL);
  984         }
  985 
  986         size = nvp->nvp_datasize;
  987         tmp = (const char *)ptr;
  988         for (ii = 0; ii < nvp->nvp_nitems; ii++) {
  989                 len = strnlen(tmp, size - 1) + 1;
  990                 size -= len;
  991                 if (size < 0) {
  992                         ERRNO_SET(EINVAL);
  993                         return (NULL);
  994                 }
  995                 tmp += len;
  996         }
  997         if (size != 0) {
  998                 ERRNO_SET(EINVAL);
  999                 return (NULL);
 1000         }
 1001 
 1002         value = nv_malloc(sizeof(*value) * nvp->nvp_nitems);
 1003         if (value == NULL)
 1004                 return (NULL);
 1005 
 1006         for (ii = 0; ii < nvp->nvp_nitems; ii++) {
 1007                 value[ii] = nv_strdup((const char *)ptr);
 1008                 if (value[ii] == NULL)
 1009                         goto out;
 1010                 len = strlen(value[ii]) + 1;
 1011                 ptr += len;
 1012                 *leftp -= len;
 1013         }
 1014         nvp->nvp_data = (uint64_t)(uintptr_t)value;
 1015 
 1016         return (ptr);
 1017 out:
 1018         for (j = 0; j < ii; j++)
 1019                 nv_free(value[j]);
 1020         nv_free(value);
 1021         return (NULL);
 1022 }
 1023 
 1024 #ifndef _KERNEL
 1025 const unsigned char *
 1026 nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
 1027     const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
 1028 {
 1029         int64_t idx;
 1030         size_t size;
 1031         unsigned int ii;
 1032         int *array;
 1033 
 1034         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
 1035 
 1036         size = sizeof(idx) * nvp->nvp_nitems;
 1037         if (nvp->nvp_datasize != size || *leftp < size ||
 1038             nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
 1039                 ERRNO_SET(EINVAL);
 1040                 return (NULL);
 1041         }
 1042 
 1043         array = (int *)nv_malloc(size);
 1044         if (array == NULL)
 1045                 return (NULL);
 1046 
 1047         for (ii = 0; ii < nvp->nvp_nitems; ii++) {
 1048                 if (isbe)
 1049                         idx = be64dec(ptr);
 1050                 else
 1051                         idx = le64dec(ptr);
 1052 
 1053                 if (idx < 0) {
 1054                         ERRNO_SET(EINVAL);
 1055                         nv_free(array);
 1056                         return (NULL);
 1057                 }
 1058 
 1059                 if ((size_t)idx >= nfds) {
 1060                         ERRNO_SET(EINVAL);
 1061                         nv_free(array);
 1062                         return (NULL);
 1063                 }
 1064 
 1065                 array[ii] = (uint64_t)fds[idx];
 1066 
 1067                 ptr += sizeof(idx);
 1068                 *leftp -= sizeof(idx);
 1069         }
 1070 
 1071         nvp->nvp_data = (uint64_t)(uintptr_t)array;
 1072 
 1073         return (ptr);
 1074 }
 1075 #endif
 1076 
 1077 const unsigned char *
 1078 nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
 1079     const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
 1080 {
 1081         nvlist_t **value;
 1082         nvpair_t *tmpnvp;
 1083         unsigned int ii, j;
 1084         size_t sizeup;
 1085 
 1086         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
 1087 
 1088         sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
 1089         if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
 1090             sizeup > *leftp) {
 1091                 ERRNO_SET(EINVAL);
 1092                 return (NULL);
 1093         }
 1094 
 1095         value = nv_malloc(nvp->nvp_nitems * sizeof(*value));
 1096         if (value == NULL)
 1097                 return (NULL);
 1098 
 1099         for (ii = 0; ii < nvp->nvp_nitems; ii++) {
 1100                 value[ii] = nvlist_create(0);
 1101                 if (value[ii] == NULL)
 1102                         goto fail;
 1103                 if (ii > 0) {
 1104                         tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
 1105                             (uint64_t)(uintptr_t)value[ii], 0, 0);
 1106                         if (tmpnvp == NULL)
 1107                                 goto fail;
 1108                         nvlist_set_array_next(value[ii - 1], tmpnvp);
 1109                 }
 1110         }
 1111         nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
 1112 
 1113         nvp->nvp_data = (uint64_t)(uintptr_t)value;
 1114         *firstel = value[0];
 1115 
 1116         return (ptr);
 1117 fail:
 1118         ERRNO_SAVE();
 1119         for (j = 0; j <= ii; j++)
 1120                 nvlist_destroy(value[j]);
 1121         nv_free(value);
 1122         ERRNO_RESTORE();
 1123 
 1124         return (NULL);
 1125 }
 1126 
 1127 const unsigned char *
 1128 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
 1129     nvpair_t **nvpp)
 1130 {
 1131         nvpair_t *nvp, *tmp;
 1132 
 1133         nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
 1134         if (nvp == NULL)
 1135                 return (NULL);
 1136         nvp->nvp_name = (char *)(nvp + 1);
 1137 
 1138         ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
 1139         if (ptr == NULL)
 1140                 goto fail;
 1141         tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
 1142         if (tmp == NULL)
 1143                 goto fail;
 1144         nvp = tmp;
 1145 
 1146         /* Update nvp_name after realloc(). */
 1147         nvp->nvp_name = (char *)(nvp + 1);
 1148         nvp->nvp_data = 0x00;
 1149         nvp->nvp_magic = NVPAIR_MAGIC;
 1150         *nvpp = nvp;
 1151         return (ptr);
 1152 fail:
 1153         nv_free(nvp);
 1154         return (NULL);
 1155 }
 1156 
 1157 int
 1158 nvpair_type(const nvpair_t *nvp)
 1159 {
 1160 
 1161         NVPAIR_ASSERT(nvp);
 1162 
 1163         return (nvp->nvp_type);
 1164 }
 1165 
 1166 const char *
 1167 nvpair_name(const nvpair_t *nvp)
 1168 {
 1169 
 1170         NVPAIR_ASSERT(nvp);
 1171 
 1172         return (nvp->nvp_name);
 1173 }
 1174 
 1175 nvpair_t *
 1176 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
 1177 {
 1178         va_list valueap;
 1179         nvpair_t *nvp;
 1180 
 1181         va_start(valueap, valuefmt);
 1182         nvp = nvpair_create_stringv(name, valuefmt, valueap);
 1183         va_end(valueap);
 1184 
 1185         return (nvp);
 1186 }
 1187 
 1188 nvpair_t *
 1189 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
 1190 {
 1191         nvpair_t *nvp;
 1192         char *str;
 1193         int len;
 1194 
 1195         len = nv_vasprintf(&str, valuefmt, valueap);
 1196         if (len < 0)
 1197                 return (NULL);
 1198         nvp = nvpair_create_string(name, str);
 1199         nv_free(str);
 1200         return (nvp);
 1201 }
 1202 
 1203 nvpair_t *
 1204 nvpair_create_null(const char *name)
 1205 {
 1206 
 1207         return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
 1208 }
 1209 
 1210 nvpair_t *
 1211 nvpair_create_bool(const char *name, bool value)
 1212 {
 1213 
 1214         return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
 1215             sizeof(uint8_t), 0));
 1216 }
 1217 
 1218 nvpair_t *
 1219 nvpair_create_number(const char *name, uint64_t value)
 1220 {
 1221 
 1222         return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
 1223 }
 1224 
 1225 nvpair_t *
 1226 nvpair_create_string(const char *name, const char *value)
 1227 {
 1228         nvpair_t *nvp;
 1229         size_t size;
 1230         char *data;
 1231 
 1232         if (value == NULL) {
 1233                 ERRNO_SET(EINVAL);
 1234                 return (NULL);
 1235         }
 1236 
 1237         data = nv_strdup(value);
 1238         if (data == NULL)
 1239                 return (NULL);
 1240         size = strlen(value) + 1;
 1241 
 1242         nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
 1243             size, 0);
 1244         if (nvp == NULL)
 1245                 nv_free(data);
 1246 
 1247         return (nvp);
 1248 }
 1249 
 1250 nvpair_t *
 1251 nvpair_create_nvlist(const char *name, const nvlist_t *value)
 1252 {
 1253         nvlist_t *nvl;
 1254         nvpair_t *nvp;
 1255 
 1256         if (value == NULL) {
 1257                 ERRNO_SET(EINVAL);
 1258                 return (NULL);
 1259         }
 1260 
 1261         nvl = nvlist_clone(value);
 1262         if (nvl == NULL)
 1263                 return (NULL);
 1264 
 1265         nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
 1266             0);
 1267         if (nvp == NULL)
 1268                 nvlist_destroy(nvl);
 1269         else
 1270                 nvlist_set_parent(nvl, nvp);
 1271 
 1272         return (nvp);
 1273 }
 1274 
 1275 #ifndef _KERNEL
 1276 nvpair_t *
 1277 nvpair_create_descriptor(const char *name, int value)
 1278 {
 1279         nvpair_t *nvp;
 1280 
 1281         value = fcntl(value, F_DUPFD_CLOEXEC, 0);
 1282         if (value < 0)
 1283                 return (NULL);
 1284 
 1285         nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
 1286             sizeof(int64_t), 0);
 1287         if (nvp == NULL) {
 1288                 ERRNO_SAVE();
 1289                 close(value);
 1290                 ERRNO_RESTORE();
 1291         }
 1292 
 1293         return (nvp);
 1294 }
 1295 #endif
 1296 
 1297 nvpair_t *
 1298 nvpair_create_binary(const char *name, const void *value, size_t size)
 1299 {
 1300         nvpair_t *nvp;
 1301         void *data;
 1302 
 1303         if (value == NULL || size == 0) {
 1304                 ERRNO_SET(EINVAL);
 1305                 return (NULL);
 1306         }
 1307 
 1308         data = nv_malloc(size);
 1309         if (data == NULL)
 1310                 return (NULL);
 1311         memcpy(data, value, size);
 1312 
 1313         nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
 1314             size, 0);
 1315         if (nvp == NULL)
 1316                 nv_free(data);
 1317 
 1318         return (nvp);
 1319 }
 1320 
 1321 nvpair_t *
 1322 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
 1323 {
 1324         nvpair_t *nvp;
 1325         size_t size;
 1326         void *data;
 1327 
 1328         if (value == NULL || nitems == 0) {
 1329                 ERRNO_SET(EINVAL);
 1330                 return (NULL);
 1331         }
 1332 
 1333         size = sizeof(value[0]) * nitems;
 1334         data = nv_malloc(size);
 1335         if (data == NULL)
 1336                 return (NULL);
 1337 
 1338         memcpy(data, value, size);
 1339         nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
 1340             size, nitems);
 1341         if (nvp == NULL) {
 1342                 ERRNO_SAVE();
 1343                 nv_free(data);
 1344                 ERRNO_RESTORE();
 1345         }
 1346 
 1347         return (nvp);
 1348 }
 1349 
 1350 nvpair_t *
 1351 nvpair_create_number_array(const char *name, const uint64_t *value,
 1352     size_t nitems)
 1353 {
 1354         nvpair_t *nvp;
 1355         size_t size;
 1356         void *data;
 1357 
 1358         if (value == NULL || nitems == 0) {
 1359                 ERRNO_SET(EINVAL);
 1360                 return (NULL);
 1361         }
 1362 
 1363         size = sizeof(value[0]) * nitems;
 1364         data = nv_malloc(size);
 1365         if (data == NULL)
 1366                 return (NULL);
 1367 
 1368         memcpy(data, value, size);
 1369         nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
 1370             (uint64_t)(uintptr_t)data, size, nitems);
 1371         if (nvp == NULL) {
 1372                 ERRNO_SAVE();
 1373                 nv_free(data);
 1374                 ERRNO_RESTORE();
 1375         }
 1376 
 1377         return (nvp);
 1378 }
 1379 
 1380 nvpair_t *
 1381 nvpair_create_string_array(const char *name, const char * const *value,
 1382     size_t nitems)
 1383 {
 1384         nvpair_t *nvp;
 1385         unsigned int ii;
 1386         size_t datasize, size;
 1387         char **data;
 1388 
 1389         if (value == NULL || nitems == 0) {
 1390                 ERRNO_SET(EINVAL);
 1391                 return (NULL);
 1392         }
 1393 
 1394         nvp = NULL;
 1395         datasize = 0;
 1396         data = nv_malloc(sizeof(value[0]) * nitems);
 1397         if (data == NULL)
 1398                 return (NULL);
 1399 
 1400         for (ii = 0; ii < nitems; ii++) {
 1401                 if (value[ii] == NULL) {
 1402                         ERRNO_SET(EINVAL);
 1403                         goto fail;
 1404                 }
 1405 
 1406                 size = strlen(value[ii]) + 1;
 1407                 datasize += size;
 1408                 data[ii] = nv_strdup(value[ii]);
 1409                 if (data[ii] == NULL)
 1410                         goto fail;
 1411         }
 1412         nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
 1413             (uint64_t)(uintptr_t)data, datasize, nitems);
 1414 
 1415 fail:
 1416         if (nvp == NULL) {
 1417                 ERRNO_SAVE();
 1418                 for (; ii > 0; ii--)
 1419                         nv_free(data[ii - 1]);
 1420                 nv_free(data);
 1421                 ERRNO_RESTORE();
 1422         }
 1423 
 1424         return (nvp);
 1425 }
 1426 
 1427 nvpair_t *
 1428 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
 1429     size_t nitems)
 1430 {
 1431         unsigned int ii;
 1432         nvlist_t **nvls;
 1433         nvpair_t *parent;
 1434         int flags;
 1435 
 1436         nvls = NULL;
 1437 
 1438         if (value == NULL || nitems == 0) {
 1439                 ERRNO_SET(EINVAL);
 1440                 return (NULL);
 1441         }
 1442 
 1443         nvls = nv_malloc(sizeof(value[0]) * nitems);
 1444         if (nvls == NULL)
 1445                 return (NULL);
 1446 
 1447         for (ii = 0; ii < nitems; ii++) {
 1448                 if (value[ii] == NULL) {
 1449                         ERRNO_SET(EINVAL);
 1450                         goto fail;
 1451                 }
 1452 
 1453                 nvls[ii] = nvlist_clone(value[ii]);
 1454                 if (nvls[ii] == NULL)
 1455                         goto fail;
 1456 
 1457                 if (ii > 0) {
 1458                         nvpair_t *nvp;
 1459 
 1460                         nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
 1461                             (uint64_t)(uintptr_t)nvls[ii], 0, 0);
 1462                         if (nvp == NULL) {
 1463                                 ERRNO_SAVE();
 1464                                 nvlist_destroy(nvls[ii]);
 1465                                 ERRNO_RESTORE();
 1466                                 goto fail;
 1467                         }
 1468                         nvlist_set_array_next(nvls[ii - 1], nvp);
 1469                 }
 1470         }
 1471         flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
 1472         nvlist_set_flags(nvls[nitems - 1], flags);
 1473 
 1474         parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
 1475             (uint64_t)(uintptr_t)nvls, 0, nitems);
 1476         if (parent == NULL)
 1477                 goto fail;
 1478 
 1479         for (ii = 0; ii < nitems; ii++)
 1480                 nvlist_set_parent(nvls[ii], parent);
 1481 
 1482         return (parent);
 1483 
 1484 fail:
 1485         ERRNO_SAVE();
 1486         for (; ii > 0; ii--)
 1487                 nvlist_destroy(nvls[ii - 1]);
 1488         nv_free(nvls);
 1489         ERRNO_RESTORE();
 1490 
 1491         return (NULL);
 1492 }
 1493 
 1494 #ifndef _KERNEL
 1495 nvpair_t *
 1496 nvpair_create_descriptor_array(const char *name, const int *value,
 1497     size_t nitems)
 1498 {
 1499         unsigned int ii;
 1500         nvpair_t *nvp;
 1501         int *fds;
 1502 
 1503         if (value == NULL) {
 1504                 ERRNO_SET(EINVAL);
 1505                 return (NULL);
 1506         }
 1507 
 1508         nvp = NULL;
 1509 
 1510         fds = nv_malloc(sizeof(value[0]) * nitems);
 1511         if (fds == NULL)
 1512                 return (NULL);
 1513         for (ii = 0; ii < nitems; ii++) {
 1514                 if (value[ii] == -1) {
 1515                         fds[ii] = -1;
 1516                 } else {
 1517                         fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
 1518                         if (fds[ii] == -1)
 1519                                 goto fail;
 1520                 }
 1521         }
 1522 
 1523         nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
 1524             (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
 1525 
 1526 fail:
 1527         if (nvp == NULL) {
 1528                 ERRNO_SAVE();
 1529                 for (; ii > 0; ii--) {
 1530                         if (fds[ii - 1] != -1)
 1531                                 close(fds[ii - 1]);
 1532                 }
 1533                 nv_free(fds);
 1534                 ERRNO_RESTORE();
 1535         }
 1536 
 1537         return (nvp);
 1538 }
 1539 #endif
 1540 
 1541 nvpair_t *
 1542 nvpair_move_string(const char *name, char *value)
 1543 {
 1544         nvpair_t *nvp;
 1545 
 1546         if (value == NULL) {
 1547                 ERRNO_SET(EINVAL);
 1548                 return (NULL);
 1549         }
 1550 
 1551         nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
 1552             strlen(value) + 1, 0);
 1553         if (nvp == NULL) {
 1554                 ERRNO_SAVE();
 1555                 nv_free(value);
 1556                 ERRNO_RESTORE();
 1557         }
 1558 
 1559         return (nvp);
 1560 }
 1561 
 1562 nvpair_t *
 1563 nvpair_move_nvlist(const char *name, nvlist_t *value)
 1564 {
 1565         nvpair_t *nvp;
 1566 
 1567         if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
 1568                 ERRNO_SET(EINVAL);
 1569                 return (NULL);
 1570         }
 1571 
 1572         if (nvlist_error(value) != 0) {
 1573                 ERRNO_SET(nvlist_error(value));
 1574                 nvlist_destroy(value);
 1575                 return (NULL);
 1576         }
 1577 
 1578         nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
 1579             0, 0);
 1580         if (nvp == NULL)
 1581                 nvlist_destroy(value);
 1582         else
 1583                 nvlist_set_parent(value, nvp);
 1584 
 1585         return (nvp);
 1586 }
 1587 
 1588 #ifndef _KERNEL
 1589 nvpair_t *
 1590 nvpair_move_descriptor(const char *name, int value)
 1591 {
 1592         nvpair_t *nvp;
 1593 
 1594         if (value < 0 || !fd_is_valid(value)) {
 1595                 ERRNO_SET(EBADF);
 1596                 return (NULL);
 1597         }
 1598 
 1599         nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
 1600             sizeof(int64_t), 0);
 1601         if (nvp == NULL) {
 1602                 ERRNO_SAVE();
 1603                 close(value);
 1604                 ERRNO_RESTORE();
 1605         }
 1606 
 1607         return (nvp);
 1608 }
 1609 #endif
 1610 
 1611 nvpair_t *
 1612 nvpair_move_binary(const char *name, void *value, size_t size)
 1613 {
 1614         nvpair_t *nvp;
 1615 
 1616         if (value == NULL || size == 0) {
 1617                 ERRNO_SET(EINVAL);
 1618                 return (NULL);
 1619         }
 1620 
 1621         nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
 1622             size, 0);
 1623         if (nvp == NULL) {
 1624                 ERRNO_SAVE();
 1625                 nv_free(value);
 1626                 ERRNO_RESTORE();
 1627         }
 1628 
 1629         return (nvp);
 1630 }
 1631 
 1632 nvpair_t *
 1633 nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
 1634 {
 1635         nvpair_t *nvp;
 1636 
 1637         if (value == NULL || nitems == 0) {
 1638                 ERRNO_SET(EINVAL);
 1639                 return (NULL);
 1640         }
 1641 
 1642         nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
 1643             (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
 1644         if (nvp == NULL) {
 1645                 ERRNO_SAVE();
 1646                 nv_free(value);
 1647                 ERRNO_RESTORE();
 1648         }
 1649 
 1650         return (nvp);
 1651 }
 1652 
 1653 nvpair_t *
 1654 nvpair_move_string_array(const char *name, char **value, size_t nitems)
 1655 {
 1656         nvpair_t *nvp;
 1657         size_t i, size;
 1658 
 1659         if (value == NULL || nitems == 0) {
 1660                 ERRNO_SET(EINVAL);
 1661                 return (NULL);
 1662         }
 1663 
 1664         size = 0;
 1665         for (i = 0; i < nitems; i++) {
 1666                 if (value[i] == NULL) {
 1667                         ERRNO_SET(EINVAL);
 1668                         return (NULL);
 1669                 }
 1670 
 1671                 size += strlen(value[i]) + 1;
 1672         }
 1673 
 1674         nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
 1675             (uint64_t)(uintptr_t)value, size, nitems);
 1676         if (nvp == NULL) {
 1677                 ERRNO_SAVE();
 1678                 for (i = 0; i < nitems; i++)
 1679                         nv_free(value[i]);
 1680                 nv_free(value);
 1681                 ERRNO_RESTORE();
 1682         }
 1683 
 1684         return (nvp);
 1685 }
 1686 
 1687 nvpair_t *
 1688 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
 1689 {
 1690         nvpair_t *nvp;
 1691 
 1692         if (value == NULL || nitems == 0) {
 1693                 ERRNO_SET(EINVAL);
 1694                 return (NULL);
 1695         }
 1696 
 1697         nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
 1698             (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
 1699         if (nvp == NULL) {
 1700                 ERRNO_SAVE();
 1701                 nv_free(value);
 1702                 ERRNO_RESTORE();
 1703         }
 1704 
 1705         return (nvp);
 1706 }
 1707 
 1708 nvpair_t *
 1709 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
 1710 {
 1711         nvpair_t *parent;
 1712         unsigned int ii;
 1713         int flags;
 1714 
 1715         if (value == NULL || nitems == 0) {
 1716                 ERRNO_SET(EINVAL);
 1717                 return (NULL);
 1718         }
 1719 
 1720         for (ii = 0; ii < nitems; ii++) {
 1721                 if (value == NULL || nvlist_error(value[ii]) != 0 ||
 1722                     nvlist_get_pararr(value[ii], NULL) != NULL) {
 1723                         ERRNO_SET(EINVAL);
 1724                         goto fail;
 1725                 }
 1726                 if (ii > 0) {
 1727                         nvpair_t *nvp;
 1728 
 1729                         nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
 1730                             (uint64_t)(uintptr_t)value[ii], 0, 0);
 1731                         if (nvp == NULL)
 1732                                 goto fail;
 1733                         nvlist_set_array_next(value[ii - 1], nvp);
 1734                 }
 1735         }
 1736         flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
 1737         nvlist_set_flags(value[nitems - 1], flags);
 1738 
 1739         parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
 1740             (uint64_t)(uintptr_t)value, 0, nitems);
 1741         if (parent == NULL)
 1742                 goto fail;
 1743 
 1744         for (ii = 0; ii < nitems; ii++)
 1745                 nvlist_set_parent(value[ii], parent);
 1746 
 1747         return (parent);
 1748 fail:
 1749         ERRNO_SAVE();
 1750         for (ii = 0; ii < nitems; ii++) {
 1751                 if (value[ii] != NULL &&
 1752                     nvlist_get_pararr(value[ii], NULL) != NULL) {
 1753                         nvlist_destroy(value[ii]);
 1754                 }
 1755         }
 1756         nv_free(value);
 1757         ERRNO_RESTORE();
 1758 
 1759         return (NULL);
 1760 }
 1761 
 1762 #ifndef _KERNEL
 1763 nvpair_t *
 1764 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
 1765 {
 1766         nvpair_t *nvp;
 1767         size_t i;
 1768 
 1769         if (value == NULL || nitems == 0) {
 1770                 ERRNO_SET(EINVAL);
 1771                 return (NULL);
 1772         }
 1773 
 1774         for (i = 0; i < nitems; i++) {
 1775                 if (value[i] != -1 && !fd_is_valid(value[i])) {
 1776                         ERRNO_SET(EBADF);
 1777                         goto fail;
 1778                 }
 1779         }
 1780 
 1781         nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
 1782             (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
 1783         if (nvp == NULL)
 1784                 goto fail;
 1785 
 1786         return (nvp);
 1787 fail:
 1788         ERRNO_SAVE();
 1789         for (i = 0; i < nitems; i++) {
 1790                 if (fd_is_valid(value[i]))
 1791                         close(value[i]);
 1792         }
 1793         nv_free(value);
 1794         ERRNO_RESTORE();
 1795 
 1796         return (NULL);
 1797 }
 1798 #endif
 1799 
 1800 bool
 1801 nvpair_get_bool(const nvpair_t *nvp)
 1802 {
 1803 
 1804         NVPAIR_ASSERT(nvp);
 1805 
 1806         return (nvp->nvp_data == 1);
 1807 }
 1808 
 1809 uint64_t
 1810 nvpair_get_number(const nvpair_t *nvp)
 1811 {
 1812 
 1813         NVPAIR_ASSERT(nvp);
 1814 
 1815         return (nvp->nvp_data);
 1816 }
 1817 
 1818 const char *
 1819 nvpair_get_string(const nvpair_t *nvp)
 1820 {
 1821 
 1822         NVPAIR_ASSERT(nvp);
 1823         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
 1824 
 1825         return ((const char *)(intptr_t)nvp->nvp_data);
 1826 }
 1827 
 1828 const nvlist_t *
 1829 nvpair_get_nvlist(const nvpair_t *nvp)
 1830 {
 1831 
 1832         NVPAIR_ASSERT(nvp);
 1833         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
 1834 
 1835         return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
 1836 }
 1837 
 1838 #ifndef _KERNEL
 1839 int
 1840 nvpair_get_descriptor(const nvpair_t *nvp)
 1841 {
 1842 
 1843         NVPAIR_ASSERT(nvp);
 1844         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
 1845 
 1846         return ((int)nvp->nvp_data);
 1847 }
 1848 #endif
 1849 
 1850 const void *
 1851 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
 1852 {
 1853 
 1854         NVPAIR_ASSERT(nvp);
 1855         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
 1856 
 1857         if (sizep != NULL)
 1858                 *sizep = nvp->nvp_datasize;
 1859 
 1860         return ((const void *)(intptr_t)nvp->nvp_data);
 1861 }
 1862 
 1863 const bool *
 1864 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
 1865 {
 1866 
 1867         NVPAIR_ASSERT(nvp);
 1868         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
 1869 
 1870         if (nitems != NULL)
 1871                 *nitems = nvp->nvp_nitems;
 1872 
 1873         return ((const bool *)(intptr_t)nvp->nvp_data);
 1874 }
 1875 
 1876 const uint64_t *
 1877 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
 1878 {
 1879 
 1880         NVPAIR_ASSERT(nvp);
 1881         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
 1882 
 1883         if (nitems != NULL)
 1884                 *nitems = nvp->nvp_nitems;
 1885 
 1886         return ((const uint64_t *)(intptr_t)nvp->nvp_data);
 1887 }
 1888 
 1889 const char * const *
 1890 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
 1891 {
 1892 
 1893         NVPAIR_ASSERT(nvp);
 1894         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
 1895 
 1896         if (nitems != NULL)
 1897                 *nitems = nvp->nvp_nitems;
 1898 
 1899         return ((const char * const *)(intptr_t)nvp->nvp_data);
 1900 }
 1901 
 1902 const nvlist_t * const *
 1903 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
 1904 {
 1905 
 1906         NVPAIR_ASSERT(nvp);
 1907         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
 1908 
 1909         if (nitems != NULL)
 1910                 *nitems = nvp->nvp_nitems;
 1911 
 1912         return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
 1913 }
 1914 
 1915 #ifndef _KERNEL
 1916 const int *
 1917 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
 1918 {
 1919 
 1920         NVPAIR_ASSERT(nvp);
 1921         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
 1922 
 1923         if (nitems != NULL)
 1924                 *nitems = nvp->nvp_nitems;
 1925 
 1926         return ((const int *)(intptr_t)nvp->nvp_data);
 1927 }
 1928 #endif
 1929 
 1930 int
 1931 nvpair_append_bool_array(nvpair_t *nvp, const bool value)
 1932 {
 1933 
 1934         NVPAIR_ASSERT(nvp);
 1935         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
 1936         return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
 1937 }
 1938 
 1939 int
 1940 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
 1941 {
 1942 
 1943         NVPAIR_ASSERT(nvp);
 1944         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
 1945         return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
 1946 }
 1947 
 1948 int
 1949 nvpair_append_string_array(nvpair_t *nvp, const char *value)
 1950 {
 1951         char *str;
 1952 
 1953         NVPAIR_ASSERT(nvp);
 1954         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
 1955         if (value == NULL) {
 1956                 ERRNO_SET(EINVAL);
 1957                 return (-1);
 1958         }
 1959         str = nv_strdup(value);
 1960         if (str == NULL) {
 1961                 return (-1);
 1962         }
 1963         if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
 1964                 nv_free(str);
 1965                 return (-1);
 1966         }
 1967         return (0);
 1968 }
 1969 
 1970 int
 1971 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
 1972 {
 1973         nvpair_t *tmpnvp;
 1974         nvlist_t *nvl, *prev;
 1975         int flags;
 1976 
 1977         NVPAIR_ASSERT(nvp);
 1978         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
 1979         if (value == NULL || nvlist_error(value) != 0 ||
 1980             nvlist_get_pararr(value, NULL) != NULL) {
 1981                 ERRNO_SET(EINVAL);
 1982                 return (-1);
 1983         }
 1984         nvl = nvlist_clone(value);
 1985         if (nvl == NULL) {
 1986                 return (-1);
 1987         }
 1988         flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
 1989         nvlist_set_flags(nvl, flags);
 1990 
 1991         tmpnvp = NULL;
 1992         prev = NULL;
 1993         if (nvp->nvp_nitems > 0) {
 1994                 nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
 1995 
 1996                 prev = nvls[nvp->nvp_nitems - 1];
 1997                 PJDLOG_ASSERT(prev != NULL);
 1998 
 1999                 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
 2000                     (uint64_t)(uintptr_t)nvl, 0, 0);
 2001                 if (tmpnvp == NULL) {
 2002                         goto fail;
 2003                 }
 2004         }
 2005         if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
 2006                 goto fail;
 2007         }
 2008         if (tmpnvp) {
 2009                 NVPAIR_ASSERT(tmpnvp);
 2010                 nvlist_set_array_next(prev, tmpnvp);
 2011         }
 2012         nvlist_set_parent(nvl, nvp);
 2013         return (0);
 2014 fail:
 2015         if (tmpnvp) {
 2016                 nvpair_free(tmpnvp);
 2017         }
 2018         nvlist_destroy(nvl);
 2019         return (-1);
 2020 }
 2021 
 2022 #ifndef _KERNEL
 2023 int
 2024 nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
 2025 {
 2026         int fd;
 2027 
 2028         NVPAIR_ASSERT(nvp);
 2029         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
 2030         fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
 2031         if (fd == -1) {
 2032                 return (-1);
 2033         }
 2034         if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
 2035                 close(fd);
 2036                 return (-1);
 2037         }
 2038         return (0);
 2039 }
 2040 #endif
 2041 
 2042 void
 2043 nvpair_free(nvpair_t *nvp)
 2044 {
 2045         size_t i;
 2046 
 2047         NVPAIR_ASSERT(nvp);
 2048         PJDLOG_ASSERT(nvp->nvp_list == NULL);
 2049 
 2050         nvp->nvp_magic = 0;
 2051         switch (nvp->nvp_type) {
 2052 #ifndef _KERNEL
 2053         case NV_TYPE_DESCRIPTOR:
 2054                 close((int)nvp->nvp_data);
 2055                 break;
 2056         case NV_TYPE_DESCRIPTOR_ARRAY:
 2057                 for (i = 0; i < nvp->nvp_nitems; i++)
 2058                         close(((int *)(intptr_t)nvp->nvp_data)[i]);
 2059                 nv_free((int *)(intptr_t)nvp->nvp_data);
 2060                 break;
 2061 #endif
 2062         case NV_TYPE_NVLIST:
 2063                 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
 2064                 break;
 2065         case NV_TYPE_STRING:
 2066                 nv_free((char *)(intptr_t)nvp->nvp_data);
 2067                 break;
 2068         case NV_TYPE_BINARY:
 2069                 nv_free((void *)(intptr_t)nvp->nvp_data);
 2070                 break;
 2071         case NV_TYPE_NVLIST_ARRAY:
 2072                 for (i = 0; i < nvp->nvp_nitems; i++) {
 2073                         nvlist_destroy(
 2074                             ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
 2075                 }
 2076                 nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
 2077                 break;
 2078         case NV_TYPE_NUMBER_ARRAY:
 2079                 nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
 2080                 break;
 2081         case NV_TYPE_BOOL_ARRAY:
 2082                 nv_free((bool *)(intptr_t)nvp->nvp_data);
 2083                 break;
 2084         case NV_TYPE_STRING_ARRAY:
 2085                 for (i = 0; i < nvp->nvp_nitems; i++)
 2086                         nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
 2087                 nv_free((char **)(intptr_t)nvp->nvp_data);
 2088                 break;
 2089         }
 2090         nv_free(nvp);
 2091 }
 2092 
 2093 void
 2094 nvpair_free_structure(nvpair_t *nvp)
 2095 {
 2096 
 2097         NVPAIR_ASSERT(nvp);
 2098         PJDLOG_ASSERT(nvp->nvp_list == NULL);
 2099 
 2100         nvp->nvp_magic = 0;
 2101         nv_free(nvp);
 2102 }
 2103 
 2104 const char *
 2105 nvpair_type_string(int type)
 2106 {
 2107 
 2108         switch (type) {
 2109         case NV_TYPE_NULL:
 2110                 return ("NULL");
 2111         case NV_TYPE_BOOL:
 2112                 return ("BOOL");
 2113         case NV_TYPE_NUMBER:
 2114                 return ("NUMBER");
 2115         case NV_TYPE_STRING:
 2116                 return ("STRING");
 2117         case NV_TYPE_NVLIST:
 2118                 return ("NVLIST");
 2119         case NV_TYPE_DESCRIPTOR:
 2120                 return ("DESCRIPTOR");
 2121         case NV_TYPE_BINARY:
 2122                 return ("BINARY");
 2123         case NV_TYPE_BOOL_ARRAY:
 2124                 return ("BOOL ARRAY");
 2125         case NV_TYPE_NUMBER_ARRAY:
 2126                 return ("NUMBER ARRAY");
 2127         case NV_TYPE_STRING_ARRAY:
 2128                 return ("STRING ARRAY");
 2129         case NV_TYPE_NVLIST_ARRAY:
 2130                 return ("NVLIST ARRAY");
 2131         case NV_TYPE_DESCRIPTOR_ARRAY:
 2132                 return ("DESCRIPTOR ARRAY");
 2133         default:
 2134                 return ("<UNKNOWN>");
 2135         }
 2136 }
 2137 

Cache object: 2ebf25d6a5e2e2dcfb573425d2ec5226


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