xref: /NextBSD/lib/libxpc/subr_nvlist.c (revision 7498fff0e4320dcdb870dbe7586a6102809cfc82)
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 "nv.h"
68 #include "nv_impl.h"
69 #include "nvlist_impl.h"
70 #include "nvpair_impl.h"
71 
72 #ifndef	HAVE_PJDLOG
73 #ifdef _KERNEL
74 #define	PJDLOG_ASSERT(...)		MPASS(__VA_ARGS__)
75 #define	PJDLOG_RASSERT(expr, ...)	KASSERT(expr, (__VA_ARGS__))
76 #define	PJDLOG_ABORT(...)		panic(__VA_ARGS__)
77 #else
78 #include <assert.h>
79 #define	PJDLOG_ASSERT(...)		assert(__VA_ARGS__)
80 #define	PJDLOG_RASSERT(expr, ...)	assert(expr)
81 #define	PJDLOG_ABORT(...)		do {				\
82 	fprintf(stderr, "%s:%u: ", __FILE__, __LINE__);			\
83 	fprintf(stderr, __VA_ARGS__);					\
84 	fprintf(stderr, "\n");						\
85 	abort();							\
86 } while (0)
87 #endif
88 #endif
89 
90 #define	NV_FLAG_PRIVATE_MASK	(NV_FLAG_BIG_ENDIAN)
91 #define	NV_FLAG_PUBLIC_MASK	(NV_FLAG_IGNORE_CASE)
92 #define	NV_FLAG_ALL_MASK	(NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
93 
94 #define	NVLIST_MAGIC	0x6e766c	/* "nvl" */
95 struct nvlist {
96 	int		 nvl_magic;
97 	int		 nvl_error;
98 	int		 nvl_flags;
99 	int		 nvl_type;
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 	uint8_t		nvlh_type;
122 	uint64_t	nvlh_descriptors;
123 	uint64_t	nvlh_size;
124 } __packed;
125 
126 nvlist_t *
nvlist_create(int flags)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 	nvl->nvl_error = 0;
135 	nvl->nvl_flags = flags;
136 	nvl->nvl_parent = NULL;
137 	nvl->nvl_type = NV_TYPE_NVLIST;
138 	TAILQ_INIT(&nvl->nvl_head);
139 	nvl->nvl_magic = NVLIST_MAGIC;
140 
141 	return (nvl);
142 }
143 
144 nvlist_t *
nvlist_create_array(int flags)145 nvlist_create_array(int flags)
146 {
147 	nvlist_t *nvl;
148 
149 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
150 
151 	nvl = nv_malloc(sizeof(*nvl));
152 	nvl->nvl_error = 0;
153 	nvl->nvl_flags = flags;
154 	nvl->nvl_parent = NULL;
155 	nvl->nvl_type = NV_TYPE_NVLIST_ARRAY;
156 	TAILQ_INIT(&nvl->nvl_head);
157 	nvl->nvl_magic = NVLIST_MAGIC;
158 
159 	return (nvl);
160 }
161 
162 nvlist_t *
nvlist_create_dictionary(int flags)163 nvlist_create_dictionary(int flags)
164 {
165 	nvlist_t *nvl;
166 
167 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
168 
169 	nvl = nv_malloc(sizeof(*nvl));
170 	nvl->nvl_error = 0;
171 	nvl->nvl_flags = flags;
172 	nvl->nvl_parent = NULL;
173 	nvl->nvl_type = NV_TYPE_NVLIST_DICTIONARY;
174 	TAILQ_INIT(&nvl->nvl_head);
175 	nvl->nvl_magic = NVLIST_MAGIC;
176 
177 	printf("1 nvl = %p\n", nvl);
178 	return (nvl);
179 }
180 
181 void
nvlist_destroy(nvlist_t * nvl)182 nvlist_destroy(nvlist_t *nvl)
183 {
184 	nvpair_t *nvp;
185 	int serrno;
186 
187 	if (nvl == NULL)
188 		return;
189 
190 	SAVE_ERRNO(serrno);
191 
192 	NVLIST_ASSERT(nvl);
193 
194 	while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
195 		nvlist_remove_nvpair(nvl, nvp);
196 		nvpair_free(nvp);
197 	}
198 	nvl->nvl_magic = 0;
199 	nv_free(nvl);
200 
201 	RESTORE_ERRNO(serrno);
202 }
203 
204 void
nvlist_set_error(nvlist_t * nvl,int error)205 nvlist_set_error(nvlist_t *nvl, int error)
206 {
207 
208 	PJDLOG_ASSERT(error != 0);
209 
210 	/*
211 	 * Check for error != 0 so that we don't do the wrong thing if somebody
212 	 * tries to abuse this API when asserts are disabled.
213 	 */
214 	if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
215 		nvl->nvl_error = error;
216 }
217 
218 int
nvlist_error(const nvlist_t * nvl)219 nvlist_error(const nvlist_t *nvl)
220 {
221 
222 	if (nvl == NULL)
223 		return (ENOMEM);
224 
225 	NVLIST_ASSERT(nvl);
226 
227 	return (nvl->nvl_error);
228 }
229 
230 nvpair_t *
nvlist_get_nvpair_parent(const nvlist_t * nvl)231 nvlist_get_nvpair_parent(const nvlist_t *nvl)
232 {
233 
234 	NVLIST_ASSERT(nvl);
235 
236 	return (nvl->nvl_parent);
237 }
238 
239 const nvlist_t *
nvlist_get_parent(const nvlist_t * nvl,void ** cookiep)240 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
241 {
242 	nvpair_t *nvp;
243 
244 	NVLIST_ASSERT(nvl);
245 
246 	nvp = nvl->nvl_parent;
247 	if (cookiep != NULL)
248 		*cookiep = nvp;
249 	if (nvp == NULL)
250 		return (NULL);
251 
252 	return (nvpair_nvlist(nvp));
253 }
254 
255 void
nvlist_set_parent(nvlist_t * nvl,nvpair_t * parent)256 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
257 {
258 
259 	NVLIST_ASSERT(nvl);
260 
261 	nvl->nvl_parent = parent;
262 }
263 
264 bool
nvlist_empty(const nvlist_t * nvl)265 nvlist_empty(const nvlist_t *nvl)
266 {
267 
268 	NVLIST_ASSERT(nvl);
269 	PJDLOG_ASSERT(nvl->nvl_error == 0);
270 
271 	return (nvlist_first_nvpair(nvl) == NULL);
272 }
273 
274 int
nvlist_type(const nvlist_t * nvl)275 nvlist_type(const nvlist_t *nvl)
276 {
277 
278 	NVLIST_ASSERT(nvl);
279 	PJDLOG_ASSERT(nvl->nvl_error == 0);
280 
281 	return (nvl->nvl_type);
282 }
283 
284 static void
nvlist_report_missing(int type,const char * name)285 nvlist_report_missing(int type, const char *name)
286 {
287 
288 	PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
289 	    name, nvpair_type_string(type));
290 }
291 
292 static nvpair_t *
nvlist_find(const nvlist_t * nvl,int type,const char * name)293 nvlist_find(const nvlist_t *nvl, int type, const char *name)
294 {
295 	nvpair_t *nvp;
296 
297 	NVLIST_ASSERT(nvl);
298 	PJDLOG_ASSERT(nvl->nvl_error == 0);
299 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
300 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
301 
302 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
303 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
304 		if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
305 			continue;
306 		if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
307 			if (strcasecmp(nvpair_name(nvp), name) != 0)
308 				continue;
309 		} else {
310 			if (strcmp(nvpair_name(nvp), name) != 0)
311 				continue;
312 		}
313 		break;
314 	}
315 
316 	if (nvp == NULL)
317 		RESTORE_ERRNO(ENOENT);
318 
319 	return (nvp);
320 }
321 
322 bool
nvlist_exists_type(const nvlist_t * nvl,const char * name,int type)323 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
324 {
325 
326 	NVLIST_ASSERT(nvl);
327 	PJDLOG_ASSERT(nvl->nvl_error == 0);
328 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
329 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
330 
331 	return (nvlist_find(nvl, type, name) != NULL);
332 }
333 
334 #ifndef _KERNEL
335 bool
nvlist_existsf_type(const nvlist_t * nvl,int type,const char * namefmt,...)336 nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...)
337 {
338 	va_list nameap;
339 	bool ret;
340 
341 	va_start(nameap, namefmt);
342 	ret = nvlist_existsv_type(nvl, type, namefmt, nameap);
343 	va_end(nameap);
344 
345 	return (ret);
346 }
347 
348 bool
nvlist_existsv_type(const nvlist_t * nvl,int type,const char * namefmt,va_list nameap)349 nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt,
350     va_list nameap)
351 {
352 	char *name;
353 	bool exists;
354 
355 	nv_vasprintf(&name, namefmt, nameap);
356 	if (name == NULL)
357 		return (false);
358 
359 	exists = nvlist_exists_type(nvl, name, type);
360 	nv_free(name);
361 	return (exists);
362 }
363 #endif
364 
365 void
nvlist_free_type(nvlist_t * nvl,const char * name,int type)366 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
367 {
368 	nvpair_t *nvp;
369 
370 	NVLIST_ASSERT(nvl);
371 	PJDLOG_ASSERT(nvl->nvl_error == 0);
372 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
373 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
374 
375 	nvp = nvlist_find(nvl, type, name);
376 	if (nvp != NULL)
377 		nvlist_free_nvpair(nvl, nvp);
378 	else
379 		nvlist_report_missing(type, name);
380 }
381 
382 #ifndef _KERNEL
383 void
nvlist_freef_type(nvlist_t * nvl,int type,const char * namefmt,...)384 nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...)
385 {
386 	va_list nameap;
387 
388 	va_start(nameap, namefmt);
389 	nvlist_freev_type(nvl, type, namefmt, nameap);
390 	va_end(nameap);
391 }
392 
393 void
nvlist_freev_type(nvlist_t * nvl,int type,const char * namefmt,va_list nameap)394 nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
395 {
396 	char *name;
397 
398 	nv_vasprintf(&name, namefmt, nameap);
399 	if (name == NULL)
400 		nvlist_report_missing(type, "<unknown>");
401 	nvlist_free_type(nvl, name, type);
402 	nv_free(name);
403 }
404 #endif
405 
406 nvlist_t *
nvlist_clone(const nvlist_t * nvl)407 nvlist_clone(const nvlist_t *nvl)
408 {
409 	nvlist_t *newnvl;
410 	nvpair_t *nvp, *newnvp;
411 
412 	NVLIST_ASSERT(nvl);
413 
414 	if (nvl->nvl_error != 0) {
415 		RESTORE_ERRNO(nvl->nvl_error);
416 		return (NULL);
417 	}
418 
419 	newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
420 	newnvl->nvl_type = nvl->nvl_type;
421 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
422 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
423 		newnvp = nvpair_clone(nvp);
424 		if (newnvp == NULL)
425 			break;
426 		nvlist_move_nvpair(newnvl, newnvp);
427 	}
428 	if (nvp != NULL) {
429 		nvlist_destroy(newnvl);
430 		return (NULL);
431 	}
432 	return (newnvl);
433 }
434 
435 #ifndef _KERNEL
436 static bool
nvlist_dump_error_check(const nvlist_t * nvl,int fd,int level)437 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
438 {
439 
440 	if (nvlist_error(nvl) != 0) {
441 		dprintf(fd, "%*serror: %d\n", level * 4, "",
442 		    nvlist_error(nvl));
443 		return (true);
444 	}
445 
446 	return (false);
447 }
448 
449 /*
450  * Dump content of nvlist.
451  */
452 void
nvlist_dump(const nvlist_t * nvl,int fd)453 nvlist_dump(const nvlist_t *nvl, int fd)
454 {
455 	const nvlist_t *tmpnvl;
456 	nvpair_t *nvp, *tmpnvp;
457 	void *cookie;
458 	int level;
459 
460 	level = 0;
461 	if (nvlist_dump_error_check(nvl, fd, level))
462 		return;
463 
464 	nvp = nvlist_first_nvpair(nvl);
465 	while (nvp != NULL) {
466 		dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
467 		    nvpair_type_string(nvpair_type(nvp)));
468 		switch (nvpair_type(nvp)) {
469 		case NV_TYPE_NULL:
470 			dprintf(fd, " null\n");
471 			break;
472 		case NV_TYPE_BOOL:
473 			dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
474 			    "TRUE" : "FALSE");
475 			break;
476 		case NV_TYPE_NUMBER:
477 		case NV_TYPE_PTR:
478 		case NV_TYPE_UINT64:
479 		case NV_TYPE_INT64:
480 		case NV_TYPE_ENDPOINT:
481 		case NV_TYPE_DATE:
482 			dprintf(fd, " %ju (%jd) (0x%jx)\n",
483 			    (uintmax_t)nvpair_get_number(nvp),
484 			    (intmax_t)nvpair_get_number(nvp),
485 			    (uintmax_t)nvpair_get_number(nvp));
486 			break;
487 		case NV_TYPE_STRING:
488 			dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
489 			break;
490 		case NV_TYPE_NVLIST:
491 		case NV_TYPE_NVLIST_ARRAY:
492 		case NV_TYPE_NVLIST_DICTIONARY:
493 			dprintf(fd, "\n");
494 			tmpnvl = nvpair_get_nvlist(nvp);
495 			if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
496 				break;
497 			tmpnvp = nvlist_first_nvpair(tmpnvl);
498 			if (tmpnvp != NULL) {
499 				nvl = tmpnvl;
500 				nvp = tmpnvp;
501 				level++;
502 				continue;
503 			}
504 			break;
505 		case NV_TYPE_DESCRIPTOR:
506 			dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
507 			break;
508 		case NV_TYPE_BINARY:
509 		    {
510 			const unsigned char *binary;
511 			unsigned int ii;
512 			size_t size;
513 
514 			binary = nvpair_get_binary(nvp, &size);
515 			dprintf(fd, " %zu ", size);
516 			for (ii = 0; ii < size; ii++)
517 				dprintf(fd, "%02hhx", binary[ii]);
518 			dprintf(fd, "\n");
519 			break;
520 		    }
521 		case NV_TYPE_UUID:
522 		    {
523 		    	char *str;
524 		    	int status;
525 		    	const uuid_t *uuid;
526 
527 		    	uuid = nvpair_get_uuid(nvp);
528 		    	uuid_to_string(uuid, &str, &status);
529 		    	if (status == uuid_s_ok)
530 		    		dprintf(fd, " [%s]\n", str);
531 
532 		    	free(str);
533 		    	break;
534 		    }
535 		default:
536 			PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
537 		}
538 
539 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
540 			cookie = NULL;
541 			nvl = nvlist_get_parent(nvl, &cookie);
542 			if (nvl == NULL)
543 				return;
544 			nvp = cookie;
545 			level--;
546 		}
547 	}
548 }
549 
550 void
nvlist_fdump(const nvlist_t * nvl,FILE * fp)551 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
552 {
553 
554 	fflush(fp);
555 	nvlist_dump(nvl, fileno(fp));
556 }
557 #endif
558 
559 /*
560  * The function obtains size of the nvlist after nvlist_pack().
561  */
562 size_t
nvlist_size(const nvlist_t * nvl)563 nvlist_size(const nvlist_t *nvl)
564 {
565 	const nvlist_t *tmpnvl;
566 	const nvpair_t *nvp, *tmpnvp;
567 	void *cookie;
568 	size_t size;
569 
570 	NVLIST_ASSERT(nvl);
571 	PJDLOG_ASSERT(nvl->nvl_error == 0);
572 
573 	size = sizeof(struct nvlist_header);
574 	nvp = nvlist_first_nvpair(nvl);
575 	while (nvp != NULL) {
576 		size += nvpair_header_size();
577 		size += strlen(nvpair_name(nvp)) + 1;
578 		if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY ||
579 			nvpair_type(nvp) == NV_TYPE_NVLIST_DICTIONARY ||
580 			nvpair_type(nvp) == NV_TYPE_NVLIST) {
581 			size += sizeof(struct nvlist_header);
582 			size += nvpair_header_size() + 1;
583 			tmpnvl = nvpair_get_nvlist(nvp);
584 			PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
585 			tmpnvp = nvlist_first_nvpair(tmpnvl);
586 			if (tmpnvp != NULL) {
587 				nvl = tmpnvl;
588 				nvp = tmpnvp;
589 				continue;
590 			}
591 		} else {
592 			size += nvpair_size(nvp);
593 		}
594 
595 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
596 			cookie = NULL;
597 			nvl = nvlist_get_parent(nvl, &cookie);
598 			if (nvl == NULL)
599 				goto out;
600 			nvp = cookie;
601 		}
602 	}
603 
604 out:
605 	return (size);
606 }
607 
608 #ifndef _KERNEL
609 static int *
nvlist_xdescriptors(const nvlist_t * nvl,int * descs,int level)610 nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
611 {
612 	const nvpair_t *nvp;
613 
614 	NVLIST_ASSERT(nvl);
615 	PJDLOG_ASSERT(nvl->nvl_error == 0);
616 	PJDLOG_ASSERT(level < 3);
617 
618 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
619 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
620 		switch (nvpair_type(nvp)) {
621 		case NV_TYPE_DESCRIPTOR:
622 			*descs = nvpair_get_descriptor(nvp);
623 			descs++;
624 			break;
625 		case NV_TYPE_NVLIST:
626 		case NV_TYPE_NVLIST_ARRAY:
627 		case NV_TYPE_NVLIST_DICTIONARY:
628 			descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
629 			    descs, level + 1);
630 			break;
631 		}
632 	}
633 
634 	return (descs);
635 }
636 #endif
637 
638 #ifndef _KERNEL
639 int *
nvlist_descriptors(const nvlist_t * nvl,size_t * nitemsp)640 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
641 {
642 	size_t nitems;
643 	int *fds;
644 
645 	nitems = nvlist_ndescriptors(nvl);
646 	fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
647 	if (fds == NULL)
648 		return (NULL);
649 	if (nitems > 0)
650 		nvlist_xdescriptors(nvl, fds, 0);
651 	fds[nitems] = -1;
652 	if (nitemsp != NULL)
653 		*nitemsp = nitems;
654 	return (fds);
655 }
656 #endif
657 
658 static size_t
nvlist_xndescriptors(const nvlist_t * nvl,int level)659 nvlist_xndescriptors(const nvlist_t *nvl, int level)
660 {
661 #ifndef _KERNEL
662 	const nvpair_t *nvp;
663 	size_t ndescs;
664 
665 	NVLIST_ASSERT(nvl);
666 	PJDLOG_ASSERT(nvl->nvl_error == 0);
667 	PJDLOG_ASSERT(level < 3);
668 
669 	ndescs = 0;
670 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
671 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
672 		switch (nvpair_type(nvp)) {
673 		case NV_TYPE_DESCRIPTOR:
674 			ndescs++;
675 			break;
676 		case NV_TYPE_NVLIST:
677 		case NV_TYPE_NVLIST_ARRAY:
678 		case NV_TYPE_NVLIST_DICTIONARY:
679 			ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
680 			    level + 1);
681 			break;
682 		}
683 	}
684 
685 	return (ndescs);
686 #else
687 	return (0);
688 #endif
689 }
690 
691 size_t
nvlist_ndescriptors(const nvlist_t * nvl)692 nvlist_ndescriptors(const nvlist_t *nvl)
693 {
694 
695 	return (nvlist_xndescriptors(nvl, 0));
696 }
697 
698 static unsigned char *
nvlist_pack_header(const nvlist_t * nvl,unsigned char * ptr,size_t * leftp)699 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
700 {
701 	struct nvlist_header nvlhdr;
702 
703 	NVLIST_ASSERT(nvl);
704 
705 	nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
706 	nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
707 	nvlhdr.nvlh_flags = nvl->nvl_flags;
708 	nvlhdr.nvlh_type = (uint8_t)nvl->nvl_type;
709 #if BYTE_ORDER == BIG_ENDIAN
710 	nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
711 #endif
712 	nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
713 	nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
714 	PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
715 	memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
716 	ptr += sizeof(nvlhdr);
717 	*leftp -= sizeof(nvlhdr);
718 
719 	return (ptr);
720 }
721 
722 void *
nvlist_xpack(const nvlist_t * nvl,void * ubuf,int64_t * fdidxp,size_t * sizep)723 nvlist_xpack(const nvlist_t *nvl, void *ubuf, int64_t *fdidxp, size_t *sizep)
724 {
725 	unsigned char *buf, *ptr;
726 	size_t left, size;
727 	const nvlist_t *tmpnvl;
728 	nvpair_t *nvp, *tmpnvp;
729 	void *cookie;
730 
731 	NVLIST_ASSERT(nvl);
732 
733 	if (nvl->nvl_error != 0) {
734 		RESTORE_ERRNO(nvl->nvl_error);
735 		return (NULL);
736 	}
737 
738 	size = nvlist_size(nvl);
739 	if (ubuf) {
740 		if (sizep == NULL || *sizep != size)
741 			return (NULL);
742 		else
743 			buf = ubuf;
744 	} else
745 		buf = nv_malloc(size);
746 	if (buf == NULL)
747 		return (NULL);
748 
749 	ptr = buf;
750 	left = size;
751 
752 	ptr = nvlist_pack_header(nvl, ptr, &left);
753 
754 	nvp = nvlist_first_nvpair(nvl);
755 	while (nvp != NULL) {
756 		NVPAIR_ASSERT(nvp);
757 
758 		nvpair_init_datasize(nvp);
759 		ptr = nvpair_pack_header(nvp, ptr, &left);
760 		if (ptr == NULL) {
761 			nv_free(buf);
762 			return (NULL);
763 		}
764 		switch (nvpair_type(nvp)) {
765 		case NV_TYPE_NULL:
766 			ptr = nvpair_pack_null(nvp, ptr, &left);
767 			break;
768 		case NV_TYPE_BOOL:
769 			ptr = nvpair_pack_bool(nvp, ptr, &left);
770 			break;
771 		case NV_TYPE_NUMBER:
772 		case NV_TYPE_PTR:
773 		case NV_TYPE_UINT64:
774 		case NV_TYPE_INT64:
775 		case NV_TYPE_ENDPOINT:
776 			ptr = nvpair_pack_number(nvp, ptr, &left);
777 			break;
778 		case NV_TYPE_STRING:
779 			ptr = nvpair_pack_string(nvp, ptr, &left);
780 			break;
781 		case NV_TYPE_NVLIST:
782 		case NV_TYPE_NVLIST_ARRAY:
783 		case NV_TYPE_NVLIST_DICTIONARY:
784 			tmpnvl = nvpair_get_nvlist(nvp);
785 			ptr = nvlist_pack_header(tmpnvl, ptr, &left);
786 			if (ptr == NULL)
787 				goto out;
788 			tmpnvp = nvlist_first_nvpair(tmpnvl);
789 			if (tmpnvp != NULL) {
790 				nvl = tmpnvl;
791 				nvp = tmpnvp;
792 				continue;
793 			}
794 			ptr = nvpair_pack_nvlist_up(ptr, &left);
795 			break;
796 #ifndef _KERNEL
797 		case NV_TYPE_DESCRIPTOR:
798 			ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
799 			break;
800 #endif
801 		case NV_TYPE_BINARY:
802 		case NV_TYPE_UUID:
803 			ptr = nvpair_pack_binary(nvp, ptr, &left);
804 			break;
805 		default:
806 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
807 		}
808 		if (ptr == NULL) {
809 			nv_free(buf);
810 			return (NULL);
811 		}
812 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
813 			cookie = NULL;
814 			nvl = nvlist_get_parent(nvl, &cookie);
815 			if (nvl == NULL)
816 				goto out;
817 			nvp = cookie;
818 			ptr = nvpair_pack_nvlist_up(ptr, &left);
819 			if (ptr == NULL)
820 				goto out;
821 		}
822 	}
823 
824 out:
825 	if (sizep != NULL)
826 		*sizep = size;
827 	return (buf);
828 }
829 
830 void *
nvlist_pack(const nvlist_t * nvl,size_t * sizep)831 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
832 {
833 
834 	return (nvlist_pack_buffer(nvl, NULL, sizep));
835 }
836 
837 void *
nvlist_pack_buffer(const nvlist_t * nvl,void * ubuf,size_t * sizep)838 nvlist_pack_buffer(const nvlist_t *nvl, void *ubuf, size_t *sizep)
839 {
840 
841 	NVLIST_ASSERT(nvl);
842 
843 	if (nvl->nvl_error != 0) {
844 		RESTORE_ERRNO(nvl->nvl_error);
845 		return (NULL);
846 	}
847 
848 	if (nvlist_ndescriptors(nvl) > 0) {
849 		RESTORE_ERRNO(EOPNOTSUPP);
850 		return (NULL);
851 	}
852 
853 	return (nvlist_xpack(nvl, ubuf, NULL, sizep));
854 }
855 
856 static bool
nvlist_check_header(struct nvlist_header * nvlhdrp)857 nvlist_check_header(struct nvlist_header *nvlhdrp)
858 {
859 
860 	if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
861 		RESTORE_ERRNO(EINVAL);
862 		return (false);
863 	}
864 	if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
865 		RESTORE_ERRNO(EINVAL);
866 		return (false);
867 	}
868 #if BYTE_ORDER == BIG_ENDIAN
869 	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
870 		nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
871 		nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
872 	}
873 #else
874 	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
875 		nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
876 		nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
877 	}
878 #endif
879 	return (true);
880 }
881 
882 const unsigned char *
nvlist_unpack_header(nvlist_t * nvl,const unsigned char * ptr,size_t nfds,bool * isbep,size_t * leftp)883 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
884     bool *isbep, size_t *leftp)
885 {
886 	struct nvlist_header nvlhdr;
887 
888 	if (*leftp < sizeof(nvlhdr))
889 		goto failed;
890 
891 	memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
892 
893 	if (!nvlist_check_header(&nvlhdr))
894 		goto failed;
895 
896 	if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
897 		goto failed;
898 
899 	/*
900 	 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
901 	 */
902 	if (nvlhdr.nvlh_descriptors > nfds)
903 		goto failed;
904 
905 	if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
906 		goto failed;
907 
908 	nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
909 
910 	ptr += sizeof(nvlhdr);
911 	if (isbep != NULL)
912 		*isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
913 	*leftp -= sizeof(nvlhdr);
914 
915 	nvl->nvl_type = nvlhdr.nvlh_type;
916 	return (ptr);
917 failed:
918 	RESTORE_ERRNO(EINVAL);
919 	return (NULL);
920 }
921 
922 nvlist_t *
nvlist_xunpack(const void * buf,size_t size,const int * fds,size_t nfds)923 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
924 {
925 	const unsigned char *ptr;
926 	nvlist_t *nvl, *retnvl, *tmpnvl;
927 	nvpair_t *nvp;
928 	size_t left;
929 	bool isbe;
930 
931 	left = size;
932 	ptr = buf;
933 
934 	tmpnvl = NULL;
935 	nvl = retnvl = nvlist_create(0);
936 	if (nvl == NULL)
937 		goto failed;
938 
939 	ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
940 	if (ptr == NULL)
941 		goto failed;
942 
943 	while (left > 0) {
944 		ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
945 		if (ptr == NULL)
946 			goto failed;
947 		switch (nvpair_type(nvp)) {
948 		case NV_TYPE_NULL:
949 			ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
950 			break;
951 		case NV_TYPE_BOOL:
952 			ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
953 			break;
954 		case NV_TYPE_NUMBER:
955 		case NV_TYPE_PTR:
956 		case NV_TYPE_UINT64:
957 		case NV_TYPE_INT64:
958 		case NV_TYPE_ENDPOINT:
959 			ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
960 			break;
961 		case NV_TYPE_STRING:
962 			ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
963 			break;
964 		case NV_TYPE_NVLIST:
965 		case NV_TYPE_NVLIST_ARRAY:
966 		case NV_TYPE_NVLIST_DICTIONARY:
967 			ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
968 			    &tmpnvl);
969 			nvlist_set_parent(tmpnvl, nvp);
970 			break;
971 #ifndef _KERNEL
972 		case NV_TYPE_DESCRIPTOR:
973 			ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
974 			    fds, nfds);
975 			break;
976 #endif
977 		case NV_TYPE_BINARY:
978 		case NV_TYPE_UUID:
979 			ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
980 			break;
981 		case NV_TYPE_NVLIST_UP:
982 			if (nvl->nvl_parent == NULL)
983 				goto failed;
984 			nvl = nvpair_nvlist(nvl->nvl_parent);
985 			continue;
986 		default:
987 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
988 		}
989 		if (ptr == NULL)
990 			goto failed;
991 		nvlist_move_nvpair(nvl, nvp);
992 		if (tmpnvl != NULL) {
993 			nvl = tmpnvl;
994 			tmpnvl = NULL;
995 		}
996 	}
997 
998 	return (retnvl);
999 failed:
1000 	nvlist_destroy(retnvl);
1001 	return (NULL);
1002 }
1003 
1004 nvlist_t *
nvlist_unpack(const void * buf,size_t size)1005 nvlist_unpack(const void *buf, size_t size)
1006 {
1007 
1008 	return (nvlist_xunpack(buf, size, NULL, 0));
1009 }
1010 
1011 #ifndef _KERNEL
1012 int
nvlist_send(int sock,const nvlist_t * nvl)1013 nvlist_send(int sock, const nvlist_t *nvl)
1014 {
1015 	size_t datasize, nfds;
1016 	int *fds;
1017 	void *data;
1018 	int64_t fdidx;
1019 	int serrno, ret;
1020 
1021 	if (nvlist_error(nvl) != 0) {
1022 		errno = nvlist_error(nvl);
1023 		return (-1);
1024 	}
1025 
1026 	fds = nvlist_descriptors(nvl, &nfds);
1027 	if (fds == NULL)
1028 		return (-1);
1029 
1030 	ret = -1;
1031 	data = NULL;
1032 	fdidx = 0;
1033 
1034 	data = nvlist_xpack(nvl, NULL, &fdidx, &datasize);
1035 	if (data == NULL)
1036 		goto out;
1037 
1038 	if (buf_send(sock, data, datasize) == -1)
1039 		goto out;
1040 
1041 	if (nfds > 0) {
1042 		if (fd_send(sock, fds, nfds) == -1)
1043 			goto out;
1044 	}
1045 
1046 	ret = 0;
1047 out:
1048 	serrno = errno;
1049 	free(fds);
1050 	free(data);
1051 	errno = serrno;
1052 	return (ret);
1053 }
1054 
1055 nvlist_t *
nvlist_recv(int sock)1056 nvlist_recv(int sock)
1057 {
1058 	struct nvlist_header nvlhdr;
1059 	nvlist_t *nvl, *ret;
1060 	unsigned char *buf;
1061 	size_t nfds, size, i;
1062 	int serrno, *fds;
1063 
1064 	if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
1065 		return (NULL);
1066 
1067 	if (!nvlist_check_header(&nvlhdr))
1068 		return (NULL);
1069 
1070 	nfds = (size_t)nvlhdr.nvlh_descriptors;
1071 	size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
1072 
1073 	buf = malloc(size);
1074 	if (buf == NULL)
1075 		return (NULL);
1076 
1077 	memcpy(buf, &nvlhdr, sizeof(nvlhdr));
1078 
1079 	ret = NULL;
1080 	fds = NULL;
1081 
1082 	if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
1083 		goto out;
1084 
1085 	if (nfds > 0) {
1086 		fds = malloc(nfds * sizeof(fds[0]));
1087 		if (fds == NULL)
1088 			goto out;
1089 		if (fd_recv(sock, fds, nfds) == -1)
1090 			goto out;
1091 	}
1092 
1093 	nvl = nvlist_xunpack(buf, size, fds, nfds);
1094 	if (nvl == NULL) {
1095 		for (i = 0; i < nfds; i++)
1096 			close(fds[i]);
1097 		goto out;
1098 	}
1099 
1100 	ret = nvl;
1101 out:
1102 	serrno = errno;
1103 	free(buf);
1104 	free(fds);
1105 	errno = serrno;
1106 
1107 	return (ret);
1108 }
1109 
1110 nvlist_t *
nvlist_xfer(int sock,nvlist_t * nvl)1111 nvlist_xfer(int sock, nvlist_t *nvl)
1112 {
1113 
1114 	if (nvlist_send(sock, nvl) < 0) {
1115 		nvlist_destroy(nvl);
1116 		return (NULL);
1117 	}
1118 	nvlist_destroy(nvl);
1119 	return (nvlist_recv(sock));
1120 }
1121 #endif
1122 
1123 nvpair_t *
nvlist_first_nvpair(const nvlist_t * nvl)1124 nvlist_first_nvpair(const nvlist_t *nvl)
1125 {
1126 
1127 	NVLIST_ASSERT(nvl);
1128 
1129 	return (TAILQ_FIRST(&nvl->nvl_head));
1130 }
1131 
1132 nvpair_t *
nvlist_next_nvpair(const nvlist_t * nvl,const nvpair_t * nvp)1133 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1134 {
1135 	nvpair_t *retnvp;
1136 
1137 	NVLIST_ASSERT(nvl);
1138 	NVPAIR_ASSERT(nvp);
1139 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1140 
1141 	retnvp = nvpair_next(nvp);
1142 	PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1143 
1144 	return (retnvp);
1145 
1146 }
1147 
1148 nvpair_t *
nvlist_prev_nvpair(const nvlist_t * nvl,const nvpair_t * nvp)1149 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1150 {
1151 	nvpair_t *retnvp;
1152 
1153 	NVLIST_ASSERT(nvl);
1154 	NVPAIR_ASSERT(nvp);
1155 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1156 
1157 	retnvp = nvpair_prev(nvp);
1158 	PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1159 
1160 	return (retnvp);
1161 }
1162 
1163 const char *
nvlist_next(const nvlist_t * nvl,int * typep,void ** cookiep)1164 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1165 {
1166 	nvpair_t *nvp;
1167 
1168 	NVLIST_ASSERT(nvl);
1169 	PJDLOG_ASSERT(cookiep != NULL);
1170 
1171 	if (*cookiep == NULL)
1172 		nvp = nvlist_first_nvpair(nvl);
1173 	else
1174 		nvp = nvlist_next_nvpair(nvl, *cookiep);
1175 	if (nvp == NULL)
1176 		return (NULL);
1177 	if (typep != NULL)
1178 		*typep = nvpair_type(nvp);
1179 	*cookiep = nvp;
1180 	return (nvpair_name(nvp));
1181 }
1182 
1183 bool
nvlist_exists(const nvlist_t * nvl,const char * name)1184 nvlist_exists(const nvlist_t *nvl, const char *name)
1185 {
1186 
1187 	return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1188 }
1189 
1190 #define	NVLIST_EXISTS(type, TYPE)					\
1191 bool									\
1192 nvlist_exists_##type(const nvlist_t *nvl, const char *name)		\
1193 {									\
1194 									\
1195 	return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL);	\
1196 }
1197 
NVLIST_EXISTS(null,NULL)1198 NVLIST_EXISTS(null, NULL)
1199 NVLIST_EXISTS(bool, BOOL)
1200 NVLIST_EXISTS(number, NUMBER)
1201 NVLIST_EXISTS(ptr, PTR)
1202 NVLIST_EXISTS(uint64, UINT64)
1203 NVLIST_EXISTS(int64, INT64)
1204 NVLIST_EXISTS(endpoint, ENDPOINT)
1205 NVLIST_EXISTS(date, DATE)
1206 NVLIST_EXISTS(string, STRING)
1207 NVLIST_EXISTS(nvlist, NVLIST)
1208 #ifndef _KERNEL
1209 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1210 #endif
1211 NVLIST_EXISTS(binary, BINARY)
1212 NVLIST_EXISTS(uuid, UUID)
1213 
1214 #undef	NVLIST_EXISTS
1215 
1216 #ifndef _KERNEL
1217 bool
1218 nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...)
1219 {
1220 	va_list nameap;
1221 	bool ret;
1222 
1223 	va_start(nameap, namefmt);
1224 	ret = nvlist_existsv(nvl, namefmt, nameap);
1225 	va_end(nameap);
1226 	return (ret);
1227 }
1228 
1229 #define	NVLIST_EXISTSF(type)						\
1230 bool									\
1231 nvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...)	\
1232 {									\
1233 	va_list nameap;							\
1234 	bool ret;							\
1235 									\
1236 	va_start(nameap, namefmt);					\
1237 	ret = nvlist_existsv_##type(nvl, namefmt, nameap);		\
1238 	va_end(nameap);							\
1239 	return (ret);							\
1240 }
1241 
1242 NVLIST_EXISTSF(null)
NVLIST_EXISTSF(bool)1243 NVLIST_EXISTSF(bool)
1244 NVLIST_EXISTSF(number)
1245 NVLIST_EXISTSF(ptr)
1246 NVLIST_EXISTSF(uint64)
1247 NVLIST_EXISTSF(int64)
1248 NVLIST_EXISTSF(endpoint)
1249 NVLIST_EXISTSF(date)
1250 NVLIST_EXISTSF(string)
1251 NVLIST_EXISTSF(nvlist)
1252 #ifndef _KERNEL
1253 NVLIST_EXISTSF(descriptor)
1254 #endif
1255 NVLIST_EXISTSF(binary)
1256 NVLIST_EXISTSF(uuid)
1257 
1258 #undef	NVLIST_EXISTSF
1259 
1260 bool
1261 nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap)
1262 {
1263 	char *name;
1264 	bool exists;
1265 
1266 	nv_vasprintf(&name, namefmt, nameap);
1267 	if (name == NULL)
1268 		return (false);
1269 
1270 	exists = nvlist_exists(nvl, name);
1271 	nv_free(name);
1272 	return (exists);
1273 }
1274 
1275 #define	NVLIST_EXISTSV(type)						\
1276 bool									\
1277 nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt,		\
1278     va_list nameap)							\
1279 {									\
1280 	char *name;							\
1281 	bool exists;							\
1282 									\
1283 	vasprintf(&name, namefmt, nameap);				\
1284 	if (name == NULL)						\
1285 		return (false);						\
1286 	exists = nvlist_exists_##type(nvl, name);			\
1287 	free(name);							\
1288 	return (exists);						\
1289 }
1290 
1291 NVLIST_EXISTSV(null)
NVLIST_EXISTSV(bool)1292 NVLIST_EXISTSV(bool)
1293 NVLIST_EXISTSV(number)
1294 NVLIST_EXISTSV(ptr)
1295 NVLIST_EXISTSV(uint64)
1296 NVLIST_EXISTSV(int64)
1297 NVLIST_EXISTSV(endpoint)
1298 NVLIST_EXISTSV(date)
1299 NVLIST_EXISTSV(string)
1300 NVLIST_EXISTSV(nvlist)
1301 NVLIST_EXISTSV(descriptor)
1302 NVLIST_EXISTSV(binary)
1303 NVLIST_EXISTSV(uuid)
1304 
1305 #undef	NVLIST_EXISTSV
1306 #endif
1307 
1308 void
1309 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1310 {
1311 	nvpair_t *newnvp;
1312 
1313 	NVPAIR_ASSERT(nvp);
1314 
1315 	if (nvlist_error(nvl) != 0) {
1316 		RESTORE_ERRNO(nvlist_error(nvl));
1317 		return;
1318 	}
1319 	if (nvlist_exists(nvl, nvpair_name(nvp))) {
1320 		nvl->nvl_error = EEXIST;
1321 		RESTORE_ERRNO(nvlist_error(nvl));
1322 		return;
1323 	}
1324 
1325 	newnvp = nvpair_clone(nvp);
1326 	if (newnvp == NULL) {
1327 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1328 		RESTORE_ERRNO(nvlist_error(nvl));
1329 		return;
1330 	}
1331 
1332 	nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1333 }
1334 
1335 void
nvlist_add_null(nvlist_t * nvl,const char * name)1336 nvlist_add_null(nvlist_t *nvl, const char *name)
1337 {
1338 
1339 	nvlist_addf_null(nvl, "%s", name);
1340 }
1341 
1342 void
nvlist_add_bool(nvlist_t * nvl,const char * name,bool value)1343 nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
1344 {
1345 
1346 	nvlist_addf_bool(nvl, value, "%s", name);
1347 }
1348 
1349 void
nvlist_add_number(nvlist_t * nvl,const char * name,uint64_t value)1350 nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
1351 {
1352 
1353 	nvlist_addf_number(nvl, value, "%s", name);
1354 }
1355 
1356 void
nvlist_add_ptr(nvlist_t * nvl,const char * name,uintptr_t value)1357 nvlist_add_ptr(nvlist_t *nvl, const char *name, uintptr_t value)
1358 {
1359 
1360 	nvlist_addf_ptr(nvl, value, "%s", name);
1361 }
1362 
1363 void
nvlist_add_uint64(nvlist_t * nvl,const char * name,uint64_t value)1364 nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t value)
1365 {
1366 
1367 	nvlist_addf_uint64(nvl, value, "%s", name);
1368 }
1369 
1370 void
nvlist_add_int64(nvlist_t * nvl,const char * name,int64_t value)1371 nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t value)
1372 {
1373 
1374 	nvlist_addf_int64(nvl, value, "%s", name);
1375 }
1376 
1377 void
nvlist_add_endpoint(nvlist_t * nvl,const char * name,int value)1378 nvlist_add_endpoint(nvlist_t *nvl, const char *name, int value)
1379 {
1380 
1381 	nvlist_addf_endpoint(nvl, value, "%s", name);
1382 }
1383 
1384 void
nvlist_add_date(nvlist_t * nvl,const char * name,uint64_t value)1385 nvlist_add_date(nvlist_t *nvl, const char *name, uint64_t value)
1386 {
1387 
1388 	nvlist_addf_date(nvl, value, "%s", name);
1389 }
1390 
1391 void
nvlist_add_string(nvlist_t * nvl,const char * name,const char * value)1392 nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
1393 {
1394 
1395 	nvlist_addf_string(nvl, value, "%s", name);
1396 }
1397 
1398 void
nvlist_add_stringf(nvlist_t * nvl,const char * name,const char * valuefmt,...)1399 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1400 {
1401 	va_list valueap;
1402 
1403 	va_start(valueap, valuefmt);
1404 	nvlist_add_stringv(nvl, name, valuefmt, valueap);
1405 	va_end(valueap);
1406 }
1407 
1408 void
nvlist_add_stringv(nvlist_t * nvl,const char * name,const char * valuefmt,va_list valueap)1409 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1410     va_list valueap)
1411 {
1412 	nvpair_t *nvp;
1413 
1414 	if (nvlist_error(nvl) != 0) {
1415 		RESTORE_ERRNO(nvlist_error(nvl));
1416 		return;
1417 	}
1418 
1419 	nvp = nvpair_create_stringv(name, valuefmt, valueap);
1420 	if (nvp == NULL) {
1421 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1422 		RESTORE_ERRNO(nvl->nvl_error);
1423 	} else
1424 		nvlist_move_nvpair(nvl, nvp);
1425 }
1426 
1427 void
nvlist_add_nvlist(nvlist_t * nvl,const char * name,const nvlist_t * value)1428 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1429 {
1430 
1431 	nvlist_addf_nvlist(nvl, value, "%s", name);
1432 }
1433 
1434 void
nvlist_add_nvlist_array(nvlist_t * nvl,const char * name,const nvlist_t * value)1435 nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, const nvlist_t *value)
1436 {
1437 
1438 	nvlist_addf_nvlist_array(nvl, value, "%s", name);
1439 }
1440 
1441 void
nvlist_add_nvlist_dictionary(nvlist_t * nvl,const char * name,const nvlist_t * value)1442 nvlist_add_nvlist_dictionary(nvlist_t *nvl, const char *name, const nvlist_t *value)
1443 {
1444 
1445 	nvlist_addf_nvlist_dictionary(nvl, value, "%s", name);
1446 }
1447 
1448 #ifndef _KERNEL
1449 void
nvlist_add_descriptor(nvlist_t * nvl,const char * name,int value)1450 nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1451 {
1452 
1453 	nvlist_addf_descriptor(nvl, value, "%s", name);
1454 }
1455 #endif
1456 
1457 void
nvlist_add_binary(nvlist_t * nvl,const char * name,const void * value,size_t size)1458 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1459     size_t size)
1460 {
1461 
1462 	nvlist_addf_binary(nvl, value, size, "%s", name);
1463 }
1464 
1465 void
nvlist_add_uuid(nvlist_t * nvl,const char * name,const uuid_t * value)1466 nvlist_add_uuid(nvlist_t *nvl, const char *name, const uuid_t *value)
1467 {
1468 
1469 	nvlist_addf_uuid(nvl, value, "%s", name);
1470 }
1471 
1472 void
nvlist_addf_null(nvlist_t * nvl,const char * namefmt,...)1473 nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...)
1474 {
1475 	va_list nameap;
1476 
1477 	va_start(nameap, namefmt);
1478 	nvlist_addv_null(nvl, namefmt, nameap);
1479 	va_end(nameap);
1480 }
1481 
1482 void
nvlist_addf_bool(nvlist_t * nvl,bool value,const char * namefmt,...)1483 nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...)
1484 {
1485 	va_list nameap;
1486 
1487 	va_start(nameap, namefmt);
1488 	nvlist_addv_bool(nvl, value, namefmt, nameap);
1489 	va_end(nameap);
1490 }
1491 
1492 void
nvlist_addf_number(nvlist_t * nvl,uint64_t value,const char * namefmt,...)1493 nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1494 {
1495 	va_list nameap;
1496 
1497 	va_start(nameap, namefmt);
1498 	nvlist_addv_number(nvl, value, namefmt, nameap);
1499 	va_end(nameap);
1500 }
1501 
1502 void
nvlist_addf_ptr(nvlist_t * nvl,uintptr_t value,const char * namefmt,...)1503 nvlist_addf_ptr(nvlist_t *nvl, uintptr_t value, const char *namefmt, ...)
1504 {
1505 	va_list nameap;
1506 
1507 	va_start(nameap, namefmt);
1508 	nvlist_addv_ptr(nvl, value, namefmt, nameap);
1509 	va_end(nameap);
1510 }
1511 
1512 void
nvlist_addf_uint64(nvlist_t * nvl,uint64_t value,const char * namefmt,...)1513 nvlist_addf_uint64(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1514 {
1515 	va_list nameap;
1516 
1517 	va_start(nameap, namefmt);
1518 	nvlist_addv_uint64(nvl, value, namefmt, nameap);
1519 	va_end(nameap);
1520 }
1521 
1522 void
nvlist_addf_int64(nvlist_t * nvl,int64_t value,const char * namefmt,...)1523 nvlist_addf_int64(nvlist_t *nvl, int64_t value, const char *namefmt, ...)
1524 {
1525 	va_list nameap;
1526 
1527 	va_start(nameap, namefmt);
1528 	nvlist_addv_int64(nvl, value, namefmt, nameap);
1529 	va_end(nameap);
1530 }
1531 
1532 void
nvlist_addf_endpoint(nvlist_t * nvl,int value,const char * namefmt,...)1533 nvlist_addf_endpoint(nvlist_t *nvl, int value, const char *namefmt, ...)
1534 {
1535 	va_list nameap;
1536 
1537 	va_start(nameap, namefmt);
1538 	nvlist_addv_endpoint(nvl, value, namefmt, nameap);
1539 	va_end(nameap);
1540 }
1541 
1542 void
nvlist_addf_date(nvlist_t * nvl,uint64_t value,const char * namefmt,...)1543 nvlist_addf_date(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1544 {
1545 	va_list nameap;
1546 
1547 	va_start(nameap, namefmt);
1548 	nvlist_addv_date(nvl, value, namefmt, nameap);
1549 	va_end(nameap);
1550 }
1551 
1552 
1553 void
nvlist_addf_string(nvlist_t * nvl,const char * value,const char * namefmt,...)1554 nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...)
1555 {
1556 	va_list nameap;
1557 
1558 	va_start(nameap, namefmt);
1559 	nvlist_addv_string(nvl, value, namefmt, nameap);
1560 	va_end(nameap);
1561 }
1562 
1563 void
nvlist_addf_nvlist(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,...)1564 nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1565     ...)
1566 {
1567 	va_list nameap;
1568 
1569 	va_start(nameap, namefmt);
1570 	nvlist_addv_nvlist(nvl, value, namefmt, nameap);
1571 	va_end(nameap);
1572 }
1573 
1574 void
nvlist_addf_nvlist_array(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,...)1575 nvlist_addf_nvlist_array(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1576     ...)
1577 {
1578 	va_list nameap;
1579 
1580 	va_start(nameap, namefmt);
1581 	nvlist_addv_nvlist_array(nvl, value, namefmt, nameap);
1582 	va_end(nameap);
1583 }
1584 
1585 void
nvlist_addf_nvlist_dictionary(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,...)1586 nvlist_addf_nvlist_dictionary(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1587     ...)
1588 {
1589 	va_list nameap;
1590 
1591 	va_start(nameap, namefmt);
1592 	nvlist_addv_nvlist_dictionary(nvl, value, namefmt, nameap);
1593 	va_end(nameap);
1594 }
1595 
1596 #ifndef _KERNEL
1597 void
nvlist_addf_descriptor(nvlist_t * nvl,int value,const char * namefmt,...)1598 nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...)
1599 {
1600 	va_list nameap;
1601 
1602 	va_start(nameap, namefmt);
1603 	nvlist_addv_descriptor(nvl, value, namefmt, nameap);
1604 	va_end(nameap);
1605 }
1606 #endif
1607 
1608 void
nvlist_addf_binary(nvlist_t * nvl,const void * value,size_t size,const char * namefmt,...)1609 nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size,
1610     const char *namefmt, ...)
1611 {
1612 	va_list nameap;
1613 
1614 	va_start(nameap, namefmt);
1615 	nvlist_addv_binary(nvl, value, size, namefmt, nameap);
1616 	va_end(nameap);
1617 }
1618 
1619 void
nvlist_addf_uuid(nvlist_t * nvl,const uuid_t * value,const char * namefmt,...)1620 nvlist_addf_uuid(nvlist_t *nvl, const uuid_t *value, const char *namefmt, ...)
1621 {
1622 	va_list nameap;
1623 
1624 	va_start(nameap, namefmt);
1625 	nvlist_addv_uuid(nvl, value, namefmt, nameap);
1626 	va_end(nameap);
1627 }
1628 
1629 void
nvlist_addv_null(nvlist_t * nvl,const char * namefmt,va_list nameap)1630 nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap)
1631 {
1632 	nvpair_t *nvp;
1633 
1634 	if (nvlist_error(nvl) != 0) {
1635 		RESTORE_ERRNO(nvlist_error(nvl));
1636 		return;
1637 	}
1638 
1639 	nvp = nvpair_createv_null(namefmt, nameap);
1640 	if (nvp == NULL) {
1641 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1642 		RESTORE_ERRNO(nvl->nvl_error);
1643 	} else
1644 		nvlist_move_nvpair(nvl, nvp);
1645 }
1646 
1647 void
nvlist_addv_bool(nvlist_t * nvl,bool value,const char * namefmt,va_list nameap)1648 nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap)
1649 {
1650 	nvpair_t *nvp;
1651 
1652 	if (nvlist_error(nvl) != 0) {
1653 		RESTORE_ERRNO(nvlist_error(nvl));
1654 		return;
1655 	}
1656 
1657 	nvp = nvpair_createv_bool(value, namefmt, nameap);
1658 	if (nvp == NULL) {
1659 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1660 		RESTORE_ERRNO(nvl->nvl_error);
1661 	} else
1662 		nvlist_move_nvpair(nvl, nvp);
1663 }
1664 
1665 void
nvlist_addv_number(nvlist_t * nvl,uint64_t value,const char * namefmt,va_list nameap)1666 nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt,
1667     va_list nameap)
1668 {
1669 	nvpair_t *nvp;
1670 
1671 	if (nvlist_error(nvl) != 0) {
1672 		RESTORE_ERRNO(nvlist_error(nvl));
1673 		return;
1674 	}
1675 
1676 	nvp = nvpair_createv_number_type(value, NV_TYPE_NUMBER, namefmt, nameap);
1677 	if (nvp == NULL) {
1678 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1679 		RESTORE_ERRNO(nvl->nvl_error);
1680 	} else
1681 		nvlist_move_nvpair(nvl, nvp);
1682 }
1683 
1684 void
nvlist_addv_ptr(nvlist_t * nvl,uintptr_t value,const char * namefmt,va_list nameap)1685 nvlist_addv_ptr(nvlist_t *nvl, uintptr_t value, const char *namefmt,
1686     va_list nameap)
1687 {
1688 	nvpair_t *nvp;
1689 
1690 	if (nvlist_error(nvl) != 0) {
1691 		RESTORE_ERRNO(nvlist_error(nvl));
1692 		return;
1693 	}
1694 
1695 	nvp = nvpair_createv_number_type(value, NV_TYPE_PTR, namefmt, nameap);
1696 	if (nvp == NULL) {
1697 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1698 		RESTORE_ERRNO(nvl->nvl_error);
1699 	} else
1700 		nvlist_move_nvpair(nvl, nvp);
1701 }
1702 
1703 void
nvlist_addv_uint64(nvlist_t * nvl,uint64_t value,const char * namefmt,va_list nameap)1704 nvlist_addv_uint64(nvlist_t *nvl, uint64_t value, const char *namefmt,
1705     va_list nameap)
1706 {
1707 	nvpair_t *nvp;
1708 
1709 	if (nvlist_error(nvl) != 0) {
1710 		RESTORE_ERRNO(nvlist_error(nvl));
1711 		return;
1712 	}
1713 
1714 	nvp = nvpair_createv_number_type(value, NV_TYPE_UINT64, namefmt, nameap);
1715 	if (nvp == NULL) {
1716 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1717 		RESTORE_ERRNO(nvl->nvl_error);
1718 	} else
1719 		nvlist_move_nvpair(nvl, nvp);
1720 }
1721 
1722 void
nvlist_addv_int64(nvlist_t * nvl,int64_t value,const char * namefmt,va_list nameap)1723 nvlist_addv_int64(nvlist_t *nvl, int64_t value, const char *namefmt,
1724     va_list nameap)
1725 {
1726 	nvpair_t *nvp;
1727 
1728 	if (nvlist_error(nvl) != 0) {
1729 		RESTORE_ERRNO(nvlist_error(nvl));
1730 		return;
1731 	}
1732 
1733 	nvp = nvpair_createv_number_type(value, NV_TYPE_INT64, namefmt, nameap);
1734 	if (nvp == NULL) {
1735 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1736 		RESTORE_ERRNO(nvl->nvl_error);
1737 	} else
1738 		nvlist_move_nvpair(nvl, nvp);
1739 }
1740 
1741 void
nvlist_addv_endpoint(nvlist_t * nvl,int value,const char * namefmt,va_list nameap)1742 nvlist_addv_endpoint(nvlist_t *nvl, int value, const char *namefmt,
1743     va_list nameap)
1744 {
1745 	nvpair_t *nvp;
1746 
1747 	if (nvlist_error(nvl) != 0) {
1748 		RESTORE_ERRNO(nvlist_error(nvl));
1749 		return;
1750 	}
1751 
1752 	nvp = nvpair_createv_number_type(value, NV_TYPE_ENDPOINT, namefmt, nameap);
1753 	if (nvp == NULL) {
1754 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1755 		RESTORE_ERRNO(nvl->nvl_error);
1756 	} else
1757 		nvlist_move_nvpair(nvl, nvp);
1758 }
1759 
1760 void
nvlist_addv_date(nvlist_t * nvl,uint64_t value,const char * namefmt,va_list nameap)1761 nvlist_addv_date(nvlist_t *nvl, uint64_t value, const char *namefmt,
1762     va_list nameap)
1763 {
1764 	nvpair_t *nvp;
1765 
1766 	if (nvlist_error(nvl) != 0) {
1767 		RESTORE_ERRNO(nvlist_error(nvl));
1768 		return;
1769 	}
1770 
1771 	nvp = nvpair_createv_number_type(value, NV_TYPE_DATE, namefmt, nameap);
1772 	if (nvp == NULL) {
1773 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1774 		RESTORE_ERRNO(nvl->nvl_error);
1775 	} else
1776 		nvlist_move_nvpair(nvl, nvp);
1777 }
1778 
1779 void
nvlist_addv_string(nvlist_t * nvl,const char * value,const char * namefmt,va_list nameap)1780 nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt,
1781     va_list nameap)
1782 {
1783 	nvpair_t *nvp;
1784 
1785 	if (nvlist_error(nvl) != 0) {
1786 		RESTORE_ERRNO(nvlist_error(nvl));
1787 		return;
1788 	}
1789 
1790 	nvp = nvpair_createv_string(value, namefmt, nameap);
1791 	if (nvp == NULL) {
1792 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1793 		RESTORE_ERRNO(nvl->nvl_error);
1794 	} else
1795 		nvlist_move_nvpair(nvl, nvp);
1796 }
1797 
1798 void
nvlist_addv_nvlist(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,va_list nameap)1799 nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1800 	va_list nameap)
1801 {
1802 	nvpair_t *nvp;
1803 
1804 	if (nvlist_error(nvl) != 0) {
1805 		RESTORE_ERRNO(nvlist_error(nvl));
1806 		return;
1807 	}
1808 
1809 	nvp = nvpair_createv_nvlist_type(value, NV_TYPE_NVLIST, namefmt, nameap);
1810 	if (nvp == NULL) {
1811 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1812 		RESTORE_ERRNO(nvl->nvl_error);
1813 	} else
1814 		nvlist_move_nvpair(nvl, nvp);
1815 }
1816 
1817 void
nvlist_addv_nvlist_array(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,va_list nameap)1818 nvlist_addv_nvlist_array(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1819     va_list nameap)
1820 {
1821 	nvpair_t *nvp;
1822 
1823 	if (nvlist_error(nvl) != 0) {
1824 		RESTORE_ERRNO(nvlist_error(nvl));
1825 		return;
1826 	}
1827 
1828 	nvp = nvpair_createv_nvlist_type(value, NV_TYPE_NVLIST_ARRAY, namefmt, nameap);
1829 	if (nvp == NULL) {
1830 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1831 		RESTORE_ERRNO(nvl->nvl_error);
1832 	} else
1833 		nvlist_move_nvpair(nvl, nvp);
1834 }
1835 
1836 void
nvlist_addv_nvlist_dictionary(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,va_list nameap)1837 nvlist_addv_nvlist_dictionary(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1838     va_list nameap)
1839 {
1840 	nvpair_t *nvp;
1841 
1842 	if (nvlist_error(nvl) != 0) {
1843 		RESTORE_ERRNO(nvlist_error(nvl));
1844 		return;
1845 	}
1846 
1847 	nvp = nvpair_createv_nvlist_type(value, NV_TYPE_NVLIST_DICTIONARY, namefmt, nameap);
1848 	if (nvp == NULL) {
1849 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1850 		RESTORE_ERRNO(nvl->nvl_error);
1851 	} else
1852 		nvlist_move_nvpair(nvl, nvp);
1853 }
1854 
1855 #ifndef _KERNEL
1856 void
nvlist_addv_descriptor(nvlist_t * nvl,int value,const char * namefmt,va_list nameap)1857 nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1858     va_list nameap)
1859 {
1860 	nvpair_t *nvp;
1861 
1862 	if (nvlist_error(nvl) != 0) {
1863 		errno = nvlist_error(nvl);
1864 		return;
1865 	}
1866 
1867 	nvp = nvpair_createv_descriptor(value, namefmt, nameap);
1868 	if (nvp == NULL)
1869 		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1870 	else
1871 		nvlist_move_nvpair(nvl, nvp);
1872 }
1873 #endif
1874 
1875 void
nvlist_addv_binary(nvlist_t * nvl,const void * value,size_t size,const char * namefmt,va_list nameap)1876 nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size,
1877     const char *namefmt, va_list nameap)
1878 {
1879 	nvpair_t *nvp;
1880 
1881 	if (nvlist_error(nvl) != 0) {
1882 		RESTORE_ERRNO(nvlist_error(nvl));
1883 		return;
1884 	}
1885 
1886 	nvp = nvpair_createv_binary(value, size, namefmt, nameap);
1887 	if (nvp == NULL) {
1888 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1889 		RESTORE_ERRNO(nvl->nvl_error);
1890 	} else
1891 		nvlist_move_nvpair(nvl, nvp);
1892 }
1893 
1894 void
nvlist_addv_uuid(nvlist_t * nvl,const uuid_t * value,const char * namefmt,va_list nameap)1895 nvlist_addv_uuid(nvlist_t *nvl, const uuid_t *value,
1896     const char *namefmt, va_list nameap)
1897 {
1898 	nvpair_t *nvp;
1899 
1900 	if (nvlist_error(nvl) != 0) {
1901 		RESTORE_ERRNO(nvlist_error(nvl));
1902 		return;
1903 	}
1904 
1905 	nvp = nvpair_createv_uuid(value, namefmt, nameap);
1906 	if (nvp == NULL)
1907 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1908 	else
1909 		nvlist_move_nvpair(nvl, nvp);
1910 }
1911 
1912 void
nvlist_move_nvpair(nvlist_t * nvl,nvpair_t * nvp)1913 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1914 {
1915 
1916 	NVPAIR_ASSERT(nvp);
1917 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1918 
1919 	if (nvlist_error(nvl) != 0) {
1920 		nvpair_free(nvp);
1921 		RESTORE_ERRNO(nvlist_error(nvl));
1922 		return;
1923 	}
1924 	if (nvlist_exists(nvl, nvpair_name(nvp))) {
1925 		nvpair_free(nvp);
1926 		nvl->nvl_error = EEXIST;
1927 		RESTORE_ERRNO(nvl->nvl_error);
1928 		return;
1929 	}
1930 
1931 	nvpair_insert(&nvl->nvl_head, nvp, nvl);
1932 }
1933 
1934 #define	NVLIST_MOVE(vtype, type)					\
1935 void									\
1936 nvlist_move_##type(nvlist_t *nvl, const char *name, vtype value)	\
1937 {									\
1938 									\
1939 	nvlist_movef_##type(nvl, value, "%s", name);			\
1940 }
1941 
NVLIST_MOVE(char *,string)1942 NVLIST_MOVE(char *, string)
1943 NVLIST_MOVE(nvlist_t *, nvlist)
1944 NVLIST_MOVE(nvlist_t *, nvlist_array)
1945 NVLIST_MOVE(nvlist_t *, nvlist_dictionary)
1946 #ifndef _KERNEL
1947 NVLIST_MOVE(int, descriptor)
1948 #endif
1949 
1950 #undef	NVLIST_MOVE
1951 
1952 void
1953 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1954 {
1955 
1956 	nvlist_movef_binary(nvl, value, size, "%s", name);
1957 }
1958 
1959 void
nvlist_move_uuid(nvlist_t * nvl,const char * name,uuid_t * value)1960 nvlist_move_uuid(nvlist_t *nvl, const char *name, uuid_t *value)
1961 {
1962 
1963 	nvlist_movef_binary(nvl, value, sizeof(uuid_t), "%s", name);
1964 }
1965 
1966 #define	NVLIST_MOVEF(vtype, type)					\
1967 void									\
1968 nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt,	\
1969     ...)								\
1970 {									\
1971 	va_list nameap;							\
1972 									\
1973 	va_start(nameap, namefmt);					\
1974 	nvlist_movev_##type(nvl, value, namefmt, nameap);		\
1975 	va_end(nameap);							\
1976 }
1977 
NVLIST_MOVEF(char *,string)1978 NVLIST_MOVEF(char *, string)
1979 NVLIST_MOVEF(nvlist_t *, nvlist)
1980 NVLIST_MOVEF(nvlist_t *, nvlist_array)
1981 NVLIST_MOVEF(nvlist_t *, nvlist_dictionary)
1982 #ifndef _KERNEL
1983 NVLIST_MOVEF(int, descriptor)
1984 #endif
1985 
1986 #undef	NVLIST_MOVEF
1987 
1988 void
1989 nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size,
1990     const char *namefmt, ...)
1991 {
1992 	va_list nameap;
1993 
1994 	va_start(nameap, namefmt);
1995 	nvlist_movev_binary(nvl, value, size, namefmt, nameap);
1996 	va_end(nameap);
1997 }
1998 
1999 void
nvlist_movef_uuid(nvlist_t * nvl,uuid_t * value,const char * namefmt,...)2000 nvlist_movef_uuid(nvlist_t *nvl, uuid_t *value, const char *namefmt, ...)
2001 {
2002 	va_list nameap;
2003 
2004 	va_start(nameap, namefmt);
2005 	nvlist_movev_uuid(nvl, value, namefmt, nameap);
2006 	va_end(nameap);
2007 }
2008 
2009 void
nvlist_movev_string(nvlist_t * nvl,char * value,const char * namefmt,va_list nameap)2010 nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt,
2011     va_list nameap)
2012 {
2013 	nvpair_t *nvp;
2014 
2015 	if (nvlist_error(nvl) != 0) {
2016 		nv_free(value);
2017 		RESTORE_ERRNO(nvlist_error(nvl));
2018 		return;
2019 	}
2020 
2021 	nvp = nvpair_movev_string(value, namefmt, nameap);
2022 	if (nvp == NULL) {
2023 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2024 		RESTORE_ERRNO(nvl->nvl_error);
2025 	} else
2026 		nvlist_move_nvpair(nvl, nvp);
2027 }
2028 
2029 void
nvlist_movev_nvlist(nvlist_t * nvl,nvlist_t * value,const char * namefmt,va_list nameap)2030 nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
2031     va_list nameap)
2032 {
2033 	nvpair_t *nvp;
2034 
2035 	if (nvlist_error(nvl) != 0) {
2036 		if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
2037 			nvlist_destroy(value);
2038 		RESTORE_ERRNO(nvlist_error(nvl));
2039 		return;
2040 	}
2041 
2042 	nvp = nvpair_movev_nvlist_type(value, NV_TYPE_NVLIST, namefmt, nameap);
2043 	if (nvp == NULL) {
2044 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2045 		RESTORE_ERRNO(nvl->nvl_error);
2046 	} else
2047 		nvlist_move_nvpair(nvl, nvp);
2048 }
2049 
2050 void
nvlist_movev_nvlist_array(nvlist_t * nvl,nvlist_t * value,const char * namefmt,va_list nameap)2051 nvlist_movev_nvlist_array(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
2052     va_list nameap)
2053 {
2054 	nvpair_t *nvp;
2055 
2056 	if (nvlist_error(nvl) != 0) {
2057 		if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
2058 			nvlist_destroy(value);
2059 		RESTORE_ERRNO(nvlist_error(nvl));
2060 		return;
2061 	}
2062 
2063 	nvp = nvpair_movev_nvlist_type(value, NV_TYPE_NVLIST_ARRAY, namefmt, nameap);
2064 	if (nvp == NULL) {
2065 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2066 		RESTORE_ERRNO(nvl->nvl_error);
2067 	} else
2068 		nvlist_move_nvpair(nvl, nvp);
2069 }
2070 
2071 void
nvlist_movev_nvlist_dictionary(nvlist_t * nvl,nvlist_t * value,const char * namefmt,va_list nameap)2072 nvlist_movev_nvlist_dictionary(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
2073     va_list nameap)
2074 {
2075 	nvpair_t *nvp;
2076 
2077 	if (nvlist_error(nvl) != 0) {
2078 		if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
2079 			nvlist_destroy(value);
2080 		RESTORE_ERRNO(nvlist_error(nvl));
2081 		return;
2082 	}
2083 
2084 	nvp = nvpair_movev_nvlist_type(value, NV_TYPE_NVLIST_DICTIONARY, namefmt, nameap);
2085 	if (nvp == NULL) {
2086 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2087 		RESTORE_ERRNO(nvl->nvl_error);
2088 	} else
2089 		nvlist_move_nvpair(nvl, nvp);
2090 }
2091 
2092 #ifndef _KERNEL
2093 void
nvlist_movev_descriptor(nvlist_t * nvl,int value,const char * namefmt,va_list nameap)2094 nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt,
2095     va_list nameap)
2096 {
2097 	nvpair_t *nvp;
2098 
2099 	if (nvlist_error(nvl) != 0) {
2100 		close(value);
2101 		errno = nvlist_error(nvl);
2102 		return;
2103 	}
2104 
2105 	nvp = nvpair_movev_descriptor(value, namefmt, nameap);
2106 	if (nvp == NULL)
2107 		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
2108 	else
2109 		nvlist_move_nvpair(nvl, nvp);
2110 }
2111 #endif
2112 
2113 void
nvlist_movev_binary(nvlist_t * nvl,void * value,size_t size,const char * namefmt,va_list nameap)2114 nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size,
2115     const char *namefmt, va_list nameap)
2116 {
2117 	nvpair_t *nvp;
2118 
2119 	if (nvlist_error(nvl) != 0) {
2120 		nv_free(value);
2121 		RESTORE_ERRNO(nvlist_error(nvl));
2122 		return;
2123 	}
2124 
2125 	nvp = nvpair_movev_binary(value, size, namefmt, nameap);
2126 	if (nvp == NULL) {
2127 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2128 		RESTORE_ERRNO(nvl->nvl_error);
2129 	} else
2130 		nvlist_move_nvpair(nvl, nvp);
2131 }
2132 
2133 void
nvlist_movev_uuid(nvlist_t * nvl,uuid_t * value,const char * namefmt,va_list nameap)2134 nvlist_movev_uuid(nvlist_t *nvl, uuid_t *value,
2135 const char *namefmt, va_list nameap)
2136 {
2137 	nvpair_t *nvp;
2138 
2139 	if (nvlist_error(nvl) != 0) {
2140 		nv_free(value);
2141 		RESTORE_ERRNO(nvlist_error(nvl));
2142 		return;
2143 	}
2144 
2145 	nvp = nvpair_movev_uuid(value, namefmt, nameap);
2146 	if (nvp == NULL)
2147 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2148 	else
2149 		nvlist_move_nvpair(nvl, nvp);
2150 }
2151 
2152 const nvpair_t *
nvlist_get_nvpair(const nvlist_t * nvl,const char * name)2153 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
2154 {
2155 
2156 	return (nvlist_find(nvl, NV_TYPE_NONE, name));
2157 }
2158 
2159 #define	NVLIST_GET(ftype, type, acc_type, TYPE)					\
2160 ftype									\
2161 nvlist_get_##type(const nvlist_t *nvl, const char *name)		\
2162 {									\
2163 	const nvpair_t *nvp;						\
2164 									\
2165 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
2166 	if (nvp == NULL)						\
2167 		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
2168 	return ((ftype)nvpair_get_##acc_type(nvp));				\
2169 }
2170 
NVLIST_GET(bool,bool,bool,BOOL)2171 NVLIST_GET(bool, bool, bool, BOOL)
2172 NVLIST_GET(uint64_t, number, number, NUMBER)
2173 NVLIST_GET(uintptr_t, ptr, number, PTR)
2174 NVLIST_GET(uint64_t, uint64, number, UINT64)
2175 NVLIST_GET(int64_t, int64, number, INT64)
2176 NVLIST_GET(int, endpoint, number, ENDPOINT)
2177 NVLIST_GET(uint64_t, date, number, DATE)
2178 NVLIST_GET(const char *, string, string, STRING)
2179 NVLIST_GET(const nvlist_t *, nvlist, nvlist, NVLIST)
2180 NVLIST_GET(const nvlist_t *, nvlist_array, nvlist, NVLIST_ARRAY)
2181 NVLIST_GET(const nvlist_t *, nvlist_dictionary, nvlist, NVLIST_DICTIONARY)
2182 #ifndef _KERNEL
2183 NVLIST_GET(int, descriptor, descriptor, DESCRIPTOR)
2184 #endif
2185 NVLIST_GET(const uuid_t *, uuid, uuid, UUID)
2186 
2187 #undef	NVLIST_GET
2188 
2189 const void *
2190 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
2191 {
2192 	nvpair_t *nvp;
2193 
2194 	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
2195 	if (nvp == NULL)
2196 		nvlist_report_missing(NV_TYPE_BINARY, name);
2197 
2198 	return (nvpair_get_binary(nvp, sizep));
2199 }
2200 
2201 #define	NVLIST_GETF(ftype, type)					\
2202 ftype									\
2203 nvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...)	\
2204 {									\
2205 	va_list nameap;							\
2206 	ftype value;							\
2207 									\
2208 	va_start(nameap, namefmt);					\
2209 	value = nvlist_getv_##type(nvl, namefmt, nameap);		\
2210 	va_end(nameap);							\
2211 									\
2212 	return (value);							\
2213 }
2214 
2215 #ifndef _KERNEL
NVLIST_GETF(bool,bool)2216 NVLIST_GETF(bool, bool)
2217 NVLIST_GETF(uint64_t, number)
2218 NVLIST_GETF(uintptr_t, ptr)
2219 NVLIST_GETF(uint64_t, uint64)
2220 NVLIST_GETF(int64_t, int64)
2221 NVLIST_GETF(int, endpoint)
2222 NVLIST_GETF(uint64_t, date)
2223 NVLIST_GETF(const char *, string)
2224 NVLIST_GETF(const nvlist_t *, nvlist)
2225 NVLIST_GETF(const nvlist_t *, nvlist_array)
2226 NVLIST_GETF(const nvlist_t *, nvlist_dictionary)
2227 NVLIST_GETF(int, descriptor)
2228 NVLIST_GETF(const uuid_t *, uuid)
2229 
2230 #undef	NVLIST_GETF
2231 
2232 const void *
2233 nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
2234 {
2235 	va_list nameap;
2236 	const void *value;
2237 
2238 	va_start(nameap, namefmt);
2239 	value = nvlist_getv_binary(nvl, sizep, namefmt, nameap);
2240 	va_end(nameap);
2241 
2242 	return (value);
2243 }
2244 
2245 #define	NVLIST_GETV(ftype, type, TYPE)					\
2246 ftype									\
2247 nvlist_getv_##type(const nvlist_t *nvl, const char *namefmt,		\
2248     va_list nameap)							\
2249 {									\
2250 	char *name;							\
2251 	ftype value;							\
2252 									\
2253 	vasprintf(&name, namefmt, nameap);				\
2254 	if (name == NULL)						\
2255 		nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>");	\
2256 	value = nvlist_get_##type(nvl, name);				\
2257 	free(name);							\
2258 									\
2259 	return (value);							\
2260 }
2261 
NVLIST_GETV(bool,bool,BOOL)2262 NVLIST_GETV(bool, bool, BOOL)
2263 NVLIST_GETV(uint64_t, number, NUMBER)
2264 NVLIST_GETV(uintptr_t, ptr, PTR)
2265 NVLIST_GETV(uint64_t, uint64, UINT64)
2266 NVLIST_GETV(int64_t, int64, INT64)
2267 NVLIST_GETV(int, endpoint, ENDPOINT)
2268 NVLIST_GETV(uint64_t, date, DATE)
2269 NVLIST_GETV(const char *, string, STRING)
2270 NVLIST_GETV(const nvlist_t *, nvlist, NVLIST)
2271 NVLIST_GETV(const nvlist_t *, nvlist_array, NVLIST_ARRAY)
2272 NVLIST_GETV(const nvlist_t *, nvlist_dictionary, NVLIST_DICTIONARY)
2273 NVLIST_GETV(int, descriptor, DESCRIPTOR)
2274 NVLIST_GETV(const uuid_t *, uuid, UUID)
2275 
2276 #undef	NVLIST_GETV
2277 
2278 const void *
2279 nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt,
2280     va_list nameap)
2281 {
2282 	char *name;
2283 	const void *binary;
2284 
2285 	nv_vasprintf(&name, namefmt, nameap);
2286 	if (name == NULL)
2287 		nvlist_report_missing(NV_TYPE_BINARY, "<unknown>");
2288 
2289 	binary = nvlist_get_binary(nvl, name, sizep);
2290 	nv_free(name);
2291 	return (binary);
2292 }
2293 #endif
2294 
2295 #define	NVLIST_TAKE(ftype, type, acc_type, TYPE)			\
2296 ftype									\
2297 nvlist_take_##type(nvlist_t *nvl, const char *name)			\
2298 {									\
2299 	nvpair_t *nvp;							\
2300 	ftype value;							\
2301 									\
2302 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
2303 	if (nvp == NULL)						\
2304 		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
2305 	value = (ftype)(intptr_t)nvpair_get_##acc_type(nvp);		\
2306 	nvlist_remove_nvpair(nvl, nvp);					\
2307 	nvpair_free_structure(nvp);					\
2308 	return (value);							\
2309 }
2310 
NVLIST_TAKE(bool,bool,bool,BOOL)2311 NVLIST_TAKE(bool, bool, bool, BOOL)
2312 NVLIST_TAKE(uint64_t, number, number, NUMBER)
2313 NVLIST_TAKE(uintptr_t, ptr, number, PTR)
2314 NVLIST_TAKE(uint64_t, uint64, number, UINT64)
2315 NVLIST_TAKE(int64_t, int64, number, INT64)
2316 NVLIST_TAKE(int, endpoint, number, ENDPOINT)
2317 NVLIST_TAKE(uint64_t, date, number, DATE)
2318 NVLIST_TAKE(char *, string, string, STRING)
2319 NVLIST_TAKE(nvlist_t *, nvlist, nvlist, NVLIST)
2320 NVLIST_TAKE(nvlist_t *, nvlist_array, nvlist, NVLIST_ARRAY)
2321 NVLIST_TAKE(nvlist_t *, nvlist_dictionary, nvlist, NVLIST_DICTIONARY)
2322 #ifndef _KERNEL
2323 NVLIST_TAKE(int, descriptor, descriptor, DESCRIPTOR)
2324 #endif
2325 NVLIST_TAKE(uuid_t *, uuid, uuid, UUID)
2326 
2327 #undef	NVLIST_TAKE
2328 
2329 void *
2330 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
2331 {
2332 	nvpair_t *nvp;
2333 	void *value;
2334 
2335 	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
2336 	if (nvp == NULL)
2337 		nvlist_report_missing(NV_TYPE_BINARY, name);
2338 
2339 	value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
2340 	nvlist_remove_nvpair(nvl, nvp);
2341 	nvpair_free_structure(nvp);
2342 	return (value);
2343 }
2344 
2345 #define	NVLIST_TAKEF(ftype, type)					\
2346 ftype									\
2347 nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...)		\
2348 {									\
2349 	va_list nameap;							\
2350 	ftype value;							\
2351 									\
2352 	va_start(nameap, namefmt);					\
2353 	value = nvlist_takev_##type(nvl, namefmt, nameap);		\
2354 	va_end(nameap);							\
2355 									\
2356 	return (value);							\
2357 }
2358 
2359 #ifndef _KERNEL
NVLIST_TAKEF(bool,bool)2360 NVLIST_TAKEF(bool, bool)
2361 NVLIST_TAKEF(uint64_t, number)
2362 NVLIST_TAKEF(uintptr_t, ptr)
2363 NVLIST_TAKEF(uint64_t, uint64)
2364 NVLIST_TAKEF(int64_t, int64)
2365 NVLIST_TAKEF(int, endpoint)
2366 NVLIST_TAKEF(uint64_t, date)
2367 NVLIST_TAKEF(char *, string)
2368 NVLIST_TAKEF(nvlist_t *, nvlist)
2369 NVLIST_TAKEF(nvlist_t *, nvlist_array)
2370 NVLIST_TAKEF(nvlist_t *, nvlist_dictionary)
2371 NVLIST_TAKEF(int, descriptor)
2372 NVLIST_TAKEF(uuid_t *, uuid)
2373 
2374 #undef	NVLIST_TAKEF
2375 
2376 void *
2377 nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
2378 {
2379 	va_list nameap;
2380 	void *value;
2381 
2382 	va_start(nameap, namefmt);
2383 	value = nvlist_takev_binary(nvl, sizep, namefmt, nameap);
2384 	va_end(nameap);
2385 
2386 	return (value);
2387 }
2388 
2389 #define	NVLIST_TAKEV(ftype, type, acc_type, TYPE)					\
2390 ftype									\
2391 nvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap)	\
2392 {									\
2393 	char *name;							\
2394 	ftype value;							\
2395 									\
2396 	vasprintf(&name, namefmt, nameap);				\
2397 	if (name == NULL)						\
2398 		nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>");	\
2399 	value = nvlist_take_##type(nvl, name);				\
2400 	free(name);							\
2401 	return (value);							\
2402 }
2403 
NVLIST_TAKEV(bool,bool,bool,BOOL)2404 NVLIST_TAKEV(bool, bool, bool, BOOL)
2405 NVLIST_TAKEV(uint64_t, number, number, NUMBER)
2406 NVLIST_TAKEV(uintptr_t, ptr, number, PTR)
2407 NVLIST_TAKEV(uint64_t, uint64, number, UINT64)
2408 NVLIST_TAKEV(int64_t, int64, number, INT64)
2409 NVLIST_TAKEV(int, endpoint, number, ENDPOINT)
2410 NVLIST_TAKEV(uint64_t, date, number, DATE)
2411 NVLIST_TAKEV(char *, string, string, STRING)
2412 NVLIST_TAKEV(nvlist_t *, nvlist, nvlist, NVLIST)
2413 NVLIST_TAKEV(nvlist_t *, nvlist_array, nvlist, NVLIST_ARRAY)
2414 NVLIST_TAKEV(nvlist_t *, nvlist_dictionary, nvlist, NVLIST_DICTIONARY)
2415 NVLIST_TAKEV(int, descriptor, descriptor, DESCRIPTOR)
2416 NVLIST_TAKEV(uuid_t *, uuid, uuid, UUID)
2417 
2418 #undef	NVLIST_TAKEV
2419 
2420 void *
2421 nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt,
2422     va_list nameap)
2423 {
2424 	char *name;
2425 	void *binary;
2426 
2427 	nv_vasprintf(&name, namefmt, nameap);
2428 	if (name == NULL)
2429 		nvlist_report_missing(NV_TYPE_BINARY, "<unknown>");
2430 
2431 	binary = nvlist_take_binary(nvl, name, sizep);
2432 	nv_free(name);
2433 	return (binary);
2434 }
2435 #endif
2436 
2437 void
nvlist_remove_nvpair(nvlist_t * nvl,nvpair_t * nvp)2438 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
2439 {
2440 
2441 	NVLIST_ASSERT(nvl);
2442 	NVPAIR_ASSERT(nvp);
2443 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
2444 
2445 	nvpair_remove(&nvl->nvl_head, nvp, nvl);
2446 }
2447 
2448 void
nvlist_free(nvlist_t * nvl,const char * name)2449 nvlist_free(nvlist_t *nvl, const char *name)
2450 {
2451 
2452 	nvlist_free_type(nvl, name, NV_TYPE_NONE);
2453 }
2454 
2455 #define	NVLIST_FREE(type, TYPE)						\
2456 void									\
2457 nvlist_free_##type(nvlist_t *nvl, const char *name)			\
2458 {									\
2459 									\
2460 	nvlist_free_type(nvl, name, NV_TYPE_##TYPE);			\
2461 }
2462 
NVLIST_FREE(null,NULL)2463 NVLIST_FREE(null, NULL)
2464 NVLIST_FREE(bool, BOOL)
2465 NVLIST_FREE(number, NUMBER)
2466 NVLIST_FREE(ptr, PTR)
2467 NVLIST_FREE(uint64, UINT64)
2468 NVLIST_FREE(int64, INT64)
2469 NVLIST_FREE(endpoint, ENDPOINT)
2470 NVLIST_FREE(date, DATE)
2471 NVLIST_FREE(string, STRING)
2472 NVLIST_FREE(nvlist, NVLIST)
2473 NVLIST_FREE(nvlist_array, NVLIST_ARRAY)
2474 NVLIST_FREE(nvlist_dictionary, NVLIST_DICTIONARY)
2475 #ifndef _KERNEL
2476 NVLIST_FREE(descriptor, DESCRIPTOR)
2477 #endif
2478 NVLIST_FREE(binary, BINARY)
2479 NVLIST_FREE(uuid, UUID)
2480 
2481 #undef	NVLIST_FREE
2482 
2483 #ifndef _KERNEL
2484 void
2485 nvlist_freef(nvlist_t *nvl, const char *namefmt, ...)
2486 {
2487 	va_list nameap;
2488 
2489 	va_start(nameap, namefmt);
2490 	nvlist_freev(nvl, namefmt, nameap);
2491 	va_end(nameap);
2492 }
2493 
2494 #define	NVLIST_FREEF(type)						\
2495 void									\
2496 nvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...)		\
2497 {									\
2498 	va_list nameap;							\
2499 									\
2500 	va_start(nameap, namefmt);					\
2501 	nvlist_freev_##type(nvl, namefmt, nameap);			\
2502 	va_end(nameap);							\
2503 }
2504 
2505 NVLIST_FREEF(null)
NVLIST_FREEF(bool)2506 NVLIST_FREEF(bool)
2507 NVLIST_FREEF(number)
2508 NVLIST_FREEF(ptr)
2509 NVLIST_FREEF(uint64)
2510 NVLIST_FREEF(int64)
2511 NVLIST_FREEF(endpoint)
2512 NVLIST_FREEF(date)
2513 NVLIST_FREEF(string)
2514 NVLIST_FREEF(nvlist)
2515 NVLIST_FREEF(nvlist_array)
2516 NVLIST_FREEF(nvlist_dictionary)
2517 NVLIST_FREEF(descriptor)
2518 NVLIST_FREEF(binary)
2519 NVLIST_FREEF(uuid)
2520 
2521 #undef	NVLIST_FREEF
2522 
2523 void
2524 nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap)
2525 {
2526 
2527 	nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap);
2528 }
2529 
2530 #define	NVLIST_FREEV(type, TYPE)					\
2531 void									\
2532 nvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap)	\
2533 {									\
2534 	char *name;							\
2535 									\
2536 	vasprintf(&name, namefmt, nameap);				\
2537 	if (name == NULL)						\
2538 		nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>");	\
2539 	nvlist_free_##type(nvl, name);					\
2540 	free(name);							\
2541 }
2542 
NVLIST_FREEV(null,NULL)2543 NVLIST_FREEV(null, NULL)
2544 NVLIST_FREEV(bool, BOOL)
2545 NVLIST_FREEV(number, NUMBER)
2546 NVLIST_FREEV(ptr, PTR)
2547 NVLIST_FREEV(uint64, UINT64)
2548 NVLIST_FREEV(int64, INT64)
2549 NVLIST_FREEV(endpoint, ENDPOINT)
2550 NVLIST_FREEV(date, DATE)
2551 NVLIST_FREEV(string, STRING)
2552 NVLIST_FREEV(nvlist, NVLIST)
2553 NVLIST_FREEV(nvlist_array, NVLIST_ARRAY)
2554 NVLIST_FREEV(nvlist_dictionary, NVLIST_DICTIONARY)
2555 NVLIST_FREEV(descriptor, DESCRIPTOR)
2556 NVLIST_FREEV(binary, BINARY)
2557 NVLIST_FREEV(uuid, UUID)
2558 #undef	NVLIST_FREEV
2559 #endif
2560 
2561 void
2562 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
2563 {
2564 
2565 	NVLIST_ASSERT(nvl);
2566 	NVPAIR_ASSERT(nvp);
2567 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
2568 
2569 	nvlist_remove_nvpair(nvl, nvp);
2570 	nvpair_free(nvp);
2571 }
2572