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