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