xref: /freebsd/sys/contrib/libnv/nvlist.c (revision 1acf3485)
154f98da9SMariusz Zaborski /*-
21acf3485SMariusz Zaborski  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
31acf3485SMariusz Zaborski  *
454f98da9SMariusz Zaborski  * Copyright (c) 2009-2013 The FreeBSD Foundation
5347a39b4SMariusz Zaborski  * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
654f98da9SMariusz Zaborski  * All rights reserved.
754f98da9SMariusz Zaborski  *
854f98da9SMariusz Zaborski  * This software was developed by Pawel Jakub Dawidek under sponsorship from
954f98da9SMariusz Zaborski  * the FreeBSD Foundation.
1054f98da9SMariusz Zaborski  *
1154f98da9SMariusz Zaborski  * Redistribution and use in source and binary forms, with or without
1254f98da9SMariusz Zaborski  * modification, are permitted provided that the following conditions
1354f98da9SMariusz Zaborski  * are met:
1454f98da9SMariusz Zaborski  * 1. Redistributions of source code must retain the above copyright
1554f98da9SMariusz Zaborski  *    notice, this list of conditions and the following disclaimer.
1654f98da9SMariusz Zaborski  * 2. Redistributions in binary form must reproduce the above copyright
1754f98da9SMariusz Zaborski  *    notice, this list of conditions and the following disclaimer in the
1854f98da9SMariusz Zaborski  *    documentation and/or other materials provided with the distribution.
1954f98da9SMariusz Zaborski  *
2054f98da9SMariusz Zaborski  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
2154f98da9SMariusz Zaborski  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2254f98da9SMariusz Zaborski  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2354f98da9SMariusz Zaborski  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
2454f98da9SMariusz Zaborski  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2554f98da9SMariusz Zaborski  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2654f98da9SMariusz Zaborski  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2754f98da9SMariusz Zaborski  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2854f98da9SMariusz Zaborski  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2954f98da9SMariusz Zaborski  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3054f98da9SMariusz Zaborski  * SUCH DAMAGE.
3154f98da9SMariusz Zaborski  */
3254f98da9SMariusz Zaborski 
3354f98da9SMariusz Zaborski #include <sys/cdefs.h>
3454f98da9SMariusz Zaborski __FBSDID("$FreeBSD$");
3554f98da9SMariusz Zaborski 
3654f98da9SMariusz Zaborski #include <sys/param.h>
3754f98da9SMariusz Zaborski #include <sys/endian.h>
3854f98da9SMariusz Zaborski #include <sys/queue.h>
3954f98da9SMariusz Zaborski 
4054f98da9SMariusz Zaborski #ifdef _KERNEL
4154f98da9SMariusz Zaborski 
4254f98da9SMariusz Zaborski #include <sys/errno.h>
4354f98da9SMariusz Zaborski #include <sys/kernel.h>
4454f98da9SMariusz Zaborski #include <sys/lock.h>
4554f98da9SMariusz Zaborski #include <sys/malloc.h>
4654f98da9SMariusz Zaborski #include <sys/systm.h>
4754f98da9SMariusz Zaborski 
4854f98da9SMariusz Zaborski #include <machine/stdarg.h>
4954f98da9SMariusz Zaborski 
5054f98da9SMariusz Zaborski #else
5154f98da9SMariusz Zaborski #include <sys/socket.h>
5254f98da9SMariusz Zaborski 
5354f98da9SMariusz Zaborski #include <errno.h>
5454f98da9SMariusz Zaborski #include <stdarg.h>
5554f98da9SMariusz Zaborski #include <stdbool.h>
5654f98da9SMariusz Zaborski #include <stdint.h>
5754f98da9SMariusz Zaborski #include <stdio.h>
5854f98da9SMariusz Zaborski #include <stdlib.h>
5954f98da9SMariusz Zaborski #include <string.h>
6054f98da9SMariusz Zaborski #include <unistd.h>
6154f98da9SMariusz Zaborski 
6254f98da9SMariusz Zaborski #include "msgio.h"
6354f98da9SMariusz Zaborski #endif
6454f98da9SMariusz Zaborski 
6554f98da9SMariusz Zaborski #ifdef HAVE_PJDLOG
6654f98da9SMariusz Zaborski #include <pjdlog.h>
6754f98da9SMariusz Zaborski #endif
6854f98da9SMariusz Zaborski 
6954f98da9SMariusz Zaborski #include <sys/nv.h>
7054f98da9SMariusz Zaborski 
7154f98da9SMariusz Zaborski #include "nv_impl.h"
7254f98da9SMariusz Zaborski #include "nvlist_impl.h"
7354f98da9SMariusz Zaborski #include "nvpair_impl.h"
7454f98da9SMariusz Zaborski 
7554f98da9SMariusz Zaborski #ifndef	HAVE_PJDLOG
7654f98da9SMariusz Zaborski #ifdef _KERNEL
7754f98da9SMariusz Zaborski #define	PJDLOG_ASSERT(...)		MPASS(__VA_ARGS__)
7854f98da9SMariusz Zaborski #define	PJDLOG_RASSERT(expr, ...)	KASSERT(expr, (__VA_ARGS__))
7954f98da9SMariusz Zaborski #define	PJDLOG_ABORT(...)		panic(__VA_ARGS__)
8054f98da9SMariusz Zaborski #else
8154f98da9SMariusz Zaborski #include <assert.h>
8254f98da9SMariusz Zaborski #define	PJDLOG_ASSERT(...)		assert(__VA_ARGS__)
8354f98da9SMariusz Zaborski #define	PJDLOG_RASSERT(expr, ...)	assert(expr)
8454f98da9SMariusz Zaborski #define	PJDLOG_ABORT(...)		do {				\
8554f98da9SMariusz Zaborski 	fprintf(stderr, "%s:%u: ", __FILE__, __LINE__);			\
8654f98da9SMariusz Zaborski 	fprintf(stderr, __VA_ARGS__);					\
8754f98da9SMariusz Zaborski 	fprintf(stderr, "\n");						\
8854f98da9SMariusz Zaborski 	abort();							\
8954f98da9SMariusz Zaborski } while (0)
9054f98da9SMariusz Zaborski #endif
9154f98da9SMariusz Zaborski #endif
9254f98da9SMariusz Zaborski 
93347a39b4SMariusz Zaborski #define	NV_FLAG_PRIVATE_MASK	(NV_FLAG_BIG_ENDIAN | NV_FLAG_IN_ARRAY)
9454f98da9SMariusz Zaborski #define	NV_FLAG_PUBLIC_MASK	(NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE)
9554f98da9SMariusz Zaborski #define	NV_FLAG_ALL_MASK	(NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
9654f98da9SMariusz Zaborski 
9754f98da9SMariusz Zaborski #define	NVLIST_MAGIC	0x6e766c	/* "nvl" */
9854f98da9SMariusz Zaborski struct nvlist {
9954f98da9SMariusz Zaborski 	int		 nvl_magic;
10054f98da9SMariusz Zaborski 	int		 nvl_error;
10154f98da9SMariusz Zaborski 	int		 nvl_flags;
10254f98da9SMariusz Zaborski 	nvpair_t	*nvl_parent;
103347a39b4SMariusz Zaborski 	nvpair_t	*nvl_array_next;
10454f98da9SMariusz Zaborski 	struct nvl_head	 nvl_head;
10554f98da9SMariusz Zaborski };
10654f98da9SMariusz Zaborski 
10754f98da9SMariusz Zaborski #define	NVLIST_ASSERT(nvl)	do {					\
10854f98da9SMariusz Zaborski 	PJDLOG_ASSERT((nvl) != NULL);					\
10954f98da9SMariusz Zaborski 	PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);		\
11054f98da9SMariusz Zaborski } while (0)
11154f98da9SMariusz Zaborski 
11254f98da9SMariusz Zaborski #ifdef _KERNEL
11354f98da9SMariusz Zaborski MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
11454f98da9SMariusz Zaborski #endif
11554f98da9SMariusz Zaborski 
11654f98da9SMariusz Zaborski #define	NVPAIR_ASSERT(nvp)	nvpair_assert(nvp)
11754f98da9SMariusz Zaborski 
11854f98da9SMariusz Zaborski #define	NVLIST_HEADER_MAGIC	0x6c
11954f98da9SMariusz Zaborski #define	NVLIST_HEADER_VERSION	0x00
12054f98da9SMariusz Zaborski struct nvlist_header {
12154f98da9SMariusz Zaborski 	uint8_t		nvlh_magic;
12254f98da9SMariusz Zaborski 	uint8_t		nvlh_version;
12354f98da9SMariusz Zaborski 	uint8_t		nvlh_flags;
12454f98da9SMariusz Zaborski 	uint64_t	nvlh_descriptors;
12554f98da9SMariusz Zaborski 	uint64_t	nvlh_size;
12654f98da9SMariusz Zaborski } __packed;
12754f98da9SMariusz Zaborski 
12854f98da9SMariusz Zaborski nvlist_t *
12954f98da9SMariusz Zaborski nvlist_create(int flags)
13054f98da9SMariusz Zaborski {
13154f98da9SMariusz Zaborski 	nvlist_t *nvl;
13254f98da9SMariusz Zaborski 
13354f98da9SMariusz Zaborski 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
13454f98da9SMariusz Zaborski 
13554f98da9SMariusz Zaborski 	nvl = nv_malloc(sizeof(*nvl));
13654f98da9SMariusz Zaborski 	if (nvl == NULL)
13754f98da9SMariusz Zaborski 		return (NULL);
13854f98da9SMariusz Zaborski 	nvl->nvl_error = 0;
13954f98da9SMariusz Zaborski 	nvl->nvl_flags = flags;
14054f98da9SMariusz Zaborski 	nvl->nvl_parent = NULL;
141347a39b4SMariusz Zaborski 	nvl->nvl_array_next = NULL;
14254f98da9SMariusz Zaborski 	TAILQ_INIT(&nvl->nvl_head);
14354f98da9SMariusz Zaborski 	nvl->nvl_magic = NVLIST_MAGIC;
14454f98da9SMariusz Zaborski 
14554f98da9SMariusz Zaborski 	return (nvl);
14654f98da9SMariusz Zaborski }
14754f98da9SMariusz Zaborski 
14854f98da9SMariusz Zaborski void
14954f98da9SMariusz Zaborski nvlist_destroy(nvlist_t *nvl)
15054f98da9SMariusz Zaborski {
15154f98da9SMariusz Zaborski 	nvpair_t *nvp;
15254f98da9SMariusz Zaborski 
15354f98da9SMariusz Zaborski 	if (nvl == NULL)
15454f98da9SMariusz Zaborski 		return;
15554f98da9SMariusz Zaborski 
15654f98da9SMariusz Zaborski 	ERRNO_SAVE();
15754f98da9SMariusz Zaborski 
15854f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
15954f98da9SMariusz Zaborski 
16054f98da9SMariusz Zaborski 	while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
16154f98da9SMariusz Zaborski 		nvlist_remove_nvpair(nvl, nvp);
16254f98da9SMariusz Zaborski 		nvpair_free(nvp);
16354f98da9SMariusz Zaborski 	}
164347a39b4SMariusz Zaborski 	if (nvl->nvl_array_next != NULL)
165347a39b4SMariusz Zaborski 		nvpair_free_structure(nvl->nvl_array_next);
166347a39b4SMariusz Zaborski 	nvl->nvl_array_next = NULL;
167347a39b4SMariusz Zaborski 	nvl->nvl_parent = NULL;
16854f98da9SMariusz Zaborski 	nvl->nvl_magic = 0;
16954f98da9SMariusz Zaborski 	nv_free(nvl);
17054f98da9SMariusz Zaborski 
17154f98da9SMariusz Zaborski 	ERRNO_RESTORE();
17254f98da9SMariusz Zaborski }
17354f98da9SMariusz Zaborski 
17454f98da9SMariusz Zaborski void
17554f98da9SMariusz Zaborski nvlist_set_error(nvlist_t *nvl, int error)
17654f98da9SMariusz Zaborski {
17754f98da9SMariusz Zaborski 
17854f98da9SMariusz Zaborski 	PJDLOG_ASSERT(error != 0);
17954f98da9SMariusz Zaborski 
18054f98da9SMariusz Zaborski 	/*
18154f98da9SMariusz Zaborski 	 * Check for error != 0 so that we don't do the wrong thing if somebody
18254f98da9SMariusz Zaborski 	 * tries to abuse this API when asserts are disabled.
18354f98da9SMariusz Zaborski 	 */
18454f98da9SMariusz Zaborski 	if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
18554f98da9SMariusz Zaborski 		nvl->nvl_error = error;
18654f98da9SMariusz Zaborski }
18754f98da9SMariusz Zaborski 
18854f98da9SMariusz Zaborski int
18954f98da9SMariusz Zaborski nvlist_error(const nvlist_t *nvl)
19054f98da9SMariusz Zaborski {
19154f98da9SMariusz Zaborski 
19254f98da9SMariusz Zaborski 	if (nvl == NULL)
19354f98da9SMariusz Zaborski 		return (ENOMEM);
19454f98da9SMariusz Zaborski 
19554f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
19654f98da9SMariusz Zaborski 
19754f98da9SMariusz Zaborski 	return (nvl->nvl_error);
19854f98da9SMariusz Zaborski }
19954f98da9SMariusz Zaborski 
20054f98da9SMariusz Zaborski nvpair_t *
20154f98da9SMariusz Zaborski nvlist_get_nvpair_parent(const nvlist_t *nvl)
20254f98da9SMariusz Zaborski {
20354f98da9SMariusz Zaborski 
20454f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
20554f98da9SMariusz Zaborski 
20654f98da9SMariusz Zaborski 	return (nvl->nvl_parent);
20754f98da9SMariusz Zaborski }
20854f98da9SMariusz Zaborski 
20954f98da9SMariusz Zaborski const nvlist_t *
21054f98da9SMariusz Zaborski nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
21154f98da9SMariusz Zaborski {
21254f98da9SMariusz Zaborski 	nvpair_t *nvp;
21354f98da9SMariusz Zaborski 
21454f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
21554f98da9SMariusz Zaborski 
21654f98da9SMariusz Zaborski 	nvp = nvl->nvl_parent;
21754f98da9SMariusz Zaborski 	if (cookiep != NULL)
21854f98da9SMariusz Zaborski 		*cookiep = nvp;
21954f98da9SMariusz Zaborski 	if (nvp == NULL)
22054f98da9SMariusz Zaborski 		return (NULL);
22154f98da9SMariusz Zaborski 
22254f98da9SMariusz Zaborski 	return (nvpair_nvlist(nvp));
22354f98da9SMariusz Zaborski }
22454f98da9SMariusz Zaborski 
22554f98da9SMariusz Zaborski void
22654f98da9SMariusz Zaborski nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
22754f98da9SMariusz Zaborski {
22854f98da9SMariusz Zaborski 
22954f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
23054f98da9SMariusz Zaborski 
23154f98da9SMariusz Zaborski 	nvl->nvl_parent = parent;
23254f98da9SMariusz Zaborski }
23354f98da9SMariusz Zaborski 
234347a39b4SMariusz Zaborski void
235347a39b4SMariusz Zaborski nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele)
236347a39b4SMariusz Zaborski {
237347a39b4SMariusz Zaborski 
238347a39b4SMariusz Zaborski 	NVLIST_ASSERT(nvl);
239347a39b4SMariusz Zaborski 
2401b550329SMariusz Zaborski 	if (ele != NULL) {
241347a39b4SMariusz Zaborski 		nvl->nvl_flags |= NV_FLAG_IN_ARRAY;
2421b550329SMariusz Zaborski 	} else {
243347a39b4SMariusz Zaborski 		nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY;
2441b550329SMariusz Zaborski 		nv_free(nvl->nvl_array_next);
2451b550329SMariusz Zaborski 	}
246347a39b4SMariusz Zaborski 
247347a39b4SMariusz Zaborski 	nvl->nvl_array_next = ele;
248347a39b4SMariusz Zaborski }
249347a39b4SMariusz Zaborski 
250347a39b4SMariusz Zaborski bool
251347a39b4SMariusz Zaborski nvlist_in_array(const nvlist_t *nvl)
252347a39b4SMariusz Zaborski {
253347a39b4SMariusz Zaborski 
254347a39b4SMariusz Zaborski 	NVLIST_ASSERT(nvl);
255347a39b4SMariusz Zaborski 
256347a39b4SMariusz Zaborski 	return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0);
257347a39b4SMariusz Zaborski }
258347a39b4SMariusz Zaborski 
259347a39b4SMariusz Zaborski const nvlist_t *
260347a39b4SMariusz Zaborski nvlist_get_array_next(const nvlist_t *nvl)
261347a39b4SMariusz Zaborski {
262347a39b4SMariusz Zaborski 	nvpair_t *nvp;
263347a39b4SMariusz Zaborski 
264347a39b4SMariusz Zaborski 	NVLIST_ASSERT(nvl);
265347a39b4SMariusz Zaborski 
266347a39b4SMariusz Zaborski 	nvp = nvl->nvl_array_next;
267347a39b4SMariusz Zaborski 	if (nvp == NULL)
268347a39b4SMariusz Zaborski 		return (NULL);
269347a39b4SMariusz Zaborski 
270347a39b4SMariusz Zaborski 	return (nvpair_get_nvlist(nvp));
271347a39b4SMariusz Zaborski }
272347a39b4SMariusz Zaborski 
273347a39b4SMariusz Zaborski const nvlist_t *
274347a39b4SMariusz Zaborski nvlist_get_pararr(const nvlist_t *nvl, void **cookiep)
275347a39b4SMariusz Zaborski {
276347a39b4SMariusz Zaborski 	const nvlist_t *ret;
277347a39b4SMariusz Zaborski 
278347a39b4SMariusz Zaborski 	ret = nvlist_get_array_next(nvl);
279347a39b4SMariusz Zaborski 	if (ret != NULL) {
280347a39b4SMariusz Zaborski 		if (cookiep != NULL)
281347a39b4SMariusz Zaborski 			*cookiep = NULL;
282347a39b4SMariusz Zaborski 		return (ret);
283347a39b4SMariusz Zaborski 	}
284347a39b4SMariusz Zaborski 
28508016b31SMariusz Zaborski 	return (nvlist_get_parent(nvl, cookiep));
286347a39b4SMariusz Zaborski }
287347a39b4SMariusz Zaborski 
28854f98da9SMariusz Zaborski bool
28954f98da9SMariusz Zaborski nvlist_empty(const nvlist_t *nvl)
29054f98da9SMariusz Zaborski {
29154f98da9SMariusz Zaborski 
29254f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
29354f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
29454f98da9SMariusz Zaborski 
29554f98da9SMariusz Zaborski 	return (nvlist_first_nvpair(nvl) == NULL);
29654f98da9SMariusz Zaborski }
29754f98da9SMariusz Zaborski 
29854f98da9SMariusz Zaborski int
29954f98da9SMariusz Zaborski nvlist_flags(const nvlist_t *nvl)
30054f98da9SMariusz Zaborski {
30154f98da9SMariusz Zaborski 
30254f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
30354f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
30454f98da9SMariusz Zaborski 
305347a39b4SMariusz Zaborski 	return (nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
306347a39b4SMariusz Zaborski }
307347a39b4SMariusz Zaborski 
308347a39b4SMariusz Zaborski void
309347a39b4SMariusz Zaborski nvlist_set_flags(nvlist_t *nvl, int flags)
310347a39b4SMariusz Zaborski {
311347a39b4SMariusz Zaborski 
312347a39b4SMariusz Zaborski 	NVLIST_ASSERT(nvl);
313347a39b4SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
314347a39b4SMariusz Zaborski 
315347a39b4SMariusz Zaborski 	nvl->nvl_flags = flags;
31654f98da9SMariusz Zaborski }
31754f98da9SMariusz Zaborski 
3185ef231f6SMariusz Zaborski void
31954f98da9SMariusz Zaborski nvlist_report_missing(int type, const char *name)
32054f98da9SMariusz Zaborski {
32154f98da9SMariusz Zaborski 
32254f98da9SMariusz Zaborski 	PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
32354f98da9SMariusz Zaborski 	    name, nvpair_type_string(type));
32454f98da9SMariusz Zaborski }
32554f98da9SMariusz Zaborski 
32654f98da9SMariusz Zaborski static nvpair_t *
32754f98da9SMariusz Zaborski nvlist_find(const nvlist_t *nvl, int type, const char *name)
32854f98da9SMariusz Zaborski {
32954f98da9SMariusz Zaborski 	nvpair_t *nvp;
33054f98da9SMariusz Zaborski 
33154f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
33254f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
33354f98da9SMariusz Zaborski 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
33454f98da9SMariusz Zaborski 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
33554f98da9SMariusz Zaborski 
33654f98da9SMariusz Zaborski 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
33754f98da9SMariusz Zaborski 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
33854f98da9SMariusz Zaborski 		if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
33954f98da9SMariusz Zaborski 			continue;
34054f98da9SMariusz Zaborski 		if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
34154f98da9SMariusz Zaborski 			if (strcasecmp(nvpair_name(nvp), name) != 0)
34254f98da9SMariusz Zaborski 				continue;
34354f98da9SMariusz Zaborski 		} else {
34454f98da9SMariusz Zaborski 			if (strcmp(nvpair_name(nvp), name) != 0)
34554f98da9SMariusz Zaborski 				continue;
34654f98da9SMariusz Zaborski 		}
34754f98da9SMariusz Zaborski 		break;
34854f98da9SMariusz Zaborski 	}
34954f98da9SMariusz Zaborski 
35054f98da9SMariusz Zaborski 	if (nvp == NULL)
35154f98da9SMariusz Zaborski 		ERRNO_SET(ENOENT);
35254f98da9SMariusz Zaborski 
35354f98da9SMariusz Zaborski 	return (nvp);
35454f98da9SMariusz Zaborski }
35554f98da9SMariusz Zaborski 
35654f98da9SMariusz Zaborski bool
35754f98da9SMariusz Zaborski nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
35854f98da9SMariusz Zaborski {
35954f98da9SMariusz Zaborski 
36054f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
36154f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
36254f98da9SMariusz Zaborski 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
36354f98da9SMariusz Zaborski 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
36454f98da9SMariusz Zaborski 
36554f98da9SMariusz Zaborski 	return (nvlist_find(nvl, type, name) != NULL);
36654f98da9SMariusz Zaborski }
36754f98da9SMariusz Zaborski 
36854f98da9SMariusz Zaborski void
36954f98da9SMariusz Zaborski nvlist_free_type(nvlist_t *nvl, const char *name, int type)
37054f98da9SMariusz Zaborski {
37154f98da9SMariusz Zaborski 	nvpair_t *nvp;
37254f98da9SMariusz Zaborski 
37354f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
37454f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
37554f98da9SMariusz Zaborski 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
37654f98da9SMariusz Zaborski 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
37754f98da9SMariusz Zaborski 
37854f98da9SMariusz Zaborski 	nvp = nvlist_find(nvl, type, name);
37954f98da9SMariusz Zaborski 	if (nvp != NULL)
38054f98da9SMariusz Zaborski 		nvlist_free_nvpair(nvl, nvp);
38154f98da9SMariusz Zaborski 	else
38254f98da9SMariusz Zaborski 		nvlist_report_missing(type, name);
38354f98da9SMariusz Zaborski }
38454f98da9SMariusz Zaborski 
38554f98da9SMariusz Zaborski nvlist_t *
38654f98da9SMariusz Zaborski nvlist_clone(const nvlist_t *nvl)
38754f98da9SMariusz Zaborski {
38854f98da9SMariusz Zaborski 	nvlist_t *newnvl;
38954f98da9SMariusz Zaborski 	nvpair_t *nvp, *newnvp;
39054f98da9SMariusz Zaborski 
39154f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
39254f98da9SMariusz Zaborski 
39354f98da9SMariusz Zaborski 	if (nvl->nvl_error != 0) {
39454f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
39554f98da9SMariusz Zaborski 		return (NULL);
39654f98da9SMariusz Zaborski 	}
39754f98da9SMariusz Zaborski 
39854f98da9SMariusz Zaborski 	newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
39954f98da9SMariusz Zaborski 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
40054f98da9SMariusz Zaborski 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
40154f98da9SMariusz Zaborski 		newnvp = nvpair_clone(nvp);
40254f98da9SMariusz Zaborski 		if (newnvp == NULL)
40354f98da9SMariusz Zaborski 			break;
40430740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(newnvl, newnvp);
40554f98da9SMariusz Zaborski 	}
40654f98da9SMariusz Zaborski 	if (nvp != NULL) {
40754f98da9SMariusz Zaborski 		nvlist_destroy(newnvl);
40854f98da9SMariusz Zaborski 		return (NULL);
40954f98da9SMariusz Zaborski 	}
41054f98da9SMariusz Zaborski 	return (newnvl);
41154f98da9SMariusz Zaborski }
41254f98da9SMariusz Zaborski 
41354f98da9SMariusz Zaborski #ifndef _KERNEL
41454f98da9SMariusz Zaborski static bool
41554f98da9SMariusz Zaborski nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
41654f98da9SMariusz Zaborski {
41754f98da9SMariusz Zaborski 
41854f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
41954f98da9SMariusz Zaborski 		dprintf(fd, "%*serror: %d\n", level * 4, "",
42054f98da9SMariusz Zaborski 		    nvlist_error(nvl));
42154f98da9SMariusz Zaborski 		return (true);
42254f98da9SMariusz Zaborski 	}
42354f98da9SMariusz Zaborski 
42454f98da9SMariusz Zaborski 	return (false);
42554f98da9SMariusz Zaborski }
42654f98da9SMariusz Zaborski 
42754f98da9SMariusz Zaborski /*
42854f98da9SMariusz Zaborski  * Dump content of nvlist.
42954f98da9SMariusz Zaborski  */
43054f98da9SMariusz Zaborski void
43154f98da9SMariusz Zaborski nvlist_dump(const nvlist_t *nvl, int fd)
43254f98da9SMariusz Zaborski {
43354f98da9SMariusz Zaborski 	const nvlist_t *tmpnvl;
43454f98da9SMariusz Zaborski 	nvpair_t *nvp, *tmpnvp;
43554f98da9SMariusz Zaborski 	void *cookie;
43654f98da9SMariusz Zaborski 	int level;
43754f98da9SMariusz Zaborski 
43854f98da9SMariusz Zaborski 	level = 0;
43954f98da9SMariusz Zaborski 	if (nvlist_dump_error_check(nvl, fd, level))
44054f98da9SMariusz Zaborski 		return;
44154f98da9SMariusz Zaborski 
44254f98da9SMariusz Zaborski 	nvp = nvlist_first_nvpair(nvl);
44354f98da9SMariusz Zaborski 	while (nvp != NULL) {
44454f98da9SMariusz Zaborski 		dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
44554f98da9SMariusz Zaborski 		    nvpair_type_string(nvpair_type(nvp)));
44654f98da9SMariusz Zaborski 		switch (nvpair_type(nvp)) {
44754f98da9SMariusz Zaborski 		case NV_TYPE_NULL:
44854f98da9SMariusz Zaborski 			dprintf(fd, " null\n");
44954f98da9SMariusz Zaborski 			break;
45054f98da9SMariusz Zaborski 		case NV_TYPE_BOOL:
45154f98da9SMariusz Zaborski 			dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
45254f98da9SMariusz Zaborski 			    "TRUE" : "FALSE");
45354f98da9SMariusz Zaborski 			break;
45454f98da9SMariusz Zaborski 		case NV_TYPE_NUMBER:
45554f98da9SMariusz Zaborski 			dprintf(fd, " %ju (%jd) (0x%jx)\n",
45654f98da9SMariusz Zaborski 			    (uintmax_t)nvpair_get_number(nvp),
45754f98da9SMariusz Zaborski 			    (intmax_t)nvpair_get_number(nvp),
45854f98da9SMariusz Zaborski 			    (uintmax_t)nvpair_get_number(nvp));
45954f98da9SMariusz Zaborski 			break;
46054f98da9SMariusz Zaborski 		case NV_TYPE_STRING:
46154f98da9SMariusz Zaborski 			dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
46254f98da9SMariusz Zaborski 			break;
46354f98da9SMariusz Zaborski 		case NV_TYPE_NVLIST:
46454f98da9SMariusz Zaborski 			dprintf(fd, "\n");
46554f98da9SMariusz Zaborski 			tmpnvl = nvpair_get_nvlist(nvp);
46654f98da9SMariusz Zaborski 			if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
46754f98da9SMariusz Zaborski 				break;
46854f98da9SMariusz Zaborski 			tmpnvp = nvlist_first_nvpair(tmpnvl);
46954f98da9SMariusz Zaborski 			if (tmpnvp != NULL) {
47054f98da9SMariusz Zaborski 				nvl = tmpnvl;
47154f98da9SMariusz Zaborski 				nvp = tmpnvp;
47254f98da9SMariusz Zaborski 				level++;
47354f98da9SMariusz Zaborski 				continue;
47454f98da9SMariusz Zaborski 			}
47554f98da9SMariusz Zaborski 			break;
47654f98da9SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR:
47754f98da9SMariusz Zaborski 			dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
47854f98da9SMariusz Zaborski 			break;
47954f98da9SMariusz Zaborski 		case NV_TYPE_BINARY:
48054f98da9SMariusz Zaborski 		    {
48154f98da9SMariusz Zaborski 			const unsigned char *binary;
48254f98da9SMariusz Zaborski 			unsigned int ii;
48354f98da9SMariusz Zaborski 			size_t size;
48454f98da9SMariusz Zaborski 
48554f98da9SMariusz Zaborski 			binary = nvpair_get_binary(nvp, &size);
48654f98da9SMariusz Zaborski 			dprintf(fd, " %zu ", size);
48754f98da9SMariusz Zaborski 			for (ii = 0; ii < size; ii++)
48854f98da9SMariusz Zaborski 				dprintf(fd, "%02hhx", binary[ii]);
48954f98da9SMariusz Zaborski 			dprintf(fd, "\n");
49054f98da9SMariusz Zaborski 			break;
49154f98da9SMariusz Zaborski 		    }
492347a39b4SMariusz Zaborski 		case NV_TYPE_BOOL_ARRAY:
493347a39b4SMariusz Zaborski 		    {
494347a39b4SMariusz Zaborski 			const bool *value;
495347a39b4SMariusz Zaborski 			unsigned int ii;
496347a39b4SMariusz Zaborski 			size_t nitems;
497347a39b4SMariusz Zaborski 
498347a39b4SMariusz Zaborski 			value = nvpair_get_bool_array(nvp, &nitems);
499347a39b4SMariusz Zaborski 			dprintf(fd, " [ ");
500347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
501347a39b4SMariusz Zaborski 				dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE");
502347a39b4SMariusz Zaborski 				if (ii != nitems - 1)
503347a39b4SMariusz Zaborski 					dprintf(fd, ", ");
504347a39b4SMariusz Zaborski 			}
505347a39b4SMariusz Zaborski 			dprintf(fd, " ]\n");
506347a39b4SMariusz Zaborski 			break;
507347a39b4SMariusz Zaborski 		    }
508347a39b4SMariusz Zaborski 		case NV_TYPE_STRING_ARRAY:
509347a39b4SMariusz Zaborski 		    {
510347a39b4SMariusz Zaborski 			const char * const *value;
511347a39b4SMariusz Zaborski 			unsigned int ii;
512347a39b4SMariusz Zaborski 			size_t nitems;
513347a39b4SMariusz Zaborski 
514347a39b4SMariusz Zaborski 			value = nvpair_get_string_array(nvp, &nitems);
515347a39b4SMariusz Zaborski 			dprintf(fd, " [ ");
516347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
517347a39b4SMariusz Zaborski 				if (value[ii] == NULL)
518347a39b4SMariusz Zaborski 					dprintf(fd, "NULL");
519347a39b4SMariusz Zaborski 				else
520347a39b4SMariusz Zaborski 					dprintf(fd, "\"%s\"", value[ii]);
521347a39b4SMariusz Zaborski 				if (ii != nitems - 1)
522347a39b4SMariusz Zaborski 					dprintf(fd, ", ");
523347a39b4SMariusz Zaborski 			}
524347a39b4SMariusz Zaborski 			dprintf(fd, " ]\n");
525347a39b4SMariusz Zaborski 			break;
526347a39b4SMariusz Zaborski 		    }
527347a39b4SMariusz Zaborski 		case NV_TYPE_NUMBER_ARRAY:
528347a39b4SMariusz Zaborski 		    {
529347a39b4SMariusz Zaborski 			const uint64_t *value;
530347a39b4SMariusz Zaborski 			unsigned int ii;
531347a39b4SMariusz Zaborski 			size_t nitems;
532347a39b4SMariusz Zaborski 
533347a39b4SMariusz Zaborski 			value = nvpair_get_number_array(nvp, &nitems);
534347a39b4SMariusz Zaborski 			dprintf(fd, " [ ");
535347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
536347a39b4SMariusz Zaborski 				dprintf(fd, "%ju (%jd) (0x%jx)",
537347a39b4SMariusz Zaborski 				    value[ii], value[ii], value[ii]);
538347a39b4SMariusz Zaborski 				if (ii != nitems - 1)
539347a39b4SMariusz Zaborski 					dprintf(fd, ", ");
540347a39b4SMariusz Zaborski 			}
541347a39b4SMariusz Zaborski 			dprintf(fd, " ]\n");
542347a39b4SMariusz Zaborski 			break;
543347a39b4SMariusz Zaborski 		    }
544347a39b4SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR_ARRAY:
545347a39b4SMariusz Zaborski 		    {
546347a39b4SMariusz Zaborski 			const int *value;
547347a39b4SMariusz Zaborski 			unsigned int ii;
548347a39b4SMariusz Zaborski 			size_t nitems;
549347a39b4SMariusz Zaborski 
550347a39b4SMariusz Zaborski 			value = nvpair_get_descriptor_array(nvp, &nitems);
551347a39b4SMariusz Zaborski 			dprintf(fd, " [ ");
552347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
553347a39b4SMariusz Zaborski 				dprintf(fd, "%d", value[ii]);
554347a39b4SMariusz Zaborski 				if (ii != nitems - 1)
555347a39b4SMariusz Zaborski 					dprintf(fd, ", ");
556347a39b4SMariusz Zaborski 			}
557347a39b4SMariusz Zaborski 			dprintf(fd, " ]\n");
558347a39b4SMariusz Zaborski 			break;
559347a39b4SMariusz Zaborski 		    }
560347a39b4SMariusz Zaborski 		case NV_TYPE_NVLIST_ARRAY:
561347a39b4SMariusz Zaborski 		    {
562347a39b4SMariusz Zaborski 			const nvlist_t * const *value;
563347a39b4SMariusz Zaborski 			unsigned int ii;
564347a39b4SMariusz Zaborski 			size_t nitems;
565347a39b4SMariusz Zaborski 
566347a39b4SMariusz Zaborski 			value = nvpair_get_nvlist_array(nvp, &nitems);
567347a39b4SMariusz Zaborski 			dprintf(fd, " %zu\n", nitems);
568347a39b4SMariusz Zaborski 			tmpnvl = NULL;
569347a39b4SMariusz Zaborski 			tmpnvp = NULL;
570347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
571347a39b4SMariusz Zaborski 				if (nvlist_dump_error_check(value[ii], fd,
572347a39b4SMariusz Zaborski 				    level + 1)) {
573347a39b4SMariusz Zaborski 					break;
574347a39b4SMariusz Zaborski 				}
575347a39b4SMariusz Zaborski 
576347a39b4SMariusz Zaborski 				if (tmpnvl == NULL) {
577347a39b4SMariusz Zaborski 					tmpnvp = nvlist_first_nvpair(value[ii]);
578347a39b4SMariusz Zaborski 					if (tmpnvp != NULL) {
579347a39b4SMariusz Zaborski 						tmpnvl = value[ii];
580347a39b4SMariusz Zaborski 					} else {
581347a39b4SMariusz Zaborski 						dprintf(fd, "%*s,\n",
582347a39b4SMariusz Zaborski 						    (level + 1) * 4, "");
583347a39b4SMariusz Zaborski 					}
584347a39b4SMariusz Zaborski 				}
585347a39b4SMariusz Zaborski 			}
586347a39b4SMariusz Zaborski 			if (tmpnvp != NULL) {
587347a39b4SMariusz Zaborski 				nvl = tmpnvl;
588347a39b4SMariusz Zaborski 				nvp = tmpnvp;
589347a39b4SMariusz Zaborski 				level++;
590347a39b4SMariusz Zaborski 				continue;
591347a39b4SMariusz Zaborski 			}
592347a39b4SMariusz Zaborski 			break;
593347a39b4SMariusz Zaborski 		    }
59454f98da9SMariusz Zaborski 		default:
59554f98da9SMariusz Zaborski 			PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
59654f98da9SMariusz Zaborski 		}
59754f98da9SMariusz Zaborski 
59854f98da9SMariusz Zaborski 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
599347a39b4SMariusz Zaborski 			do {
60054f98da9SMariusz Zaborski 				cookie = NULL;
601347a39b4SMariusz Zaborski 				if (nvlist_in_array(nvl))
602347a39b4SMariusz Zaborski 					dprintf(fd, "%*s,\n", level * 4, "");
603347a39b4SMariusz Zaborski 				nvl = nvlist_get_pararr(nvl, &cookie);
60454f98da9SMariusz Zaborski 				if (nvl == NULL)
60554f98da9SMariusz Zaborski 					return;
606347a39b4SMariusz Zaborski 				if (nvlist_in_array(nvl) && cookie == NULL) {
607347a39b4SMariusz Zaborski 					nvp = nvlist_first_nvpair(nvl);
608347a39b4SMariusz Zaborski 				} else {
60954f98da9SMariusz Zaborski 					nvp = cookie;
61054f98da9SMariusz Zaborski 					level--;
61154f98da9SMariusz Zaborski 				}
612347a39b4SMariusz Zaborski 			} while (nvp == NULL);
613347a39b4SMariusz Zaborski 			if (nvlist_in_array(nvl) && cookie == NULL)
614347a39b4SMariusz Zaborski 				break;
615347a39b4SMariusz Zaborski 		}
61654f98da9SMariusz Zaborski 	}
61754f98da9SMariusz Zaborski }
61854f98da9SMariusz Zaborski 
61954f98da9SMariusz Zaborski void
62054f98da9SMariusz Zaborski nvlist_fdump(const nvlist_t *nvl, FILE *fp)
62154f98da9SMariusz Zaborski {
62254f98da9SMariusz Zaborski 
62354f98da9SMariusz Zaborski 	fflush(fp);
62454f98da9SMariusz Zaborski 	nvlist_dump(nvl, fileno(fp));
62554f98da9SMariusz Zaborski }
62654f98da9SMariusz Zaborski #endif
62754f98da9SMariusz Zaborski 
62854f98da9SMariusz Zaborski /*
62954f98da9SMariusz Zaborski  * The function obtains size of the nvlist after nvlist_pack().
63054f98da9SMariusz Zaborski  */
63154f98da9SMariusz Zaborski size_t
63254f98da9SMariusz Zaborski nvlist_size(const nvlist_t *nvl)
63354f98da9SMariusz Zaborski {
63454f98da9SMariusz Zaborski 	const nvlist_t *tmpnvl;
635347a39b4SMariusz Zaborski 	const nvlist_t * const *nvlarray;
63654f98da9SMariusz Zaborski 	const nvpair_t *nvp, *tmpnvp;
63754f98da9SMariusz Zaborski 	void *cookie;
638347a39b4SMariusz Zaborski 	size_t size, nitems;
639347a39b4SMariusz Zaborski 	unsigned int ii;
64054f98da9SMariusz Zaborski 
64154f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
64254f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
64354f98da9SMariusz Zaborski 
64454f98da9SMariusz Zaborski 	size = sizeof(struct nvlist_header);
64554f98da9SMariusz Zaborski 	nvp = nvlist_first_nvpair(nvl);
64654f98da9SMariusz Zaborski 	while (nvp != NULL) {
64754f98da9SMariusz Zaborski 		size += nvpair_header_size();
64854f98da9SMariusz Zaborski 		size += strlen(nvpair_name(nvp)) + 1;
64954f98da9SMariusz Zaborski 		if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
65054f98da9SMariusz Zaborski 			size += sizeof(struct nvlist_header);
65154f98da9SMariusz Zaborski 			size += nvpair_header_size() + 1;
65254f98da9SMariusz Zaborski 			tmpnvl = nvpair_get_nvlist(nvp);
65354f98da9SMariusz Zaborski 			PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
65454f98da9SMariusz Zaborski 			tmpnvp = nvlist_first_nvpair(tmpnvl);
65554f98da9SMariusz Zaborski 			if (tmpnvp != NULL) {
65654f98da9SMariusz Zaborski 				nvl = tmpnvl;
65754f98da9SMariusz Zaborski 				nvp = tmpnvp;
65854f98da9SMariusz Zaborski 				continue;
65954f98da9SMariusz Zaborski 			}
660347a39b4SMariusz Zaborski 		} else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) {
661347a39b4SMariusz Zaborski 			nvlarray = nvpair_get_nvlist_array(nvp, &nitems);
662347a39b4SMariusz Zaborski 			PJDLOG_ASSERT(nitems > 0);
663347a39b4SMariusz Zaborski 
664347a39b4SMariusz Zaborski 			size += (nvpair_header_size() + 1) * nitems;
665347a39b4SMariusz Zaborski 			size += sizeof(struct nvlist_header) * nitems;
666347a39b4SMariusz Zaborski 
667347a39b4SMariusz Zaborski 			tmpnvl = NULL;
668347a39b4SMariusz Zaborski 			tmpnvp = NULL;
669347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
670347a39b4SMariusz Zaborski 				PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0);
671347a39b4SMariusz Zaborski 				tmpnvp = nvlist_first_nvpair(nvlarray[ii]);
672347a39b4SMariusz Zaborski 				if (tmpnvp != NULL) {
673347a39b4SMariusz Zaborski 					tmpnvl = nvlarray[ii];
674347a39b4SMariusz Zaborski 					break;
675347a39b4SMariusz Zaborski 				}
676347a39b4SMariusz Zaborski 			}
677347a39b4SMariusz Zaborski 			if (tmpnvp != NULL) {
678347a39b4SMariusz Zaborski 				nvp = tmpnvp;
679347a39b4SMariusz Zaborski 				nvl = tmpnvl;
680347a39b4SMariusz Zaborski 				continue;
681347a39b4SMariusz Zaborski 			}
682347a39b4SMariusz Zaborski 
68354f98da9SMariusz Zaborski 		} else {
68454f98da9SMariusz Zaborski 			size += nvpair_size(nvp);
68554f98da9SMariusz Zaborski 		}
68654f98da9SMariusz Zaborski 
68754f98da9SMariusz Zaborski 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
688347a39b4SMariusz Zaborski 			do {
68954f98da9SMariusz Zaborski 				cookie = NULL;
690347a39b4SMariusz Zaborski 				nvl = nvlist_get_pararr(nvl, &cookie);
69154f98da9SMariusz Zaborski 				if (nvl == NULL)
69254f98da9SMariusz Zaborski 					goto out;
693347a39b4SMariusz Zaborski 				if (nvlist_in_array(nvl) && cookie == NULL) {
694347a39b4SMariusz Zaborski 					nvp = nvlist_first_nvpair(nvl);
695347a39b4SMariusz Zaborski 				} else {
69654f98da9SMariusz Zaborski 					nvp = cookie;
69754f98da9SMariusz Zaborski 				}
698347a39b4SMariusz Zaborski 			} while (nvp == NULL);
699347a39b4SMariusz Zaborski 			if (nvlist_in_array(nvl) && cookie == NULL)
700347a39b4SMariusz Zaborski 				break;
701347a39b4SMariusz Zaborski 		}
70254f98da9SMariusz Zaborski 	}
70354f98da9SMariusz Zaborski 
70454f98da9SMariusz Zaborski out:
70554f98da9SMariusz Zaborski 	return (size);
70654f98da9SMariusz Zaborski }
70754f98da9SMariusz Zaborski 
70854f98da9SMariusz Zaborski #ifndef _KERNEL
70954f98da9SMariusz Zaborski static int *
71054f98da9SMariusz Zaborski nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
71154f98da9SMariusz Zaborski {
7129a8ce256SJilles Tjoelker 	void *cookie;
71354f98da9SMariusz Zaborski 	nvpair_t *nvp;
71454f98da9SMariusz Zaborski 	int type;
71554f98da9SMariusz Zaborski 
71654f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
71754f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
71854f98da9SMariusz Zaborski 
7199a8ce256SJilles Tjoelker 	cookie = NULL;
72054f98da9SMariusz Zaborski 	do {
7219a8ce256SJilles Tjoelker 		while (nvlist_next(nvl, &type, &cookie) != NULL) {
7229a8ce256SJilles Tjoelker 			nvp = cookie;
72354f98da9SMariusz Zaborski 			switch (type) {
72454f98da9SMariusz Zaborski 			case NV_TYPE_DESCRIPTOR:
72554f98da9SMariusz Zaborski 				*descs = nvpair_get_descriptor(nvp);
72654f98da9SMariusz Zaborski 				descs++;
72754f98da9SMariusz Zaborski 				break;
728347a39b4SMariusz Zaborski 			case NV_TYPE_DESCRIPTOR_ARRAY:
729347a39b4SMariusz Zaborski 			    {
730347a39b4SMariusz Zaborski 				const int *value;
731347a39b4SMariusz Zaborski 				size_t nitems;
732347a39b4SMariusz Zaborski 				unsigned int ii;
733347a39b4SMariusz Zaborski 
734347a39b4SMariusz Zaborski 				value = nvpair_get_descriptor_array(nvp,
735347a39b4SMariusz Zaborski 				    &nitems);
736347a39b4SMariusz Zaborski 				for (ii = 0; ii < nitems; ii++) {
737347a39b4SMariusz Zaborski 					*descs = value[ii];
738347a39b4SMariusz Zaborski 					descs++;
739347a39b4SMariusz Zaborski 				}
740347a39b4SMariusz Zaborski 				break;
741347a39b4SMariusz Zaborski 			    }
74254f98da9SMariusz Zaborski 			case NV_TYPE_NVLIST:
74354f98da9SMariusz Zaborski 				nvl = nvpair_get_nvlist(nvp);
7449a8ce256SJilles Tjoelker 				cookie = NULL;
74554f98da9SMariusz Zaborski 				break;
746347a39b4SMariusz Zaborski 			case NV_TYPE_NVLIST_ARRAY:
747347a39b4SMariusz Zaborski 			    {
748347a39b4SMariusz Zaborski 				const nvlist_t * const *value;
749347a39b4SMariusz Zaborski 				size_t nitems;
750347a39b4SMariusz Zaborski 
751347a39b4SMariusz Zaborski 				value = nvpair_get_nvlist_array(nvp, &nitems);
752347a39b4SMariusz Zaborski 				PJDLOG_ASSERT(value != NULL);
753347a39b4SMariusz Zaborski 				PJDLOG_ASSERT(nitems > 0);
754347a39b4SMariusz Zaborski 
755347a39b4SMariusz Zaborski 				nvl = value[0];
7569a8ce256SJilles Tjoelker 				cookie = NULL;
757347a39b4SMariusz Zaborski 				break;
75854f98da9SMariusz Zaborski 			    }
75954f98da9SMariusz Zaborski 			}
760347a39b4SMariusz Zaborski 		}
7619a8ce256SJilles Tjoelker 	} while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
76254f98da9SMariusz Zaborski 
76354f98da9SMariusz Zaborski 	return (descs);
76454f98da9SMariusz Zaborski }
76554f98da9SMariusz Zaborski #endif
76654f98da9SMariusz Zaborski 
76754f98da9SMariusz Zaborski #ifndef _KERNEL
76854f98da9SMariusz Zaborski int *
76954f98da9SMariusz Zaborski nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
77054f98da9SMariusz Zaborski {
77154f98da9SMariusz Zaborski 	size_t nitems;
77254f98da9SMariusz Zaborski 	int *fds;
77354f98da9SMariusz Zaborski 
77454f98da9SMariusz Zaborski 	nitems = nvlist_ndescriptors(nvl);
77554f98da9SMariusz Zaborski 	fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
77654f98da9SMariusz Zaborski 	if (fds == NULL)
77754f98da9SMariusz Zaborski 		return (NULL);
77854f98da9SMariusz Zaborski 	if (nitems > 0)
77954f98da9SMariusz Zaborski 		nvlist_xdescriptors(nvl, fds);
78054f98da9SMariusz Zaborski 	fds[nitems] = -1;
78154f98da9SMariusz Zaborski 	if (nitemsp != NULL)
78254f98da9SMariusz Zaborski 		*nitemsp = nitems;
78354f98da9SMariusz Zaborski 	return (fds);
78454f98da9SMariusz Zaborski }
78554f98da9SMariusz Zaborski #endif
78654f98da9SMariusz Zaborski 
78754f98da9SMariusz Zaborski size_t
78854f98da9SMariusz Zaborski nvlist_ndescriptors(const nvlist_t *nvl)
78954f98da9SMariusz Zaborski {
79054f98da9SMariusz Zaborski #ifndef _KERNEL
7919a8ce256SJilles Tjoelker 	void *cookie;
79254f98da9SMariusz Zaborski 	nvpair_t *nvp;
79354f98da9SMariusz Zaborski 	size_t ndescs;
79454f98da9SMariusz Zaborski 	int type;
79554f98da9SMariusz Zaborski 
79654f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
79754f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
79854f98da9SMariusz Zaborski 
79954f98da9SMariusz Zaborski 	ndescs = 0;
8009a8ce256SJilles Tjoelker 	cookie = NULL;
80154f98da9SMariusz Zaborski 	do {
8029a8ce256SJilles Tjoelker 		while (nvlist_next(nvl, &type, &cookie) != NULL) {
8039a8ce256SJilles Tjoelker 			nvp = cookie;
80454f98da9SMariusz Zaborski 			switch (type) {
80554f98da9SMariusz Zaborski 			case NV_TYPE_DESCRIPTOR:
80654f98da9SMariusz Zaborski 				ndescs++;
80754f98da9SMariusz Zaborski 				break;
80854f98da9SMariusz Zaborski 			case NV_TYPE_NVLIST:
80954f98da9SMariusz Zaborski 				nvl = nvpair_get_nvlist(nvp);
8109a8ce256SJilles Tjoelker 				cookie = NULL;
81154f98da9SMariusz Zaborski 				break;
812347a39b4SMariusz Zaborski 			case NV_TYPE_NVLIST_ARRAY:
813347a39b4SMariusz Zaborski 			    {
814347a39b4SMariusz Zaborski 				const nvlist_t * const *value;
815347a39b4SMariusz Zaborski 				size_t nitems;
816347a39b4SMariusz Zaborski 
817347a39b4SMariusz Zaborski 				value = nvpair_get_nvlist_array(nvp, &nitems);
818347a39b4SMariusz Zaborski 				PJDLOG_ASSERT(value != NULL);
819347a39b4SMariusz Zaborski 				PJDLOG_ASSERT(nitems > 0);
820347a39b4SMariusz Zaborski 
821347a39b4SMariusz Zaborski 				nvl = value[0];
8229a8ce256SJilles Tjoelker 				cookie = NULL;
823347a39b4SMariusz Zaborski 				break;
824347a39b4SMariusz Zaborski 			    }
825347a39b4SMariusz Zaborski 			case NV_TYPE_DESCRIPTOR_ARRAY:
826347a39b4SMariusz Zaborski 			    {
827347a39b4SMariusz Zaborski 				size_t nitems;
828347a39b4SMariusz Zaborski 
829347a39b4SMariusz Zaborski 				(void)nvpair_get_descriptor_array(nvp,
830347a39b4SMariusz Zaborski 				    &nitems);
831347a39b4SMariusz Zaborski 				ndescs += nitems;
832347a39b4SMariusz Zaborski 				break;
83354f98da9SMariusz Zaborski 			    }
83454f98da9SMariusz Zaborski 			}
835347a39b4SMariusz Zaborski 		}
8369a8ce256SJilles Tjoelker 	} while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
83754f98da9SMariusz Zaborski 
83854f98da9SMariusz Zaborski 	return (ndescs);
83954f98da9SMariusz Zaborski #else
84054f98da9SMariusz Zaborski 	return (0);
84154f98da9SMariusz Zaborski #endif
84254f98da9SMariusz Zaborski }
84354f98da9SMariusz Zaborski 
84454f98da9SMariusz Zaborski static unsigned char *
84554f98da9SMariusz Zaborski nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
84654f98da9SMariusz Zaborski {
84754f98da9SMariusz Zaborski 	struct nvlist_header nvlhdr;
84854f98da9SMariusz Zaborski 
84954f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
85054f98da9SMariusz Zaborski 
85154f98da9SMariusz Zaborski 	nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
85254f98da9SMariusz Zaborski 	nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
85354f98da9SMariusz Zaborski 	nvlhdr.nvlh_flags = nvl->nvl_flags;
85454f98da9SMariusz Zaborski #if BYTE_ORDER == BIG_ENDIAN
85554f98da9SMariusz Zaborski 	nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
85654f98da9SMariusz Zaborski #endif
85754f98da9SMariusz Zaborski 	nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
85854f98da9SMariusz Zaborski 	nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
85954f98da9SMariusz Zaborski 	PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
86054f98da9SMariusz Zaborski 	memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
86154f98da9SMariusz Zaborski 	ptr += sizeof(nvlhdr);
86254f98da9SMariusz Zaborski 	*leftp -= sizeof(nvlhdr);
86354f98da9SMariusz Zaborski 
86454f98da9SMariusz Zaborski 	return (ptr);
86554f98da9SMariusz Zaborski }
86654f98da9SMariusz Zaborski 
86754f98da9SMariusz Zaborski static void *
86854f98da9SMariusz Zaborski nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
86954f98da9SMariusz Zaborski {
87054f98da9SMariusz Zaborski 	unsigned char *buf, *ptr;
87154f98da9SMariusz Zaborski 	size_t left, size;
87254f98da9SMariusz Zaborski 	const nvlist_t *tmpnvl;
87354f98da9SMariusz Zaborski 	nvpair_t *nvp, *tmpnvp;
87454f98da9SMariusz Zaborski 	void *cookie;
87554f98da9SMariusz Zaborski 
87654f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
87754f98da9SMariusz Zaborski 
87854f98da9SMariusz Zaborski 	if (nvl->nvl_error != 0) {
87954f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
88054f98da9SMariusz Zaborski 		return (NULL);
88154f98da9SMariusz Zaborski 	}
88254f98da9SMariusz Zaborski 
88354f98da9SMariusz Zaborski 	size = nvlist_size(nvl);
88454f98da9SMariusz Zaborski 	buf = nv_malloc(size);
88554f98da9SMariusz Zaborski 	if (buf == NULL)
88654f98da9SMariusz Zaborski 		return (NULL);
88754f98da9SMariusz Zaborski 
88854f98da9SMariusz Zaborski 	ptr = buf;
88954f98da9SMariusz Zaborski 	left = size;
89054f98da9SMariusz Zaborski 
89154f98da9SMariusz Zaborski 	ptr = nvlist_pack_header(nvl, ptr, &left);
89254f98da9SMariusz Zaborski 
89354f98da9SMariusz Zaborski 	nvp = nvlist_first_nvpair(nvl);
89454f98da9SMariusz Zaborski 	while (nvp != NULL) {
89554f98da9SMariusz Zaborski 		NVPAIR_ASSERT(nvp);
89654f98da9SMariusz Zaborski 
89754f98da9SMariusz Zaborski 		nvpair_init_datasize(nvp);
89854f98da9SMariusz Zaborski 		ptr = nvpair_pack_header(nvp, ptr, &left);
899c68f8061SMariusz Zaborski 		if (ptr == NULL)
900c68f8061SMariusz Zaborski 			goto fail;
90154f98da9SMariusz Zaborski 		switch (nvpair_type(nvp)) {
90254f98da9SMariusz Zaborski 		case NV_TYPE_NULL:
90354f98da9SMariusz Zaborski 			ptr = nvpair_pack_null(nvp, ptr, &left);
90454f98da9SMariusz Zaborski 			break;
90554f98da9SMariusz Zaborski 		case NV_TYPE_BOOL:
90654f98da9SMariusz Zaborski 			ptr = nvpair_pack_bool(nvp, ptr, &left);
90754f98da9SMariusz Zaborski 			break;
90854f98da9SMariusz Zaborski 		case NV_TYPE_NUMBER:
90954f98da9SMariusz Zaborski 			ptr = nvpair_pack_number(nvp, ptr, &left);
91054f98da9SMariusz Zaborski 			break;
91154f98da9SMariusz Zaborski 		case NV_TYPE_STRING:
91254f98da9SMariusz Zaborski 			ptr = nvpair_pack_string(nvp, ptr, &left);
91354f98da9SMariusz Zaborski 			break;
91454f98da9SMariusz Zaborski 		case NV_TYPE_NVLIST:
91554f98da9SMariusz Zaborski 			tmpnvl = nvpair_get_nvlist(nvp);
91654f98da9SMariusz Zaborski 			ptr = nvlist_pack_header(tmpnvl, ptr, &left);
91754f98da9SMariusz Zaborski 			if (ptr == NULL)
918c68f8061SMariusz Zaborski 				goto fail;
91954f98da9SMariusz Zaborski 			tmpnvp = nvlist_first_nvpair(tmpnvl);
92054f98da9SMariusz Zaborski 			if (tmpnvp != NULL) {
92154f98da9SMariusz Zaborski 				nvl = tmpnvl;
92254f98da9SMariusz Zaborski 				nvp = tmpnvp;
92354f98da9SMariusz Zaborski 				continue;
92454f98da9SMariusz Zaborski 			}
92554f98da9SMariusz Zaborski 			ptr = nvpair_pack_nvlist_up(ptr, &left);
92654f98da9SMariusz Zaborski 			break;
92754f98da9SMariusz Zaborski #ifndef _KERNEL
92854f98da9SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR:
92954f98da9SMariusz Zaborski 			ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
93054f98da9SMariusz Zaborski 			break;
931347a39b4SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR_ARRAY:
932347a39b4SMariusz Zaborski 			ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp,
933347a39b4SMariusz Zaborski 			    &left);
934347a39b4SMariusz Zaborski 			break;
93554f98da9SMariusz Zaborski #endif
93654f98da9SMariusz Zaborski 		case NV_TYPE_BINARY:
93754f98da9SMariusz Zaborski 			ptr = nvpair_pack_binary(nvp, ptr, &left);
93854f98da9SMariusz Zaborski 			break;
939347a39b4SMariusz Zaborski 		case NV_TYPE_BOOL_ARRAY:
940347a39b4SMariusz Zaborski 			ptr = nvpair_pack_bool_array(nvp, ptr, &left);
941347a39b4SMariusz Zaborski 			break;
942347a39b4SMariusz Zaborski 		case NV_TYPE_NUMBER_ARRAY:
943347a39b4SMariusz Zaborski 			ptr = nvpair_pack_number_array(nvp, ptr, &left);
944347a39b4SMariusz Zaborski 			break;
945347a39b4SMariusz Zaborski 		case NV_TYPE_STRING_ARRAY:
946347a39b4SMariusz Zaborski 			ptr = nvpair_pack_string_array(nvp, ptr, &left);
947347a39b4SMariusz Zaborski 			break;
948347a39b4SMariusz Zaborski 		case NV_TYPE_NVLIST_ARRAY:
949347a39b4SMariusz Zaborski 		    {
950347a39b4SMariusz Zaborski 			const nvlist_t * const * value;
951347a39b4SMariusz Zaborski 			size_t nitems;
952347a39b4SMariusz Zaborski 			unsigned int ii;
953347a39b4SMariusz Zaborski 
954347a39b4SMariusz Zaborski 			tmpnvl = NULL;
955347a39b4SMariusz Zaborski 			value = nvpair_get_nvlist_array(nvp, &nitems);
956347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
957347a39b4SMariusz Zaborski 				ptr = nvlist_pack_header(value[ii], ptr, &left);
958347a39b4SMariusz Zaborski 				if (ptr == NULL)
959347a39b4SMariusz Zaborski 					goto out;
960347a39b4SMariusz Zaborski 				tmpnvp = nvlist_first_nvpair(value[ii]);
961347a39b4SMariusz Zaborski 				if (tmpnvp != NULL) {
962347a39b4SMariusz Zaborski 					tmpnvl = value[ii];
963347a39b4SMariusz Zaborski 					break;
964347a39b4SMariusz Zaborski 				}
965347a39b4SMariusz Zaborski 				ptr = nvpair_pack_nvlist_array_next(ptr, &left);
966347a39b4SMariusz Zaborski 				if (ptr == NULL)
967347a39b4SMariusz Zaborski 					goto out;
968347a39b4SMariusz Zaborski 			}
969347a39b4SMariusz Zaborski 			if (tmpnvl != NULL) {
970347a39b4SMariusz Zaborski 				nvl = tmpnvl;
971347a39b4SMariusz Zaborski 				nvp = tmpnvp;
972347a39b4SMariusz Zaborski 				continue;
973347a39b4SMariusz Zaborski 			}
974347a39b4SMariusz Zaborski 			break;
975347a39b4SMariusz Zaborski 		    }
97654f98da9SMariusz Zaborski 		default:
97754f98da9SMariusz Zaborski 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
97854f98da9SMariusz Zaborski 		}
979c68f8061SMariusz Zaborski 		if (ptr == NULL)
980c68f8061SMariusz Zaborski 			goto fail;
98154f98da9SMariusz Zaborski 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
982347a39b4SMariusz Zaborski 			do {
98354f98da9SMariusz Zaborski 				cookie = NULL;
984347a39b4SMariusz Zaborski 				if (nvlist_in_array(nvl)) {
985347a39b4SMariusz Zaborski 					ptr = nvpair_pack_nvlist_array_next(ptr,
986347a39b4SMariusz Zaborski 					    &left);
987347a39b4SMariusz Zaborski 					if (ptr == NULL)
988347a39b4SMariusz Zaborski 						goto fail;
989347a39b4SMariusz Zaborski 				}
990347a39b4SMariusz Zaborski 				nvl = nvlist_get_pararr(nvl, &cookie);
99154f98da9SMariusz Zaborski 				if (nvl == NULL)
99254f98da9SMariusz Zaborski 					goto out;
993347a39b4SMariusz Zaborski 				if (nvlist_in_array(nvl) && cookie == NULL) {
994347a39b4SMariusz Zaborski 					nvp = nvlist_first_nvpair(nvl);
995347a39b4SMariusz Zaborski 					ptr = nvlist_pack_header(nvl, ptr,
996347a39b4SMariusz Zaborski 					    &left);
997347a39b4SMariusz Zaborski 					if (ptr == NULL)
998347a39b4SMariusz Zaborski 						goto fail;
999347a39b4SMariusz Zaborski 				} else if (nvpair_type((nvpair_t *)cookie) !=
1000347a39b4SMariusz Zaborski 				    NV_TYPE_NVLIST_ARRAY) {
100154f98da9SMariusz Zaborski 					ptr = nvpair_pack_nvlist_up(ptr, &left);
100254f98da9SMariusz Zaborski 					if (ptr == NULL)
1003c68f8061SMariusz Zaborski 						goto fail;
1004347a39b4SMariusz Zaborski 					nvp = cookie;
1005347a39b4SMariusz Zaborski 				} else {
1006347a39b4SMariusz Zaborski 					nvp = cookie;
1007347a39b4SMariusz Zaborski 				}
1008347a39b4SMariusz Zaborski 			} while (nvp == NULL);
1009347a39b4SMariusz Zaborski 			if (nvlist_in_array(nvl) && cookie == NULL)
1010347a39b4SMariusz Zaborski 				break;
101154f98da9SMariusz Zaborski 		}
101254f98da9SMariusz Zaborski 	}
101354f98da9SMariusz Zaborski 
101454f98da9SMariusz Zaborski out:
101554f98da9SMariusz Zaborski 	if (sizep != NULL)
101654f98da9SMariusz Zaborski 		*sizep = size;
101754f98da9SMariusz Zaborski 	return (buf);
1018c68f8061SMariusz Zaborski fail:
1019c68f8061SMariusz Zaborski 	nv_free(buf);
1020c68f8061SMariusz Zaborski 	return (NULL);
102154f98da9SMariusz Zaborski }
102254f98da9SMariusz Zaborski 
102354f98da9SMariusz Zaborski void *
102454f98da9SMariusz Zaborski nvlist_pack(const nvlist_t *nvl, size_t *sizep)
102554f98da9SMariusz Zaborski {
102654f98da9SMariusz Zaborski 
102754f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
102854f98da9SMariusz Zaborski 
102954f98da9SMariusz Zaborski 	if (nvl->nvl_error != 0) {
103054f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
103154f98da9SMariusz Zaborski 		return (NULL);
103254f98da9SMariusz Zaborski 	}
103354f98da9SMariusz Zaborski 
103454f98da9SMariusz Zaborski 	if (nvlist_ndescriptors(nvl) > 0) {
103554f98da9SMariusz Zaborski 		ERRNO_SET(EOPNOTSUPP);
103654f98da9SMariusz Zaborski 		return (NULL);
103754f98da9SMariusz Zaborski 	}
103854f98da9SMariusz Zaborski 
103954f98da9SMariusz Zaborski 	return (nvlist_xpack(nvl, NULL, sizep));
104054f98da9SMariusz Zaborski }
104154f98da9SMariusz Zaborski 
104254f98da9SMariusz Zaborski static bool
104354f98da9SMariusz Zaborski nvlist_check_header(struct nvlist_header *nvlhdrp)
104454f98da9SMariusz Zaborski {
104554f98da9SMariusz Zaborski 
104654f98da9SMariusz Zaborski 	if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
104754f98da9SMariusz Zaborski 		ERRNO_SET(EINVAL);
104854f98da9SMariusz Zaborski 		return (false);
104954f98da9SMariusz Zaborski 	}
105054f98da9SMariusz Zaborski 	if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
105154f98da9SMariusz Zaborski 		ERRNO_SET(EINVAL);
105254f98da9SMariusz Zaborski 		return (false);
105354f98da9SMariusz Zaborski 	}
105454f98da9SMariusz Zaborski #if BYTE_ORDER == BIG_ENDIAN
105554f98da9SMariusz Zaborski 	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
105654f98da9SMariusz Zaborski 		nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
105754f98da9SMariusz Zaborski 		nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
105854f98da9SMariusz Zaborski 	}
105954f98da9SMariusz Zaborski #else
106054f98da9SMariusz Zaborski 	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
106154f98da9SMariusz Zaborski 		nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
106254f98da9SMariusz Zaborski 		nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
106354f98da9SMariusz Zaborski 	}
106454f98da9SMariusz Zaborski #endif
106554f98da9SMariusz Zaborski 	return (true);
106654f98da9SMariusz Zaborski }
106754f98da9SMariusz Zaborski 
106854f98da9SMariusz Zaborski const unsigned char *
106954f98da9SMariusz Zaborski nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
107054f98da9SMariusz Zaborski     bool *isbep, size_t *leftp)
107154f98da9SMariusz Zaborski {
107254f98da9SMariusz Zaborski 	struct nvlist_header nvlhdr;
1073347a39b4SMariusz Zaborski 	int inarrayf;
107454f98da9SMariusz Zaborski 
107554f98da9SMariusz Zaborski 	if (*leftp < sizeof(nvlhdr))
1076a3c485d3SMariusz Zaborski 		goto fail;
107754f98da9SMariusz Zaborski 
107854f98da9SMariusz Zaborski 	memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
107954f98da9SMariusz Zaborski 
108054f98da9SMariusz Zaborski 	if (!nvlist_check_header(&nvlhdr))
1081a3c485d3SMariusz Zaborski 		goto fail;
108254f98da9SMariusz Zaborski 
108354f98da9SMariusz Zaborski 	if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
1084a3c485d3SMariusz Zaborski 		goto fail;
108554f98da9SMariusz Zaborski 
108654f98da9SMariusz Zaborski 	/*
108754f98da9SMariusz Zaborski 	 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
108854f98da9SMariusz Zaborski 	 */
108954f98da9SMariusz Zaborski 	if (nvlhdr.nvlh_descriptors > nfds)
1090a3c485d3SMariusz Zaborski 		goto fail;
109154f98da9SMariusz Zaborski 
109254f98da9SMariusz Zaborski 	if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
1093a3c485d3SMariusz Zaborski 		goto fail;
109454f98da9SMariusz Zaborski 
1095347a39b4SMariusz Zaborski 	inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY);
1096347a39b4SMariusz Zaborski 	nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf;
109754f98da9SMariusz Zaborski 
109854f98da9SMariusz Zaborski 	ptr += sizeof(nvlhdr);
109954f98da9SMariusz Zaborski 	if (isbep != NULL)
110054f98da9SMariusz Zaborski 		*isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
110154f98da9SMariusz Zaborski 	*leftp -= sizeof(nvlhdr);
110254f98da9SMariusz Zaborski 
110354f98da9SMariusz Zaborski 	return (ptr);
1104a3c485d3SMariusz Zaborski fail:
110554f98da9SMariusz Zaborski 	ERRNO_SET(EINVAL);
110654f98da9SMariusz Zaborski 	return (NULL);
110754f98da9SMariusz Zaborski }
110854f98da9SMariusz Zaborski 
110954f98da9SMariusz Zaborski static nvlist_t *
111054f98da9SMariusz Zaborski nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
111154f98da9SMariusz Zaborski     int flags)
111254f98da9SMariusz Zaborski {
111354f98da9SMariusz Zaborski 	const unsigned char *ptr;
1114347a39b4SMariusz Zaborski 	nvlist_t *nvl, *retnvl, *tmpnvl, *array;
111554f98da9SMariusz Zaborski 	nvpair_t *nvp;
111654f98da9SMariusz Zaborski 	size_t left;
111754f98da9SMariusz Zaborski 	bool isbe;
111854f98da9SMariusz Zaborski 
111954f98da9SMariusz Zaborski 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
112054f98da9SMariusz Zaborski 
112154f98da9SMariusz Zaborski 	left = size;
112254f98da9SMariusz Zaborski 	ptr = buf;
112354f98da9SMariusz Zaborski 
1124347a39b4SMariusz Zaborski 	tmpnvl = array = NULL;
112554f98da9SMariusz Zaborski 	nvl = retnvl = nvlist_create(0);
112654f98da9SMariusz Zaborski 	if (nvl == NULL)
1127a3c485d3SMariusz Zaborski 		goto fail;
112854f98da9SMariusz Zaborski 
112954f98da9SMariusz Zaborski 	ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
113054f98da9SMariusz Zaborski 	if (ptr == NULL)
1131a3c485d3SMariusz Zaborski 		goto fail;
113254f98da9SMariusz Zaborski 	if (nvl->nvl_flags != flags) {
113354f98da9SMariusz Zaborski 		ERRNO_SET(EILSEQ);
1134a3c485d3SMariusz Zaborski 		goto fail;
113554f98da9SMariusz Zaborski 	}
113654f98da9SMariusz Zaborski 
113754f98da9SMariusz Zaborski 	while (left > 0) {
113854f98da9SMariusz Zaborski 		ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
113954f98da9SMariusz Zaborski 		if (ptr == NULL)
1140a3c485d3SMariusz Zaborski 			goto fail;
114154f98da9SMariusz Zaborski 		switch (nvpair_type(nvp)) {
114254f98da9SMariusz Zaborski 		case NV_TYPE_NULL:
114354f98da9SMariusz Zaborski 			ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
114454f98da9SMariusz Zaborski 			break;
114554f98da9SMariusz Zaborski 		case NV_TYPE_BOOL:
114654f98da9SMariusz Zaborski 			ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
114754f98da9SMariusz Zaborski 			break;
114854f98da9SMariusz Zaborski 		case NV_TYPE_NUMBER:
114954f98da9SMariusz Zaborski 			ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
115054f98da9SMariusz Zaborski 			break;
115154f98da9SMariusz Zaborski 		case NV_TYPE_STRING:
115254f98da9SMariusz Zaborski 			ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
115354f98da9SMariusz Zaborski 			break;
115454f98da9SMariusz Zaborski 		case NV_TYPE_NVLIST:
115554f98da9SMariusz Zaborski 			ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
115654f98da9SMariusz Zaborski 			    &tmpnvl);
115751dae13fSMariusz Zaborski 			if (tmpnvl == NULL || ptr == NULL)
1158a3c485d3SMariusz Zaborski 				goto fail;
115954f98da9SMariusz Zaborski 			nvlist_set_parent(tmpnvl, nvp);
116054f98da9SMariusz Zaborski 			break;
116154f98da9SMariusz Zaborski #ifndef _KERNEL
116254f98da9SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR:
116354f98da9SMariusz Zaborski 			ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
116454f98da9SMariusz Zaborski 			    fds, nfds);
116554f98da9SMariusz Zaborski 			break;
1166347a39b4SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR_ARRAY:
1167347a39b4SMariusz Zaborski 			ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr,
1168347a39b4SMariusz Zaborski 			    &left, fds, nfds);
1169347a39b4SMariusz Zaborski 			break;
117054f98da9SMariusz Zaborski #endif
117154f98da9SMariusz Zaborski 		case NV_TYPE_BINARY:
117254f98da9SMariusz Zaborski 			ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
117354f98da9SMariusz Zaborski 			break;
117454f98da9SMariusz Zaborski 		case NV_TYPE_NVLIST_UP:
117554f98da9SMariusz Zaborski 			if (nvl->nvl_parent == NULL)
1176a3c485d3SMariusz Zaborski 				goto fail;
117754f98da9SMariusz Zaborski 			nvl = nvpair_nvlist(nvl->nvl_parent);
117854f98da9SMariusz Zaborski 			nvpair_free_structure(nvp);
117954f98da9SMariusz Zaborski 			continue;
1180347a39b4SMariusz Zaborski 		case NV_TYPE_NVLIST_ARRAY_NEXT:
1181347a39b4SMariusz Zaborski 			if (nvl->nvl_array_next == NULL) {
1182347a39b4SMariusz Zaborski 				if (nvl->nvl_parent == NULL)
1183a3c485d3SMariusz Zaborski 					goto fail;
1184347a39b4SMariusz Zaborski 				nvl = nvpair_nvlist(nvl->nvl_parent);
1185347a39b4SMariusz Zaborski 			} else {
1186347a39b4SMariusz Zaborski 				nvl = __DECONST(nvlist_t *,
1187347a39b4SMariusz Zaborski 				    nvlist_get_array_next(nvl));
1188347a39b4SMariusz Zaborski 				ptr = nvlist_unpack_header(nvl, ptr, nfds,
1189347a39b4SMariusz Zaborski 				    &isbe, &left);
1190347a39b4SMariusz Zaborski 				if (ptr == NULL)
1191a3c485d3SMariusz Zaborski 					goto fail;
1192347a39b4SMariusz Zaborski 			}
1193347a39b4SMariusz Zaborski 			nvpair_free_structure(nvp);
1194347a39b4SMariusz Zaborski 			continue;
1195347a39b4SMariusz Zaborski 		case NV_TYPE_BOOL_ARRAY:
1196347a39b4SMariusz Zaborski 			ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left);
1197347a39b4SMariusz Zaborski 			break;
1198347a39b4SMariusz Zaborski 		case NV_TYPE_NUMBER_ARRAY:
1199347a39b4SMariusz Zaborski 			ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left);
1200347a39b4SMariusz Zaborski 			break;
1201347a39b4SMariusz Zaborski 		case NV_TYPE_STRING_ARRAY:
1202347a39b4SMariusz Zaborski 			ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left);
1203347a39b4SMariusz Zaborski 			break;
1204347a39b4SMariusz Zaborski 		case NV_TYPE_NVLIST_ARRAY:
1205347a39b4SMariusz Zaborski 			ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left,
1206347a39b4SMariusz Zaborski 			    &array);
1207347a39b4SMariusz Zaborski 			if (ptr == NULL)
1208a3c485d3SMariusz Zaborski 				goto fail;
12091dacabe1SMariusz Zaborski 			PJDLOG_ASSERT(array != NULL);
1210347a39b4SMariusz Zaborski 			tmpnvl = array;
12111dacabe1SMariusz Zaborski 			do {
1212347a39b4SMariusz Zaborski 				nvlist_set_parent(array, nvp);
1213347a39b4SMariusz Zaborski 				array = __DECONST(nvlist_t *,
1214347a39b4SMariusz Zaborski 				    nvlist_get_array_next(array));
12151dacabe1SMariusz Zaborski 			} while (array != NULL);
1216347a39b4SMariusz Zaborski 			ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe,
1217347a39b4SMariusz Zaborski 			    &left);
1218347a39b4SMariusz Zaborski 			break;
121954f98da9SMariusz Zaborski 		default:
122054f98da9SMariusz Zaborski 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
122154f98da9SMariusz Zaborski 		}
122254f98da9SMariusz Zaborski 		if (ptr == NULL)
1223a3c485d3SMariusz Zaborski 			goto fail;
122430740f45SMariusz Zaborski 		if (!nvlist_move_nvpair(nvl, nvp))
1225a3c485d3SMariusz Zaborski 			goto fail;
122654f98da9SMariusz Zaborski 		if (tmpnvl != NULL) {
122754f98da9SMariusz Zaborski 			nvl = tmpnvl;
122854f98da9SMariusz Zaborski 			tmpnvl = NULL;
122954f98da9SMariusz Zaborski 		}
123054f98da9SMariusz Zaborski 	}
123154f98da9SMariusz Zaborski 
123254f98da9SMariusz Zaborski 	return (retnvl);
1233a3c485d3SMariusz Zaborski fail:
123454f98da9SMariusz Zaborski 	nvlist_destroy(retnvl);
123554f98da9SMariusz Zaborski 	return (NULL);
123654f98da9SMariusz Zaborski }
123754f98da9SMariusz Zaborski 
123854f98da9SMariusz Zaborski nvlist_t *
123954f98da9SMariusz Zaborski nvlist_unpack(const void *buf, size_t size, int flags)
124054f98da9SMariusz Zaborski {
124154f98da9SMariusz Zaborski 
124254f98da9SMariusz Zaborski 	return (nvlist_xunpack(buf, size, NULL, 0, flags));
124354f98da9SMariusz Zaborski }
124454f98da9SMariusz Zaborski 
124554f98da9SMariusz Zaborski #ifndef _KERNEL
124654f98da9SMariusz Zaborski int
124754f98da9SMariusz Zaborski nvlist_send(int sock, const nvlist_t *nvl)
124854f98da9SMariusz Zaborski {
124954f98da9SMariusz Zaborski 	size_t datasize, nfds;
125054f98da9SMariusz Zaborski 	int *fds;
125154f98da9SMariusz Zaborski 	void *data;
125254f98da9SMariusz Zaborski 	int64_t fdidx;
125354f98da9SMariusz Zaborski 	int ret;
125454f98da9SMariusz Zaborski 
125554f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
125654f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
125754f98da9SMariusz Zaborski 		return (-1);
125854f98da9SMariusz Zaborski 	}
125954f98da9SMariusz Zaborski 
126054f98da9SMariusz Zaborski 	fds = nvlist_descriptors(nvl, &nfds);
126154f98da9SMariusz Zaborski 	if (fds == NULL)
126254f98da9SMariusz Zaborski 		return (-1);
126354f98da9SMariusz Zaborski 
126454f98da9SMariusz Zaborski 	ret = -1;
126554f98da9SMariusz Zaborski 	fdidx = 0;
126654f98da9SMariusz Zaborski 
126754f98da9SMariusz Zaborski 	data = nvlist_xpack(nvl, &fdidx, &datasize);
126854f98da9SMariusz Zaborski 	if (data == NULL)
126954f98da9SMariusz Zaborski 		goto out;
127054f98da9SMariusz Zaborski 
127154f98da9SMariusz Zaborski 	if (buf_send(sock, data, datasize) == -1)
127254f98da9SMariusz Zaborski 		goto out;
127354f98da9SMariusz Zaborski 
127454f98da9SMariusz Zaborski 	if (nfds > 0) {
127554f98da9SMariusz Zaborski 		if (fd_send(sock, fds, nfds) == -1)
127654f98da9SMariusz Zaborski 			goto out;
127754f98da9SMariusz Zaborski 	}
127854f98da9SMariusz Zaborski 
127954f98da9SMariusz Zaborski 	ret = 0;
128054f98da9SMariusz Zaborski out:
128154f98da9SMariusz Zaborski 	ERRNO_SAVE();
128254f98da9SMariusz Zaborski 	nv_free(fds);
128354f98da9SMariusz Zaborski 	nv_free(data);
128454f98da9SMariusz Zaborski 	ERRNO_RESTORE();
128554f98da9SMariusz Zaborski 	return (ret);
128654f98da9SMariusz Zaborski }
128754f98da9SMariusz Zaborski 
128854f98da9SMariusz Zaborski nvlist_t *
128954f98da9SMariusz Zaborski nvlist_recv(int sock, int flags)
129054f98da9SMariusz Zaborski {
129154f98da9SMariusz Zaborski 	struct nvlist_header nvlhdr;
129254f98da9SMariusz Zaborski 	nvlist_t *nvl, *ret;
129354f98da9SMariusz Zaborski 	unsigned char *buf;
129454f98da9SMariusz Zaborski 	size_t nfds, size, i;
129554f98da9SMariusz Zaborski 	int *fds;
129654f98da9SMariusz Zaborski 
129754f98da9SMariusz Zaborski 	if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
129854f98da9SMariusz Zaborski 		return (NULL);
129954f98da9SMariusz Zaborski 
130054f98da9SMariusz Zaborski 	if (!nvlist_check_header(&nvlhdr))
130154f98da9SMariusz Zaborski 		return (NULL);
130254f98da9SMariusz Zaborski 
130354f98da9SMariusz Zaborski 	nfds = (size_t)nvlhdr.nvlh_descriptors;
130454f98da9SMariusz Zaborski 	size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
130554f98da9SMariusz Zaborski 
130654f98da9SMariusz Zaborski 	buf = nv_malloc(size);
130754f98da9SMariusz Zaborski 	if (buf == NULL)
130854f98da9SMariusz Zaborski 		return (NULL);
130954f98da9SMariusz Zaborski 
131054f98da9SMariusz Zaborski 	memcpy(buf, &nvlhdr, sizeof(nvlhdr));
131154f98da9SMariusz Zaborski 
131254f98da9SMariusz Zaborski 	ret = NULL;
131354f98da9SMariusz Zaborski 	fds = NULL;
131454f98da9SMariusz Zaborski 
131554f98da9SMariusz Zaborski 	if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
131654f98da9SMariusz Zaborski 		goto out;
131754f98da9SMariusz Zaborski 
131854f98da9SMariusz Zaborski 	if (nfds > 0) {
131954f98da9SMariusz Zaborski 		fds = nv_malloc(nfds * sizeof(fds[0]));
132054f98da9SMariusz Zaborski 		if (fds == NULL)
132154f98da9SMariusz Zaborski 			goto out;
132254f98da9SMariusz Zaborski 		if (fd_recv(sock, fds, nfds) == -1)
132354f98da9SMariusz Zaborski 			goto out;
132454f98da9SMariusz Zaborski 	}
132554f98da9SMariusz Zaborski 
132654f98da9SMariusz Zaborski 	nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
132754f98da9SMariusz Zaborski 	if (nvl == NULL) {
132854f98da9SMariusz Zaborski 		ERRNO_SAVE();
132954f98da9SMariusz Zaborski 		for (i = 0; i < nfds; i++)
133054f98da9SMariusz Zaborski 			close(fds[i]);
133154f98da9SMariusz Zaborski 		ERRNO_RESTORE();
133254f98da9SMariusz Zaborski 		goto out;
133354f98da9SMariusz Zaborski 	}
133454f98da9SMariusz Zaborski 
133554f98da9SMariusz Zaborski 	ret = nvl;
133654f98da9SMariusz Zaborski out:
133754f98da9SMariusz Zaborski 	ERRNO_SAVE();
133854f98da9SMariusz Zaborski 	nv_free(buf);
133954f98da9SMariusz Zaborski 	nv_free(fds);
134054f98da9SMariusz Zaborski 	ERRNO_RESTORE();
134154f98da9SMariusz Zaborski 
134254f98da9SMariusz Zaborski 	return (ret);
134354f98da9SMariusz Zaborski }
134454f98da9SMariusz Zaborski 
134554f98da9SMariusz Zaborski nvlist_t *
134654f98da9SMariusz Zaborski nvlist_xfer(int sock, nvlist_t *nvl, int flags)
134754f98da9SMariusz Zaborski {
134854f98da9SMariusz Zaborski 
134954f98da9SMariusz Zaborski 	if (nvlist_send(sock, nvl) < 0) {
135054f98da9SMariusz Zaborski 		nvlist_destroy(nvl);
135154f98da9SMariusz Zaborski 		return (NULL);
135254f98da9SMariusz Zaborski 	}
135354f98da9SMariusz Zaborski 	nvlist_destroy(nvl);
135454f98da9SMariusz Zaborski 	return (nvlist_recv(sock, flags));
135554f98da9SMariusz Zaborski }
135654f98da9SMariusz Zaborski #endif
135754f98da9SMariusz Zaborski 
135854f98da9SMariusz Zaborski nvpair_t *
135954f98da9SMariusz Zaborski nvlist_first_nvpair(const nvlist_t *nvl)
136054f98da9SMariusz Zaborski {
136154f98da9SMariusz Zaborski 
136254f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
136354f98da9SMariusz Zaborski 
136454f98da9SMariusz Zaborski 	return (TAILQ_FIRST(&nvl->nvl_head));
136554f98da9SMariusz Zaborski }
136654f98da9SMariusz Zaborski 
136754f98da9SMariusz Zaborski nvpair_t *
136854f98da9SMariusz Zaborski nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
136954f98da9SMariusz Zaborski {
137054f98da9SMariusz Zaborski 	nvpair_t *retnvp;
137154f98da9SMariusz Zaborski 
137254f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
137354f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
137454f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
137554f98da9SMariusz Zaborski 
137654f98da9SMariusz Zaborski 	retnvp = nvpair_next(nvp);
137754f98da9SMariusz Zaborski 	PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
137854f98da9SMariusz Zaborski 
137954f98da9SMariusz Zaborski 	return (retnvp);
138054f98da9SMariusz Zaborski 
138154f98da9SMariusz Zaborski }
138254f98da9SMariusz Zaborski 
138354f98da9SMariusz Zaborski nvpair_t *
138454f98da9SMariusz Zaborski nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
138554f98da9SMariusz Zaborski {
138654f98da9SMariusz Zaborski 	nvpair_t *retnvp;
138754f98da9SMariusz Zaborski 
138854f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
138954f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
139054f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
139154f98da9SMariusz Zaborski 
139254f98da9SMariusz Zaborski 	retnvp = nvpair_prev(nvp);
139354f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
139454f98da9SMariusz Zaborski 
139554f98da9SMariusz Zaborski 	return (retnvp);
139654f98da9SMariusz Zaborski }
139754f98da9SMariusz Zaborski 
139854f98da9SMariusz Zaborski const char *
139954f98da9SMariusz Zaborski nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
140054f98da9SMariusz Zaborski {
140154f98da9SMariusz Zaborski 	nvpair_t *nvp;
140254f98da9SMariusz Zaborski 
140354f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
140454f98da9SMariusz Zaborski 
140589ca10c6SMariusz Zaborski 	if (cookiep == NULL || *cookiep == NULL)
140654f98da9SMariusz Zaborski 		nvp = nvlist_first_nvpair(nvl);
140754f98da9SMariusz Zaborski 	else
140854f98da9SMariusz Zaborski 		nvp = nvlist_next_nvpair(nvl, *cookiep);
140954f98da9SMariusz Zaborski 	if (nvp == NULL)
141054f98da9SMariusz Zaborski 		return (NULL);
141154f98da9SMariusz Zaborski 	if (typep != NULL)
141254f98da9SMariusz Zaborski 		*typep = nvpair_type(nvp);
141389ca10c6SMariusz Zaborski 	if (cookiep != NULL)
141454f98da9SMariusz Zaborski 		*cookiep = nvp;
141554f98da9SMariusz Zaborski 	return (nvpair_name(nvp));
141654f98da9SMariusz Zaborski }
141754f98da9SMariusz Zaborski 
141854f98da9SMariusz Zaborski bool
141954f98da9SMariusz Zaborski nvlist_exists(const nvlist_t *nvl, const char *name)
142054f98da9SMariusz Zaborski {
142154f98da9SMariusz Zaborski 
142254f98da9SMariusz Zaborski 	return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
142354f98da9SMariusz Zaborski }
142454f98da9SMariusz Zaborski 
142554f98da9SMariusz Zaborski #define	NVLIST_EXISTS(type, TYPE)					\
142654f98da9SMariusz Zaborski bool									\
142754f98da9SMariusz Zaborski nvlist_exists_##type(const nvlist_t *nvl, const char *name)		\
142854f98da9SMariusz Zaborski {									\
142954f98da9SMariusz Zaborski 									\
143054f98da9SMariusz Zaborski 	return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL);	\
143154f98da9SMariusz Zaborski }
143254f98da9SMariusz Zaborski 
143354f98da9SMariusz Zaborski NVLIST_EXISTS(null, NULL)
143454f98da9SMariusz Zaborski NVLIST_EXISTS(bool, BOOL)
143554f98da9SMariusz Zaborski NVLIST_EXISTS(number, NUMBER)
143654f98da9SMariusz Zaborski NVLIST_EXISTS(string, STRING)
143754f98da9SMariusz Zaborski NVLIST_EXISTS(nvlist, NVLIST)
1438347a39b4SMariusz Zaborski NVLIST_EXISTS(binary, BINARY)
1439347a39b4SMariusz Zaborski NVLIST_EXISTS(bool_array, BOOL_ARRAY)
1440347a39b4SMariusz Zaborski NVLIST_EXISTS(number_array, NUMBER_ARRAY)
1441347a39b4SMariusz Zaborski NVLIST_EXISTS(string_array, STRING_ARRAY)
1442347a39b4SMariusz Zaborski NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY)
144354f98da9SMariusz Zaborski #ifndef _KERNEL
144454f98da9SMariusz Zaborski NVLIST_EXISTS(descriptor, DESCRIPTOR)
1445347a39b4SMariusz Zaborski NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY)
144654f98da9SMariusz Zaborski #endif
144754f98da9SMariusz Zaborski 
144854f98da9SMariusz Zaborski #undef	NVLIST_EXISTS
144954f98da9SMariusz Zaborski 
145054f98da9SMariusz Zaborski void
145154f98da9SMariusz Zaborski nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
145254f98da9SMariusz Zaborski {
145354f98da9SMariusz Zaborski 	nvpair_t *newnvp;
145454f98da9SMariusz Zaborski 
145554f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
145654f98da9SMariusz Zaborski 
145754f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
145854f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
145954f98da9SMariusz Zaborski 		return;
146054f98da9SMariusz Zaborski 	}
146154f98da9SMariusz Zaborski 	if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
146254f98da9SMariusz Zaborski 		if (nvlist_exists(nvl, nvpair_name(nvp))) {
146354f98da9SMariusz Zaborski 			nvl->nvl_error = EEXIST;
146454f98da9SMariusz Zaborski 			ERRNO_SET(nvlist_error(nvl));
146554f98da9SMariusz Zaborski 			return;
146654f98da9SMariusz Zaborski 		}
146754f98da9SMariusz Zaborski 	}
146854f98da9SMariusz Zaborski 
146954f98da9SMariusz Zaborski 	newnvp = nvpair_clone(nvp);
147054f98da9SMariusz Zaborski 	if (newnvp == NULL) {
147154f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
147254f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
147354f98da9SMariusz Zaborski 		return;
147454f98da9SMariusz Zaborski 	}
147554f98da9SMariusz Zaborski 
147654f98da9SMariusz Zaborski 	nvpair_insert(&nvl->nvl_head, newnvp, nvl);
147754f98da9SMariusz Zaborski }
147854f98da9SMariusz Zaborski 
147954f98da9SMariusz Zaborski void
148054f98da9SMariusz Zaborski nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
148154f98da9SMariusz Zaborski {
148254f98da9SMariusz Zaborski 	va_list valueap;
148354f98da9SMariusz Zaborski 
148454f98da9SMariusz Zaborski 	va_start(valueap, valuefmt);
148554f98da9SMariusz Zaborski 	nvlist_add_stringv(nvl, name, valuefmt, valueap);
148654f98da9SMariusz Zaborski 	va_end(valueap);
148754f98da9SMariusz Zaborski }
148854f98da9SMariusz Zaborski 
148954f98da9SMariusz Zaborski void
149054f98da9SMariusz Zaborski nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
149154f98da9SMariusz Zaborski     va_list valueap)
149254f98da9SMariusz Zaborski {
149354f98da9SMariusz Zaborski 	nvpair_t *nvp;
149454f98da9SMariusz Zaborski 
149554f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
149654f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
149754f98da9SMariusz Zaborski 		return;
149854f98da9SMariusz Zaborski 	}
149954f98da9SMariusz Zaborski 
150054f98da9SMariusz Zaborski 	nvp = nvpair_create_stringv(name, valuefmt, valueap);
150154f98da9SMariusz Zaborski 	if (nvp == NULL) {
150254f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
150354f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
150454f98da9SMariusz Zaborski 	} else {
150530740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
150654f98da9SMariusz Zaborski 	}
150754f98da9SMariusz Zaborski }
150854f98da9SMariusz Zaborski 
150954f98da9SMariusz Zaborski void
151054f98da9SMariusz Zaborski nvlist_add_null(nvlist_t *nvl, const char *name)
151154f98da9SMariusz Zaborski {
151254f98da9SMariusz Zaborski 	nvpair_t *nvp;
151354f98da9SMariusz Zaborski 
151454f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
151554f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
151654f98da9SMariusz Zaborski 		return;
151754f98da9SMariusz Zaborski 	}
151854f98da9SMariusz Zaborski 
151954f98da9SMariusz Zaborski 	nvp = nvpair_create_null(name);
152054f98da9SMariusz Zaborski 	if (nvp == NULL) {
152154f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
152254f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
152354f98da9SMariusz Zaborski 	} else {
152430740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
152554f98da9SMariusz Zaborski 	}
152654f98da9SMariusz Zaborski }
152754f98da9SMariusz Zaborski 
152854f98da9SMariusz Zaborski void
152954f98da9SMariusz Zaborski nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
153054f98da9SMariusz Zaborski     size_t size)
153154f98da9SMariusz Zaborski {
153254f98da9SMariusz Zaborski 	nvpair_t *nvp;
153354f98da9SMariusz Zaborski 
153454f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
153554f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
153654f98da9SMariusz Zaborski 		return;
153754f98da9SMariusz Zaborski 	}
153854f98da9SMariusz Zaborski 
153954f98da9SMariusz Zaborski 	nvp = nvpair_create_binary(name, value, size);
154054f98da9SMariusz Zaborski 	if (nvp == NULL) {
154154f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
154254f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
154354f98da9SMariusz Zaborski 	} else {
154430740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
154554f98da9SMariusz Zaborski 	}
154654f98da9SMariusz Zaborski }
154754f98da9SMariusz Zaborski 
154854f98da9SMariusz Zaborski 
154954f98da9SMariusz Zaborski #define	NVLIST_ADD(vtype, type)						\
155054f98da9SMariusz Zaborski void									\
155154f98da9SMariusz Zaborski nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value)		\
155254f98da9SMariusz Zaborski {									\
155354f98da9SMariusz Zaborski 	nvpair_t *nvp;							\
155454f98da9SMariusz Zaborski 									\
155554f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {					\
155654f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));				\
155754f98da9SMariusz Zaborski 		return;							\
155854f98da9SMariusz Zaborski 	}								\
155954f98da9SMariusz Zaborski 									\
156054f98da9SMariusz Zaborski 	nvp = nvpair_create_##type(name, value);			\
156154f98da9SMariusz Zaborski 	if (nvp == NULL) {						\
156254f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);		\
156354f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);				\
156454f98da9SMariusz Zaborski 	} else {							\
156530740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);			\
156654f98da9SMariusz Zaborski 	}								\
156754f98da9SMariusz Zaborski }
156854f98da9SMariusz Zaborski 
156954f98da9SMariusz Zaborski NVLIST_ADD(bool, bool)
157054f98da9SMariusz Zaborski NVLIST_ADD(uint64_t, number)
157154f98da9SMariusz Zaborski NVLIST_ADD(const char *, string)
157254f98da9SMariusz Zaborski NVLIST_ADD(const nvlist_t *, nvlist)
157354f98da9SMariusz Zaborski #ifndef _KERNEL
157454f98da9SMariusz Zaborski NVLIST_ADD(int, descriptor);
157554f98da9SMariusz Zaborski #endif
157654f98da9SMariusz Zaborski 
157754f98da9SMariusz Zaborski #undef	NVLIST_ADD
157854f98da9SMariusz Zaborski 
1579347a39b4SMariusz Zaborski #define	NVLIST_ADD_ARRAY(vtype, type)					\
1580347a39b4SMariusz Zaborski void									\
1581347a39b4SMariusz Zaborski nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value,	\
1582347a39b4SMariusz Zaborski     size_t nitems)							\
1583347a39b4SMariusz Zaborski {									\
1584347a39b4SMariusz Zaborski 	nvpair_t *nvp;							\
1585347a39b4SMariusz Zaborski 									\
1586347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {					\
1587347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));				\
1588347a39b4SMariusz Zaborski 		return;							\
1589347a39b4SMariusz Zaborski 	}								\
1590347a39b4SMariusz Zaborski 									\
1591347a39b4SMariusz Zaborski 	nvp = nvpair_create_##type##_array(name, value, nitems);	\
1592347a39b4SMariusz Zaborski 	if (nvp == NULL) {						\
1593347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);		\
1594347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);				\
1595347a39b4SMariusz Zaborski 	} else {							\
1596347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);			\
1597347a39b4SMariusz Zaborski 	}								\
1598347a39b4SMariusz Zaborski }
1599347a39b4SMariusz Zaborski 
1600347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const bool *, bool)
1601347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const uint64_t *, number)
1602347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const char * const *, string)
1603347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist)
1604347a39b4SMariusz Zaborski #ifndef _KERNEL
1605347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const int *, descriptor)
1606347a39b4SMariusz Zaborski #endif
1607347a39b4SMariusz Zaborski 
1608347a39b4SMariusz Zaborski #undef	NVLIST_ADD_ARRAY
1609347a39b4SMariusz Zaborski 
161030740f45SMariusz Zaborski bool
161154f98da9SMariusz Zaborski nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
161254f98da9SMariusz Zaborski {
161354f98da9SMariusz Zaborski 
161454f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
161554f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
161654f98da9SMariusz Zaborski 
161754f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
161854f98da9SMariusz Zaborski 		nvpair_free(nvp);
161954f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
162030740f45SMariusz Zaborski 		return (false);
162154f98da9SMariusz Zaborski 	}
162254f98da9SMariusz Zaborski 	if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
162354f98da9SMariusz Zaborski 		if (nvlist_exists(nvl, nvpair_name(nvp))) {
162454f98da9SMariusz Zaborski 			nvpair_free(nvp);
162554f98da9SMariusz Zaborski 			nvl->nvl_error = EEXIST;
162654f98da9SMariusz Zaborski 			ERRNO_SET(nvl->nvl_error);
162730740f45SMariusz Zaborski 			return (false);
162854f98da9SMariusz Zaborski 		}
162954f98da9SMariusz Zaborski 	}
163054f98da9SMariusz Zaborski 
163154f98da9SMariusz Zaborski 	nvpair_insert(&nvl->nvl_head, nvp, nvl);
163230740f45SMariusz Zaborski 	return (true);
163354f98da9SMariusz Zaborski }
163454f98da9SMariusz Zaborski 
163554f98da9SMariusz Zaborski void
163654f98da9SMariusz Zaborski nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
163754f98da9SMariusz Zaborski {
163854f98da9SMariusz Zaborski 	nvpair_t *nvp;
163954f98da9SMariusz Zaborski 
164054f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
164154f98da9SMariusz Zaborski 		nv_free(value);
164254f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
164354f98da9SMariusz Zaborski 		return;
164454f98da9SMariusz Zaborski 	}
164554f98da9SMariusz Zaborski 
164654f98da9SMariusz Zaborski 	nvp = nvpair_move_string(name, value);
164754f98da9SMariusz Zaborski 	if (nvp == NULL) {
164854f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
164954f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
165054f98da9SMariusz Zaborski 	} else {
165130740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
165254f98da9SMariusz Zaborski 	}
165354f98da9SMariusz Zaborski }
165454f98da9SMariusz Zaborski 
165554f98da9SMariusz Zaborski void
165654f98da9SMariusz Zaborski nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
165754f98da9SMariusz Zaborski {
165854f98da9SMariusz Zaborski 	nvpair_t *nvp;
165954f98da9SMariusz Zaborski 
166054f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
166154f98da9SMariusz Zaborski 		if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
166254f98da9SMariusz Zaborski 			nvlist_destroy(value);
166354f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
166454f98da9SMariusz Zaborski 		return;
166554f98da9SMariusz Zaborski 	}
166654f98da9SMariusz Zaborski 
166754f98da9SMariusz Zaborski 	nvp = nvpair_move_nvlist(name, value);
166854f98da9SMariusz Zaborski 	if (nvp == NULL) {
166954f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
167054f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
167154f98da9SMariusz Zaborski 	} else {
167230740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
167354f98da9SMariusz Zaborski 	}
167454f98da9SMariusz Zaborski }
167554f98da9SMariusz Zaborski 
167654f98da9SMariusz Zaborski #ifndef _KERNEL
167754f98da9SMariusz Zaborski void
167854f98da9SMariusz Zaborski nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
167954f98da9SMariusz Zaborski {
168054f98da9SMariusz Zaborski 	nvpair_t *nvp;
168154f98da9SMariusz Zaborski 
168254f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
168354f98da9SMariusz Zaborski 		close(value);
168454f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
168554f98da9SMariusz Zaborski 		return;
168654f98da9SMariusz Zaborski 	}
168754f98da9SMariusz Zaborski 
168854f98da9SMariusz Zaborski 	nvp = nvpair_move_descriptor(name, value);
168954f98da9SMariusz Zaborski 	if (nvp == NULL) {
169054f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
169154f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
169254f98da9SMariusz Zaborski 	} else {
169330740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
169454f98da9SMariusz Zaborski 	}
169554f98da9SMariusz Zaborski }
169654f98da9SMariusz Zaborski #endif
169754f98da9SMariusz Zaborski 
169854f98da9SMariusz Zaborski void
169954f98da9SMariusz Zaborski nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
170054f98da9SMariusz Zaborski {
170154f98da9SMariusz Zaborski 	nvpair_t *nvp;
170254f98da9SMariusz Zaborski 
170354f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
170454f98da9SMariusz Zaborski 		nv_free(value);
170554f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
170654f98da9SMariusz Zaborski 		return;
170754f98da9SMariusz Zaborski 	}
170854f98da9SMariusz Zaborski 
170954f98da9SMariusz Zaborski 	nvp = nvpair_move_binary(name, value, size);
171054f98da9SMariusz Zaborski 	if (nvp == NULL) {
171154f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
171254f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
171354f98da9SMariusz Zaborski 	} else {
171430740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
171554f98da9SMariusz Zaborski 	}
171654f98da9SMariusz Zaborski }
171754f98da9SMariusz Zaborski 
1718347a39b4SMariusz Zaborski void
1719347a39b4SMariusz Zaborski nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value,
1720347a39b4SMariusz Zaborski     size_t nitems)
1721347a39b4SMariusz Zaborski {
1722347a39b4SMariusz Zaborski 	nvpair_t *nvp;
1723347a39b4SMariusz Zaborski 
1724347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
1725347a39b4SMariusz Zaborski 		nv_free(value);
1726347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
1727347a39b4SMariusz Zaborski 		return;
1728347a39b4SMariusz Zaborski 	}
1729347a39b4SMariusz Zaborski 
1730347a39b4SMariusz Zaborski 	nvp = nvpair_move_bool_array(name, value, nitems);
1731347a39b4SMariusz Zaborski 	if (nvp == NULL) {
1732347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1733347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
1734347a39b4SMariusz Zaborski 	} else {
1735347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
1736347a39b4SMariusz Zaborski 	}
1737347a39b4SMariusz Zaborski }
1738347a39b4SMariusz Zaborski 
1739347a39b4SMariusz Zaborski void
1740347a39b4SMariusz Zaborski nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value,
1741347a39b4SMariusz Zaborski     size_t nitems)
1742347a39b4SMariusz Zaborski {
1743347a39b4SMariusz Zaborski 	nvpair_t *nvp;
1744347a39b4SMariusz Zaborski 	size_t i;
1745347a39b4SMariusz Zaborski 
1746347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
1747347a39b4SMariusz Zaborski 		if (value != NULL) {
1748347a39b4SMariusz Zaborski 			for (i = 0; i < nitems; i++)
1749347a39b4SMariusz Zaborski 				nv_free(value[i]);
1750347a39b4SMariusz Zaborski 			nv_free(value);
1751347a39b4SMariusz Zaborski 		}
1752347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
1753347a39b4SMariusz Zaborski 		return;
1754347a39b4SMariusz Zaborski 	}
1755347a39b4SMariusz Zaborski 
1756347a39b4SMariusz Zaborski 	nvp = nvpair_move_string_array(name, value, nitems);
1757347a39b4SMariusz Zaborski 	if (nvp == NULL) {
1758347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1759347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
1760347a39b4SMariusz Zaborski 	} else {
1761347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
1762347a39b4SMariusz Zaborski 	}
1763347a39b4SMariusz Zaborski }
1764347a39b4SMariusz Zaborski 
1765347a39b4SMariusz Zaborski void
1766347a39b4SMariusz Zaborski nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value,
1767347a39b4SMariusz Zaborski     size_t nitems)
1768347a39b4SMariusz Zaborski {
1769347a39b4SMariusz Zaborski 	nvpair_t *nvp;
1770347a39b4SMariusz Zaborski 	size_t i;
1771347a39b4SMariusz Zaborski 
1772347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
1773347a39b4SMariusz Zaborski 		if (value != NULL) {
1774347a39b4SMariusz Zaborski 			for (i = 0; i < nitems; i++) {
1775347a39b4SMariusz Zaborski 				if (nvlist_get_pararr(value[i], NULL) == NULL)
1776347a39b4SMariusz Zaborski 					nvlist_destroy(value[i]);
1777347a39b4SMariusz Zaborski 			}
1778347a39b4SMariusz Zaborski 		}
1779347a39b4SMariusz Zaborski 		nv_free(value);
1780347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
1781347a39b4SMariusz Zaborski 		return;
1782347a39b4SMariusz Zaborski 	}
1783347a39b4SMariusz Zaborski 
1784347a39b4SMariusz Zaborski 	nvp = nvpair_move_nvlist_array(name, value, nitems);
1785347a39b4SMariusz Zaborski 	if (nvp == NULL) {
1786347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1787347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
1788347a39b4SMariusz Zaborski 	} else {
1789347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
1790347a39b4SMariusz Zaborski 	}
1791347a39b4SMariusz Zaborski }
1792347a39b4SMariusz Zaborski 
1793347a39b4SMariusz Zaborski void
1794347a39b4SMariusz Zaborski nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value,
1795347a39b4SMariusz Zaborski     size_t nitems)
1796347a39b4SMariusz Zaborski {
1797347a39b4SMariusz Zaborski 	nvpair_t *nvp;
1798347a39b4SMariusz Zaborski 
1799347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
1800347a39b4SMariusz Zaborski 		nv_free(value);
1801347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
1802347a39b4SMariusz Zaborski 		return;
1803347a39b4SMariusz Zaborski 	}
1804347a39b4SMariusz Zaborski 
1805347a39b4SMariusz Zaborski 	nvp = nvpair_move_number_array(name, value, nitems);
1806347a39b4SMariusz Zaborski 	if (nvp == NULL) {
1807347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1808347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
1809347a39b4SMariusz Zaborski 	} else {
1810347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
1811347a39b4SMariusz Zaborski 	}
1812347a39b4SMariusz Zaborski }
1813347a39b4SMariusz Zaborski 
1814347a39b4SMariusz Zaborski #ifndef _KERNEL
1815347a39b4SMariusz Zaborski void
1816347a39b4SMariusz Zaborski nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value,
1817347a39b4SMariusz Zaborski     size_t nitems)
1818347a39b4SMariusz Zaborski {
1819347a39b4SMariusz Zaborski 	nvpair_t *nvp;
1820347a39b4SMariusz Zaborski 	size_t i;
1821347a39b4SMariusz Zaborski 
1822347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
1823347a39b4SMariusz Zaborski 		if (value != 0) {
1824347a39b4SMariusz Zaborski 			for (i = 0; i < nitems; i++)
1825347a39b4SMariusz Zaborski 				close(value[i]);
1826347a39b4SMariusz Zaborski 			nv_free(value);
1827347a39b4SMariusz Zaborski 		}
1828347a39b4SMariusz Zaborski 
1829347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
1830347a39b4SMariusz Zaborski 		return;
1831347a39b4SMariusz Zaborski 	}
1832347a39b4SMariusz Zaborski 
1833347a39b4SMariusz Zaborski 	nvp = nvpair_move_descriptor_array(name, value, nitems);
1834347a39b4SMariusz Zaborski 	if (nvp == NULL) {
1835347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1836347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
1837347a39b4SMariusz Zaborski 	} else {
1838347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
1839347a39b4SMariusz Zaborski 	}
1840347a39b4SMariusz Zaborski }
1841347a39b4SMariusz Zaborski #endif
1842347a39b4SMariusz Zaborski 
184354f98da9SMariusz Zaborski const nvpair_t *
184454f98da9SMariusz Zaborski nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
184554f98da9SMariusz Zaborski {
184654f98da9SMariusz Zaborski 
184754f98da9SMariusz Zaborski 	return (nvlist_find(nvl, NV_TYPE_NONE, name));
184854f98da9SMariusz Zaborski }
184954f98da9SMariusz Zaborski 
185054f98da9SMariusz Zaborski #define	NVLIST_GET(ftype, type, TYPE)					\
185154f98da9SMariusz Zaborski ftype									\
185254f98da9SMariusz Zaborski nvlist_get_##type(const nvlist_t *nvl, const char *name)		\
185354f98da9SMariusz Zaborski {									\
185454f98da9SMariusz Zaborski 	const nvpair_t *nvp;						\
185554f98da9SMariusz Zaborski 									\
185654f98da9SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
185754f98da9SMariusz Zaborski 	if (nvp == NULL)						\
185854f98da9SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
185954f98da9SMariusz Zaborski 	return (nvpair_get_##type(nvp));				\
186054f98da9SMariusz Zaborski }
186154f98da9SMariusz Zaborski 
186254f98da9SMariusz Zaborski NVLIST_GET(bool, bool, BOOL)
186354f98da9SMariusz Zaborski NVLIST_GET(uint64_t, number, NUMBER)
186454f98da9SMariusz Zaborski NVLIST_GET(const char *, string, STRING)
186554f98da9SMariusz Zaborski NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
186654f98da9SMariusz Zaborski #ifndef _KERNEL
186754f98da9SMariusz Zaborski NVLIST_GET(int, descriptor, DESCRIPTOR)
186854f98da9SMariusz Zaborski #endif
186954f98da9SMariusz Zaborski 
187054f98da9SMariusz Zaborski #undef	NVLIST_GET
187154f98da9SMariusz Zaborski 
187254f98da9SMariusz Zaborski const void *
187354f98da9SMariusz Zaborski nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
187454f98da9SMariusz Zaborski {
187554f98da9SMariusz Zaborski 	nvpair_t *nvp;
187654f98da9SMariusz Zaborski 
187754f98da9SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
187854f98da9SMariusz Zaborski 	if (nvp == NULL)
187954f98da9SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_BINARY, name);
188054f98da9SMariusz Zaborski 
188154f98da9SMariusz Zaborski 	return (nvpair_get_binary(nvp, sizep));
188254f98da9SMariusz Zaborski }
188354f98da9SMariusz Zaborski 
1884347a39b4SMariusz Zaborski #define	NVLIST_GET_ARRAY(ftype, type, TYPE)				\
1885347a39b4SMariusz Zaborski ftype									\
1886347a39b4SMariusz Zaborski nvlist_get_##type##_array(const nvlist_t *nvl, const char *name,	\
1887347a39b4SMariusz Zaborski     size_t *nitems)							\
1888347a39b4SMariusz Zaborski {									\
1889347a39b4SMariusz Zaborski 	const nvpair_t *nvp;						\
1890347a39b4SMariusz Zaborski 									\
1891347a39b4SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);		\
1892347a39b4SMariusz Zaborski 	if (nvp == NULL)						\
1893347a39b4SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name);	\
1894347a39b4SMariusz Zaborski 	return (nvpair_get_##type##_array(nvp, nitems));		\
1895347a39b4SMariusz Zaborski }
1896347a39b4SMariusz Zaborski 
1897347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const bool *, bool, BOOL)
1898347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER)
1899347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const char * const *, string, STRING)
1900347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST)
1901347a39b4SMariusz Zaborski #ifndef _KERNEL
1902347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR)
1903347a39b4SMariusz Zaborski #endif
1904347a39b4SMariusz Zaborski 
1905347a39b4SMariusz Zaborski #undef	NVLIST_GET_ARRAY
1906347a39b4SMariusz Zaborski 
190754f98da9SMariusz Zaborski #define	NVLIST_TAKE(ftype, type, TYPE)					\
190854f98da9SMariusz Zaborski ftype									\
190954f98da9SMariusz Zaborski nvlist_take_##type(nvlist_t *nvl, const char *name)			\
191054f98da9SMariusz Zaborski {									\
191154f98da9SMariusz Zaborski 	nvpair_t *nvp;							\
191254f98da9SMariusz Zaborski 	ftype value;							\
191354f98da9SMariusz Zaborski 									\
191454f98da9SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
191554f98da9SMariusz Zaborski 	if (nvp == NULL)						\
191654f98da9SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
191754f98da9SMariusz Zaborski 	value = (ftype)(intptr_t)nvpair_get_##type(nvp);		\
191854f98da9SMariusz Zaborski 	nvlist_remove_nvpair(nvl, nvp);					\
191954f98da9SMariusz Zaborski 	nvpair_free_structure(nvp);					\
192054f98da9SMariusz Zaborski 	return (value);							\
192154f98da9SMariusz Zaborski }
192254f98da9SMariusz Zaborski 
192354f98da9SMariusz Zaborski NVLIST_TAKE(bool, bool, BOOL)
192454f98da9SMariusz Zaborski NVLIST_TAKE(uint64_t, number, NUMBER)
192554f98da9SMariusz Zaborski NVLIST_TAKE(char *, string, STRING)
192654f98da9SMariusz Zaborski NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
192754f98da9SMariusz Zaborski #ifndef _KERNEL
192854f98da9SMariusz Zaborski NVLIST_TAKE(int, descriptor, DESCRIPTOR)
192954f98da9SMariusz Zaborski #endif
193054f98da9SMariusz Zaborski 
193154f98da9SMariusz Zaborski #undef	NVLIST_TAKE
193254f98da9SMariusz Zaborski 
193354f98da9SMariusz Zaborski void *
193454f98da9SMariusz Zaborski nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
193554f98da9SMariusz Zaborski {
193654f98da9SMariusz Zaborski 	nvpair_t *nvp;
193754f98da9SMariusz Zaborski 	void *value;
193854f98da9SMariusz Zaborski 
193954f98da9SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
194054f98da9SMariusz Zaborski 	if (nvp == NULL)
194154f98da9SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_BINARY, name);
194254f98da9SMariusz Zaborski 
194354f98da9SMariusz Zaborski 	value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
194454f98da9SMariusz Zaborski 	nvlist_remove_nvpair(nvl, nvp);
194554f98da9SMariusz Zaborski 	nvpair_free_structure(nvp);
194654f98da9SMariusz Zaborski 	return (value);
194754f98da9SMariusz Zaborski }
194854f98da9SMariusz Zaborski 
1949347a39b4SMariusz Zaborski #define	NVLIST_TAKE_ARRAY(ftype, type, TYPE)				\
1950347a39b4SMariusz Zaborski ftype									\
1951347a39b4SMariusz Zaborski nvlist_take_##type##_array(nvlist_t *nvl, const char *name,		\
1952347a39b4SMariusz Zaborski     size_t *nitems)							\
1953347a39b4SMariusz Zaborski {									\
1954347a39b4SMariusz Zaborski 	nvpair_t *nvp;							\
1955347a39b4SMariusz Zaborski 	ftype value;							\
1956347a39b4SMariusz Zaborski 									\
1957347a39b4SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);		\
1958347a39b4SMariusz Zaborski 	if (nvp == NULL)						\
1959347a39b4SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name);	\
1960347a39b4SMariusz Zaborski 	value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\
1961347a39b4SMariusz Zaborski 	nvlist_remove_nvpair(nvl, nvp);					\
1962347a39b4SMariusz Zaborski 	nvpair_free_structure(nvp);					\
1963347a39b4SMariusz Zaborski 	return (value);							\
1964347a39b4SMariusz Zaborski }
1965347a39b4SMariusz Zaborski 
1966347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(bool *, bool, BOOL)
1967347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER)
1968347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(char **, string, STRING)
1969347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST)
1970347a39b4SMariusz Zaborski #ifndef _KERNEL
1971347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR)
1972347a39b4SMariusz Zaborski #endif
1973347a39b4SMariusz Zaborski 
197454f98da9SMariusz Zaborski void
197554f98da9SMariusz Zaborski nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
197654f98da9SMariusz Zaborski {
197754f98da9SMariusz Zaborski 
197854f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
197954f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
198054f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
198154f98da9SMariusz Zaborski 
198254f98da9SMariusz Zaborski 	nvpair_remove(&nvl->nvl_head, nvp, nvl);
198354f98da9SMariusz Zaborski }
198454f98da9SMariusz Zaborski 
198554f98da9SMariusz Zaborski void
198654f98da9SMariusz Zaborski nvlist_free(nvlist_t *nvl, const char *name)
198754f98da9SMariusz Zaborski {
198854f98da9SMariusz Zaborski 
198954f98da9SMariusz Zaborski 	nvlist_free_type(nvl, name, NV_TYPE_NONE);
199054f98da9SMariusz Zaborski }
199154f98da9SMariusz Zaborski 
199254f98da9SMariusz Zaborski #define	NVLIST_FREE(type, TYPE)						\
199354f98da9SMariusz Zaborski void									\
199454f98da9SMariusz Zaborski nvlist_free_##type(nvlist_t *nvl, const char *name)			\
199554f98da9SMariusz Zaborski {									\
199654f98da9SMariusz Zaborski 									\
199754f98da9SMariusz Zaborski 	nvlist_free_type(nvl, name, NV_TYPE_##TYPE);			\
199854f98da9SMariusz Zaborski }
199954f98da9SMariusz Zaborski 
200054f98da9SMariusz Zaborski NVLIST_FREE(null, NULL)
200154f98da9SMariusz Zaborski NVLIST_FREE(bool, BOOL)
200254f98da9SMariusz Zaborski NVLIST_FREE(number, NUMBER)
200354f98da9SMariusz Zaborski NVLIST_FREE(string, STRING)
200454f98da9SMariusz Zaborski NVLIST_FREE(nvlist, NVLIST)
2005347a39b4SMariusz Zaborski NVLIST_FREE(binary, BINARY)
2006347a39b4SMariusz Zaborski NVLIST_FREE(bool_array, BOOL_ARRAY)
2007347a39b4SMariusz Zaborski NVLIST_FREE(number_array, NUMBER_ARRAY)
2008347a39b4SMariusz Zaborski NVLIST_FREE(string_array, STRING_ARRAY)
2009347a39b4SMariusz Zaborski NVLIST_FREE(nvlist_array, NVLIST_ARRAY)
201054f98da9SMariusz Zaborski #ifndef _KERNEL
201154f98da9SMariusz Zaborski NVLIST_FREE(descriptor, DESCRIPTOR)
2012347a39b4SMariusz Zaborski NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY)
201354f98da9SMariusz Zaborski #endif
201454f98da9SMariusz Zaborski 
201554f98da9SMariusz Zaborski #undef	NVLIST_FREE
201654f98da9SMariusz Zaborski 
201754f98da9SMariusz Zaborski void
201854f98da9SMariusz Zaborski nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
201954f98da9SMariusz Zaborski {
202054f98da9SMariusz Zaborski 
202154f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
202254f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
202354f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
202454f98da9SMariusz Zaborski 
202554f98da9SMariusz Zaborski 	nvlist_remove_nvpair(nvl, nvp);
202654f98da9SMariusz Zaborski 	nvpair_free(nvp);
202754f98da9SMariusz Zaborski }
202854f98da9SMariusz Zaborski 
2029