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