xref: /freebsd/sys/contrib/libnv/nvlist.c (revision 119b75925c562202145d7bac7b676b98029c6cb9)
1 /*-
2  * Copyright (c) 2009-2013 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <sys/param.h>
34 #include <sys/endian.h>
35 #include <sys/queue.h>
36 
37 #ifdef _KERNEL
38 
39 #include <sys/errno.h>
40 #include <sys/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/systm.h>
44 
45 #include <machine/stdarg.h>
46 
47 #else
48 #include <sys/socket.h>
49 
50 #include <errno.h>
51 #include <stdarg.h>
52 #include <stdbool.h>
53 #include <stdint.h>
54 #define	_WITH_DPRINTF
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)
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 	struct nvl_head	 nvl_head;
102 };
103 
104 #define	NVLIST_ASSERT(nvl)	do {					\
105 	PJDLOG_ASSERT((nvl) != NULL);					\
106 	PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);		\
107 } while (0)
108 
109 #ifdef _KERNEL
110 MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
111 #endif
112 
113 #define	NVPAIR_ASSERT(nvp)	nvpair_assert(nvp)
114 
115 #define	NVLIST_HEADER_MAGIC	0x6c
116 #define	NVLIST_HEADER_VERSION	0x00
117 struct nvlist_header {
118 	uint8_t		nvlh_magic;
119 	uint8_t		nvlh_version;
120 	uint8_t		nvlh_flags;
121 	uint64_t	nvlh_descriptors;
122 	uint64_t	nvlh_size;
123 } __packed;
124 
125 nvlist_t *
126 nvlist_create(int flags)
127 {
128 	nvlist_t *nvl;
129 
130 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
131 
132 	nvl = nv_malloc(sizeof(*nvl));
133 	if (nvl == NULL)
134 		return (NULL);
135 	nvl->nvl_error = 0;
136 	nvl->nvl_flags = flags;
137 	nvl->nvl_parent = NULL;
138 	TAILQ_INIT(&nvl->nvl_head);
139 	nvl->nvl_magic = NVLIST_MAGIC;
140 
141 	return (nvl);
142 }
143 
144 void
145 nvlist_destroy(nvlist_t *nvl)
146 {
147 	nvpair_t *nvp;
148 
149 	if (nvl == NULL)
150 		return;
151 
152 	ERRNO_SAVE();
153 
154 	NVLIST_ASSERT(nvl);
155 
156 	while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
157 		nvlist_remove_nvpair(nvl, nvp);
158 		nvpair_free(nvp);
159 	}
160 	nvl->nvl_magic = 0;
161 	nv_free(nvl);
162 
163 	ERRNO_RESTORE();
164 }
165 
166 void
167 nvlist_set_error(nvlist_t *nvl, int error)
168 {
169 
170 	PJDLOG_ASSERT(error != 0);
171 
172 	/*
173 	 * Check for error != 0 so that we don't do the wrong thing if somebody
174 	 * tries to abuse this API when asserts are disabled.
175 	 */
176 	if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
177 		nvl->nvl_error = error;
178 }
179 
180 int
181 nvlist_error(const nvlist_t *nvl)
182 {
183 
184 	if (nvl == NULL)
185 		return (ENOMEM);
186 
187 	NVLIST_ASSERT(nvl);
188 
189 	return (nvl->nvl_error);
190 }
191 
192 nvpair_t *
193 nvlist_get_nvpair_parent(const nvlist_t *nvl)
194 {
195 
196 	NVLIST_ASSERT(nvl);
197 
198 	return (nvl->nvl_parent);
199 }
200 
201 const nvlist_t *
202 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
203 {
204 	nvpair_t *nvp;
205 
206 	NVLIST_ASSERT(nvl);
207 
208 	nvp = nvl->nvl_parent;
209 	if (cookiep != NULL)
210 		*cookiep = nvp;
211 	if (nvp == NULL)
212 		return (NULL);
213 
214 	return (nvpair_nvlist(nvp));
215 }
216 
217 void
218 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
219 {
220 
221 	NVLIST_ASSERT(nvl);
222 
223 	nvl->nvl_parent = parent;
224 }
225 
226 bool
227 nvlist_empty(const nvlist_t *nvl)
228 {
229 
230 	NVLIST_ASSERT(nvl);
231 	PJDLOG_ASSERT(nvl->nvl_error == 0);
232 
233 	return (nvlist_first_nvpair(nvl) == NULL);
234 }
235 
236 int
237 nvlist_flags(const nvlist_t *nvl)
238 {
239 
240 	NVLIST_ASSERT(nvl);
241 	PJDLOG_ASSERT(nvl->nvl_error == 0);
242 	PJDLOG_ASSERT((nvl->nvl_flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
243 
244 	return (nvl->nvl_flags);
245 }
246 
247 static void
248 nvlist_report_missing(int type, const char *name)
249 {
250 
251 	PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
252 	    name, nvpair_type_string(type));
253 }
254 
255 static nvpair_t *
256 nvlist_find(const nvlist_t *nvl, int type, const char *name)
257 {
258 	nvpair_t *nvp;
259 
260 	NVLIST_ASSERT(nvl);
261 	PJDLOG_ASSERT(nvl->nvl_error == 0);
262 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
263 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
264 
265 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
266 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
267 		if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
268 			continue;
269 		if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
270 			if (strcasecmp(nvpair_name(nvp), name) != 0)
271 				continue;
272 		} else {
273 			if (strcmp(nvpair_name(nvp), name) != 0)
274 				continue;
275 		}
276 		break;
277 	}
278 
279 	if (nvp == NULL)
280 		ERRNO_SET(ENOENT);
281 
282 	return (nvp);
283 }
284 
285 bool
286 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
287 {
288 
289 	NVLIST_ASSERT(nvl);
290 	PJDLOG_ASSERT(nvl->nvl_error == 0);
291 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
292 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
293 
294 	return (nvlist_find(nvl, type, name) != NULL);
295 }
296 
297 void
298 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
299 {
300 	nvpair_t *nvp;
301 
302 	NVLIST_ASSERT(nvl);
303 	PJDLOG_ASSERT(nvl->nvl_error == 0);
304 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
305 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
306 
307 	nvp = nvlist_find(nvl, type, name);
308 	if (nvp != NULL)
309 		nvlist_free_nvpair(nvl, nvp);
310 	else
311 		nvlist_report_missing(type, name);
312 }
313 
314 nvlist_t *
315 nvlist_clone(const nvlist_t *nvl)
316 {
317 	nvlist_t *newnvl;
318 	nvpair_t *nvp, *newnvp;
319 
320 	NVLIST_ASSERT(nvl);
321 
322 	if (nvl->nvl_error != 0) {
323 		ERRNO_SET(nvl->nvl_error);
324 		return (NULL);
325 	}
326 
327 	newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
328 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
329 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
330 		newnvp = nvpair_clone(nvp);
331 		if (newnvp == NULL)
332 			break;
333 		nvlist_move_nvpair(newnvl, newnvp);
334 	}
335 	if (nvp != NULL) {
336 		nvlist_destroy(newnvl);
337 		return (NULL);
338 	}
339 	return (newnvl);
340 }
341 
342 #ifndef _KERNEL
343 static bool
344 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
345 {
346 
347 	if (nvlist_error(nvl) != 0) {
348 		dprintf(fd, "%*serror: %d\n", level * 4, "",
349 		    nvlist_error(nvl));
350 		return (true);
351 	}
352 
353 	return (false);
354 }
355 
356 /*
357  * Dump content of nvlist.
358  */
359 void
360 nvlist_dump(const nvlist_t *nvl, int fd)
361 {
362 	const nvlist_t *tmpnvl;
363 	nvpair_t *nvp, *tmpnvp;
364 	void *cookie;
365 	int level;
366 
367 	level = 0;
368 	if (nvlist_dump_error_check(nvl, fd, level))
369 		return;
370 
371 	nvp = nvlist_first_nvpair(nvl);
372 	while (nvp != NULL) {
373 		dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
374 		    nvpair_type_string(nvpair_type(nvp)));
375 		switch (nvpair_type(nvp)) {
376 		case NV_TYPE_NULL:
377 			dprintf(fd, " null\n");
378 			break;
379 		case NV_TYPE_BOOL:
380 			dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
381 			    "TRUE" : "FALSE");
382 			break;
383 		case NV_TYPE_NUMBER:
384 			dprintf(fd, " %ju (%jd) (0x%jx)\n",
385 			    (uintmax_t)nvpair_get_number(nvp),
386 			    (intmax_t)nvpair_get_number(nvp),
387 			    (uintmax_t)nvpair_get_number(nvp));
388 			break;
389 		case NV_TYPE_STRING:
390 			dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
391 			break;
392 		case NV_TYPE_NVLIST:
393 			dprintf(fd, "\n");
394 			tmpnvl = nvpair_get_nvlist(nvp);
395 			if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
396 				break;
397 			tmpnvp = nvlist_first_nvpair(tmpnvl);
398 			if (tmpnvp != NULL) {
399 				nvl = tmpnvl;
400 				nvp = tmpnvp;
401 				level++;
402 				continue;
403 			}
404 			break;
405 		case NV_TYPE_DESCRIPTOR:
406 			dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
407 			break;
408 		case NV_TYPE_BINARY:
409 		    {
410 			const unsigned char *binary;
411 			unsigned int ii;
412 			size_t size;
413 
414 			binary = nvpair_get_binary(nvp, &size);
415 			dprintf(fd, " %zu ", size);
416 			for (ii = 0; ii < size; ii++)
417 				dprintf(fd, "%02hhx", binary[ii]);
418 			dprintf(fd, "\n");
419 			break;
420 		    }
421 		default:
422 			PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
423 		}
424 
425 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
426 			cookie = NULL;
427 			nvl = nvlist_get_parent(nvl, &cookie);
428 			if (nvl == NULL)
429 				return;
430 			nvp = cookie;
431 			level--;
432 		}
433 	}
434 }
435 
436 void
437 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
438 {
439 
440 	fflush(fp);
441 	nvlist_dump(nvl, fileno(fp));
442 }
443 #endif
444 
445 /*
446  * The function obtains size of the nvlist after nvlist_pack().
447  */
448 size_t
449 nvlist_size(const nvlist_t *nvl)
450 {
451 	const nvlist_t *tmpnvl;
452 	const nvpair_t *nvp, *tmpnvp;
453 	void *cookie;
454 	size_t size;
455 
456 	NVLIST_ASSERT(nvl);
457 	PJDLOG_ASSERT(nvl->nvl_error == 0);
458 
459 	size = sizeof(struct nvlist_header);
460 	nvp = nvlist_first_nvpair(nvl);
461 	while (nvp != NULL) {
462 		size += nvpair_header_size();
463 		size += strlen(nvpair_name(nvp)) + 1;
464 		if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
465 			size += sizeof(struct nvlist_header);
466 			size += nvpair_header_size() + 1;
467 			tmpnvl = nvpair_get_nvlist(nvp);
468 			PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
469 			tmpnvp = nvlist_first_nvpair(tmpnvl);
470 			if (tmpnvp != NULL) {
471 				nvl = tmpnvl;
472 				nvp = tmpnvp;
473 				continue;
474 			}
475 		} else {
476 			size += nvpair_size(nvp);
477 		}
478 
479 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
480 			cookie = NULL;
481 			nvl = nvlist_get_parent(nvl, &cookie);
482 			if (nvl == NULL)
483 				goto out;
484 			nvp = cookie;
485 		}
486 	}
487 
488 out:
489 	return (size);
490 }
491 
492 #ifndef _KERNEL
493 static int *
494 nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
495 {
496 	nvpair_t *nvp;
497 	const char *name;
498 	int type;
499 
500 	NVLIST_ASSERT(nvl);
501 	PJDLOG_ASSERT(nvl->nvl_error == 0);
502 
503 	nvp = NULL;
504 	do {
505 		while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
506 			switch (type) {
507 			case NV_TYPE_DESCRIPTOR:
508 				*descs = nvpair_get_descriptor(nvp);
509 				descs++;
510 				break;
511 			case NV_TYPE_NVLIST:
512 				nvl = nvpair_get_nvlist(nvp);
513 				nvp = NULL;
514 				break;
515 			}
516 		}
517 	} while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
518 
519 	return (descs);
520 }
521 #endif
522 
523 #ifndef _KERNEL
524 int *
525 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
526 {
527 	size_t nitems;
528 	int *fds;
529 
530 	nitems = nvlist_ndescriptors(nvl);
531 	fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
532 	if (fds == NULL)
533 		return (NULL);
534 	if (nitems > 0)
535 		nvlist_xdescriptors(nvl, fds);
536 	fds[nitems] = -1;
537 	if (nitemsp != NULL)
538 		*nitemsp = nitems;
539 	return (fds);
540 }
541 #endif
542 
543 size_t
544 nvlist_ndescriptors(const nvlist_t *nvl)
545 {
546 #ifndef _KERNEL
547 	nvpair_t *nvp;
548 	const char *name;
549 	size_t ndescs;
550 	int type;
551 
552 	NVLIST_ASSERT(nvl);
553 	PJDLOG_ASSERT(nvl->nvl_error == 0);
554 
555 	ndescs = 0;
556 	nvp = NULL;
557 	do {
558 		while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
559 			switch (type) {
560 			case NV_TYPE_DESCRIPTOR:
561 				ndescs++;
562 				break;
563 			case NV_TYPE_NVLIST:
564 				nvl = nvpair_get_nvlist(nvp);
565 				nvp = NULL;
566 				break;
567 			}
568 		}
569 	} while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
570 
571 	return (ndescs);
572 #else
573 	return (0);
574 #endif
575 }
576 
577 static unsigned char *
578 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
579 {
580 	struct nvlist_header nvlhdr;
581 
582 	NVLIST_ASSERT(nvl);
583 
584 	nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
585 	nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
586 	nvlhdr.nvlh_flags = nvl->nvl_flags;
587 #if BYTE_ORDER == BIG_ENDIAN
588 	nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
589 #endif
590 	nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
591 	nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
592 	PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
593 	memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
594 	ptr += sizeof(nvlhdr);
595 	*leftp -= sizeof(nvlhdr);
596 
597 	return (ptr);
598 }
599 
600 static void *
601 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
602 {
603 	unsigned char *buf, *ptr;
604 	size_t left, size;
605 	const nvlist_t *tmpnvl;
606 	nvpair_t *nvp, *tmpnvp;
607 	void *cookie;
608 
609 	NVLIST_ASSERT(nvl);
610 
611 	if (nvl->nvl_error != 0) {
612 		ERRNO_SET(nvl->nvl_error);
613 		return (NULL);
614 	}
615 
616 	size = nvlist_size(nvl);
617 	buf = nv_malloc(size);
618 	if (buf == NULL)
619 		return (NULL);
620 
621 	ptr = buf;
622 	left = size;
623 
624 	ptr = nvlist_pack_header(nvl, ptr, &left);
625 
626 	nvp = nvlist_first_nvpair(nvl);
627 	while (nvp != NULL) {
628 		NVPAIR_ASSERT(nvp);
629 
630 		nvpair_init_datasize(nvp);
631 		ptr = nvpair_pack_header(nvp, ptr, &left);
632 		if (ptr == NULL) {
633 			nv_free(buf);
634 			return (NULL);
635 		}
636 		switch (nvpair_type(nvp)) {
637 		case NV_TYPE_NULL:
638 			ptr = nvpair_pack_null(nvp, ptr, &left);
639 			break;
640 		case NV_TYPE_BOOL:
641 			ptr = nvpair_pack_bool(nvp, ptr, &left);
642 			break;
643 		case NV_TYPE_NUMBER:
644 			ptr = nvpair_pack_number(nvp, ptr, &left);
645 			break;
646 		case NV_TYPE_STRING:
647 			ptr = nvpair_pack_string(nvp, ptr, &left);
648 			break;
649 		case NV_TYPE_NVLIST:
650 			tmpnvl = nvpair_get_nvlist(nvp);
651 			ptr = nvlist_pack_header(tmpnvl, ptr, &left);
652 			if (ptr == NULL)
653 				goto out;
654 			tmpnvp = nvlist_first_nvpair(tmpnvl);
655 			if (tmpnvp != NULL) {
656 				nvl = tmpnvl;
657 				nvp = tmpnvp;
658 				continue;
659 			}
660 			ptr = nvpair_pack_nvlist_up(ptr, &left);
661 			break;
662 #ifndef _KERNEL
663 		case NV_TYPE_DESCRIPTOR:
664 			ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
665 			break;
666 #endif
667 		case NV_TYPE_BINARY:
668 			ptr = nvpair_pack_binary(nvp, ptr, &left);
669 			break;
670 		default:
671 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
672 		}
673 		if (ptr == NULL) {
674 			nv_free(buf);
675 			return (NULL);
676 		}
677 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
678 			cookie = NULL;
679 			nvl = nvlist_get_parent(nvl, &cookie);
680 			if (nvl == NULL)
681 				goto out;
682 			nvp = cookie;
683 			ptr = nvpair_pack_nvlist_up(ptr, &left);
684 			if (ptr == NULL)
685 				goto out;
686 		}
687 	}
688 
689 out:
690 	if (sizep != NULL)
691 		*sizep = size;
692 	return (buf);
693 }
694 
695 void *
696 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
697 {
698 
699 	NVLIST_ASSERT(nvl);
700 
701 	if (nvl->nvl_error != 0) {
702 		ERRNO_SET(nvl->nvl_error);
703 		return (NULL);
704 	}
705 
706 	if (nvlist_ndescriptors(nvl) > 0) {
707 		ERRNO_SET(EOPNOTSUPP);
708 		return (NULL);
709 	}
710 
711 	return (nvlist_xpack(nvl, NULL, sizep));
712 }
713 
714 static bool
715 nvlist_check_header(struct nvlist_header *nvlhdrp)
716 {
717 
718 	if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
719 		ERRNO_SET(EINVAL);
720 		return (false);
721 	}
722 	if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
723 		ERRNO_SET(EINVAL);
724 		return (false);
725 	}
726 #if BYTE_ORDER == BIG_ENDIAN
727 	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
728 		nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
729 		nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
730 	}
731 #else
732 	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
733 		nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
734 		nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
735 	}
736 #endif
737 	return (true);
738 }
739 
740 const unsigned char *
741 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
742     bool *isbep, size_t *leftp)
743 {
744 	struct nvlist_header nvlhdr;
745 
746 	if (*leftp < sizeof(nvlhdr))
747 		goto failed;
748 
749 	memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
750 
751 	if (!nvlist_check_header(&nvlhdr))
752 		goto failed;
753 
754 	if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
755 		goto failed;
756 
757 	/*
758 	 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
759 	 */
760 	if (nvlhdr.nvlh_descriptors > nfds)
761 		goto failed;
762 
763 	if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
764 		goto failed;
765 
766 	nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
767 
768 	ptr += sizeof(nvlhdr);
769 	if (isbep != NULL)
770 		*isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
771 	*leftp -= sizeof(nvlhdr);
772 
773 	return (ptr);
774 failed:
775 	ERRNO_SET(EINVAL);
776 	return (NULL);
777 }
778 
779 static nvlist_t *
780 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
781     int flags)
782 {
783 	const unsigned char *ptr;
784 	nvlist_t *nvl, *retnvl, *tmpnvl;
785 	nvpair_t *nvp;
786 	size_t left;
787 	bool isbe;
788 
789 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
790 
791 	left = size;
792 	ptr = buf;
793 
794 	tmpnvl = NULL;
795 	nvl = retnvl = nvlist_create(0);
796 	if (nvl == NULL)
797 		goto failed;
798 
799 	ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
800 	if (ptr == NULL)
801 		goto failed;
802 	if (nvl->nvl_flags != flags) {
803 		ERRNO_SET(EILSEQ);
804 		goto failed;
805 	}
806 
807 	while (left > 0) {
808 		ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
809 		if (ptr == NULL)
810 			goto failed;
811 		switch (nvpair_type(nvp)) {
812 		case NV_TYPE_NULL:
813 			ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
814 			break;
815 		case NV_TYPE_BOOL:
816 			ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
817 			break;
818 		case NV_TYPE_NUMBER:
819 			ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
820 			break;
821 		case NV_TYPE_STRING:
822 			ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
823 			break;
824 		case NV_TYPE_NVLIST:
825 			ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
826 			    &tmpnvl);
827 			nvlist_set_parent(tmpnvl, nvp);
828 			break;
829 #ifndef _KERNEL
830 		case NV_TYPE_DESCRIPTOR:
831 			ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
832 			    fds, nfds);
833 			break;
834 #endif
835 		case NV_TYPE_BINARY:
836 			ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
837 			break;
838 		case NV_TYPE_NVLIST_UP:
839 			if (nvl->nvl_parent == NULL)
840 				goto failed;
841 			nvl = nvpair_nvlist(nvl->nvl_parent);
842 			nvpair_free_structure(nvp);
843 			continue;
844 		default:
845 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
846 		}
847 		if (ptr == NULL)
848 			goto failed;
849 		nvlist_move_nvpair(nvl, nvp);
850 		if (tmpnvl != NULL) {
851 			nvl = tmpnvl;
852 			tmpnvl = NULL;
853 		}
854 	}
855 
856 	return (retnvl);
857 failed:
858 	nvlist_destroy(retnvl);
859 	return (NULL);
860 }
861 
862 nvlist_t *
863 nvlist_unpack(const void *buf, size_t size, int flags)
864 {
865 
866 	return (nvlist_xunpack(buf, size, NULL, 0, flags));
867 }
868 
869 #ifndef _KERNEL
870 int
871 nvlist_send(int sock, const nvlist_t *nvl)
872 {
873 	size_t datasize, nfds;
874 	int *fds;
875 	void *data;
876 	int64_t fdidx;
877 	int ret;
878 
879 	if (nvlist_error(nvl) != 0) {
880 		ERRNO_SET(nvlist_error(nvl));
881 		return (-1);
882 	}
883 
884 	fds = nvlist_descriptors(nvl, &nfds);
885 	if (fds == NULL)
886 		return (-1);
887 
888 	ret = -1;
889 	data = NULL;
890 	fdidx = 0;
891 
892 	data = nvlist_xpack(nvl, &fdidx, &datasize);
893 	if (data == NULL)
894 		goto out;
895 
896 	if (buf_send(sock, data, datasize) == -1)
897 		goto out;
898 
899 	if (nfds > 0) {
900 		if (fd_send(sock, fds, nfds) == -1)
901 			goto out;
902 	}
903 
904 	ret = 0;
905 out:
906 	ERRNO_SAVE();
907 	nv_free(fds);
908 	nv_free(data);
909 	ERRNO_RESTORE();
910 	return (ret);
911 }
912 
913 nvlist_t *
914 nvlist_recv(int sock, int flags)
915 {
916 	struct nvlist_header nvlhdr;
917 	nvlist_t *nvl, *ret;
918 	unsigned char *buf;
919 	size_t nfds, size, i;
920 	int *fds;
921 
922 	if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
923 		return (NULL);
924 
925 	if (!nvlist_check_header(&nvlhdr))
926 		return (NULL);
927 
928 	nfds = (size_t)nvlhdr.nvlh_descriptors;
929 	size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
930 
931 	buf = nv_malloc(size);
932 	if (buf == NULL)
933 		return (NULL);
934 
935 	memcpy(buf, &nvlhdr, sizeof(nvlhdr));
936 
937 	ret = NULL;
938 	fds = NULL;
939 
940 	if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
941 		goto out;
942 
943 	if (nfds > 0) {
944 		fds = nv_malloc(nfds * sizeof(fds[0]));
945 		if (fds == NULL)
946 			goto out;
947 		if (fd_recv(sock, fds, nfds) == -1)
948 			goto out;
949 	}
950 
951 	nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
952 	if (nvl == NULL) {
953 		ERRNO_SAVE();
954 		for (i = 0; i < nfds; i++)
955 			close(fds[i]);
956 		ERRNO_RESTORE();
957 		goto out;
958 	}
959 
960 	ret = nvl;
961 out:
962 	ERRNO_SAVE();
963 	nv_free(buf);
964 	nv_free(fds);
965 	ERRNO_RESTORE();
966 
967 	return (ret);
968 }
969 
970 nvlist_t *
971 nvlist_xfer(int sock, nvlist_t *nvl, int flags)
972 {
973 
974 	if (nvlist_send(sock, nvl) < 0) {
975 		nvlist_destroy(nvl);
976 		return (NULL);
977 	}
978 	nvlist_destroy(nvl);
979 	return (nvlist_recv(sock, flags));
980 }
981 #endif
982 
983 nvpair_t *
984 nvlist_first_nvpair(const nvlist_t *nvl)
985 {
986 
987 	NVLIST_ASSERT(nvl);
988 
989 	return (TAILQ_FIRST(&nvl->nvl_head));
990 }
991 
992 nvpair_t *
993 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
994 {
995 	nvpair_t *retnvp;
996 
997 	NVLIST_ASSERT(nvl);
998 	NVPAIR_ASSERT(nvp);
999 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1000 
1001 	retnvp = nvpair_next(nvp);
1002 	PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1003 
1004 	return (retnvp);
1005 
1006 }
1007 
1008 nvpair_t *
1009 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1010 {
1011 	nvpair_t *retnvp;
1012 
1013 	NVLIST_ASSERT(nvl);
1014 	NVPAIR_ASSERT(nvp);
1015 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1016 
1017 	retnvp = nvpair_prev(nvp);
1018 	PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1019 
1020 	return (retnvp);
1021 }
1022 
1023 const char *
1024 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1025 {
1026 	nvpair_t *nvp;
1027 
1028 	NVLIST_ASSERT(nvl);
1029 	PJDLOG_ASSERT(cookiep != NULL);
1030 
1031 	if (*cookiep == NULL)
1032 		nvp = nvlist_first_nvpair(nvl);
1033 	else
1034 		nvp = nvlist_next_nvpair(nvl, *cookiep);
1035 	if (nvp == NULL)
1036 		return (NULL);
1037 	if (typep != NULL)
1038 		*typep = nvpair_type(nvp);
1039 	*cookiep = nvp;
1040 	return (nvpair_name(nvp));
1041 }
1042 
1043 bool
1044 nvlist_exists(const nvlist_t *nvl, const char *name)
1045 {
1046 
1047 	return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1048 }
1049 
1050 #define	NVLIST_EXISTS(type, TYPE)					\
1051 bool									\
1052 nvlist_exists_##type(const nvlist_t *nvl, const char *name)		\
1053 {									\
1054 									\
1055 	return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL);	\
1056 }
1057 
1058 NVLIST_EXISTS(null, NULL)
1059 NVLIST_EXISTS(bool, BOOL)
1060 NVLIST_EXISTS(number, NUMBER)
1061 NVLIST_EXISTS(string, STRING)
1062 NVLIST_EXISTS(nvlist, NVLIST)
1063 #ifndef _KERNEL
1064 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1065 #endif
1066 NVLIST_EXISTS(binary, BINARY)
1067 
1068 #undef	NVLIST_EXISTS
1069 
1070 void
1071 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1072 {
1073 	nvpair_t *newnvp;
1074 
1075 	NVPAIR_ASSERT(nvp);
1076 
1077 	if (nvlist_error(nvl) != 0) {
1078 		ERRNO_SET(nvlist_error(nvl));
1079 		return;
1080 	}
1081 	if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1082 		if (nvlist_exists(nvl, nvpair_name(nvp))) {
1083 			nvl->nvl_error = EEXIST;
1084 			ERRNO_SET(nvlist_error(nvl));
1085 			return;
1086 		}
1087 	}
1088 
1089 	newnvp = nvpair_clone(nvp);
1090 	if (newnvp == NULL) {
1091 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1092 		ERRNO_SET(nvlist_error(nvl));
1093 		return;
1094 	}
1095 
1096 	nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1097 }
1098 
1099 void
1100 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1101 {
1102 	va_list valueap;
1103 
1104 	va_start(valueap, valuefmt);
1105 	nvlist_add_stringv(nvl, name, valuefmt, valueap);
1106 	va_end(valueap);
1107 }
1108 
1109 void
1110 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1111     va_list valueap)
1112 {
1113 	nvpair_t *nvp;
1114 
1115 	if (nvlist_error(nvl) != 0) {
1116 		ERRNO_SET(nvlist_error(nvl));
1117 		return;
1118 	}
1119 
1120 	nvp = nvpair_create_stringv(name, valuefmt, valueap);
1121 	if (nvp == NULL) {
1122 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1123 		ERRNO_SET(nvl->nvl_error);
1124 	} else {
1125 		nvlist_move_nvpair(nvl, nvp);
1126 	}
1127 }
1128 
1129 void
1130 nvlist_add_null(nvlist_t *nvl, const char *name)
1131 {
1132 	nvpair_t *nvp;
1133 
1134 	if (nvlist_error(nvl) != 0) {
1135 		ERRNO_SET(nvlist_error(nvl));
1136 		return;
1137 	}
1138 
1139 	nvp = nvpair_create_null(name);
1140 	if (nvp == NULL) {
1141 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1142 		ERRNO_SET(nvl->nvl_error);
1143 	} else {
1144 		nvlist_move_nvpair(nvl, nvp);
1145 	}
1146 }
1147 
1148 void
1149 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1150     size_t size)
1151 {
1152 	nvpair_t *nvp;
1153 
1154 	if (nvlist_error(nvl) != 0) {
1155 		ERRNO_SET(nvlist_error(nvl));
1156 		return;
1157 	}
1158 
1159 	nvp = nvpair_create_binary(name, value, size);
1160 	if (nvp == NULL) {
1161 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1162 		ERRNO_SET(nvl->nvl_error);
1163 	} else {
1164 		nvlist_move_nvpair(nvl, nvp);
1165 	}
1166 }
1167 
1168 
1169 #define	NVLIST_ADD(vtype, type)						\
1170 void									\
1171 nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value)		\
1172 {									\
1173 	nvpair_t *nvp;							\
1174 									\
1175 	if (nvlist_error(nvl) != 0) {					\
1176 		ERRNO_SET(nvlist_error(nvl));				\
1177 		return;							\
1178 	}								\
1179 									\
1180 	nvp = nvpair_create_##type(name, value);			\
1181 	if (nvp == NULL) {						\
1182 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);		\
1183 		ERRNO_SET(nvl->nvl_error);				\
1184 	} else {							\
1185 		nvlist_move_nvpair(nvl, nvp);				\
1186 	}								\
1187 }
1188 
1189 NVLIST_ADD(bool, bool)
1190 NVLIST_ADD(uint64_t, number)
1191 NVLIST_ADD(const char *, string)
1192 NVLIST_ADD(const nvlist_t *, nvlist)
1193 #ifndef _KERNEL
1194 NVLIST_ADD(int, descriptor);
1195 #endif
1196 
1197 #undef	NVLIST_ADD
1198 
1199 void
1200 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1201 {
1202 
1203 	NVPAIR_ASSERT(nvp);
1204 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1205 
1206 	if (nvlist_error(nvl) != 0) {
1207 		nvpair_free(nvp);
1208 		ERRNO_SET(nvlist_error(nvl));
1209 		return;
1210 	}
1211 	if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1212 		if (nvlist_exists(nvl, nvpair_name(nvp))) {
1213 			nvpair_free(nvp);
1214 			nvl->nvl_error = EEXIST;
1215 			ERRNO_SET(nvl->nvl_error);
1216 			return;
1217 		}
1218 	}
1219 
1220 	nvpair_insert(&nvl->nvl_head, nvp, nvl);
1221 }
1222 
1223 void
1224 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1225 {
1226 	nvpair_t *nvp;
1227 
1228 	if (nvlist_error(nvl) != 0) {
1229 		nv_free(value);
1230 		ERRNO_SET(nvlist_error(nvl));
1231 		return;
1232 	}
1233 
1234 	nvp = nvpair_move_string(name, value);
1235 	if (nvp == NULL) {
1236 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1237 		ERRNO_SET(nvl->nvl_error);
1238 	} else {
1239 		nvlist_move_nvpair(nvl, nvp);
1240 	}
1241 }
1242 
1243 void
1244 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1245 {
1246 	nvpair_t *nvp;
1247 
1248 	if (nvlist_error(nvl) != 0) {
1249 		if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1250 			nvlist_destroy(value);
1251 		ERRNO_SET(nvlist_error(nvl));
1252 		return;
1253 	}
1254 
1255 	nvp = nvpair_move_nvlist(name, value);
1256 	if (nvp == NULL) {
1257 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1258 		ERRNO_SET(nvl->nvl_error);
1259 	} else {
1260 		nvlist_move_nvpair(nvl, nvp);
1261 	}
1262 }
1263 
1264 #ifndef _KERNEL
1265 void
1266 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1267 {
1268 	nvpair_t *nvp;
1269 
1270 	if (nvlist_error(nvl) != 0) {
1271 		close(value);
1272 		ERRNO_SET(nvlist_error(nvl));
1273 		return;
1274 	}
1275 
1276 	nvp = nvpair_move_descriptor(name, value);
1277 	if (nvp == NULL) {
1278 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1279 		ERRNO_SET(nvl->nvl_error);
1280 	} else {
1281 		nvlist_move_nvpair(nvl, nvp);
1282 	}
1283 }
1284 #endif
1285 
1286 void
1287 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1288 {
1289 	nvpair_t *nvp;
1290 
1291 	if (nvlist_error(nvl) != 0) {
1292 		nv_free(value);
1293 		ERRNO_SET(nvlist_error(nvl));
1294 		return;
1295 	}
1296 
1297 	nvp = nvpair_move_binary(name, value, size);
1298 	if (nvp == NULL) {
1299 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1300 		ERRNO_SET(nvl->nvl_error);
1301 	} else {
1302 		nvlist_move_nvpair(nvl, nvp);
1303 	}
1304 }
1305 
1306 const nvpair_t *
1307 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1308 {
1309 
1310 	return (nvlist_find(nvl, NV_TYPE_NONE, name));
1311 }
1312 
1313 #define	NVLIST_GET(ftype, type, TYPE)					\
1314 ftype									\
1315 nvlist_get_##type(const nvlist_t *nvl, const char *name)		\
1316 {									\
1317 	const nvpair_t *nvp;						\
1318 									\
1319 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
1320 	if (nvp == NULL)						\
1321 		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
1322 	return (nvpair_get_##type(nvp));				\
1323 }
1324 
1325 NVLIST_GET(bool, bool, BOOL)
1326 NVLIST_GET(uint64_t, number, NUMBER)
1327 NVLIST_GET(const char *, string, STRING)
1328 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1329 #ifndef _KERNEL
1330 NVLIST_GET(int, descriptor, DESCRIPTOR)
1331 #endif
1332 
1333 #undef	NVLIST_GET
1334 
1335 const void *
1336 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1337 {
1338 	nvpair_t *nvp;
1339 
1340 	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1341 	if (nvp == NULL)
1342 		nvlist_report_missing(NV_TYPE_BINARY, name);
1343 
1344 	return (nvpair_get_binary(nvp, sizep));
1345 }
1346 
1347 #define	NVLIST_TAKE(ftype, type, TYPE)					\
1348 ftype									\
1349 nvlist_take_##type(nvlist_t *nvl, const char *name)			\
1350 {									\
1351 	nvpair_t *nvp;							\
1352 	ftype value;							\
1353 									\
1354 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
1355 	if (nvp == NULL)						\
1356 		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
1357 	value = (ftype)(intptr_t)nvpair_get_##type(nvp);		\
1358 	nvlist_remove_nvpair(nvl, nvp);					\
1359 	nvpair_free_structure(nvp);					\
1360 	return (value);							\
1361 }
1362 
1363 NVLIST_TAKE(bool, bool, BOOL)
1364 NVLIST_TAKE(uint64_t, number, NUMBER)
1365 NVLIST_TAKE(char *, string, STRING)
1366 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1367 #ifndef _KERNEL
1368 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1369 #endif
1370 
1371 #undef	NVLIST_TAKE
1372 
1373 void *
1374 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1375 {
1376 	nvpair_t *nvp;
1377 	void *value;
1378 
1379 	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1380 	if (nvp == NULL)
1381 		nvlist_report_missing(NV_TYPE_BINARY, name);
1382 
1383 	value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1384 	nvlist_remove_nvpair(nvl, nvp);
1385 	nvpair_free_structure(nvp);
1386 	return (value);
1387 }
1388 
1389 void
1390 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1391 {
1392 
1393 	NVLIST_ASSERT(nvl);
1394 	NVPAIR_ASSERT(nvp);
1395 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1396 
1397 	nvpair_remove(&nvl->nvl_head, nvp, nvl);
1398 }
1399 
1400 void
1401 nvlist_free(nvlist_t *nvl, const char *name)
1402 {
1403 
1404 	nvlist_free_type(nvl, name, NV_TYPE_NONE);
1405 }
1406 
1407 #define	NVLIST_FREE(type, TYPE)						\
1408 void									\
1409 nvlist_free_##type(nvlist_t *nvl, const char *name)			\
1410 {									\
1411 									\
1412 	nvlist_free_type(nvl, name, NV_TYPE_##TYPE);			\
1413 }
1414 
1415 NVLIST_FREE(null, NULL)
1416 NVLIST_FREE(bool, BOOL)
1417 NVLIST_FREE(number, NUMBER)
1418 NVLIST_FREE(string, STRING)
1419 NVLIST_FREE(nvlist, NVLIST)
1420 #ifndef _KERNEL
1421 NVLIST_FREE(descriptor, DESCRIPTOR)
1422 #endif
1423 NVLIST_FREE(binary, BINARY)
1424 
1425 #undef	NVLIST_FREE
1426 
1427 void
1428 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1429 {
1430 
1431 	NVLIST_ASSERT(nvl);
1432 	NVPAIR_ASSERT(nvp);
1433 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1434 
1435 	nvlist_remove_nvpair(nvl, nvp);
1436 	nvpair_free(nvp);
1437 }
1438 
1439