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