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