xref: /freebsd/sys/contrib/libnv/nvlist.c (revision 4d846d26)
154f98da9SMariusz Zaborski /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
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;
10289d5cbb8SMariusz Zaborski 	size_t		 nvl_datasize;
10354f98da9SMariusz Zaborski 	nvpair_t	*nvl_parent;
104347a39b4SMariusz Zaborski 	nvpair_t	*nvl_array_next;
10554f98da9SMariusz Zaborski 	struct nvl_head	 nvl_head;
10654f98da9SMariusz Zaborski };
10754f98da9SMariusz Zaborski 
10854f98da9SMariusz Zaborski #define	NVLIST_ASSERT(nvl)	do {					\
10954f98da9SMariusz Zaborski 	PJDLOG_ASSERT((nvl) != NULL);					\
11054f98da9SMariusz Zaborski 	PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);		\
11154f98da9SMariusz Zaborski } while (0)
11254f98da9SMariusz Zaborski 
11354f98da9SMariusz Zaborski #ifdef _KERNEL
11454f98da9SMariusz Zaborski MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
11554f98da9SMariusz Zaborski #endif
11654f98da9SMariusz Zaborski 
11754f98da9SMariusz Zaborski #define	NVPAIR_ASSERT(nvp)	nvpair_assert(nvp)
11854f98da9SMariusz Zaborski 
11954f98da9SMariusz Zaborski #define	NVLIST_HEADER_MAGIC	0x6c
12054f98da9SMariusz Zaborski #define	NVLIST_HEADER_VERSION	0x00
12154f98da9SMariusz Zaborski struct nvlist_header {
12254f98da9SMariusz Zaborski 	uint8_t		nvlh_magic;
12354f98da9SMariusz Zaborski 	uint8_t		nvlh_version;
12454f98da9SMariusz Zaborski 	uint8_t		nvlh_flags;
12554f98da9SMariusz Zaborski 	uint64_t	nvlh_descriptors;
12654f98da9SMariusz Zaborski 	uint64_t	nvlh_size;
12754f98da9SMariusz Zaborski } __packed;
12854f98da9SMariusz Zaborski 
12954f98da9SMariusz Zaborski nvlist_t *
nvlist_create(int flags)13054f98da9SMariusz Zaborski nvlist_create(int flags)
13154f98da9SMariusz Zaborski {
13254f98da9SMariusz Zaborski 	nvlist_t *nvl;
13354f98da9SMariusz Zaborski 
13454f98da9SMariusz Zaborski 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
13554f98da9SMariusz Zaborski 
13654f98da9SMariusz Zaborski 	nvl = nv_malloc(sizeof(*nvl));
13754f98da9SMariusz Zaborski 	if (nvl == NULL)
13854f98da9SMariusz Zaborski 		return (NULL);
13954f98da9SMariusz Zaborski 	nvl->nvl_error = 0;
14054f98da9SMariusz Zaborski 	nvl->nvl_flags = flags;
14154f98da9SMariusz Zaborski 	nvl->nvl_parent = NULL;
142347a39b4SMariusz Zaborski 	nvl->nvl_array_next = NULL;
14389d5cbb8SMariusz Zaborski 	nvl->nvl_datasize = sizeof(struct nvlist_header);
14454f98da9SMariusz Zaborski 	TAILQ_INIT(&nvl->nvl_head);
14554f98da9SMariusz Zaborski 	nvl->nvl_magic = NVLIST_MAGIC;
14654f98da9SMariusz Zaborski 
14754f98da9SMariusz Zaborski 	return (nvl);
14854f98da9SMariusz Zaborski }
14954f98da9SMariusz Zaborski 
15054f98da9SMariusz Zaborski void
nvlist_destroy(nvlist_t * nvl)15154f98da9SMariusz Zaborski nvlist_destroy(nvlist_t *nvl)
15254f98da9SMariusz Zaborski {
15354f98da9SMariusz Zaborski 	nvpair_t *nvp;
15454f98da9SMariusz Zaborski 
15554f98da9SMariusz Zaborski 	if (nvl == NULL)
15654f98da9SMariusz Zaborski 		return;
15754f98da9SMariusz Zaborski 
15854f98da9SMariusz Zaborski 	ERRNO_SAVE();
15954f98da9SMariusz Zaborski 
16054f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
16154f98da9SMariusz Zaborski 
16254f98da9SMariusz Zaborski 	while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
16354f98da9SMariusz Zaborski 		nvlist_remove_nvpair(nvl, nvp);
16454f98da9SMariusz Zaborski 		nvpair_free(nvp);
16554f98da9SMariusz Zaborski 	}
166347a39b4SMariusz Zaborski 	if (nvl->nvl_array_next != NULL)
167347a39b4SMariusz Zaborski 		nvpair_free_structure(nvl->nvl_array_next);
168347a39b4SMariusz Zaborski 	nvl->nvl_array_next = NULL;
169347a39b4SMariusz Zaborski 	nvl->nvl_parent = NULL;
17054f98da9SMariusz Zaborski 	nvl->nvl_magic = 0;
17154f98da9SMariusz Zaborski 	nv_free(nvl);
17254f98da9SMariusz Zaborski 
17354f98da9SMariusz Zaborski 	ERRNO_RESTORE();
17454f98da9SMariusz Zaborski }
17554f98da9SMariusz Zaborski 
17654f98da9SMariusz Zaborski void
nvlist_set_error(nvlist_t * nvl,int error)17754f98da9SMariusz Zaborski nvlist_set_error(nvlist_t *nvl, int error)
17854f98da9SMariusz Zaborski {
17954f98da9SMariusz Zaborski 
18054f98da9SMariusz Zaborski 	PJDLOG_ASSERT(error != 0);
18154f98da9SMariusz Zaborski 
18254f98da9SMariusz Zaborski 	/*
18354f98da9SMariusz Zaborski 	 * Check for error != 0 so that we don't do the wrong thing if somebody
18454f98da9SMariusz Zaborski 	 * tries to abuse this API when asserts are disabled.
18554f98da9SMariusz Zaborski 	 */
18654f98da9SMariusz Zaborski 	if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
18754f98da9SMariusz Zaborski 		nvl->nvl_error = error;
18854f98da9SMariusz Zaborski }
18954f98da9SMariusz Zaborski 
19054f98da9SMariusz Zaborski int
nvlist_error(const nvlist_t * nvl)19154f98da9SMariusz Zaborski nvlist_error(const nvlist_t *nvl)
19254f98da9SMariusz Zaborski {
19354f98da9SMariusz Zaborski 
19454f98da9SMariusz Zaborski 	if (nvl == NULL)
19554f98da9SMariusz Zaborski 		return (ENOMEM);
19654f98da9SMariusz Zaborski 
19754f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
19854f98da9SMariusz Zaborski 
19954f98da9SMariusz Zaborski 	return (nvl->nvl_error);
20054f98da9SMariusz Zaborski }
20154f98da9SMariusz Zaborski 
20254f98da9SMariusz Zaborski nvpair_t *
nvlist_get_nvpair_parent(const nvlist_t * nvl)20354f98da9SMariusz Zaborski nvlist_get_nvpair_parent(const nvlist_t *nvl)
20454f98da9SMariusz Zaborski {
20554f98da9SMariusz Zaborski 
20654f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
20754f98da9SMariusz Zaborski 
20854f98da9SMariusz Zaborski 	return (nvl->nvl_parent);
20954f98da9SMariusz Zaborski }
21054f98da9SMariusz Zaborski 
21154f98da9SMariusz Zaborski const nvlist_t *
nvlist_get_parent(const nvlist_t * nvl,void ** cookiep)21254f98da9SMariusz Zaborski nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
21354f98da9SMariusz Zaborski {
21454f98da9SMariusz Zaborski 	nvpair_t *nvp;
21554f98da9SMariusz Zaborski 
21654f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
21754f98da9SMariusz Zaborski 
21854f98da9SMariusz Zaborski 	nvp = nvl->nvl_parent;
21954f98da9SMariusz Zaborski 	if (cookiep != NULL)
22054f98da9SMariusz Zaborski 		*cookiep = nvp;
22154f98da9SMariusz Zaborski 	if (nvp == NULL)
22254f98da9SMariusz Zaborski 		return (NULL);
22354f98da9SMariusz Zaborski 
22454f98da9SMariusz Zaborski 	return (nvpair_nvlist(nvp));
22554f98da9SMariusz Zaborski }
22654f98da9SMariusz Zaborski 
22754f98da9SMariusz Zaborski void
nvlist_set_parent(nvlist_t * nvl,nvpair_t * parent)22854f98da9SMariusz Zaborski nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
22954f98da9SMariusz Zaborski {
23054f98da9SMariusz Zaborski 
23154f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
23254f98da9SMariusz Zaborski 
23354f98da9SMariusz Zaborski 	nvl->nvl_parent = parent;
23454f98da9SMariusz Zaborski }
23554f98da9SMariusz Zaborski 
236347a39b4SMariusz Zaborski void
nvlist_set_array_next(nvlist_t * nvl,nvpair_t * ele)237347a39b4SMariusz Zaborski nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele)
238347a39b4SMariusz Zaborski {
239347a39b4SMariusz Zaborski 
240347a39b4SMariusz Zaborski 	NVLIST_ASSERT(nvl);
241347a39b4SMariusz Zaborski 
2421b550329SMariusz Zaborski 	if (ele != NULL) {
243347a39b4SMariusz Zaborski 		nvl->nvl_flags |= NV_FLAG_IN_ARRAY;
2441b550329SMariusz Zaborski 	} else {
245347a39b4SMariusz Zaborski 		nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY;
2461b550329SMariusz Zaborski 		nv_free(nvl->nvl_array_next);
2471b550329SMariusz Zaborski 	}
248347a39b4SMariusz Zaborski 
249347a39b4SMariusz Zaborski 	nvl->nvl_array_next = ele;
250347a39b4SMariusz Zaborski }
251347a39b4SMariusz Zaborski 
25289d5cbb8SMariusz Zaborski static void
nvlist_update_size(nvlist_t * nvl,nvpair_t * new,ssize_t mul)25389d5cbb8SMariusz Zaborski nvlist_update_size(nvlist_t *nvl, nvpair_t *new, ssize_t mul)
25489d5cbb8SMariusz Zaborski {
25589d5cbb8SMariusz Zaborski 	ssize_t size;
25689d5cbb8SMariusz Zaborski 	size_t nitems;
25789d5cbb8SMariusz Zaborski 	const nvlist_t *nvlistnew;
25889d5cbb8SMariusz Zaborski 	const nvlist_t * const *nvlarray;
25989d5cbb8SMariusz Zaborski 	nvlist_t *parent;
26089d5cbb8SMariusz Zaborski 	unsigned int ii;
26189d5cbb8SMariusz Zaborski 
26289d5cbb8SMariusz Zaborski 	NVLIST_ASSERT(nvl);
26389d5cbb8SMariusz Zaborski 	NVPAIR_ASSERT(new);
26489d5cbb8SMariusz Zaborski 	PJDLOG_ASSERT(mul == 1 || mul == -1);
26589d5cbb8SMariusz Zaborski 
26689d5cbb8SMariusz Zaborski 	size = nvpair_header_size();
26789d5cbb8SMariusz Zaborski 	size += strlen(nvpair_name(new)) + 1;
26889d5cbb8SMariusz Zaborski 
26989d5cbb8SMariusz Zaborski 	if (nvpair_type(new) == NV_TYPE_NVLIST) {
27089d5cbb8SMariusz Zaborski 		nvlistnew = nvpair_get_nvlist(new);
27189d5cbb8SMariusz Zaborski 		size += nvlistnew->nvl_datasize;
27289d5cbb8SMariusz Zaborski 		size += nvpair_header_size() + 1;
27389d5cbb8SMariusz Zaborski 	} else if (nvpair_type(new) == NV_TYPE_NVLIST_ARRAY) {
27489d5cbb8SMariusz Zaborski 		nvlarray = nvpair_get_nvlist_array(new, &nitems);
27589d5cbb8SMariusz Zaborski 		PJDLOG_ASSERT(nitems > 0);
27689d5cbb8SMariusz Zaborski 
27789d5cbb8SMariusz Zaborski 		size += (nvpair_header_size() + 1) * nitems;
27889d5cbb8SMariusz Zaborski 		for (ii = 0; ii < nitems; ii++) {
27989d5cbb8SMariusz Zaborski 			PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0);
28089d5cbb8SMariusz Zaborski 			size += nvlarray[ii]->nvl_datasize;
28189d5cbb8SMariusz Zaborski 		}
28289d5cbb8SMariusz Zaborski 	} else {
28389d5cbb8SMariusz Zaborski 		size += nvpair_size(new);
28489d5cbb8SMariusz Zaborski 	}
28589d5cbb8SMariusz Zaborski 
28689d5cbb8SMariusz Zaborski 	size *= mul;
28789d5cbb8SMariusz Zaborski 
28889d5cbb8SMariusz Zaborski 	nvl->nvl_datasize += size;
28989d5cbb8SMariusz Zaborski 
29089d5cbb8SMariusz Zaborski 	parent = nvl;
29189d5cbb8SMariusz Zaborski 	while ((parent = __DECONST(nvlist_t *,
29289d5cbb8SMariusz Zaborski 	    nvlist_get_parent(parent, NULL))) != NULL) {
29389d5cbb8SMariusz Zaborski 		parent->nvl_datasize += size;
29489d5cbb8SMariusz Zaborski 	}
29589d5cbb8SMariusz Zaborski }
29689d5cbb8SMariusz Zaborski 
297b5d787d9SMariusz Zaborski nvpair_t *
nvlist_get_array_next_nvpair(nvlist_t * nvl)298b5d787d9SMariusz Zaborski nvlist_get_array_next_nvpair(nvlist_t *nvl)
299b5d787d9SMariusz Zaborski {
300b5d787d9SMariusz Zaborski 
301b5d787d9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
302b5d787d9SMariusz Zaborski 
303b5d787d9SMariusz Zaborski 	return (nvl->nvl_array_next);
304b5d787d9SMariusz Zaborski }
305b5d787d9SMariusz Zaborski 
306347a39b4SMariusz Zaborski bool
nvlist_in_array(const nvlist_t * nvl)307347a39b4SMariusz Zaborski nvlist_in_array(const nvlist_t *nvl)
308347a39b4SMariusz Zaborski {
309347a39b4SMariusz Zaborski 
310347a39b4SMariusz Zaborski 	NVLIST_ASSERT(nvl);
311347a39b4SMariusz Zaborski 
312347a39b4SMariusz Zaborski 	return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0);
313347a39b4SMariusz Zaborski }
314347a39b4SMariusz Zaborski 
315347a39b4SMariusz Zaborski const nvlist_t *
nvlist_get_array_next(const nvlist_t * nvl)316347a39b4SMariusz Zaborski nvlist_get_array_next(const nvlist_t *nvl)
317347a39b4SMariusz Zaborski {
318347a39b4SMariusz Zaborski 	nvpair_t *nvp;
319347a39b4SMariusz Zaborski 
320347a39b4SMariusz Zaborski 	NVLIST_ASSERT(nvl);
321347a39b4SMariusz Zaborski 
322347a39b4SMariusz Zaborski 	nvp = nvl->nvl_array_next;
323347a39b4SMariusz Zaborski 	if (nvp == NULL)
324347a39b4SMariusz Zaborski 		return (NULL);
325347a39b4SMariusz Zaborski 
326347a39b4SMariusz Zaborski 	return (nvpair_get_nvlist(nvp));
327347a39b4SMariusz Zaborski }
328347a39b4SMariusz Zaborski 
329347a39b4SMariusz Zaborski const nvlist_t *
nvlist_get_pararr(const nvlist_t * nvl,void ** cookiep)330347a39b4SMariusz Zaborski nvlist_get_pararr(const nvlist_t *nvl, void **cookiep)
331347a39b4SMariusz Zaborski {
332347a39b4SMariusz Zaborski 	const nvlist_t *ret;
333347a39b4SMariusz Zaborski 
334347a39b4SMariusz Zaborski 	ret = nvlist_get_array_next(nvl);
335347a39b4SMariusz Zaborski 	if (ret != NULL) {
336347a39b4SMariusz Zaborski 		if (cookiep != NULL)
337347a39b4SMariusz Zaborski 			*cookiep = NULL;
338347a39b4SMariusz Zaborski 		return (ret);
339347a39b4SMariusz Zaborski 	}
340347a39b4SMariusz Zaborski 
34108016b31SMariusz Zaborski 	return (nvlist_get_parent(nvl, cookiep));
342347a39b4SMariusz Zaborski }
343347a39b4SMariusz Zaborski 
34454f98da9SMariusz Zaborski bool
nvlist_empty(const nvlist_t * nvl)34554f98da9SMariusz Zaborski nvlist_empty(const nvlist_t *nvl)
34654f98da9SMariusz Zaborski {
34754f98da9SMariusz Zaborski 
34854f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
34954f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
35054f98da9SMariusz Zaborski 
35154f98da9SMariusz Zaborski 	return (nvlist_first_nvpair(nvl) == NULL);
35254f98da9SMariusz Zaborski }
35354f98da9SMariusz Zaborski 
35454f98da9SMariusz Zaborski int
nvlist_flags(const nvlist_t * nvl)35554f98da9SMariusz Zaborski nvlist_flags(const nvlist_t *nvl)
35654f98da9SMariusz Zaborski {
35754f98da9SMariusz Zaborski 
35854f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
35954f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
36054f98da9SMariusz Zaborski 
361347a39b4SMariusz Zaborski 	return (nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
362347a39b4SMariusz Zaborski }
363347a39b4SMariusz Zaborski 
364347a39b4SMariusz Zaborski void
nvlist_set_flags(nvlist_t * nvl,int flags)365347a39b4SMariusz Zaborski nvlist_set_flags(nvlist_t *nvl, int flags)
366347a39b4SMariusz Zaborski {
367347a39b4SMariusz Zaborski 
368347a39b4SMariusz Zaborski 	NVLIST_ASSERT(nvl);
369347a39b4SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
370347a39b4SMariusz Zaborski 
371347a39b4SMariusz Zaborski 	nvl->nvl_flags = flags;
37254f98da9SMariusz Zaborski }
37354f98da9SMariusz Zaborski 
374431c5bb8SMariusz Zaborski void
nvlist_report_missing(int type,const char * name)37554f98da9SMariusz Zaborski nvlist_report_missing(int type, const char *name)
37654f98da9SMariusz Zaborski {
37754f98da9SMariusz Zaborski 
37854f98da9SMariusz Zaborski 	PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
37954f98da9SMariusz Zaborski 	    name, nvpair_type_string(type));
38054f98da9SMariusz Zaborski }
38154f98da9SMariusz Zaborski 
38254f98da9SMariusz Zaborski static nvpair_t *
nvlist_find(const nvlist_t * nvl,int type,const char * name)38354f98da9SMariusz Zaborski nvlist_find(const nvlist_t *nvl, int type, const char *name)
38454f98da9SMariusz Zaborski {
38554f98da9SMariusz Zaborski 	nvpair_t *nvp;
38654f98da9SMariusz Zaborski 
38754f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
38854f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
38954f98da9SMariusz Zaborski 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
39054f98da9SMariusz Zaborski 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
39154f98da9SMariusz Zaborski 
39254f98da9SMariusz Zaborski 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
39354f98da9SMariusz Zaborski 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
39454f98da9SMariusz Zaborski 		if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
39554f98da9SMariusz Zaborski 			continue;
39654f98da9SMariusz Zaborski 		if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
39754f98da9SMariusz Zaborski 			if (strcasecmp(nvpair_name(nvp), name) != 0)
39854f98da9SMariusz Zaborski 				continue;
39954f98da9SMariusz Zaborski 		} else {
40054f98da9SMariusz Zaborski 			if (strcmp(nvpair_name(nvp), name) != 0)
40154f98da9SMariusz Zaborski 				continue;
40254f98da9SMariusz Zaborski 		}
40354f98da9SMariusz Zaborski 		break;
40454f98da9SMariusz Zaborski 	}
40554f98da9SMariusz Zaborski 
40654f98da9SMariusz Zaborski 	if (nvp == NULL)
40754f98da9SMariusz Zaborski 		ERRNO_SET(ENOENT);
40854f98da9SMariusz Zaborski 
40954f98da9SMariusz Zaborski 	return (nvp);
41054f98da9SMariusz Zaborski }
41154f98da9SMariusz Zaborski 
41254f98da9SMariusz Zaborski bool
nvlist_exists_type(const nvlist_t * nvl,const char * name,int type)41354f98da9SMariusz Zaborski nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
41454f98da9SMariusz Zaborski {
41554f98da9SMariusz Zaborski 
41654f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
41754f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
41854f98da9SMariusz Zaborski 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
41954f98da9SMariusz Zaborski 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
42054f98da9SMariusz Zaborski 
42154f98da9SMariusz Zaborski 	return (nvlist_find(nvl, type, name) != NULL);
42254f98da9SMariusz Zaborski }
42354f98da9SMariusz Zaborski 
42454f98da9SMariusz Zaborski void
nvlist_free_type(nvlist_t * nvl,const char * name,int type)42554f98da9SMariusz Zaborski nvlist_free_type(nvlist_t *nvl, const char *name, int type)
42654f98da9SMariusz Zaborski {
42754f98da9SMariusz Zaborski 	nvpair_t *nvp;
42854f98da9SMariusz Zaborski 
42954f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
43054f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
43154f98da9SMariusz Zaborski 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
43254f98da9SMariusz Zaborski 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
43354f98da9SMariusz Zaborski 
43454f98da9SMariusz Zaborski 	nvp = nvlist_find(nvl, type, name);
43554f98da9SMariusz Zaborski 	if (nvp != NULL)
43654f98da9SMariusz Zaborski 		nvlist_free_nvpair(nvl, nvp);
43754f98da9SMariusz Zaborski 	else
43854f98da9SMariusz Zaborski 		nvlist_report_missing(type, name);
43954f98da9SMariusz Zaborski }
44054f98da9SMariusz Zaborski 
44154f98da9SMariusz Zaborski nvlist_t *
nvlist_clone(const nvlist_t * nvl)44254f98da9SMariusz Zaborski nvlist_clone(const nvlist_t *nvl)
44354f98da9SMariusz Zaborski {
44454f98da9SMariusz Zaborski 	nvlist_t *newnvl;
44554f98da9SMariusz Zaborski 	nvpair_t *nvp, *newnvp;
44654f98da9SMariusz Zaborski 
44754f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
44854f98da9SMariusz Zaborski 
44954f98da9SMariusz Zaborski 	if (nvl->nvl_error != 0) {
45054f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
45154f98da9SMariusz Zaborski 		return (NULL);
45254f98da9SMariusz Zaborski 	}
45354f98da9SMariusz Zaborski 
45454f98da9SMariusz Zaborski 	newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
45554f98da9SMariusz Zaborski 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
45654f98da9SMariusz Zaborski 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
45754f98da9SMariusz Zaborski 		newnvp = nvpair_clone(nvp);
45854f98da9SMariusz Zaborski 		if (newnvp == NULL)
45954f98da9SMariusz Zaborski 			break;
46030740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(newnvl, newnvp);
46154f98da9SMariusz Zaborski 	}
46254f98da9SMariusz Zaborski 	if (nvp != NULL) {
46354f98da9SMariusz Zaborski 		nvlist_destroy(newnvl);
46454f98da9SMariusz Zaborski 		return (NULL);
46554f98da9SMariusz Zaborski 	}
46654f98da9SMariusz Zaborski 	return (newnvl);
46754f98da9SMariusz Zaborski }
46854f98da9SMariusz Zaborski 
46954f98da9SMariusz Zaborski #ifndef _KERNEL
47054f98da9SMariusz Zaborski static bool
nvlist_dump_error_check(const nvlist_t * nvl,int fd,int level)47154f98da9SMariusz Zaborski nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
47254f98da9SMariusz Zaborski {
47354f98da9SMariusz Zaborski 
47454f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
47554f98da9SMariusz Zaborski 		dprintf(fd, "%*serror: %d\n", level * 4, "",
47654f98da9SMariusz Zaborski 		    nvlist_error(nvl));
47754f98da9SMariusz Zaborski 		return (true);
47854f98da9SMariusz Zaborski 	}
47954f98da9SMariusz Zaborski 
48054f98da9SMariusz Zaborski 	return (false);
48154f98da9SMariusz Zaborski }
48254f98da9SMariusz Zaborski 
48354f98da9SMariusz Zaborski /*
48454f98da9SMariusz Zaborski  * Dump content of nvlist.
48554f98da9SMariusz Zaborski  */
48654f98da9SMariusz Zaborski void
nvlist_dump(const nvlist_t * nvl,int fd)48754f98da9SMariusz Zaborski nvlist_dump(const nvlist_t *nvl, int fd)
48854f98da9SMariusz Zaborski {
48954f98da9SMariusz Zaborski 	const nvlist_t *tmpnvl;
49054f98da9SMariusz Zaborski 	nvpair_t *nvp, *tmpnvp;
49154f98da9SMariusz Zaborski 	void *cookie;
49254f98da9SMariusz Zaborski 	int level;
49354f98da9SMariusz Zaborski 
49454f98da9SMariusz Zaborski 	level = 0;
49554f98da9SMariusz Zaborski 	if (nvlist_dump_error_check(nvl, fd, level))
49654f98da9SMariusz Zaborski 		return;
49754f98da9SMariusz Zaborski 
49854f98da9SMariusz Zaborski 	nvp = nvlist_first_nvpair(nvl);
49954f98da9SMariusz Zaborski 	while (nvp != NULL) {
50054f98da9SMariusz Zaborski 		dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
50154f98da9SMariusz Zaborski 		    nvpair_type_string(nvpair_type(nvp)));
50254f98da9SMariusz Zaborski 		switch (nvpair_type(nvp)) {
50354f98da9SMariusz Zaborski 		case NV_TYPE_NULL:
50454f98da9SMariusz Zaborski 			dprintf(fd, " null\n");
50554f98da9SMariusz Zaborski 			break;
50654f98da9SMariusz Zaborski 		case NV_TYPE_BOOL:
50754f98da9SMariusz Zaborski 			dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
50854f98da9SMariusz Zaborski 			    "TRUE" : "FALSE");
50954f98da9SMariusz Zaborski 			break;
51054f98da9SMariusz Zaborski 		case NV_TYPE_NUMBER:
51154f98da9SMariusz Zaborski 			dprintf(fd, " %ju (%jd) (0x%jx)\n",
51254f98da9SMariusz Zaborski 			    (uintmax_t)nvpair_get_number(nvp),
51354f98da9SMariusz Zaborski 			    (intmax_t)nvpair_get_number(nvp),
51454f98da9SMariusz Zaborski 			    (uintmax_t)nvpair_get_number(nvp));
51554f98da9SMariusz Zaborski 			break;
51654f98da9SMariusz Zaborski 		case NV_TYPE_STRING:
51754f98da9SMariusz Zaborski 			dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
51854f98da9SMariusz Zaborski 			break;
51954f98da9SMariusz Zaborski 		case NV_TYPE_NVLIST:
52054f98da9SMariusz Zaborski 			dprintf(fd, "\n");
52154f98da9SMariusz Zaborski 			tmpnvl = nvpair_get_nvlist(nvp);
52254f98da9SMariusz Zaborski 			if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
52354f98da9SMariusz Zaborski 				break;
52454f98da9SMariusz Zaborski 			tmpnvp = nvlist_first_nvpair(tmpnvl);
52554f98da9SMariusz Zaborski 			if (tmpnvp != NULL) {
52654f98da9SMariusz Zaborski 				nvl = tmpnvl;
52754f98da9SMariusz Zaborski 				nvp = tmpnvp;
52854f98da9SMariusz Zaborski 				level++;
52954f98da9SMariusz Zaborski 				continue;
53054f98da9SMariusz Zaborski 			}
53154f98da9SMariusz Zaborski 			break;
53254f98da9SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR:
53354f98da9SMariusz Zaborski 			dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
53454f98da9SMariusz Zaborski 			break;
53554f98da9SMariusz Zaborski 		case NV_TYPE_BINARY:
53654f98da9SMariusz Zaborski 		    {
53754f98da9SMariusz Zaborski 			const unsigned char *binary;
53854f98da9SMariusz Zaborski 			unsigned int ii;
53954f98da9SMariusz Zaborski 			size_t size;
54054f98da9SMariusz Zaborski 
54154f98da9SMariusz Zaborski 			binary = nvpair_get_binary(nvp, &size);
54254f98da9SMariusz Zaborski 			dprintf(fd, " %zu ", size);
54354f98da9SMariusz Zaborski 			for (ii = 0; ii < size; ii++)
54454f98da9SMariusz Zaborski 				dprintf(fd, "%02hhx", binary[ii]);
54554f98da9SMariusz Zaborski 			dprintf(fd, "\n");
54654f98da9SMariusz Zaborski 			break;
54754f98da9SMariusz Zaborski 		    }
548347a39b4SMariusz Zaborski 		case NV_TYPE_BOOL_ARRAY:
549347a39b4SMariusz Zaborski 		    {
550347a39b4SMariusz Zaborski 			const bool *value;
551347a39b4SMariusz Zaborski 			unsigned int ii;
552347a39b4SMariusz Zaborski 			size_t nitems;
553347a39b4SMariusz Zaborski 
554347a39b4SMariusz Zaborski 			value = nvpair_get_bool_array(nvp, &nitems);
555347a39b4SMariusz Zaborski 			dprintf(fd, " [ ");
556347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
557347a39b4SMariusz Zaborski 				dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE");
558347a39b4SMariusz Zaborski 				if (ii != nitems - 1)
559347a39b4SMariusz Zaborski 					dprintf(fd, ", ");
560347a39b4SMariusz Zaborski 			}
561347a39b4SMariusz Zaborski 			dprintf(fd, " ]\n");
562347a39b4SMariusz Zaborski 			break;
563347a39b4SMariusz Zaborski 		    }
564347a39b4SMariusz Zaborski 		case NV_TYPE_STRING_ARRAY:
565347a39b4SMariusz Zaborski 		    {
566347a39b4SMariusz Zaborski 			const char * const *value;
567347a39b4SMariusz Zaborski 			unsigned int ii;
568347a39b4SMariusz Zaborski 			size_t nitems;
569347a39b4SMariusz Zaborski 
570347a39b4SMariusz Zaborski 			value = nvpair_get_string_array(nvp, &nitems);
571347a39b4SMariusz Zaborski 			dprintf(fd, " [ ");
572347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
573347a39b4SMariusz Zaborski 				if (value[ii] == NULL)
574347a39b4SMariusz Zaborski 					dprintf(fd, "NULL");
575347a39b4SMariusz Zaborski 				else
576347a39b4SMariusz Zaborski 					dprintf(fd, "\"%s\"", value[ii]);
577347a39b4SMariusz Zaborski 				if (ii != nitems - 1)
578347a39b4SMariusz Zaborski 					dprintf(fd, ", ");
579347a39b4SMariusz Zaborski 			}
580347a39b4SMariusz Zaborski 			dprintf(fd, " ]\n");
581347a39b4SMariusz Zaborski 			break;
582347a39b4SMariusz Zaborski 		    }
583347a39b4SMariusz Zaborski 		case NV_TYPE_NUMBER_ARRAY:
584347a39b4SMariusz Zaborski 		    {
585347a39b4SMariusz Zaborski 			const uint64_t *value;
586347a39b4SMariusz Zaborski 			unsigned int ii;
587347a39b4SMariusz Zaborski 			size_t nitems;
588347a39b4SMariusz Zaborski 
589347a39b4SMariusz Zaborski 			value = nvpair_get_number_array(nvp, &nitems);
590347a39b4SMariusz Zaborski 			dprintf(fd, " [ ");
591347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
592347a39b4SMariusz Zaborski 				dprintf(fd, "%ju (%jd) (0x%jx)",
593347a39b4SMariusz Zaborski 				    value[ii], value[ii], value[ii]);
594347a39b4SMariusz Zaborski 				if (ii != nitems - 1)
595347a39b4SMariusz Zaborski 					dprintf(fd, ", ");
596347a39b4SMariusz Zaborski 			}
597347a39b4SMariusz Zaborski 			dprintf(fd, " ]\n");
598347a39b4SMariusz Zaborski 			break;
599347a39b4SMariusz Zaborski 		    }
600347a39b4SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR_ARRAY:
601347a39b4SMariusz Zaborski 		    {
602347a39b4SMariusz Zaborski 			const int *value;
603347a39b4SMariusz Zaborski 			unsigned int ii;
604347a39b4SMariusz Zaborski 			size_t nitems;
605347a39b4SMariusz Zaborski 
606347a39b4SMariusz Zaborski 			value = nvpair_get_descriptor_array(nvp, &nitems);
607347a39b4SMariusz Zaborski 			dprintf(fd, " [ ");
608347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
609347a39b4SMariusz Zaborski 				dprintf(fd, "%d", value[ii]);
610347a39b4SMariusz Zaborski 				if (ii != nitems - 1)
611347a39b4SMariusz Zaborski 					dprintf(fd, ", ");
612347a39b4SMariusz Zaborski 			}
613347a39b4SMariusz Zaborski 			dprintf(fd, " ]\n");
614347a39b4SMariusz Zaborski 			break;
615347a39b4SMariusz Zaborski 		    }
616347a39b4SMariusz Zaborski 		case NV_TYPE_NVLIST_ARRAY:
617347a39b4SMariusz Zaborski 		    {
618347a39b4SMariusz Zaborski 			const nvlist_t * const *value;
619347a39b4SMariusz Zaborski 			unsigned int ii;
620347a39b4SMariusz Zaborski 			size_t nitems;
621347a39b4SMariusz Zaborski 
622347a39b4SMariusz Zaborski 			value = nvpair_get_nvlist_array(nvp, &nitems);
623347a39b4SMariusz Zaborski 			dprintf(fd, " %zu\n", nitems);
624347a39b4SMariusz Zaborski 			tmpnvl = NULL;
625347a39b4SMariusz Zaborski 			tmpnvp = NULL;
626347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
627347a39b4SMariusz Zaborski 				if (nvlist_dump_error_check(value[ii], fd,
628347a39b4SMariusz Zaborski 				    level + 1)) {
629347a39b4SMariusz Zaborski 					break;
630347a39b4SMariusz Zaborski 				}
631347a39b4SMariusz Zaborski 
632347a39b4SMariusz Zaborski 				if (tmpnvl == NULL) {
633347a39b4SMariusz Zaborski 					tmpnvp = nvlist_first_nvpair(value[ii]);
634347a39b4SMariusz Zaborski 					if (tmpnvp != NULL) {
635347a39b4SMariusz Zaborski 						tmpnvl = value[ii];
636347a39b4SMariusz Zaborski 					} else {
637347a39b4SMariusz Zaborski 						dprintf(fd, "%*s,\n",
638347a39b4SMariusz Zaborski 						    (level + 1) * 4, "");
639347a39b4SMariusz Zaborski 					}
640347a39b4SMariusz Zaborski 				}
641347a39b4SMariusz Zaborski 			}
642347a39b4SMariusz Zaborski 			if (tmpnvp != NULL) {
643347a39b4SMariusz Zaborski 				nvl = tmpnvl;
644347a39b4SMariusz Zaborski 				nvp = tmpnvp;
645347a39b4SMariusz Zaborski 				level++;
646347a39b4SMariusz Zaborski 				continue;
647347a39b4SMariusz Zaborski 			}
648347a39b4SMariusz Zaborski 			break;
649347a39b4SMariusz Zaborski 		    }
65054f98da9SMariusz Zaborski 		default:
65154f98da9SMariusz Zaborski 			PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
65254f98da9SMariusz Zaborski 		}
65354f98da9SMariusz Zaborski 
65454f98da9SMariusz Zaborski 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
655347a39b4SMariusz Zaborski 			do {
65654f98da9SMariusz Zaborski 				cookie = NULL;
657347a39b4SMariusz Zaborski 				if (nvlist_in_array(nvl))
658347a39b4SMariusz Zaborski 					dprintf(fd, "%*s,\n", level * 4, "");
659347a39b4SMariusz Zaborski 				nvl = nvlist_get_pararr(nvl, &cookie);
66054f98da9SMariusz Zaborski 				if (nvl == NULL)
66154f98da9SMariusz Zaborski 					return;
662347a39b4SMariusz Zaborski 				if (nvlist_in_array(nvl) && cookie == NULL) {
663347a39b4SMariusz Zaborski 					nvp = nvlist_first_nvpair(nvl);
664347a39b4SMariusz Zaborski 				} else {
66554f98da9SMariusz Zaborski 					nvp = cookie;
66654f98da9SMariusz Zaborski 					level--;
66754f98da9SMariusz Zaborski 				}
668347a39b4SMariusz Zaborski 			} while (nvp == NULL);
669347a39b4SMariusz Zaborski 			if (nvlist_in_array(nvl) && cookie == NULL)
670347a39b4SMariusz Zaborski 				break;
671347a39b4SMariusz Zaborski 		}
67254f98da9SMariusz Zaborski 	}
67354f98da9SMariusz Zaborski }
67454f98da9SMariusz Zaborski 
67554f98da9SMariusz Zaborski void
nvlist_fdump(const nvlist_t * nvl,FILE * fp)67654f98da9SMariusz Zaborski nvlist_fdump(const nvlist_t *nvl, FILE *fp)
67754f98da9SMariusz Zaborski {
67854f98da9SMariusz Zaborski 
67954f98da9SMariusz Zaborski 	fflush(fp);
68054f98da9SMariusz Zaborski 	nvlist_dump(nvl, fileno(fp));
68154f98da9SMariusz Zaborski }
68254f98da9SMariusz Zaborski #endif
68354f98da9SMariusz Zaborski 
68454f98da9SMariusz Zaborski /*
68554f98da9SMariusz Zaborski  * The function obtains size of the nvlist after nvlist_pack().
68654f98da9SMariusz Zaborski  */
68754f98da9SMariusz Zaborski size_t
nvlist_size(const nvlist_t * nvl)68854f98da9SMariusz Zaborski nvlist_size(const nvlist_t *nvl)
68954f98da9SMariusz Zaborski {
69054f98da9SMariusz Zaborski 
69189d5cbb8SMariusz Zaborski 	return (nvl->nvl_datasize);
69254f98da9SMariusz Zaborski }
69354f98da9SMariusz Zaborski 
69454f98da9SMariusz Zaborski #ifndef _KERNEL
69554f98da9SMariusz Zaborski static int *
nvlist_xdescriptors(const nvlist_t * nvl,int * descs)69654f98da9SMariusz Zaborski nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
69754f98da9SMariusz Zaborski {
6989a8ce256SJilles Tjoelker 	void *cookie;
69954f98da9SMariusz Zaborski 	nvpair_t *nvp;
70054f98da9SMariusz Zaborski 	int type;
70154f98da9SMariusz Zaborski 
70254f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
70354f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
70454f98da9SMariusz Zaborski 
7059a8ce256SJilles Tjoelker 	cookie = NULL;
70654f98da9SMariusz Zaborski 	do {
7079a8ce256SJilles Tjoelker 		while (nvlist_next(nvl, &type, &cookie) != NULL) {
7089a8ce256SJilles Tjoelker 			nvp = cookie;
70954f98da9SMariusz Zaborski 			switch (type) {
71054f98da9SMariusz Zaborski 			case NV_TYPE_DESCRIPTOR:
71154f98da9SMariusz Zaborski 				*descs = nvpair_get_descriptor(nvp);
71254f98da9SMariusz Zaborski 				descs++;
71354f98da9SMariusz Zaborski 				break;
714347a39b4SMariusz Zaborski 			case NV_TYPE_DESCRIPTOR_ARRAY:
715347a39b4SMariusz Zaborski 			    {
716347a39b4SMariusz Zaborski 				const int *value;
717347a39b4SMariusz Zaborski 				size_t nitems;
718347a39b4SMariusz Zaborski 				unsigned int ii;
719347a39b4SMariusz Zaborski 
720347a39b4SMariusz Zaborski 				value = nvpair_get_descriptor_array(nvp,
721347a39b4SMariusz Zaborski 				    &nitems);
722347a39b4SMariusz Zaborski 				for (ii = 0; ii < nitems; ii++) {
723347a39b4SMariusz Zaborski 					*descs = value[ii];
724347a39b4SMariusz Zaborski 					descs++;
725347a39b4SMariusz Zaborski 				}
726347a39b4SMariusz Zaborski 				break;
727347a39b4SMariusz Zaborski 			    }
72854f98da9SMariusz Zaborski 			case NV_TYPE_NVLIST:
72954f98da9SMariusz Zaborski 				nvl = nvpair_get_nvlist(nvp);
7309a8ce256SJilles Tjoelker 				cookie = NULL;
73154f98da9SMariusz Zaborski 				break;
732347a39b4SMariusz Zaborski 			case NV_TYPE_NVLIST_ARRAY:
733347a39b4SMariusz Zaborski 			    {
734347a39b4SMariusz Zaborski 				const nvlist_t * const *value;
735347a39b4SMariusz Zaborski 				size_t nitems;
736347a39b4SMariusz Zaborski 
737347a39b4SMariusz Zaborski 				value = nvpair_get_nvlist_array(nvp, &nitems);
738347a39b4SMariusz Zaborski 				PJDLOG_ASSERT(value != NULL);
739347a39b4SMariusz Zaborski 				PJDLOG_ASSERT(nitems > 0);
740347a39b4SMariusz Zaborski 
741347a39b4SMariusz Zaborski 				nvl = value[0];
7429a8ce256SJilles Tjoelker 				cookie = NULL;
743347a39b4SMariusz Zaborski 				break;
74454f98da9SMariusz Zaborski 			    }
74554f98da9SMariusz Zaborski 			}
746347a39b4SMariusz Zaborski 		}
7479a8ce256SJilles Tjoelker 	} while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
74854f98da9SMariusz Zaborski 
74954f98da9SMariusz Zaborski 	return (descs);
75054f98da9SMariusz Zaborski }
75154f98da9SMariusz Zaborski #endif
75254f98da9SMariusz Zaborski 
75354f98da9SMariusz Zaborski #ifndef _KERNEL
75454f98da9SMariusz Zaborski int *
nvlist_descriptors(const nvlist_t * nvl,size_t * nitemsp)75554f98da9SMariusz Zaborski nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
75654f98da9SMariusz Zaborski {
75754f98da9SMariusz Zaborski 	size_t nitems;
75854f98da9SMariusz Zaborski 	int *fds;
75954f98da9SMariusz Zaborski 
76054f98da9SMariusz Zaborski 	nitems = nvlist_ndescriptors(nvl);
76154f98da9SMariusz Zaborski 	fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
76254f98da9SMariusz Zaborski 	if (fds == NULL)
76354f98da9SMariusz Zaborski 		return (NULL);
76454f98da9SMariusz Zaborski 	if (nitems > 0)
76554f98da9SMariusz Zaborski 		nvlist_xdescriptors(nvl, fds);
76654f98da9SMariusz Zaborski 	fds[nitems] = -1;
76754f98da9SMariusz Zaborski 	if (nitemsp != NULL)
76854f98da9SMariusz Zaborski 		*nitemsp = nitems;
76954f98da9SMariusz Zaborski 	return (fds);
77054f98da9SMariusz Zaborski }
77154f98da9SMariusz Zaborski #endif
77254f98da9SMariusz Zaborski 
77354f98da9SMariusz Zaborski size_t
nvlist_ndescriptors(const nvlist_t * nvl)77454f98da9SMariusz Zaborski nvlist_ndescriptors(const nvlist_t *nvl)
77554f98da9SMariusz Zaborski {
77654f98da9SMariusz Zaborski #ifndef _KERNEL
7779a8ce256SJilles Tjoelker 	void *cookie;
77854f98da9SMariusz Zaborski 	nvpair_t *nvp;
77954f98da9SMariusz Zaborski 	size_t ndescs;
78054f98da9SMariusz Zaborski 	int type;
78154f98da9SMariusz Zaborski 
78254f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
78354f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvl->nvl_error == 0);
78454f98da9SMariusz Zaborski 
78554f98da9SMariusz Zaborski 	ndescs = 0;
7869a8ce256SJilles Tjoelker 	cookie = NULL;
78754f98da9SMariusz Zaborski 	do {
7889a8ce256SJilles Tjoelker 		while (nvlist_next(nvl, &type, &cookie) != NULL) {
7899a8ce256SJilles Tjoelker 			nvp = cookie;
79054f98da9SMariusz Zaborski 			switch (type) {
79154f98da9SMariusz Zaborski 			case NV_TYPE_DESCRIPTOR:
79254f98da9SMariusz Zaborski 				ndescs++;
79354f98da9SMariusz Zaborski 				break;
79454f98da9SMariusz Zaborski 			case NV_TYPE_NVLIST:
79554f98da9SMariusz Zaborski 				nvl = nvpair_get_nvlist(nvp);
7969a8ce256SJilles Tjoelker 				cookie = NULL;
79754f98da9SMariusz Zaborski 				break;
798347a39b4SMariusz Zaborski 			case NV_TYPE_NVLIST_ARRAY:
799347a39b4SMariusz Zaborski 			    {
800347a39b4SMariusz Zaborski 				const nvlist_t * const *value;
801347a39b4SMariusz Zaborski 				size_t nitems;
802347a39b4SMariusz Zaborski 
803347a39b4SMariusz Zaborski 				value = nvpair_get_nvlist_array(nvp, &nitems);
804347a39b4SMariusz Zaborski 				PJDLOG_ASSERT(value != NULL);
805347a39b4SMariusz Zaborski 				PJDLOG_ASSERT(nitems > 0);
806347a39b4SMariusz Zaborski 
807347a39b4SMariusz Zaborski 				nvl = value[0];
8089a8ce256SJilles Tjoelker 				cookie = NULL;
809347a39b4SMariusz Zaborski 				break;
810347a39b4SMariusz Zaborski 			    }
811347a39b4SMariusz Zaborski 			case NV_TYPE_DESCRIPTOR_ARRAY:
812347a39b4SMariusz Zaborski 			    {
813347a39b4SMariusz Zaborski 				size_t nitems;
814347a39b4SMariusz Zaborski 
815347a39b4SMariusz Zaborski 				(void)nvpair_get_descriptor_array(nvp,
816347a39b4SMariusz Zaborski 				    &nitems);
817347a39b4SMariusz Zaborski 				ndescs += nitems;
818347a39b4SMariusz Zaborski 				break;
81954f98da9SMariusz Zaborski 			    }
82054f98da9SMariusz Zaborski 			}
821347a39b4SMariusz Zaborski 		}
8229a8ce256SJilles Tjoelker 	} while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
82354f98da9SMariusz Zaborski 
82454f98da9SMariusz Zaborski 	return (ndescs);
82554f98da9SMariusz Zaborski #else
82654f98da9SMariusz Zaborski 	return (0);
82754f98da9SMariusz Zaborski #endif
82854f98da9SMariusz Zaborski }
82954f98da9SMariusz Zaborski 
83054f98da9SMariusz Zaborski static unsigned char *
nvlist_pack_header(const nvlist_t * nvl,unsigned char * ptr,size_t * leftp)83154f98da9SMariusz Zaborski nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
83254f98da9SMariusz Zaborski {
83354f98da9SMariusz Zaborski 	struct nvlist_header nvlhdr;
83454f98da9SMariusz Zaborski 
83554f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
83654f98da9SMariusz Zaborski 
83754f98da9SMariusz Zaborski 	nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
83854f98da9SMariusz Zaborski 	nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
83954f98da9SMariusz Zaborski 	nvlhdr.nvlh_flags = nvl->nvl_flags;
84054f98da9SMariusz Zaborski #if BYTE_ORDER == BIG_ENDIAN
84154f98da9SMariusz Zaborski 	nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
84254f98da9SMariusz Zaborski #endif
84354f98da9SMariusz Zaborski 	nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
84454f98da9SMariusz Zaborski 	nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
84554f98da9SMariusz Zaborski 	PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
84654f98da9SMariusz Zaborski 	memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
84754f98da9SMariusz Zaborski 	ptr += sizeof(nvlhdr);
84854f98da9SMariusz Zaborski 	*leftp -= sizeof(nvlhdr);
84954f98da9SMariusz Zaborski 
85054f98da9SMariusz Zaborski 	return (ptr);
85154f98da9SMariusz Zaborski }
85254f98da9SMariusz Zaborski 
85354f98da9SMariusz Zaborski static void *
nvlist_xpack(const nvlist_t * nvl,int64_t * fdidxp,size_t * sizep)85454f98da9SMariusz Zaborski nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
85554f98da9SMariusz Zaborski {
85654f98da9SMariusz Zaborski 	unsigned char *buf, *ptr;
85754f98da9SMariusz Zaborski 	size_t left, size;
85854f98da9SMariusz Zaborski 	const nvlist_t *tmpnvl;
85954f98da9SMariusz Zaborski 	nvpair_t *nvp, *tmpnvp;
86054f98da9SMariusz Zaborski 	void *cookie;
86154f98da9SMariusz Zaborski 
86254f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
86354f98da9SMariusz Zaborski 
86454f98da9SMariusz Zaborski 	if (nvl->nvl_error != 0) {
86554f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
86654f98da9SMariusz Zaborski 		return (NULL);
86754f98da9SMariusz Zaborski 	}
86854f98da9SMariusz Zaborski 
86954f98da9SMariusz Zaborski 	size = nvlist_size(nvl);
87054f98da9SMariusz Zaborski 	buf = nv_malloc(size);
87154f98da9SMariusz Zaborski 	if (buf == NULL)
87254f98da9SMariusz Zaborski 		return (NULL);
87354f98da9SMariusz Zaborski 
87454f98da9SMariusz Zaborski 	ptr = buf;
87554f98da9SMariusz Zaborski 	left = size;
87654f98da9SMariusz Zaborski 
87754f98da9SMariusz Zaborski 	ptr = nvlist_pack_header(nvl, ptr, &left);
87854f98da9SMariusz Zaborski 
87954f98da9SMariusz Zaborski 	nvp = nvlist_first_nvpair(nvl);
88054f98da9SMariusz Zaborski 	while (nvp != NULL) {
88154f98da9SMariusz Zaborski 		NVPAIR_ASSERT(nvp);
88254f98da9SMariusz Zaborski 
88354f98da9SMariusz Zaborski 		nvpair_init_datasize(nvp);
88454f98da9SMariusz Zaborski 		ptr = nvpair_pack_header(nvp, ptr, &left);
885c68f8061SMariusz Zaborski 		if (ptr == NULL)
886c68f8061SMariusz Zaborski 			goto fail;
88754f98da9SMariusz Zaborski 		switch (nvpair_type(nvp)) {
88854f98da9SMariusz Zaborski 		case NV_TYPE_NULL:
88954f98da9SMariusz Zaborski 			ptr = nvpair_pack_null(nvp, ptr, &left);
89054f98da9SMariusz Zaborski 			break;
89154f98da9SMariusz Zaborski 		case NV_TYPE_BOOL:
89254f98da9SMariusz Zaborski 			ptr = nvpair_pack_bool(nvp, ptr, &left);
89354f98da9SMariusz Zaborski 			break;
89454f98da9SMariusz Zaborski 		case NV_TYPE_NUMBER:
89554f98da9SMariusz Zaborski 			ptr = nvpair_pack_number(nvp, ptr, &left);
89654f98da9SMariusz Zaborski 			break;
89754f98da9SMariusz Zaborski 		case NV_TYPE_STRING:
89854f98da9SMariusz Zaborski 			ptr = nvpair_pack_string(nvp, ptr, &left);
89954f98da9SMariusz Zaborski 			break;
90054f98da9SMariusz Zaborski 		case NV_TYPE_NVLIST:
90154f98da9SMariusz Zaborski 			tmpnvl = nvpair_get_nvlist(nvp);
90254f98da9SMariusz Zaborski 			ptr = nvlist_pack_header(tmpnvl, ptr, &left);
90354f98da9SMariusz Zaborski 			if (ptr == NULL)
904c68f8061SMariusz Zaborski 				goto fail;
90554f98da9SMariusz Zaborski 			tmpnvp = nvlist_first_nvpair(tmpnvl);
90654f98da9SMariusz Zaborski 			if (tmpnvp != NULL) {
90754f98da9SMariusz Zaborski 				nvl = tmpnvl;
90854f98da9SMariusz Zaborski 				nvp = tmpnvp;
90954f98da9SMariusz Zaborski 				continue;
91054f98da9SMariusz Zaborski 			}
91154f98da9SMariusz Zaborski 			ptr = nvpair_pack_nvlist_up(ptr, &left);
91254f98da9SMariusz Zaborski 			break;
91354f98da9SMariusz Zaborski #ifndef _KERNEL
91454f98da9SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR:
91554f98da9SMariusz Zaborski 			ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
91654f98da9SMariusz Zaborski 			break;
917347a39b4SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR_ARRAY:
918347a39b4SMariusz Zaborski 			ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp,
919347a39b4SMariusz Zaborski 			    &left);
920347a39b4SMariusz Zaborski 			break;
92154f98da9SMariusz Zaborski #endif
92254f98da9SMariusz Zaborski 		case NV_TYPE_BINARY:
92354f98da9SMariusz Zaborski 			ptr = nvpair_pack_binary(nvp, ptr, &left);
92454f98da9SMariusz Zaborski 			break;
925347a39b4SMariusz Zaborski 		case NV_TYPE_BOOL_ARRAY:
926347a39b4SMariusz Zaborski 			ptr = nvpair_pack_bool_array(nvp, ptr, &left);
927347a39b4SMariusz Zaborski 			break;
928347a39b4SMariusz Zaborski 		case NV_TYPE_NUMBER_ARRAY:
929347a39b4SMariusz Zaborski 			ptr = nvpair_pack_number_array(nvp, ptr, &left);
930347a39b4SMariusz Zaborski 			break;
931347a39b4SMariusz Zaborski 		case NV_TYPE_STRING_ARRAY:
932347a39b4SMariusz Zaborski 			ptr = nvpair_pack_string_array(nvp, ptr, &left);
933347a39b4SMariusz Zaborski 			break;
934347a39b4SMariusz Zaborski 		case NV_TYPE_NVLIST_ARRAY:
935347a39b4SMariusz Zaborski 		    {
936347a39b4SMariusz Zaborski 			const nvlist_t * const * value;
937347a39b4SMariusz Zaborski 			size_t nitems;
938347a39b4SMariusz Zaborski 			unsigned int ii;
939347a39b4SMariusz Zaborski 
940347a39b4SMariusz Zaborski 			tmpnvl = NULL;
941347a39b4SMariusz Zaborski 			value = nvpair_get_nvlist_array(nvp, &nitems);
942347a39b4SMariusz Zaborski 			for (ii = 0; ii < nitems; ii++) {
943347a39b4SMariusz Zaborski 				ptr = nvlist_pack_header(value[ii], ptr, &left);
944347a39b4SMariusz Zaborski 				if (ptr == NULL)
945347a39b4SMariusz Zaborski 					goto out;
946347a39b4SMariusz Zaborski 				tmpnvp = nvlist_first_nvpair(value[ii]);
947347a39b4SMariusz Zaborski 				if (tmpnvp != NULL) {
948347a39b4SMariusz Zaborski 					tmpnvl = value[ii];
949347a39b4SMariusz Zaborski 					break;
950347a39b4SMariusz Zaborski 				}
951347a39b4SMariusz Zaborski 				ptr = nvpair_pack_nvlist_array_next(ptr, &left);
952347a39b4SMariusz Zaborski 				if (ptr == NULL)
953347a39b4SMariusz Zaborski 					goto out;
954347a39b4SMariusz Zaborski 			}
955347a39b4SMariusz Zaborski 			if (tmpnvl != NULL) {
956347a39b4SMariusz Zaborski 				nvl = tmpnvl;
957347a39b4SMariusz Zaborski 				nvp = tmpnvp;
958347a39b4SMariusz Zaborski 				continue;
959347a39b4SMariusz Zaborski 			}
960347a39b4SMariusz Zaborski 			break;
961347a39b4SMariusz Zaborski 		    }
96254f98da9SMariusz Zaborski 		default:
96354f98da9SMariusz Zaborski 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
96454f98da9SMariusz Zaborski 		}
965c68f8061SMariusz Zaborski 		if (ptr == NULL)
966c68f8061SMariusz Zaborski 			goto fail;
96754f98da9SMariusz Zaborski 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
968347a39b4SMariusz Zaborski 			do {
96954f98da9SMariusz Zaborski 				cookie = NULL;
970347a39b4SMariusz Zaborski 				if (nvlist_in_array(nvl)) {
971347a39b4SMariusz Zaborski 					ptr = nvpair_pack_nvlist_array_next(ptr,
972347a39b4SMariusz Zaborski 					    &left);
973347a39b4SMariusz Zaborski 					if (ptr == NULL)
974347a39b4SMariusz Zaborski 						goto fail;
975347a39b4SMariusz Zaborski 				}
976347a39b4SMariusz Zaborski 				nvl = nvlist_get_pararr(nvl, &cookie);
97754f98da9SMariusz Zaborski 				if (nvl == NULL)
97854f98da9SMariusz Zaborski 					goto out;
979347a39b4SMariusz Zaborski 				if (nvlist_in_array(nvl) && cookie == NULL) {
980347a39b4SMariusz Zaborski 					nvp = nvlist_first_nvpair(nvl);
981347a39b4SMariusz Zaborski 					ptr = nvlist_pack_header(nvl, ptr,
982347a39b4SMariusz Zaborski 					    &left);
983347a39b4SMariusz Zaborski 					if (ptr == NULL)
984347a39b4SMariusz Zaborski 						goto fail;
985347a39b4SMariusz Zaborski 				} else if (nvpair_type((nvpair_t *)cookie) !=
986347a39b4SMariusz Zaborski 				    NV_TYPE_NVLIST_ARRAY) {
98754f98da9SMariusz Zaborski 					ptr = nvpair_pack_nvlist_up(ptr, &left);
98854f98da9SMariusz Zaborski 					if (ptr == NULL)
989c68f8061SMariusz Zaborski 						goto fail;
990347a39b4SMariusz Zaborski 					nvp = cookie;
991347a39b4SMariusz Zaborski 				} else {
992347a39b4SMariusz Zaborski 					nvp = cookie;
993347a39b4SMariusz Zaborski 				}
994347a39b4SMariusz Zaborski 			} while (nvp == NULL);
995347a39b4SMariusz Zaborski 			if (nvlist_in_array(nvl) && cookie == NULL)
996347a39b4SMariusz Zaborski 				break;
99754f98da9SMariusz Zaborski 		}
99854f98da9SMariusz Zaborski 	}
99954f98da9SMariusz Zaborski 
100054f98da9SMariusz Zaborski out:
100154f98da9SMariusz Zaborski 	if (sizep != NULL)
100254f98da9SMariusz Zaborski 		*sizep = size;
100354f98da9SMariusz Zaborski 	return (buf);
1004c68f8061SMariusz Zaborski fail:
1005c68f8061SMariusz Zaborski 	nv_free(buf);
1006c68f8061SMariusz Zaborski 	return (NULL);
100754f98da9SMariusz Zaborski }
100854f98da9SMariusz Zaborski 
100954f98da9SMariusz Zaborski void *
nvlist_pack(const nvlist_t * nvl,size_t * sizep)101054f98da9SMariusz Zaborski nvlist_pack(const nvlist_t *nvl, size_t *sizep)
101154f98da9SMariusz Zaborski {
101254f98da9SMariusz Zaborski 
101354f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
101454f98da9SMariusz Zaborski 
101554f98da9SMariusz Zaborski 	if (nvl->nvl_error != 0) {
101654f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
101754f98da9SMariusz Zaborski 		return (NULL);
101854f98da9SMariusz Zaborski 	}
101954f98da9SMariusz Zaborski 
102054f98da9SMariusz Zaborski 	if (nvlist_ndescriptors(nvl) > 0) {
102154f98da9SMariusz Zaborski 		ERRNO_SET(EOPNOTSUPP);
102254f98da9SMariusz Zaborski 		return (NULL);
102354f98da9SMariusz Zaborski 	}
102454f98da9SMariusz Zaborski 
102554f98da9SMariusz Zaborski 	return (nvlist_xpack(nvl, NULL, sizep));
102654f98da9SMariusz Zaborski }
102754f98da9SMariusz Zaborski 
102854f98da9SMariusz Zaborski static bool
nvlist_check_header(struct nvlist_header * nvlhdrp)102954f98da9SMariusz Zaborski nvlist_check_header(struct nvlist_header *nvlhdrp)
103054f98da9SMariusz Zaborski {
103154f98da9SMariusz Zaborski 
103254f98da9SMariusz Zaborski 	if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
103354f98da9SMariusz Zaborski 		ERRNO_SET(EINVAL);
103454f98da9SMariusz Zaborski 		return (false);
103554f98da9SMariusz Zaborski 	}
103654f98da9SMariusz Zaborski 	if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
103754f98da9SMariusz Zaborski 		ERRNO_SET(EINVAL);
103854f98da9SMariusz Zaborski 		return (false);
103954f98da9SMariusz Zaborski 	}
104054f98da9SMariusz Zaborski #if BYTE_ORDER == BIG_ENDIAN
104154f98da9SMariusz Zaborski 	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
104254f98da9SMariusz Zaborski 		nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
104354f98da9SMariusz Zaborski 		nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
104454f98da9SMariusz Zaborski 	}
104554f98da9SMariusz Zaborski #else
104654f98da9SMariusz Zaborski 	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
104754f98da9SMariusz Zaborski 		nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
104854f98da9SMariusz Zaborski 		nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
104954f98da9SMariusz Zaborski 	}
105054f98da9SMariusz Zaborski #endif
105154f98da9SMariusz Zaborski 	return (true);
105254f98da9SMariusz Zaborski }
105354f98da9SMariusz Zaborski 
105454f98da9SMariusz Zaborski const unsigned char *
nvlist_unpack_header(nvlist_t * nvl,const unsigned char * ptr,size_t nfds,bool * isbep,size_t * leftp)105554f98da9SMariusz Zaborski nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
105654f98da9SMariusz Zaborski     bool *isbep, size_t *leftp)
105754f98da9SMariusz Zaborski {
105854f98da9SMariusz Zaborski 	struct nvlist_header nvlhdr;
1059347a39b4SMariusz Zaborski 	int inarrayf;
106054f98da9SMariusz Zaborski 
106154f98da9SMariusz Zaborski 	if (*leftp < sizeof(nvlhdr))
1062a3c485d3SMariusz Zaborski 		goto fail;
106354f98da9SMariusz Zaborski 
106454f98da9SMariusz Zaborski 	memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
106554f98da9SMariusz Zaborski 
106654f98da9SMariusz Zaborski 	if (!nvlist_check_header(&nvlhdr))
1067a3c485d3SMariusz Zaborski 		goto fail;
106854f98da9SMariusz Zaborski 
106954f98da9SMariusz Zaborski 	if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
1070a3c485d3SMariusz Zaborski 		goto fail;
107154f98da9SMariusz Zaborski 
107254f98da9SMariusz Zaborski 	/*
107354f98da9SMariusz Zaborski 	 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
107454f98da9SMariusz Zaborski 	 */
107554f98da9SMariusz Zaborski 	if (nvlhdr.nvlh_descriptors > nfds)
1076a3c485d3SMariusz Zaborski 		goto fail;
107754f98da9SMariusz Zaborski 
107854f98da9SMariusz Zaborski 	if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
1079a3c485d3SMariusz Zaborski 		goto fail;
108054f98da9SMariusz Zaborski 
1081347a39b4SMariusz Zaborski 	inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY);
1082347a39b4SMariusz Zaborski 	nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf;
108354f98da9SMariusz Zaborski 
108454f98da9SMariusz Zaborski 	ptr += sizeof(nvlhdr);
108554f98da9SMariusz Zaborski 	if (isbep != NULL)
108654f98da9SMariusz Zaborski 		*isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
108754f98da9SMariusz Zaborski 	*leftp -= sizeof(nvlhdr);
108854f98da9SMariusz Zaborski 
108954f98da9SMariusz Zaborski 	return (ptr);
1090a3c485d3SMariusz Zaborski fail:
109154f98da9SMariusz Zaborski 	ERRNO_SET(EINVAL);
109254f98da9SMariusz Zaborski 	return (NULL);
109354f98da9SMariusz Zaborski }
109454f98da9SMariusz Zaborski 
109554f98da9SMariusz Zaborski static nvlist_t *
nvlist_xunpack(const void * buf,size_t size,const int * fds,size_t nfds,int flags)109654f98da9SMariusz Zaborski nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
109754f98da9SMariusz Zaborski     int flags)
109854f98da9SMariusz Zaborski {
109954f98da9SMariusz Zaborski 	const unsigned char *ptr;
1100347a39b4SMariusz Zaborski 	nvlist_t *nvl, *retnvl, *tmpnvl, *array;
110154f98da9SMariusz Zaborski 	nvpair_t *nvp;
110254f98da9SMariusz Zaborski 	size_t left;
110354f98da9SMariusz Zaborski 	bool isbe;
110454f98da9SMariusz Zaborski 
110554f98da9SMariusz Zaborski 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
110654f98da9SMariusz Zaborski 
110754f98da9SMariusz Zaborski 	left = size;
110854f98da9SMariusz Zaborski 	ptr = buf;
110954f98da9SMariusz Zaborski 
1110347a39b4SMariusz Zaborski 	tmpnvl = array = NULL;
111154f98da9SMariusz Zaborski 	nvl = retnvl = nvlist_create(0);
111254f98da9SMariusz Zaborski 	if (nvl == NULL)
1113a3c485d3SMariusz Zaborski 		goto fail;
111454f98da9SMariusz Zaborski 
111554f98da9SMariusz Zaborski 	ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
111654f98da9SMariusz Zaborski 	if (ptr == NULL)
1117a3c485d3SMariusz Zaborski 		goto fail;
111854f98da9SMariusz Zaborski 	if (nvl->nvl_flags != flags) {
111954f98da9SMariusz Zaborski 		ERRNO_SET(EILSEQ);
1120a3c485d3SMariusz Zaborski 		goto fail;
112154f98da9SMariusz Zaborski 	}
112254f98da9SMariusz Zaborski 
112354f98da9SMariusz Zaborski 	while (left > 0) {
112454f98da9SMariusz Zaborski 		ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
112554f98da9SMariusz Zaborski 		if (ptr == NULL)
1126a3c485d3SMariusz Zaborski 			goto fail;
112754f98da9SMariusz Zaborski 		switch (nvpair_type(nvp)) {
112854f98da9SMariusz Zaborski 		case NV_TYPE_NULL:
112954f98da9SMariusz Zaborski 			ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
113054f98da9SMariusz Zaborski 			break;
113154f98da9SMariusz Zaborski 		case NV_TYPE_BOOL:
113254f98da9SMariusz Zaborski 			ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
113354f98da9SMariusz Zaborski 			break;
113454f98da9SMariusz Zaborski 		case NV_TYPE_NUMBER:
113554f98da9SMariusz Zaborski 			ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
113654f98da9SMariusz Zaborski 			break;
113754f98da9SMariusz Zaborski 		case NV_TYPE_STRING:
113854f98da9SMariusz Zaborski 			ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
113954f98da9SMariusz Zaborski 			break;
114054f98da9SMariusz Zaborski 		case NV_TYPE_NVLIST:
114154f98da9SMariusz Zaborski 			ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
114254f98da9SMariusz Zaborski 			    &tmpnvl);
114351dae13fSMariusz Zaborski 			if (tmpnvl == NULL || ptr == NULL)
1144a3c485d3SMariusz Zaborski 				goto fail;
114554f98da9SMariusz Zaborski 			nvlist_set_parent(tmpnvl, nvp);
114654f98da9SMariusz Zaborski 			break;
114754f98da9SMariusz Zaborski #ifndef _KERNEL
114854f98da9SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR:
114954f98da9SMariusz Zaborski 			ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
115054f98da9SMariusz Zaborski 			    fds, nfds);
115154f98da9SMariusz Zaborski 			break;
1152347a39b4SMariusz Zaborski 		case NV_TYPE_DESCRIPTOR_ARRAY:
1153347a39b4SMariusz Zaborski 			ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr,
1154347a39b4SMariusz Zaborski 			    &left, fds, nfds);
1155347a39b4SMariusz Zaborski 			break;
115654f98da9SMariusz Zaborski #endif
115754f98da9SMariusz Zaborski 		case NV_TYPE_BINARY:
115854f98da9SMariusz Zaborski 			ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
115954f98da9SMariusz Zaborski 			break;
116054f98da9SMariusz Zaborski 		case NV_TYPE_NVLIST_UP:
116154f98da9SMariusz Zaborski 			if (nvl->nvl_parent == NULL)
1162a3c485d3SMariusz Zaborski 				goto fail;
116354f98da9SMariusz Zaborski 			nvl = nvpair_nvlist(nvl->nvl_parent);
116454f98da9SMariusz Zaborski 			nvpair_free_structure(nvp);
116554f98da9SMariusz Zaborski 			continue;
1166347a39b4SMariusz Zaborski 		case NV_TYPE_NVLIST_ARRAY_NEXT:
1167347a39b4SMariusz Zaborski 			if (nvl->nvl_array_next == NULL) {
1168347a39b4SMariusz Zaborski 				if (nvl->nvl_parent == NULL)
1169a3c485d3SMariusz Zaborski 					goto fail;
1170347a39b4SMariusz Zaborski 				nvl = nvpair_nvlist(nvl->nvl_parent);
1171347a39b4SMariusz Zaborski 			} else {
1172347a39b4SMariusz Zaborski 				nvl = __DECONST(nvlist_t *,
1173347a39b4SMariusz Zaborski 				    nvlist_get_array_next(nvl));
1174347a39b4SMariusz Zaborski 				ptr = nvlist_unpack_header(nvl, ptr, nfds,
1175347a39b4SMariusz Zaborski 				    &isbe, &left);
1176347a39b4SMariusz Zaborski 				if (ptr == NULL)
1177a3c485d3SMariusz Zaborski 					goto fail;
1178347a39b4SMariusz Zaborski 			}
1179347a39b4SMariusz Zaborski 			nvpair_free_structure(nvp);
1180347a39b4SMariusz Zaborski 			continue;
1181347a39b4SMariusz Zaborski 		case NV_TYPE_BOOL_ARRAY:
1182347a39b4SMariusz Zaborski 			ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left);
1183347a39b4SMariusz Zaborski 			break;
1184347a39b4SMariusz Zaborski 		case NV_TYPE_NUMBER_ARRAY:
1185347a39b4SMariusz Zaborski 			ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left);
1186347a39b4SMariusz Zaborski 			break;
1187347a39b4SMariusz Zaborski 		case NV_TYPE_STRING_ARRAY:
1188347a39b4SMariusz Zaborski 			ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left);
1189347a39b4SMariusz Zaborski 			break;
1190347a39b4SMariusz Zaborski 		case NV_TYPE_NVLIST_ARRAY:
1191347a39b4SMariusz Zaborski 			ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left,
1192347a39b4SMariusz Zaborski 			    &array);
1193347a39b4SMariusz Zaborski 			if (ptr == NULL)
1194a3c485d3SMariusz Zaborski 				goto fail;
11951dacabe1SMariusz Zaborski 			PJDLOG_ASSERT(array != NULL);
1196347a39b4SMariusz Zaborski 			tmpnvl = array;
11971dacabe1SMariusz Zaborski 			do {
1198347a39b4SMariusz Zaborski 				nvlist_set_parent(array, nvp);
1199347a39b4SMariusz Zaborski 				array = __DECONST(nvlist_t *,
1200347a39b4SMariusz Zaborski 				    nvlist_get_array_next(array));
12011dacabe1SMariusz Zaborski 			} while (array != NULL);
1202347a39b4SMariusz Zaborski 			ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe,
1203347a39b4SMariusz Zaborski 			    &left);
1204347a39b4SMariusz Zaborski 			break;
120554f98da9SMariusz Zaborski 		default:
120654f98da9SMariusz Zaborski 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
120754f98da9SMariusz Zaborski 		}
120854f98da9SMariusz Zaborski 		if (ptr == NULL)
1209a3c485d3SMariusz Zaborski 			goto fail;
121030740f45SMariusz Zaborski 		if (!nvlist_move_nvpair(nvl, nvp))
1211a3c485d3SMariusz Zaborski 			goto fail;
121254f98da9SMariusz Zaborski 		if (tmpnvl != NULL) {
121354f98da9SMariusz Zaborski 			nvl = tmpnvl;
121454f98da9SMariusz Zaborski 			tmpnvl = NULL;
121554f98da9SMariusz Zaborski 		}
121654f98da9SMariusz Zaborski 	}
121754f98da9SMariusz Zaborski 
121854f98da9SMariusz Zaborski 	return (retnvl);
1219a3c485d3SMariusz Zaborski fail:
122054f98da9SMariusz Zaborski 	nvlist_destroy(retnvl);
122154f98da9SMariusz Zaborski 	return (NULL);
122254f98da9SMariusz Zaborski }
122354f98da9SMariusz Zaborski 
122454f98da9SMariusz Zaborski nvlist_t *
nvlist_unpack(const void * buf,size_t size,int flags)122554f98da9SMariusz Zaborski nvlist_unpack(const void *buf, size_t size, int flags)
122654f98da9SMariusz Zaborski {
122754f98da9SMariusz Zaborski 
122854f98da9SMariusz Zaborski 	return (nvlist_xunpack(buf, size, NULL, 0, flags));
122954f98da9SMariusz Zaborski }
123054f98da9SMariusz Zaborski 
123154f98da9SMariusz Zaborski #ifndef _KERNEL
123254f98da9SMariusz Zaborski int
nvlist_send(int sock,const nvlist_t * nvl)123354f98da9SMariusz Zaborski nvlist_send(int sock, const nvlist_t *nvl)
123454f98da9SMariusz Zaborski {
123554f98da9SMariusz Zaborski 	size_t datasize, nfds;
123654f98da9SMariusz Zaborski 	int *fds;
123754f98da9SMariusz Zaborski 	void *data;
123854f98da9SMariusz Zaborski 	int64_t fdidx;
123954f98da9SMariusz Zaborski 	int ret;
124054f98da9SMariusz Zaborski 
124154f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
124254f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
124354f98da9SMariusz Zaborski 		return (-1);
124454f98da9SMariusz Zaborski 	}
124554f98da9SMariusz Zaborski 
124654f98da9SMariusz Zaborski 	fds = nvlist_descriptors(nvl, &nfds);
124754f98da9SMariusz Zaborski 	if (fds == NULL)
124854f98da9SMariusz Zaborski 		return (-1);
124954f98da9SMariusz Zaborski 
125054f98da9SMariusz Zaborski 	ret = -1;
125154f98da9SMariusz Zaborski 	fdidx = 0;
125254f98da9SMariusz Zaborski 
125354f98da9SMariusz Zaborski 	data = nvlist_xpack(nvl, &fdidx, &datasize);
125454f98da9SMariusz Zaborski 	if (data == NULL)
125554f98da9SMariusz Zaborski 		goto out;
125654f98da9SMariusz Zaborski 
125754f98da9SMariusz Zaborski 	if (buf_send(sock, data, datasize) == -1)
125854f98da9SMariusz Zaborski 		goto out;
125954f98da9SMariusz Zaborski 
126054f98da9SMariusz Zaborski 	if (nfds > 0) {
126154f98da9SMariusz Zaborski 		if (fd_send(sock, fds, nfds) == -1)
126254f98da9SMariusz Zaborski 			goto out;
126354f98da9SMariusz Zaborski 	}
126454f98da9SMariusz Zaborski 
126554f98da9SMariusz Zaborski 	ret = 0;
126654f98da9SMariusz Zaborski out:
126754f98da9SMariusz Zaborski 	ERRNO_SAVE();
126854f98da9SMariusz Zaborski 	nv_free(fds);
126954f98da9SMariusz Zaborski 	nv_free(data);
127054f98da9SMariusz Zaborski 	ERRNO_RESTORE();
127154f98da9SMariusz Zaborski 	return (ret);
127254f98da9SMariusz Zaborski }
127354f98da9SMariusz Zaborski 
127454f98da9SMariusz Zaborski nvlist_t *
nvlist_recv(int sock,int flags)127554f98da9SMariusz Zaborski nvlist_recv(int sock, int flags)
127654f98da9SMariusz Zaborski {
127754f98da9SMariusz Zaborski 	struct nvlist_header nvlhdr;
127854f98da9SMariusz Zaborski 	nvlist_t *nvl, *ret;
127954f98da9SMariusz Zaborski 	unsigned char *buf;
12805916ae1fSRobert Wing 	size_t nfds, size, i, offset;
12815916ae1fSRobert Wing 	int *fds, soflags, sotype;
12825916ae1fSRobert Wing 	socklen_t solen;
128354f98da9SMariusz Zaborski 
12845916ae1fSRobert Wing 	solen = sizeof(sotype);
12855916ae1fSRobert Wing 	if (getsockopt(sock, SOL_SOCKET, SO_TYPE, &sotype, &solen) != 0)
12865916ae1fSRobert Wing 		return (NULL);
12875916ae1fSRobert Wing 
12885916ae1fSRobert Wing 	soflags = sotype == SOCK_DGRAM ? MSG_PEEK : 0;
12895916ae1fSRobert Wing 	if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr), soflags) == -1)
129054f98da9SMariusz Zaborski 		return (NULL);
129154f98da9SMariusz Zaborski 
129254f98da9SMariusz Zaborski 	if (!nvlist_check_header(&nvlhdr))
129354f98da9SMariusz Zaborski 		return (NULL);
129454f98da9SMariusz Zaborski 
129554f98da9SMariusz Zaborski 	nfds = (size_t)nvlhdr.nvlh_descriptors;
129654f98da9SMariusz Zaborski 	size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
129754f98da9SMariusz Zaborski 
129854f98da9SMariusz Zaborski 	buf = nv_malloc(size);
129954f98da9SMariusz Zaborski 	if (buf == NULL)
130054f98da9SMariusz Zaborski 		return (NULL);
130154f98da9SMariusz Zaborski 
130254f98da9SMariusz Zaborski 	ret = NULL;
130354f98da9SMariusz Zaborski 	fds = NULL;
130454f98da9SMariusz Zaborski 
13055916ae1fSRobert Wing 	if (sotype == SOCK_DGRAM)
13065916ae1fSRobert Wing 		offset = 0;
13075916ae1fSRobert Wing 	else {
13085916ae1fSRobert Wing 		memcpy(buf, &nvlhdr, sizeof(nvlhdr));
13095916ae1fSRobert Wing 		offset = sizeof(nvlhdr);
13105916ae1fSRobert Wing 	}
13115916ae1fSRobert Wing 
13125916ae1fSRobert Wing 	if (buf_recv(sock, buf + offset, size - offset, 0) == -1)
131354f98da9SMariusz Zaborski 		goto out;
131454f98da9SMariusz Zaborski 
131554f98da9SMariusz Zaborski 	if (nfds > 0) {
131654f98da9SMariusz Zaborski 		fds = nv_malloc(nfds * sizeof(fds[0]));
131754f98da9SMariusz Zaborski 		if (fds == NULL)
131854f98da9SMariusz Zaborski 			goto out;
131954f98da9SMariusz Zaborski 		if (fd_recv(sock, fds, nfds) == -1)
132054f98da9SMariusz Zaborski 			goto out;
132154f98da9SMariusz Zaborski 	}
132254f98da9SMariusz Zaborski 
132354f98da9SMariusz Zaborski 	nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
132454f98da9SMariusz Zaborski 	if (nvl == NULL) {
132554f98da9SMariusz Zaborski 		ERRNO_SAVE();
132654f98da9SMariusz Zaborski 		for (i = 0; i < nfds; i++)
132754f98da9SMariusz Zaborski 			close(fds[i]);
132854f98da9SMariusz Zaborski 		ERRNO_RESTORE();
132954f98da9SMariusz Zaborski 		goto out;
133054f98da9SMariusz Zaborski 	}
133154f98da9SMariusz Zaborski 
133254f98da9SMariusz Zaborski 	ret = nvl;
133354f98da9SMariusz Zaborski out:
133454f98da9SMariusz Zaborski 	ERRNO_SAVE();
133554f98da9SMariusz Zaborski 	nv_free(buf);
133654f98da9SMariusz Zaborski 	nv_free(fds);
133754f98da9SMariusz Zaborski 	ERRNO_RESTORE();
133854f98da9SMariusz Zaborski 
133954f98da9SMariusz Zaborski 	return (ret);
134054f98da9SMariusz Zaborski }
134154f98da9SMariusz Zaborski 
134254f98da9SMariusz Zaborski nvlist_t *
nvlist_xfer(int sock,nvlist_t * nvl,int flags)134354f98da9SMariusz Zaborski nvlist_xfer(int sock, nvlist_t *nvl, int flags)
134454f98da9SMariusz Zaborski {
134554f98da9SMariusz Zaborski 
134654f98da9SMariusz Zaborski 	if (nvlist_send(sock, nvl) < 0) {
134754f98da9SMariusz Zaborski 		nvlist_destroy(nvl);
134854f98da9SMariusz Zaborski 		return (NULL);
134954f98da9SMariusz Zaborski 	}
135054f98da9SMariusz Zaborski 	nvlist_destroy(nvl);
135154f98da9SMariusz Zaborski 	return (nvlist_recv(sock, flags));
135254f98da9SMariusz Zaborski }
135354f98da9SMariusz Zaborski #endif
135454f98da9SMariusz Zaborski 
135554f98da9SMariusz Zaborski nvpair_t *
nvlist_first_nvpair(const nvlist_t * nvl)135654f98da9SMariusz Zaborski nvlist_first_nvpair(const nvlist_t *nvl)
135754f98da9SMariusz Zaborski {
135854f98da9SMariusz Zaborski 
135954f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
136054f98da9SMariusz Zaborski 
136154f98da9SMariusz Zaborski 	return (TAILQ_FIRST(&nvl->nvl_head));
136254f98da9SMariusz Zaborski }
136354f98da9SMariusz Zaborski 
136454f98da9SMariusz Zaborski nvpair_t *
nvlist_next_nvpair(const nvlist_t * nvl __unused,const nvpair_t * nvp)1365dab22642SMariusz Zaborski nvlist_next_nvpair(const nvlist_t *nvl __unused, const nvpair_t *nvp)
136654f98da9SMariusz Zaborski {
136754f98da9SMariusz Zaborski 	nvpair_t *retnvp;
136854f98da9SMariusz Zaborski 
136954f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
137054f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
137154f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
137254f98da9SMariusz Zaborski 
137354f98da9SMariusz Zaborski 	retnvp = nvpair_next(nvp);
137454f98da9SMariusz Zaborski 	PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
137554f98da9SMariusz Zaborski 
137654f98da9SMariusz Zaborski 	return (retnvp);
137754f98da9SMariusz Zaborski 
137854f98da9SMariusz Zaborski }
137954f98da9SMariusz Zaborski 
138054f98da9SMariusz Zaborski nvpair_t *
nvlist_prev_nvpair(const nvlist_t * nvl __unused,const nvpair_t * nvp)1381dab22642SMariusz Zaborski nvlist_prev_nvpair(const nvlist_t *nvl __unused, const nvpair_t *nvp)
138254f98da9SMariusz Zaborski {
138354f98da9SMariusz Zaborski 	nvpair_t *retnvp;
138454f98da9SMariusz Zaborski 
138554f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
138654f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
138754f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
138854f98da9SMariusz Zaborski 
138954f98da9SMariusz Zaborski 	retnvp = nvpair_prev(nvp);
139054f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
139154f98da9SMariusz Zaborski 
139254f98da9SMariusz Zaborski 	return (retnvp);
139354f98da9SMariusz Zaborski }
139454f98da9SMariusz Zaborski 
139554f98da9SMariusz Zaborski const char *
nvlist_next(const nvlist_t * nvl,int * typep,void ** cookiep)139654f98da9SMariusz Zaborski nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
139754f98da9SMariusz Zaborski {
139854f98da9SMariusz Zaborski 	nvpair_t *nvp;
139954f98da9SMariusz Zaborski 
140054f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
140154f98da9SMariusz Zaborski 
140289ca10c6SMariusz Zaborski 	if (cookiep == NULL || *cookiep == NULL)
140354f98da9SMariusz Zaborski 		nvp = nvlist_first_nvpair(nvl);
140454f98da9SMariusz Zaborski 	else
140554f98da9SMariusz Zaborski 		nvp = nvlist_next_nvpair(nvl, *cookiep);
140654f98da9SMariusz Zaborski 	if (nvp == NULL)
140754f98da9SMariusz Zaborski 		return (NULL);
140854f98da9SMariusz Zaborski 	if (typep != NULL)
140954f98da9SMariusz Zaborski 		*typep = nvpair_type(nvp);
141089ca10c6SMariusz Zaborski 	if (cookiep != NULL)
141154f98da9SMariusz Zaborski 		*cookiep = nvp;
141254f98da9SMariusz Zaborski 	return (nvpair_name(nvp));
141354f98da9SMariusz Zaborski }
141454f98da9SMariusz Zaborski 
141554f98da9SMariusz Zaborski bool
nvlist_exists(const nvlist_t * nvl,const char * name)141654f98da9SMariusz Zaborski nvlist_exists(const nvlist_t *nvl, const char *name)
141754f98da9SMariusz Zaborski {
141854f98da9SMariusz Zaborski 
141954f98da9SMariusz Zaborski 	return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
142054f98da9SMariusz Zaborski }
142154f98da9SMariusz Zaborski 
142254f98da9SMariusz Zaborski #define	NVLIST_EXISTS(type, TYPE)					\
142354f98da9SMariusz Zaborski bool									\
142454f98da9SMariusz Zaborski nvlist_exists_##type(const nvlist_t *nvl, const char *name)		\
142554f98da9SMariusz Zaborski {									\
142654f98da9SMariusz Zaborski 									\
142754f98da9SMariusz Zaborski 	return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL);	\
142854f98da9SMariusz Zaborski }
142954f98da9SMariusz Zaborski 
NVLIST_EXISTS(null,NULL)143054f98da9SMariusz Zaborski NVLIST_EXISTS(null, NULL)
143154f98da9SMariusz Zaborski NVLIST_EXISTS(bool, BOOL)
143254f98da9SMariusz Zaborski NVLIST_EXISTS(number, NUMBER)
143354f98da9SMariusz Zaborski NVLIST_EXISTS(string, STRING)
143454f98da9SMariusz Zaborski NVLIST_EXISTS(nvlist, NVLIST)
1435347a39b4SMariusz Zaborski NVLIST_EXISTS(binary, BINARY)
1436347a39b4SMariusz Zaborski NVLIST_EXISTS(bool_array, BOOL_ARRAY)
1437347a39b4SMariusz Zaborski NVLIST_EXISTS(number_array, NUMBER_ARRAY)
1438347a39b4SMariusz Zaborski NVLIST_EXISTS(string_array, STRING_ARRAY)
1439347a39b4SMariusz Zaborski NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY)
144054f98da9SMariusz Zaborski #ifndef _KERNEL
144154f98da9SMariusz Zaborski NVLIST_EXISTS(descriptor, DESCRIPTOR)
1442347a39b4SMariusz Zaborski NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY)
144354f98da9SMariusz Zaborski #endif
144454f98da9SMariusz Zaborski 
144554f98da9SMariusz Zaborski #undef	NVLIST_EXISTS
144654f98da9SMariusz Zaborski 
144754f98da9SMariusz Zaborski void
144854f98da9SMariusz Zaborski nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
144954f98da9SMariusz Zaborski {
145054f98da9SMariusz Zaborski 	nvpair_t *newnvp;
145154f98da9SMariusz Zaborski 
145254f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
145354f98da9SMariusz Zaborski 
145454f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
145554f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
145654f98da9SMariusz Zaborski 		return;
145754f98da9SMariusz Zaborski 	}
145854f98da9SMariusz Zaborski 	if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
145954f98da9SMariusz Zaborski 		if (nvlist_exists(nvl, nvpair_name(nvp))) {
146054f98da9SMariusz Zaborski 			nvl->nvl_error = EEXIST;
146154f98da9SMariusz Zaborski 			ERRNO_SET(nvlist_error(nvl));
146254f98da9SMariusz Zaborski 			return;
146354f98da9SMariusz Zaborski 		}
146454f98da9SMariusz Zaborski 	}
146554f98da9SMariusz Zaborski 
146654f98da9SMariusz Zaborski 	newnvp = nvpair_clone(nvp);
146754f98da9SMariusz Zaborski 	if (newnvp == NULL) {
146854f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
146954f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
147054f98da9SMariusz Zaborski 		return;
147154f98da9SMariusz Zaborski 	}
147254f98da9SMariusz Zaborski 
147354f98da9SMariusz Zaborski 	nvpair_insert(&nvl->nvl_head, newnvp, nvl);
147489d5cbb8SMariusz Zaborski 	nvlist_update_size(nvl, newnvp, 1);
147554f98da9SMariusz Zaborski }
147654f98da9SMariusz Zaborski 
147754f98da9SMariusz Zaborski void
nvlist_add_stringf(nvlist_t * nvl,const char * name,const char * valuefmt,...)147854f98da9SMariusz Zaborski nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
147954f98da9SMariusz Zaborski {
148054f98da9SMariusz Zaborski 	va_list valueap;
148154f98da9SMariusz Zaborski 
148254f98da9SMariusz Zaborski 	va_start(valueap, valuefmt);
148354f98da9SMariusz Zaborski 	nvlist_add_stringv(nvl, name, valuefmt, valueap);
148454f98da9SMariusz Zaborski 	va_end(valueap);
148554f98da9SMariusz Zaborski }
148654f98da9SMariusz Zaborski 
148754f98da9SMariusz Zaborski void
nvlist_add_stringv(nvlist_t * nvl,const char * name,const char * valuefmt,va_list valueap)148854f98da9SMariusz Zaborski nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
148954f98da9SMariusz Zaborski     va_list valueap)
149054f98da9SMariusz Zaborski {
149154f98da9SMariusz Zaborski 	nvpair_t *nvp;
149254f98da9SMariusz Zaborski 
149354f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
149454f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
149554f98da9SMariusz Zaborski 		return;
149654f98da9SMariusz Zaborski 	}
149754f98da9SMariusz Zaborski 
149854f98da9SMariusz Zaborski 	nvp = nvpair_create_stringv(name, valuefmt, valueap);
149954f98da9SMariusz Zaborski 	if (nvp == NULL) {
150054f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
150154f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
150254f98da9SMariusz Zaborski 	} else {
150330740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
150454f98da9SMariusz Zaborski 	}
150554f98da9SMariusz Zaborski }
150654f98da9SMariusz Zaborski 
150754f98da9SMariusz Zaborski void
nvlist_add_null(nvlist_t * nvl,const char * name)150854f98da9SMariusz Zaborski nvlist_add_null(nvlist_t *nvl, const char *name)
150954f98da9SMariusz Zaborski {
151054f98da9SMariusz Zaborski 	nvpair_t *nvp;
151154f98da9SMariusz Zaborski 
151254f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
151354f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
151454f98da9SMariusz Zaborski 		return;
151554f98da9SMariusz Zaborski 	}
151654f98da9SMariusz Zaborski 
151754f98da9SMariusz Zaborski 	nvp = nvpair_create_null(name);
151854f98da9SMariusz Zaborski 	if (nvp == NULL) {
151954f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
152054f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
152154f98da9SMariusz Zaborski 	} else {
152230740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
152354f98da9SMariusz Zaborski 	}
152454f98da9SMariusz Zaborski }
152554f98da9SMariusz Zaborski 
152654f98da9SMariusz Zaborski void
nvlist_add_binary(nvlist_t * nvl,const char * name,const void * value,size_t size)152754f98da9SMariusz Zaborski nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
152854f98da9SMariusz Zaborski     size_t size)
152954f98da9SMariusz Zaborski {
153054f98da9SMariusz Zaborski 	nvpair_t *nvp;
153154f98da9SMariusz Zaborski 
153254f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
153354f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
153454f98da9SMariusz Zaborski 		return;
153554f98da9SMariusz Zaborski 	}
153654f98da9SMariusz Zaborski 
153754f98da9SMariusz Zaborski 	nvp = nvpair_create_binary(name, value, size);
153854f98da9SMariusz Zaborski 	if (nvp == NULL) {
153954f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
154054f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
154154f98da9SMariusz Zaborski 	} else {
154230740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
154354f98da9SMariusz Zaborski 	}
154454f98da9SMariusz Zaborski }
154554f98da9SMariusz Zaborski 
154654f98da9SMariusz Zaborski 
154754f98da9SMariusz Zaborski #define	NVLIST_ADD(vtype, type)						\
154854f98da9SMariusz Zaborski void									\
154954f98da9SMariusz Zaborski nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value)		\
155054f98da9SMariusz Zaborski {									\
155154f98da9SMariusz Zaborski 	nvpair_t *nvp;							\
155254f98da9SMariusz Zaborski 									\
155354f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {					\
155454f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));				\
155554f98da9SMariusz Zaborski 		return;							\
155654f98da9SMariusz Zaborski 	}								\
155754f98da9SMariusz Zaborski 									\
155854f98da9SMariusz Zaborski 	nvp = nvpair_create_##type(name, value);			\
155954f98da9SMariusz Zaborski 	if (nvp == NULL) {						\
156054f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);		\
156154f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);				\
156254f98da9SMariusz Zaborski 	} else {							\
156330740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);			\
156454f98da9SMariusz Zaborski 	}								\
156554f98da9SMariusz Zaborski }
156654f98da9SMariusz Zaborski 
156754f98da9SMariusz Zaborski NVLIST_ADD(bool, bool)
156854f98da9SMariusz Zaborski NVLIST_ADD(uint64_t, number)
156954f98da9SMariusz Zaborski NVLIST_ADD(const char *, string)
157054f98da9SMariusz Zaborski NVLIST_ADD(const nvlist_t *, nvlist)
157154f98da9SMariusz Zaborski #ifndef _KERNEL
157254f98da9SMariusz Zaborski NVLIST_ADD(int, descriptor);
157354f98da9SMariusz Zaborski #endif
157454f98da9SMariusz Zaborski 
157554f98da9SMariusz Zaborski #undef	NVLIST_ADD
157654f98da9SMariusz Zaborski 
1577347a39b4SMariusz Zaborski #define	NVLIST_ADD_ARRAY(vtype, type)					\
1578347a39b4SMariusz Zaborski void									\
1579347a39b4SMariusz Zaborski nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value,	\
1580347a39b4SMariusz Zaborski     size_t nitems)							\
1581347a39b4SMariusz Zaborski {									\
1582347a39b4SMariusz Zaborski 	nvpair_t *nvp;							\
1583347a39b4SMariusz Zaborski 									\
1584347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {					\
1585347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));				\
1586347a39b4SMariusz Zaborski 		return;							\
1587347a39b4SMariusz Zaborski 	}								\
1588347a39b4SMariusz Zaborski 									\
1589347a39b4SMariusz Zaborski 	nvp = nvpair_create_##type##_array(name, value, nitems);	\
1590347a39b4SMariusz Zaborski 	if (nvp == NULL) {						\
1591347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);		\
1592347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);				\
1593347a39b4SMariusz Zaborski 	} else {							\
1594347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);			\
1595347a39b4SMariusz Zaborski 	}								\
1596347a39b4SMariusz Zaborski }
1597347a39b4SMariusz Zaborski 
NVLIST_ADD_ARRAY(const bool *,bool)1598347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const bool *, bool)
1599347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const uint64_t *, number)
1600347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const char * const *, string)
1601347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist)
1602347a39b4SMariusz Zaborski #ifndef _KERNEL
1603347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const int *, descriptor)
1604347a39b4SMariusz Zaborski #endif
1605347a39b4SMariusz Zaborski 
1606347a39b4SMariusz Zaborski #undef	NVLIST_ADD_ARRAY
1607347a39b4SMariusz Zaborski 
160824881c06SMariusz Zaborski #define	NVLIST_APPEND_ARRAY(vtype, type, TYPE)				\
160924881c06SMariusz Zaborski void									\
161024881c06SMariusz Zaborski nvlist_append_##type##_array(nvlist_t *nvl, const char *name, vtype value)\
161124881c06SMariusz Zaborski {									\
161224881c06SMariusz Zaborski 	nvpair_t *nvp;							\
161324881c06SMariusz Zaborski 									\
161424881c06SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {					\
161524881c06SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));				\
161624881c06SMariusz Zaborski 		return;							\
161724881c06SMariusz Zaborski 	}								\
161824881c06SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);		\
161924881c06SMariusz Zaborski 	if (nvp == NULL) {						\
162024881c06SMariusz Zaborski 		nvlist_add_##type##_array(nvl, name, &value, 1);	\
162124881c06SMariusz Zaborski 		return;							\
162224881c06SMariusz Zaborski 	}								\
162389d5cbb8SMariusz Zaborski 	nvlist_update_size(nvl, nvp, -1);				\
162424881c06SMariusz Zaborski 	if (nvpair_append_##type##_array(nvp, value) == -1) {		\
162524881c06SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);		\
162624881c06SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);				\
162724881c06SMariusz Zaborski 	}								\
162889d5cbb8SMariusz Zaborski 	nvlist_update_size(nvl, nvp, 1);				\
162924881c06SMariusz Zaborski }
163024881c06SMariusz Zaborski 
163124881c06SMariusz Zaborski NVLIST_APPEND_ARRAY(const bool, bool, BOOL)
163224881c06SMariusz Zaborski NVLIST_APPEND_ARRAY(const uint64_t, number, NUMBER)
163324881c06SMariusz Zaborski NVLIST_APPEND_ARRAY(const char *, string, STRING)
163424881c06SMariusz Zaborski NVLIST_APPEND_ARRAY(const nvlist_t *, nvlist, NVLIST)
163524881c06SMariusz Zaborski #ifndef _KERNEL
163624881c06SMariusz Zaborski NVLIST_APPEND_ARRAY(const int, descriptor, DESCRIPTOR)
163724881c06SMariusz Zaborski #endif
163824881c06SMariusz Zaborski 
163924881c06SMariusz Zaborski #undef	NVLIST_APPEND_ARRAY
164024881c06SMariusz Zaborski 
164130740f45SMariusz Zaborski bool
164254f98da9SMariusz Zaborski nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
164354f98da9SMariusz Zaborski {
164454f98da9SMariusz Zaborski 
164554f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
164654f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
164754f98da9SMariusz Zaborski 
164854f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
164954f98da9SMariusz Zaborski 		nvpair_free(nvp);
165054f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
165130740f45SMariusz Zaborski 		return (false);
165254f98da9SMariusz Zaborski 	}
165354f98da9SMariusz Zaborski 	if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
165454f98da9SMariusz Zaborski 		if (nvlist_exists(nvl, nvpair_name(nvp))) {
165554f98da9SMariusz Zaborski 			nvpair_free(nvp);
165654f98da9SMariusz Zaborski 			nvl->nvl_error = EEXIST;
165754f98da9SMariusz Zaborski 			ERRNO_SET(nvl->nvl_error);
165830740f45SMariusz Zaborski 			return (false);
165954f98da9SMariusz Zaborski 		}
166054f98da9SMariusz Zaborski 	}
166154f98da9SMariusz Zaborski 
166254f98da9SMariusz Zaborski 	nvpair_insert(&nvl->nvl_head, nvp, nvl);
166389d5cbb8SMariusz Zaborski 	nvlist_update_size(nvl, nvp, 1);
166430740f45SMariusz Zaborski 	return (true);
166554f98da9SMariusz Zaborski }
166654f98da9SMariusz Zaborski 
166754f98da9SMariusz Zaborski void
nvlist_move_string(nvlist_t * nvl,const char * name,char * value)166854f98da9SMariusz Zaborski nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
166954f98da9SMariusz Zaborski {
167054f98da9SMariusz Zaborski 	nvpair_t *nvp;
167154f98da9SMariusz Zaborski 
167254f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
167354f98da9SMariusz Zaborski 		nv_free(value);
167454f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
167554f98da9SMariusz Zaborski 		return;
167654f98da9SMariusz Zaborski 	}
167754f98da9SMariusz Zaborski 
167854f98da9SMariusz Zaborski 	nvp = nvpair_move_string(name, value);
167954f98da9SMariusz Zaborski 	if (nvp == NULL) {
168054f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
168154f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
168254f98da9SMariusz Zaborski 	} else {
168330740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
168454f98da9SMariusz Zaborski 	}
168554f98da9SMariusz Zaborski }
168654f98da9SMariusz Zaborski 
168754f98da9SMariusz Zaborski void
nvlist_move_nvlist(nvlist_t * nvl,const char * name,nvlist_t * value)168854f98da9SMariusz Zaborski nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
168954f98da9SMariusz Zaborski {
169054f98da9SMariusz Zaborski 	nvpair_t *nvp;
169154f98da9SMariusz Zaborski 
169254f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
169354f98da9SMariusz Zaborski 		if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
169454f98da9SMariusz Zaborski 			nvlist_destroy(value);
169554f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
169654f98da9SMariusz Zaborski 		return;
169754f98da9SMariusz Zaborski 	}
169854f98da9SMariusz Zaborski 
169954f98da9SMariusz Zaborski 	nvp = nvpair_move_nvlist(name, value);
170054f98da9SMariusz Zaborski 	if (nvp == NULL) {
170154f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
170254f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
170354f98da9SMariusz Zaborski 	} else {
170430740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
170554f98da9SMariusz Zaborski 	}
170654f98da9SMariusz Zaborski }
170754f98da9SMariusz Zaborski 
170854f98da9SMariusz Zaborski #ifndef _KERNEL
170954f98da9SMariusz Zaborski void
nvlist_move_descriptor(nvlist_t * nvl,const char * name,int value)171054f98da9SMariusz Zaborski nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
171154f98da9SMariusz Zaborski {
171254f98da9SMariusz Zaborski 	nvpair_t *nvp;
171354f98da9SMariusz Zaborski 
171454f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
171554f98da9SMariusz Zaborski 		close(value);
171654f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
171754f98da9SMariusz Zaborski 		return;
171854f98da9SMariusz Zaborski 	}
171954f98da9SMariusz Zaborski 
172054f98da9SMariusz Zaborski 	nvp = nvpair_move_descriptor(name, value);
172154f98da9SMariusz Zaborski 	if (nvp == NULL) {
172254f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
172354f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
172454f98da9SMariusz Zaborski 	} else {
172530740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
172654f98da9SMariusz Zaborski 	}
172754f98da9SMariusz Zaborski }
172854f98da9SMariusz Zaborski #endif
172954f98da9SMariusz Zaborski 
173054f98da9SMariusz Zaborski void
nvlist_move_binary(nvlist_t * nvl,const char * name,void * value,size_t size)173154f98da9SMariusz Zaborski nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
173254f98da9SMariusz Zaborski {
173354f98da9SMariusz Zaborski 	nvpair_t *nvp;
173454f98da9SMariusz Zaborski 
173554f98da9SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
173654f98da9SMariusz Zaborski 		nv_free(value);
173754f98da9SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
173854f98da9SMariusz Zaborski 		return;
173954f98da9SMariusz Zaborski 	}
174054f98da9SMariusz Zaborski 
174154f98da9SMariusz Zaborski 	nvp = nvpair_move_binary(name, value, size);
174254f98da9SMariusz Zaborski 	if (nvp == NULL) {
174354f98da9SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
174454f98da9SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
174554f98da9SMariusz Zaborski 	} else {
174630740f45SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
174754f98da9SMariusz Zaborski 	}
174854f98da9SMariusz Zaborski }
174954f98da9SMariusz Zaborski 
1750347a39b4SMariusz Zaborski void
nvlist_move_bool_array(nvlist_t * nvl,const char * name,bool * value,size_t nitems)1751347a39b4SMariusz Zaborski nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value,
1752347a39b4SMariusz Zaborski     size_t nitems)
1753347a39b4SMariusz Zaborski {
1754347a39b4SMariusz Zaborski 	nvpair_t *nvp;
1755347a39b4SMariusz Zaborski 
1756347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
1757347a39b4SMariusz Zaborski 		nv_free(value);
1758347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
1759347a39b4SMariusz Zaborski 		return;
1760347a39b4SMariusz Zaborski 	}
1761347a39b4SMariusz Zaborski 
1762347a39b4SMariusz Zaborski 	nvp = nvpair_move_bool_array(name, value, nitems);
1763347a39b4SMariusz Zaborski 	if (nvp == NULL) {
1764347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1765347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
1766347a39b4SMariusz Zaborski 	} else {
1767347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
1768347a39b4SMariusz Zaborski 	}
1769347a39b4SMariusz Zaborski }
1770347a39b4SMariusz Zaborski 
1771347a39b4SMariusz Zaborski void
nvlist_move_string_array(nvlist_t * nvl,const char * name,char ** value,size_t nitems)1772347a39b4SMariusz Zaborski nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value,
1773347a39b4SMariusz Zaborski     size_t nitems)
1774347a39b4SMariusz Zaborski {
1775347a39b4SMariusz Zaborski 	nvpair_t *nvp;
1776347a39b4SMariusz Zaborski 	size_t i;
1777347a39b4SMariusz Zaborski 
1778347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
1779347a39b4SMariusz Zaborski 		if (value != NULL) {
1780347a39b4SMariusz Zaborski 			for (i = 0; i < nitems; i++)
1781347a39b4SMariusz Zaborski 				nv_free(value[i]);
1782347a39b4SMariusz Zaborski 			nv_free(value);
1783347a39b4SMariusz Zaborski 		}
1784347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
1785347a39b4SMariusz Zaborski 		return;
1786347a39b4SMariusz Zaborski 	}
1787347a39b4SMariusz Zaborski 
1788347a39b4SMariusz Zaborski 	nvp = nvpair_move_string_array(name, value, nitems);
1789347a39b4SMariusz Zaborski 	if (nvp == NULL) {
1790347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1791347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
1792347a39b4SMariusz Zaborski 	} else {
1793347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
1794347a39b4SMariusz Zaborski 	}
1795347a39b4SMariusz Zaborski }
1796347a39b4SMariusz Zaborski 
1797347a39b4SMariusz Zaborski void
nvlist_move_nvlist_array(nvlist_t * nvl,const char * name,nvlist_t ** value,size_t nitems)1798347a39b4SMariusz Zaborski nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value,
1799347a39b4SMariusz Zaborski     size_t nitems)
1800347a39b4SMariusz Zaborski {
1801347a39b4SMariusz Zaborski 	nvpair_t *nvp;
1802347a39b4SMariusz Zaborski 	size_t i;
1803347a39b4SMariusz Zaborski 
1804347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
1805347a39b4SMariusz Zaborski 		if (value != NULL) {
1806347a39b4SMariusz Zaborski 			for (i = 0; i < nitems; i++) {
1807347a39b4SMariusz Zaborski 				if (nvlist_get_pararr(value[i], NULL) == NULL)
1808347a39b4SMariusz Zaborski 					nvlist_destroy(value[i]);
1809347a39b4SMariusz Zaborski 			}
1810347a39b4SMariusz Zaborski 		}
1811347a39b4SMariusz Zaborski 		nv_free(value);
1812347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
1813347a39b4SMariusz Zaborski 		return;
1814347a39b4SMariusz Zaborski 	}
1815347a39b4SMariusz Zaborski 
1816347a39b4SMariusz Zaborski 	nvp = nvpair_move_nvlist_array(name, value, nitems);
1817347a39b4SMariusz Zaborski 	if (nvp == NULL) {
1818347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1819347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
1820347a39b4SMariusz Zaborski 	} else {
1821347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
1822347a39b4SMariusz Zaborski 	}
1823347a39b4SMariusz Zaborski }
1824347a39b4SMariusz Zaborski 
1825347a39b4SMariusz Zaborski void
nvlist_move_number_array(nvlist_t * nvl,const char * name,uint64_t * value,size_t nitems)1826347a39b4SMariusz Zaborski nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value,
1827347a39b4SMariusz Zaborski     size_t nitems)
1828347a39b4SMariusz Zaborski {
1829347a39b4SMariusz Zaborski 	nvpair_t *nvp;
1830347a39b4SMariusz Zaborski 
1831347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
1832347a39b4SMariusz Zaborski 		nv_free(value);
1833347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
1834347a39b4SMariusz Zaborski 		return;
1835347a39b4SMariusz Zaborski 	}
1836347a39b4SMariusz Zaborski 
1837347a39b4SMariusz Zaborski 	nvp = nvpair_move_number_array(name, value, nitems);
1838347a39b4SMariusz Zaborski 	if (nvp == NULL) {
1839347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1840347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
1841347a39b4SMariusz Zaborski 	} else {
1842347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
1843347a39b4SMariusz Zaborski 	}
1844347a39b4SMariusz Zaborski }
1845347a39b4SMariusz Zaborski 
1846347a39b4SMariusz Zaborski #ifndef _KERNEL
1847347a39b4SMariusz Zaborski void
nvlist_move_descriptor_array(nvlist_t * nvl,const char * name,int * value,size_t nitems)1848347a39b4SMariusz Zaborski nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value,
1849347a39b4SMariusz Zaborski     size_t nitems)
1850347a39b4SMariusz Zaborski {
1851347a39b4SMariusz Zaborski 	nvpair_t *nvp;
1852347a39b4SMariusz Zaborski 	size_t i;
1853347a39b4SMariusz Zaborski 
1854347a39b4SMariusz Zaborski 	if (nvlist_error(nvl) != 0) {
1855347a39b4SMariusz Zaborski 		if (value != 0) {
1856347a39b4SMariusz Zaborski 			for (i = 0; i < nitems; i++)
1857347a39b4SMariusz Zaborski 				close(value[i]);
1858347a39b4SMariusz Zaborski 			nv_free(value);
1859347a39b4SMariusz Zaborski 		}
1860347a39b4SMariusz Zaborski 
1861347a39b4SMariusz Zaborski 		ERRNO_SET(nvlist_error(nvl));
1862347a39b4SMariusz Zaborski 		return;
1863347a39b4SMariusz Zaborski 	}
1864347a39b4SMariusz Zaborski 
1865347a39b4SMariusz Zaborski 	nvp = nvpair_move_descriptor_array(name, value, nitems);
1866347a39b4SMariusz Zaborski 	if (nvp == NULL) {
1867347a39b4SMariusz Zaborski 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1868347a39b4SMariusz Zaborski 		ERRNO_SET(nvl->nvl_error);
1869347a39b4SMariusz Zaborski 	} else {
1870347a39b4SMariusz Zaborski 		(void)nvlist_move_nvpair(nvl, nvp);
1871347a39b4SMariusz Zaborski 	}
1872347a39b4SMariusz Zaborski }
1873347a39b4SMariusz Zaborski #endif
1874347a39b4SMariusz Zaborski 
187554f98da9SMariusz Zaborski const nvpair_t *
nvlist_get_nvpair(const nvlist_t * nvl,const char * name)187654f98da9SMariusz Zaborski nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
187754f98da9SMariusz Zaborski {
187854f98da9SMariusz Zaborski 
187954f98da9SMariusz Zaborski 	return (nvlist_find(nvl, NV_TYPE_NONE, name));
188054f98da9SMariusz Zaborski }
188154f98da9SMariusz Zaborski 
188254f98da9SMariusz Zaborski #define	NVLIST_GET(ftype, type, TYPE)					\
188354f98da9SMariusz Zaborski ftype									\
188454f98da9SMariusz Zaborski nvlist_get_##type(const nvlist_t *nvl, const char *name)		\
188554f98da9SMariusz Zaborski {									\
188654f98da9SMariusz Zaborski 	const nvpair_t *nvp;						\
188754f98da9SMariusz Zaborski 									\
188854f98da9SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
188954f98da9SMariusz Zaborski 	if (nvp == NULL)						\
189054f98da9SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
189154f98da9SMariusz Zaborski 	return (nvpair_get_##type(nvp));				\
189254f98da9SMariusz Zaborski }
189354f98da9SMariusz Zaborski 
NVLIST_GET(bool,bool,BOOL)189454f98da9SMariusz Zaborski NVLIST_GET(bool, bool, BOOL)
189554f98da9SMariusz Zaborski NVLIST_GET(uint64_t, number, NUMBER)
189654f98da9SMariusz Zaborski NVLIST_GET(const char *, string, STRING)
189754f98da9SMariusz Zaborski NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
189854f98da9SMariusz Zaborski #ifndef _KERNEL
189954f98da9SMariusz Zaborski NVLIST_GET(int, descriptor, DESCRIPTOR)
190054f98da9SMariusz Zaborski #endif
190154f98da9SMariusz Zaborski 
190254f98da9SMariusz Zaborski #undef	NVLIST_GET
190354f98da9SMariusz Zaborski 
190454f98da9SMariusz Zaborski const void *
190554f98da9SMariusz Zaborski nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
190654f98da9SMariusz Zaborski {
190754f98da9SMariusz Zaborski 	nvpair_t *nvp;
190854f98da9SMariusz Zaborski 
190954f98da9SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
191054f98da9SMariusz Zaborski 	if (nvp == NULL)
191154f98da9SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_BINARY, name);
191254f98da9SMariusz Zaborski 
191354f98da9SMariusz Zaborski 	return (nvpair_get_binary(nvp, sizep));
191454f98da9SMariusz Zaborski }
191554f98da9SMariusz Zaborski 
1916347a39b4SMariusz Zaborski #define	NVLIST_GET_ARRAY(ftype, type, TYPE)				\
1917347a39b4SMariusz Zaborski ftype									\
1918347a39b4SMariusz Zaborski nvlist_get_##type##_array(const nvlist_t *nvl, const char *name,	\
1919347a39b4SMariusz Zaborski     size_t *nitems)							\
1920347a39b4SMariusz Zaborski {									\
1921347a39b4SMariusz Zaborski 	const nvpair_t *nvp;						\
1922347a39b4SMariusz Zaborski 									\
1923347a39b4SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);		\
1924347a39b4SMariusz Zaborski 	if (nvp == NULL)						\
1925347a39b4SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name);	\
1926347a39b4SMariusz Zaborski 	return (nvpair_get_##type##_array(nvp, nitems));		\
1927347a39b4SMariusz Zaborski }
1928347a39b4SMariusz Zaborski 
NVLIST_GET_ARRAY(const bool *,bool,BOOL)1929347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const bool *, bool, BOOL)
1930347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER)
1931347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const char * const *, string, STRING)
1932347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST)
1933347a39b4SMariusz Zaborski #ifndef _KERNEL
1934347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR)
1935347a39b4SMariusz Zaborski #endif
1936347a39b4SMariusz Zaborski 
1937347a39b4SMariusz Zaborski #undef	NVLIST_GET_ARRAY
1938347a39b4SMariusz Zaborski 
193954f98da9SMariusz Zaborski #define	NVLIST_TAKE(ftype, type, TYPE)					\
194054f98da9SMariusz Zaborski ftype									\
194154f98da9SMariusz Zaborski nvlist_take_##type(nvlist_t *nvl, const char *name)			\
194254f98da9SMariusz Zaborski {									\
194354f98da9SMariusz Zaborski 	nvpair_t *nvp;							\
194454f98da9SMariusz Zaborski 	ftype value;							\
194554f98da9SMariusz Zaborski 									\
194654f98da9SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
194754f98da9SMariusz Zaborski 	if (nvp == NULL)						\
194854f98da9SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
194954f98da9SMariusz Zaborski 	value = (ftype)(intptr_t)nvpair_get_##type(nvp);		\
195054f98da9SMariusz Zaborski 	nvlist_remove_nvpair(nvl, nvp);					\
195154f98da9SMariusz Zaborski 	nvpair_free_structure(nvp);					\
195254f98da9SMariusz Zaborski 	return (value);							\
195354f98da9SMariusz Zaborski }
195454f98da9SMariusz Zaborski 
195554f98da9SMariusz Zaborski NVLIST_TAKE(bool, bool, BOOL)
195654f98da9SMariusz Zaborski NVLIST_TAKE(uint64_t, number, NUMBER)
195754f98da9SMariusz Zaborski NVLIST_TAKE(char *, string, STRING)
195854f98da9SMariusz Zaborski NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
195954f98da9SMariusz Zaborski #ifndef _KERNEL
196054f98da9SMariusz Zaborski NVLIST_TAKE(int, descriptor, DESCRIPTOR)
196154f98da9SMariusz Zaborski #endif
196254f98da9SMariusz Zaborski 
196354f98da9SMariusz Zaborski #undef	NVLIST_TAKE
196454f98da9SMariusz Zaborski 
196554f98da9SMariusz Zaborski void *
196654f98da9SMariusz Zaborski nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
196754f98da9SMariusz Zaborski {
196854f98da9SMariusz Zaborski 	nvpair_t *nvp;
196954f98da9SMariusz Zaborski 	void *value;
197054f98da9SMariusz Zaborski 
197154f98da9SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
197254f98da9SMariusz Zaborski 	if (nvp == NULL)
197354f98da9SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_BINARY, name);
197454f98da9SMariusz Zaborski 
197554f98da9SMariusz Zaborski 	value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
197654f98da9SMariusz Zaborski 	nvlist_remove_nvpair(nvl, nvp);
197754f98da9SMariusz Zaborski 	nvpair_free_structure(nvp);
197854f98da9SMariusz Zaborski 	return (value);
197954f98da9SMariusz Zaborski }
198054f98da9SMariusz Zaborski 
1981347a39b4SMariusz Zaborski #define	NVLIST_TAKE_ARRAY(ftype, type, TYPE)				\
1982347a39b4SMariusz Zaborski ftype									\
1983347a39b4SMariusz Zaborski nvlist_take_##type##_array(nvlist_t *nvl, const char *name,		\
1984347a39b4SMariusz Zaborski     size_t *nitems)							\
1985347a39b4SMariusz Zaborski {									\
1986347a39b4SMariusz Zaborski 	nvpair_t *nvp;							\
1987347a39b4SMariusz Zaborski 	ftype value;							\
1988347a39b4SMariusz Zaborski 									\
1989347a39b4SMariusz Zaborski 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);		\
1990347a39b4SMariusz Zaborski 	if (nvp == NULL)						\
1991347a39b4SMariusz Zaborski 		nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name);	\
1992347a39b4SMariusz Zaborski 	value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\
1993347a39b4SMariusz Zaborski 	nvlist_remove_nvpair(nvl, nvp);					\
1994347a39b4SMariusz Zaborski 	nvpair_free_structure(nvp);					\
1995347a39b4SMariusz Zaborski 	return (value);							\
1996347a39b4SMariusz Zaborski }
1997347a39b4SMariusz Zaborski 
NVLIST_TAKE_ARRAY(bool *,bool,BOOL)1998347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(bool *, bool, BOOL)
1999347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER)
2000347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(char **, string, STRING)
2001347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST)
2002347a39b4SMariusz Zaborski #ifndef _KERNEL
2003347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR)
2004347a39b4SMariusz Zaborski #endif
2005347a39b4SMariusz Zaborski 
200654f98da9SMariusz Zaborski void
200754f98da9SMariusz Zaborski nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
200854f98da9SMariusz Zaborski {
200954f98da9SMariusz Zaborski 
201054f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
201154f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
201254f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
201354f98da9SMariusz Zaborski 
201454f98da9SMariusz Zaborski 	nvpair_remove(&nvl->nvl_head, nvp, nvl);
201589d5cbb8SMariusz Zaborski 	nvlist_update_size(nvl, nvp, -1);
201654f98da9SMariusz Zaborski }
201754f98da9SMariusz Zaborski 
201854f98da9SMariusz Zaborski void
nvlist_free(nvlist_t * nvl,const char * name)201954f98da9SMariusz Zaborski nvlist_free(nvlist_t *nvl, const char *name)
202054f98da9SMariusz Zaborski {
202154f98da9SMariusz Zaborski 
202254f98da9SMariusz Zaborski 	nvlist_free_type(nvl, name, NV_TYPE_NONE);
202354f98da9SMariusz Zaborski }
202454f98da9SMariusz Zaborski 
202554f98da9SMariusz Zaborski #define	NVLIST_FREE(type, TYPE)						\
202654f98da9SMariusz Zaborski void									\
202754f98da9SMariusz Zaborski nvlist_free_##type(nvlist_t *nvl, const char *name)			\
202854f98da9SMariusz Zaborski {									\
202954f98da9SMariusz Zaborski 									\
203054f98da9SMariusz Zaborski 	nvlist_free_type(nvl, name, NV_TYPE_##TYPE);			\
203154f98da9SMariusz Zaborski }
203254f98da9SMariusz Zaborski 
NVLIST_FREE(null,NULL)203354f98da9SMariusz Zaborski NVLIST_FREE(null, NULL)
203454f98da9SMariusz Zaborski NVLIST_FREE(bool, BOOL)
203554f98da9SMariusz Zaborski NVLIST_FREE(number, NUMBER)
203654f98da9SMariusz Zaborski NVLIST_FREE(string, STRING)
203754f98da9SMariusz Zaborski NVLIST_FREE(nvlist, NVLIST)
2038347a39b4SMariusz Zaborski NVLIST_FREE(binary, BINARY)
2039347a39b4SMariusz Zaborski NVLIST_FREE(bool_array, BOOL_ARRAY)
2040347a39b4SMariusz Zaborski NVLIST_FREE(number_array, NUMBER_ARRAY)
2041347a39b4SMariusz Zaborski NVLIST_FREE(string_array, STRING_ARRAY)
2042347a39b4SMariusz Zaborski NVLIST_FREE(nvlist_array, NVLIST_ARRAY)
204354f98da9SMariusz Zaborski #ifndef _KERNEL
204454f98da9SMariusz Zaborski NVLIST_FREE(descriptor, DESCRIPTOR)
2045347a39b4SMariusz Zaborski NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY)
204654f98da9SMariusz Zaborski #endif
204754f98da9SMariusz Zaborski 
204854f98da9SMariusz Zaborski #undef	NVLIST_FREE
204954f98da9SMariusz Zaborski 
205054f98da9SMariusz Zaborski void
205154f98da9SMariusz Zaborski nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
205254f98da9SMariusz Zaborski {
205354f98da9SMariusz Zaborski 
205454f98da9SMariusz Zaborski 	NVLIST_ASSERT(nvl);
205554f98da9SMariusz Zaborski 	NVPAIR_ASSERT(nvp);
205654f98da9SMariusz Zaborski 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
205754f98da9SMariusz Zaborski 
205854f98da9SMariusz Zaborski 	nvlist_remove_nvpair(nvl, nvp);
205954f98da9SMariusz Zaborski 	nvpair_free(nvp);
206054f98da9SMariusz Zaborski }
206154f98da9SMariusz Zaborski 
2062