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