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