subr_nvlist.c revision 279439
1258065Spjd/*-
2258065Spjd * Copyright (c) 2009-2013 The FreeBSD Foundation
3258065Spjd * All rights reserved.
4258065Spjd *
5258065Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from
6258065Spjd * the FreeBSD Foundation.
7258065Spjd *
8258065Spjd * Redistribution and use in source and binary forms, with or without
9258065Spjd * modification, are permitted provided that the following conditions
10258065Spjd * are met:
11258065Spjd * 1. Redistributions of source code must retain the above copyright
12258065Spjd *    notice, this list of conditions and the following disclaimer.
13258065Spjd * 2. Redistributions in binary form must reproduce the above copyright
14258065Spjd *    notice, this list of conditions and the following disclaimer in the
15258065Spjd *    documentation and/or other materials provided with the distribution.
16258065Spjd *
17258065Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18258065Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19258065Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20258065Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21258065Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22258065Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23258065Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24258065Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25258065Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26258065Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27258065Spjd * SUCH DAMAGE.
28258065Spjd */
29258065Spjd
30258065Spjd#include <sys/cdefs.h>
31258065Spjd__FBSDID("$FreeBSD: head/sys/kern/subr_nvlist.c 279439 2015-03-01 00:34:27Z rstone $");
32258065Spjd
33258065Spjd#include <sys/param.h>
34258065Spjd#include <sys/endian.h>
35258065Spjd#include <sys/queue.h>
36279438Srstone
37279438Srstone#ifdef _KERNEL
38279438Srstone
39279438Srstone#include <sys/errno.h>
40279438Srstone#include <sys/kernel.h>
41279438Srstone#include <sys/lock.h>
42279438Srstone#include <sys/malloc.h>
43279438Srstone#include <sys/systm.h>
44279438Srstone
45279438Srstone#include <machine/stdarg.h>
46279438Srstone
47279438Srstone#else
48258065Spjd#include <sys/socket.h>
49258065Spjd
50258065Spjd#include <errno.h>
51258065Spjd#include <stdarg.h>
52258065Spjd#include <stdbool.h>
53258065Spjd#include <stdint.h>
54258065Spjd#define	_WITH_DPRINTF
55258065Spjd#include <stdio.h>
56258065Spjd#include <stdlib.h>
57258065Spjd#include <string.h>
58258065Spjd#include <unistd.h>
59279439Srstone
60279439Srstone#include "msgio.h"
61279438Srstone#endif
62258065Spjd
63258065Spjd#ifdef HAVE_PJDLOG
64258065Spjd#include <pjdlog.h>
65258065Spjd#endif
66258065Spjd
67279439Srstone#include <sys/nv.h>
68279439Srstone#include <sys/nv_impl.h>
69279439Srstone#include <sys/nvlist_impl.h>
70279439Srstone#include <sys/nvpair_impl.h>
71258065Spjd
72258065Spjd#ifndef	HAVE_PJDLOG
73279438Srstone#ifdef _KERNEL
74279438Srstone#define	PJDLOG_ASSERT(...)		MPASS(__VA_ARGS__)
75279438Srstone#define	PJDLOG_RASSERT(expr, ...)	KASSERT(expr, (__VA_ARGS__))
76279438Srstone#define	PJDLOG_ABORT(...)		panic(__VA_ARGS__)
77279438Srstone#else
78258065Spjd#include <assert.h>
79258065Spjd#define	PJDLOG_ASSERT(...)		assert(__VA_ARGS__)
80258065Spjd#define	PJDLOG_RASSERT(expr, ...)	assert(expr)
81258065Spjd#define	PJDLOG_ABORT(...)		do {				\
82258065Spjd	fprintf(stderr, "%s:%u: ", __FILE__, __LINE__);			\
83258065Spjd	fprintf(stderr, __VA_ARGS__);					\
84258065Spjd	fprintf(stderr, "\n");						\
85258065Spjd	abort();							\
86258065Spjd} while (0)
87258065Spjd#endif
88279438Srstone#endif
89258065Spjd
90258065Spjd#define	NV_FLAG_PRIVATE_MASK	(NV_FLAG_BIG_ENDIAN)
91258065Spjd#define	NV_FLAG_PUBLIC_MASK	(NV_FLAG_IGNORE_CASE)
92258065Spjd#define	NV_FLAG_ALL_MASK	(NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
93258065Spjd
94258065Spjd#define	NVLIST_MAGIC	0x6e766c	/* "nvl" */
95258065Spjdstruct nvlist {
96271579Spjd	int		 nvl_magic;
97271579Spjd	int		 nvl_error;
98271579Spjd	int		 nvl_flags;
99271579Spjd	nvpair_t	*nvl_parent;
100271579Spjd	struct nvl_head	 nvl_head;
101258065Spjd};
102258065Spjd
103258065Spjd#define	NVLIST_ASSERT(nvl)	do {					\
104258065Spjd	PJDLOG_ASSERT((nvl) != NULL);					\
105258065Spjd	PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);		\
106258065Spjd} while (0)
107258065Spjd
108279438Srstone#ifdef _KERNEL
109279438SrstoneMALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
110279438Srstone#endif
111279438Srstone
112258065Spjd#define	NVPAIR_ASSERT(nvp)	nvpair_assert(nvp)
113258065Spjd
114258065Spjd#define	NVLIST_HEADER_MAGIC	0x6c
115258065Spjd#define	NVLIST_HEADER_VERSION	0x00
116258065Spjdstruct nvlist_header {
117258065Spjd	uint8_t		nvlh_magic;
118258065Spjd	uint8_t		nvlh_version;
119258065Spjd	uint8_t		nvlh_flags;
120258065Spjd	uint64_t	nvlh_descriptors;
121258065Spjd	uint64_t	nvlh_size;
122258065Spjd} __packed;
123258065Spjd
124258065Spjdnvlist_t *
125258065Spjdnvlist_create(int flags)
126258065Spjd{
127258065Spjd	nvlist_t *nvl;
128258065Spjd
129258065Spjd	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
130258065Spjd
131279438Srstone	nvl = nv_malloc(sizeof(*nvl));
132258065Spjd	nvl->nvl_error = 0;
133258065Spjd	nvl->nvl_flags = flags;
134271579Spjd	nvl->nvl_parent = NULL;
135258065Spjd	TAILQ_INIT(&nvl->nvl_head);
136258065Spjd	nvl->nvl_magic = NVLIST_MAGIC;
137258065Spjd
138258065Spjd	return (nvl);
139258065Spjd}
140258065Spjd
141258065Spjdvoid
142258065Spjdnvlist_destroy(nvlist_t *nvl)
143258065Spjd{
144258065Spjd	nvpair_t *nvp;
145258065Spjd	int serrno;
146258065Spjd
147258065Spjd	if (nvl == NULL)
148258065Spjd		return;
149258065Spjd
150279438Srstone	SAVE_ERRNO(serrno);
151258065Spjd
152258065Spjd	NVLIST_ASSERT(nvl);
153258065Spjd
154260222Spjd	while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
155258065Spjd		nvlist_remove_nvpair(nvl, nvp);
156260222Spjd		nvpair_free(nvp);
157260222Spjd	}
158258065Spjd	nvl->nvl_magic = 0;
159279438Srstone	nv_free(nvl);
160258065Spjd
161279438Srstone	RESTORE_ERRNO(serrno);
162258065Spjd}
163258065Spjd
164279434Srstonevoid
165279434Srstonenvlist_set_error(nvlist_t *nvl, int error)
166279434Srstone{
167279434Srstone
168279434Srstone	PJDLOG_ASSERT(error != 0);
169279434Srstone
170279434Srstone	/*
171279434Srstone	 * Check for error != 0 so that we don't do the wrong thing if somebody
172279434Srstone	 * tries to abuse this API when asserts are disabled.
173279434Srstone	 */
174279434Srstone	if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
175279434Srstone		nvl->nvl_error = error;
176279434Srstone}
177279434Srstone
178258065Spjdint
179258065Spjdnvlist_error(const nvlist_t *nvl)
180258065Spjd{
181258065Spjd
182258065Spjd	if (nvl == NULL)
183258065Spjd		return (ENOMEM);
184258065Spjd
185258065Spjd	NVLIST_ASSERT(nvl);
186258065Spjd
187258065Spjd	return (nvl->nvl_error);
188258065Spjd}
189258065Spjd
190271579Spjdnvpair_t *
191271579Spjdnvlist_get_nvpair_parent(const nvlist_t *nvl)
192271579Spjd{
193271579Spjd
194271579Spjd	NVLIST_ASSERT(nvl);
195271579Spjd
196271579Spjd	return (nvl->nvl_parent);
197271579Spjd}
198271579Spjd
199271579Spjdconst nvlist_t *
200277921Spjdnvlist_get_parent(const nvlist_t *nvl, void **cookiep)
201271579Spjd{
202277921Spjd	nvpair_t *nvp;
203271579Spjd
204271579Spjd	NVLIST_ASSERT(nvl);
205271579Spjd
206277921Spjd	nvp = nvl->nvl_parent;
207277921Spjd	if (cookiep != NULL)
208277921Spjd		*cookiep = nvp;
209277921Spjd	if (nvp == NULL)
210271579Spjd		return (NULL);
211271579Spjd
212277921Spjd	return (nvpair_nvlist(nvp));
213271579Spjd}
214271579Spjd
215271579Spjdvoid
216271579Spjdnvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
217271579Spjd{
218271579Spjd
219271579Spjd	NVLIST_ASSERT(nvl);
220271579Spjd
221271579Spjd	nvl->nvl_parent = parent;
222271579Spjd}
223271579Spjd
224258065Spjdbool
225258065Spjdnvlist_empty(const nvlist_t *nvl)
226258065Spjd{
227258065Spjd
228258065Spjd	NVLIST_ASSERT(nvl);
229258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
230258065Spjd
231258065Spjd	return (nvlist_first_nvpair(nvl) == NULL);
232258065Spjd}
233258065Spjd
234258065Spjdstatic void
235279435Srstonenvlist_report_missing(int type, const char *name)
236258065Spjd{
237258065Spjd
238258065Spjd	PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
239279435Srstone	    name, nvpair_type_string(type));
240258065Spjd}
241258065Spjd
242258065Spjdstatic nvpair_t *
243279435Srstonenvlist_find(const nvlist_t *nvl, int type, const char *name)
244258065Spjd{
245258065Spjd	nvpair_t *nvp;
246258065Spjd
247258065Spjd	NVLIST_ASSERT(nvl);
248258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
249258065Spjd	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
250258065Spjd	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
251258065Spjd
252258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
253258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
254258065Spjd		if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
255258065Spjd			continue;
256258065Spjd		if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
257258065Spjd			if (strcasecmp(nvpair_name(nvp), name) != 0)
258258065Spjd				continue;
259258065Spjd		} else {
260258065Spjd			if (strcmp(nvpair_name(nvp), name) != 0)
261258065Spjd				continue;
262258065Spjd		}
263258065Spjd		break;
264258065Spjd	}
265258065Spjd
266258065Spjd	if (nvp == NULL)
267279438Srstone		RESTORE_ERRNO(ENOENT);
268258065Spjd
269258065Spjd	return (nvp);
270258065Spjd}
271258065Spjd
272258065Spjdbool
273258065Spjdnvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
274258065Spjd{
275258065Spjd
276279435Srstone	NVLIST_ASSERT(nvl);
277279435Srstone	PJDLOG_ASSERT(nvl->nvl_error == 0);
278279435Srstone	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
279279435Srstone	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
280279435Srstone
281279435Srstone	return (nvlist_find(nvl, type, name) != NULL);
282258065Spjd}
283258065Spjd
284279438Srstone#ifndef _KERNEL
285258065Spjdbool
286258065Spjdnvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...)
287258065Spjd{
288258065Spjd	va_list nameap;
289258065Spjd	bool ret;
290258065Spjd
291258065Spjd	va_start(nameap, namefmt);
292258065Spjd	ret = nvlist_existsv_type(nvl, type, namefmt, nameap);
293258065Spjd	va_end(nameap);
294258065Spjd
295258065Spjd	return (ret);
296258065Spjd}
297258065Spjd
298258065Spjdbool
299258065Spjdnvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt,
300258065Spjd    va_list nameap)
301258065Spjd{
302279435Srstone	char *name;
303279435Srstone	bool exists;
304258065Spjd
305279438Srstone	nv_vasprintf(&name, namefmt, nameap);
306279435Srstone	if (name == NULL)
307279435Srstone		return (false);
308258065Spjd
309279435Srstone	exists = nvlist_exists_type(nvl, name, type);
310279438Srstone	nv_free(name);
311279435Srstone	return (exists);
312258065Spjd}
313279438Srstone#endif
314258065Spjd
315258065Spjdvoid
316258065Spjdnvlist_free_type(nvlist_t *nvl, const char *name, int type)
317258065Spjd{
318279435Srstone	nvpair_t *nvp;
319258065Spjd
320279435Srstone	NVLIST_ASSERT(nvl);
321279435Srstone	PJDLOG_ASSERT(nvl->nvl_error == 0);
322279435Srstone	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
323279435Srstone	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
324279435Srstone
325279435Srstone	nvp = nvlist_find(nvl, type, name);
326279435Srstone	if (nvp != NULL)
327279435Srstone		nvlist_free_nvpair(nvl, nvp);
328279435Srstone	else
329279435Srstone		nvlist_report_missing(type, name);
330258065Spjd}
331258065Spjd
332279438Srstone#ifndef _KERNEL
333258065Spjdvoid
334258065Spjdnvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...)
335258065Spjd{
336258065Spjd	va_list nameap;
337258065Spjd
338258065Spjd	va_start(nameap, namefmt);
339258065Spjd	nvlist_freev_type(nvl, type, namefmt, nameap);
340258065Spjd	va_end(nameap);
341258065Spjd}
342258065Spjd
343258065Spjdvoid
344258065Spjdnvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
345258065Spjd{
346279435Srstone	char *name;
347258065Spjd
348279438Srstone	nv_vasprintf(&name, namefmt, nameap);
349279435Srstone	if (name == NULL)
350279435Srstone		nvlist_report_missing(type, "<unknown>");
351279435Srstone	nvlist_free_type(nvl, name, type);
352279438Srstone	nv_free(name);
353258065Spjd}
354279438Srstone#endif
355258065Spjd
356258065Spjdnvlist_t *
357258065Spjdnvlist_clone(const nvlist_t *nvl)
358258065Spjd{
359258065Spjd	nvlist_t *newnvl;
360258065Spjd	nvpair_t *nvp, *newnvp;
361258065Spjd
362258065Spjd	NVLIST_ASSERT(nvl);
363258065Spjd
364258065Spjd	if (nvl->nvl_error != 0) {
365279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
366258065Spjd		return (NULL);
367258065Spjd	}
368258065Spjd
369258065Spjd	newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
370258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
371258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
372258065Spjd		newnvp = nvpair_clone(nvp);
373258065Spjd		if (newnvp == NULL)
374258065Spjd			break;
375258065Spjd		nvlist_move_nvpair(newnvl, newnvp);
376258065Spjd	}
377258065Spjd	if (nvp != NULL) {
378258065Spjd		nvlist_destroy(newnvl);
379258065Spjd		return (NULL);
380258065Spjd	}
381258065Spjd	return (newnvl);
382258065Spjd}
383258065Spjd
384279438Srstone#ifndef _KERNEL
385271579Spjdstatic bool
386271579Spjdnvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
387271579Spjd{
388271579Spjd
389271579Spjd	if (nvlist_error(nvl) != 0) {
390271579Spjd		dprintf(fd, "%*serror: %d\n", level * 4, "",
391271579Spjd		    nvlist_error(nvl));
392271579Spjd		return (true);
393271579Spjd	}
394271579Spjd
395271579Spjd	return (false);
396271579Spjd}
397271579Spjd
398258065Spjd/*
399258065Spjd * Dump content of nvlist.
400258065Spjd */
401271579Spjdvoid
402271579Spjdnvlist_dump(const nvlist_t *nvl, int fd)
403258065Spjd{
404277925Spjd	const nvlist_t *tmpnvl;
405277925Spjd	nvpair_t *nvp, *tmpnvp;
406277927Spjd	void *cookie;
407271579Spjd	int level;
408258065Spjd
409271579Spjd	level = 0;
410271579Spjd	if (nvlist_dump_error_check(nvl, fd, level))
411258065Spjd		return;
412258065Spjd
413271579Spjd	nvp = nvlist_first_nvpair(nvl);
414271579Spjd	while (nvp != NULL) {
415258065Spjd		dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
416258065Spjd		    nvpair_type_string(nvpair_type(nvp)));
417258065Spjd		switch (nvpair_type(nvp)) {
418258065Spjd		case NV_TYPE_NULL:
419258065Spjd			dprintf(fd, " null\n");
420258065Spjd			break;
421258065Spjd		case NV_TYPE_BOOL:
422258065Spjd			dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
423258065Spjd			    "TRUE" : "FALSE");
424258065Spjd			break;
425258065Spjd		case NV_TYPE_NUMBER:
426258065Spjd			dprintf(fd, " %ju (%jd) (0x%jx)\n",
427258065Spjd			    (uintmax_t)nvpair_get_number(nvp),
428258065Spjd			    (intmax_t)nvpair_get_number(nvp),
429258065Spjd			    (uintmax_t)nvpair_get_number(nvp));
430258065Spjd			break;
431258065Spjd		case NV_TYPE_STRING:
432258065Spjd			dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
433258065Spjd			break;
434258065Spjd		case NV_TYPE_NVLIST:
435258065Spjd			dprintf(fd, "\n");
436277925Spjd			tmpnvl = nvpair_get_nvlist(nvp);
437277925Spjd			if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
438271579Spjd				break;
439277925Spjd			tmpnvp = nvlist_first_nvpair(tmpnvl);
440277925Spjd			if (tmpnvp != NULL) {
441277925Spjd				nvl = tmpnvl;
442277925Spjd				nvp = tmpnvp;
443277925Spjd				level++;
444277925Spjd				continue;
445271579Spjd			}
446277925Spjd			break;
447258065Spjd		case NV_TYPE_DESCRIPTOR:
448258065Spjd			dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
449258065Spjd			break;
450258065Spjd		case NV_TYPE_BINARY:
451258065Spjd		    {
452258065Spjd			const unsigned char *binary;
453258065Spjd			unsigned int ii;
454258065Spjd			size_t size;
455258065Spjd
456258065Spjd			binary = nvpair_get_binary(nvp, &size);
457258065Spjd			dprintf(fd, " %zu ", size);
458258065Spjd			for (ii = 0; ii < size; ii++)
459258065Spjd				dprintf(fd, "%02hhx", binary[ii]);
460258065Spjd			dprintf(fd, "\n");
461258065Spjd			break;
462258065Spjd		    }
463258065Spjd		default:
464258065Spjd			PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
465258065Spjd		}
466271579Spjd
467271579Spjd		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
468277927Spjd			cookie = NULL;
469277927Spjd			nvl = nvlist_get_parent(nvl, &cookie);
470277921Spjd			if (nvl == NULL)
471271579Spjd				return;
472277927Spjd			nvp = cookie;
473277921Spjd			level--;
474271579Spjd		}
475258065Spjd	}
476258065Spjd}
477258065Spjd
478258065Spjdvoid
479258065Spjdnvlist_fdump(const nvlist_t *nvl, FILE *fp)
480258065Spjd{
481258065Spjd
482258065Spjd	fflush(fp);
483258065Spjd	nvlist_dump(nvl, fileno(fp));
484258065Spjd}
485279438Srstone#endif
486258065Spjd
487258065Spjd/*
488258065Spjd * The function obtains size of the nvlist after nvlist_pack().
489258065Spjd */
490271579Spjdsize_t
491271579Spjdnvlist_size(const nvlist_t *nvl)
492258065Spjd{
493277925Spjd	const nvlist_t *tmpnvl;
494277925Spjd	const nvpair_t *nvp, *tmpnvp;
495277927Spjd	void *cookie;
496258065Spjd	size_t size;
497258065Spjd
498258065Spjd	NVLIST_ASSERT(nvl);
499258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
500258065Spjd
501258065Spjd	size = sizeof(struct nvlist_header);
502271579Spjd	nvp = nvlist_first_nvpair(nvl);
503271579Spjd	while (nvp != NULL) {
504258065Spjd		size += nvpair_header_size();
505258065Spjd		size += strlen(nvpair_name(nvp)) + 1;
506271579Spjd		if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
507271579Spjd			size += sizeof(struct nvlist_header);
508271579Spjd			size += nvpair_header_size() + 1;
509277925Spjd			tmpnvl = nvpair_get_nvlist(nvp);
510277925Spjd			PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
511277925Spjd			tmpnvp = nvlist_first_nvpair(tmpnvl);
512277925Spjd			if (tmpnvp != NULL) {
513277925Spjd				nvl = tmpnvl;
514277925Spjd				nvp = tmpnvp;
515277925Spjd				continue;
516277925Spjd			}
517271579Spjd		} else {
518258065Spjd			size += nvpair_size(nvp);
519271579Spjd		}
520271579Spjd
521271579Spjd		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
522277927Spjd			cookie = NULL;
523277927Spjd			nvl = nvlist_get_parent(nvl, &cookie);
524277921Spjd			if (nvl == NULL)
525271579Spjd				goto out;
526277927Spjd			nvp = cookie;
527271579Spjd		}
528258065Spjd	}
529258065Spjd
530271579Spjdout:
531258065Spjd	return (size);
532258065Spjd}
533258065Spjd
534279438Srstone#ifndef _KERNEL
535258065Spjdstatic int *
536258065Spjdnvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
537258065Spjd{
538258065Spjd	const nvpair_t *nvp;
539258065Spjd
540258065Spjd	NVLIST_ASSERT(nvl);
541258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
542258065Spjd	PJDLOG_ASSERT(level < 3);
543258065Spjd
544258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
545258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
546258065Spjd		switch (nvpair_type(nvp)) {
547258065Spjd		case NV_TYPE_DESCRIPTOR:
548258065Spjd			*descs = nvpair_get_descriptor(nvp);
549258065Spjd			descs++;
550258065Spjd			break;
551258065Spjd		case NV_TYPE_NVLIST:
552258065Spjd			descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
553258065Spjd			    descs, level + 1);
554258065Spjd			break;
555258065Spjd		}
556258065Spjd	}
557258065Spjd
558258065Spjd	return (descs);
559258065Spjd}
560279438Srstone#endif
561258065Spjd
562279438Srstone#ifndef _KERNEL
563258065Spjdint *
564258065Spjdnvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
565258065Spjd{
566258065Spjd	size_t nitems;
567258065Spjd	int *fds;
568258065Spjd
569258065Spjd	nitems = nvlist_ndescriptors(nvl);
570279438Srstone	fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
571258065Spjd	if (fds == NULL)
572258065Spjd		return (NULL);
573258065Spjd	if (nitems > 0)
574258065Spjd		nvlist_xdescriptors(nvl, fds, 0);
575258065Spjd	fds[nitems] = -1;
576258065Spjd	if (nitemsp != NULL)
577258065Spjd		*nitemsp = nitems;
578258065Spjd	return (fds);
579258065Spjd}
580279438Srstone#endif
581258065Spjd
582258065Spjdstatic size_t
583258065Spjdnvlist_xndescriptors(const nvlist_t *nvl, int level)
584258065Spjd{
585279438Srstone#ifndef _KERNEL
586258065Spjd	const nvpair_t *nvp;
587258065Spjd	size_t ndescs;
588258065Spjd
589258065Spjd	NVLIST_ASSERT(nvl);
590258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
591258065Spjd	PJDLOG_ASSERT(level < 3);
592258065Spjd
593258065Spjd	ndescs = 0;
594258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
595258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
596258065Spjd		switch (nvpair_type(nvp)) {
597258065Spjd		case NV_TYPE_DESCRIPTOR:
598258065Spjd			ndescs++;
599258065Spjd			break;
600258065Spjd		case NV_TYPE_NVLIST:
601258065Spjd			ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
602258065Spjd			    level + 1);
603258065Spjd			break;
604258065Spjd		}
605258065Spjd	}
606258065Spjd
607258065Spjd	return (ndescs);
608279438Srstone#else
609279438Srstone	return (0);
610279438Srstone#endif
611258065Spjd}
612258065Spjd
613258065Spjdsize_t
614258065Spjdnvlist_ndescriptors(const nvlist_t *nvl)
615258065Spjd{
616258065Spjd
617258065Spjd	return (nvlist_xndescriptors(nvl, 0));
618258065Spjd}
619258065Spjd
620258065Spjdstatic unsigned char *
621258065Spjdnvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
622258065Spjd{
623258065Spjd	struct nvlist_header nvlhdr;
624258065Spjd
625258065Spjd	NVLIST_ASSERT(nvl);
626258065Spjd
627258065Spjd	nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
628258065Spjd	nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
629258065Spjd	nvlhdr.nvlh_flags = nvl->nvl_flags;
630258065Spjd#if BYTE_ORDER == BIG_ENDIAN
631258065Spjd	nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
632258065Spjd#endif
633258065Spjd	nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
634258065Spjd	nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
635258065Spjd	PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
636258065Spjd	memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
637258065Spjd	ptr += sizeof(nvlhdr);
638258065Spjd	*leftp -= sizeof(nvlhdr);
639258065Spjd
640258065Spjd	return (ptr);
641258065Spjd}
642258065Spjd
643258065Spjdvoid *
644258065Spjdnvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
645258065Spjd{
646258065Spjd	unsigned char *buf, *ptr;
647258065Spjd	size_t left, size;
648277925Spjd	const nvlist_t *tmpnvl;
649277925Spjd	nvpair_t *nvp, *tmpnvp;
650277927Spjd	void *cookie;
651258065Spjd
652258065Spjd	NVLIST_ASSERT(nvl);
653258065Spjd
654258065Spjd	if (nvl->nvl_error != 0) {
655279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
656258065Spjd		return (NULL);
657258065Spjd	}
658258065Spjd
659258065Spjd	size = nvlist_size(nvl);
660279438Srstone	buf = nv_malloc(size);
661258065Spjd	if (buf == NULL)
662258065Spjd		return (NULL);
663258065Spjd
664258065Spjd	ptr = buf;
665258065Spjd	left = size;
666258065Spjd
667258065Spjd	ptr = nvlist_pack_header(nvl, ptr, &left);
668258065Spjd
669271579Spjd	nvp = nvlist_first_nvpair(nvl);
670271579Spjd	while (nvp != NULL) {
671271579Spjd		NVPAIR_ASSERT(nvp);
672271579Spjd
673271579Spjd		nvpair_init_datasize(nvp);
674271579Spjd		ptr = nvpair_pack_header(nvp, ptr, &left);
675258065Spjd		if (ptr == NULL) {
676279438Srstone			nv_free(buf);
677258065Spjd			return (NULL);
678258065Spjd		}
679271579Spjd		switch (nvpair_type(nvp)) {
680271579Spjd		case NV_TYPE_NULL:
681271579Spjd			ptr = nvpair_pack_null(nvp, ptr, &left);
682271579Spjd			break;
683271579Spjd		case NV_TYPE_BOOL:
684271579Spjd			ptr = nvpair_pack_bool(nvp, ptr, &left);
685271579Spjd			break;
686271579Spjd		case NV_TYPE_NUMBER:
687271579Spjd			ptr = nvpair_pack_number(nvp, ptr, &left);
688271579Spjd			break;
689271579Spjd		case NV_TYPE_STRING:
690271579Spjd			ptr = nvpair_pack_string(nvp, ptr, &left);
691271579Spjd			break;
692271579Spjd		case NV_TYPE_NVLIST:
693277925Spjd			tmpnvl = nvpair_get_nvlist(nvp);
694277925Spjd			ptr = nvlist_pack_header(tmpnvl, ptr, &left);
695277925Spjd			if (ptr == NULL)
696277925Spjd				goto out;
697277925Spjd			tmpnvp = nvlist_first_nvpair(tmpnvl);
698277925Spjd			if (tmpnvp != NULL) {
699277925Spjd				nvl = tmpnvl;
700277925Spjd				nvp = tmpnvp;
701277925Spjd				continue;
702277925Spjd			}
703277925Spjd			ptr = nvpair_pack_nvlist_up(ptr, &left);
704277925Spjd			break;
705279438Srstone#ifndef _KERNEL
706271579Spjd		case NV_TYPE_DESCRIPTOR:
707271579Spjd			ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
708271579Spjd			break;
709279438Srstone#endif
710271579Spjd		case NV_TYPE_BINARY:
711271579Spjd			ptr = nvpair_pack_binary(nvp, ptr, &left);
712271579Spjd			break;
713271579Spjd		default:
714271579Spjd			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
715271579Spjd		}
716271579Spjd		if (ptr == NULL) {
717279438Srstone			nv_free(buf);
718271579Spjd			return (NULL);
719271579Spjd		}
720271579Spjd		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
721277927Spjd			cookie = NULL;
722277927Spjd			nvl = nvlist_get_parent(nvl, &cookie);
723277921Spjd			if (nvl == NULL)
724271579Spjd				goto out;
725277927Spjd			nvp = cookie;
726271579Spjd			ptr = nvpair_pack_nvlist_up(ptr, &left);
727271579Spjd			if (ptr == NULL)
728271579Spjd				goto out;
729271579Spjd		}
730258065Spjd	}
731258065Spjd
732271579Spjdout:
733258065Spjd	if (sizep != NULL)
734258065Spjd		*sizep = size;
735258065Spjd	return (buf);
736258065Spjd}
737258065Spjd
738258065Spjdvoid *
739258065Spjdnvlist_pack(const nvlist_t *nvl, size_t *sizep)
740258065Spjd{
741258065Spjd
742258065Spjd	NVLIST_ASSERT(nvl);
743258065Spjd
744258065Spjd	if (nvl->nvl_error != 0) {
745279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
746258065Spjd		return (NULL);
747258065Spjd	}
748258065Spjd
749258065Spjd	if (nvlist_ndescriptors(nvl) > 0) {
750279438Srstone		RESTORE_ERRNO(EOPNOTSUPP);
751258065Spjd		return (NULL);
752258065Spjd	}
753258065Spjd
754258065Spjd	return (nvlist_xpack(nvl, NULL, sizep));
755258065Spjd}
756258065Spjd
757258065Spjdstatic bool
758258065Spjdnvlist_check_header(struct nvlist_header *nvlhdrp)
759258065Spjd{
760258065Spjd
761258065Spjd	if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
762279438Srstone		RESTORE_ERRNO(EINVAL);
763258065Spjd		return (false);
764258065Spjd	}
765264021Sjilles	if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
766279438Srstone		RESTORE_ERRNO(EINVAL);
767258065Spjd		return (false);
768258065Spjd	}
769258065Spjd#if BYTE_ORDER == BIG_ENDIAN
770258065Spjd	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
771258065Spjd		nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
772258065Spjd		nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
773258065Spjd	}
774258065Spjd#else
775258065Spjd	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
776258065Spjd		nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
777258065Spjd		nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
778258065Spjd	}
779258065Spjd#endif
780258065Spjd	return (true);
781258065Spjd}
782258065Spjd
783271579Spjdconst unsigned char *
784258065Spjdnvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
785272843Spjd    bool *isbep, size_t *leftp)
786258065Spjd{
787258065Spjd	struct nvlist_header nvlhdr;
788258065Spjd
789258065Spjd	if (*leftp < sizeof(nvlhdr))
790258065Spjd		goto failed;
791258065Spjd
792258065Spjd	memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
793258065Spjd
794258065Spjd	if (!nvlist_check_header(&nvlhdr))
795258065Spjd		goto failed;
796258065Spjd
797258065Spjd	if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
798258065Spjd		goto failed;
799258065Spjd
800258065Spjd	/*
801258065Spjd	 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
802258065Spjd	 */
803258065Spjd	if (nvlhdr.nvlh_descriptors > nfds)
804258065Spjd		goto failed;
805258065Spjd
806258065Spjd	if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
807258065Spjd		goto failed;
808258065Spjd
809258065Spjd	nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
810258065Spjd
811258065Spjd	ptr += sizeof(nvlhdr);
812272843Spjd	if (isbep != NULL)
813272843Spjd		*isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
814258065Spjd	*leftp -= sizeof(nvlhdr);
815258065Spjd
816258065Spjd	return (ptr);
817258065Spjdfailed:
818279438Srstone	RESTORE_ERRNO(EINVAL);
819258065Spjd	return (NULL);
820258065Spjd}
821258065Spjd
822258065Spjdnvlist_t *
823258065Spjdnvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
824258065Spjd{
825258065Spjd	const unsigned char *ptr;
826271579Spjd	nvlist_t *nvl, *retnvl, *tmpnvl;
827258065Spjd	nvpair_t *nvp;
828258065Spjd	size_t left;
829272843Spjd	bool isbe;
830258065Spjd
831258065Spjd	left = size;
832258065Spjd	ptr = buf;
833258065Spjd
834271579Spjd	tmpnvl = NULL;
835271579Spjd	nvl = retnvl = nvlist_create(0);
836258065Spjd	if (nvl == NULL)
837258065Spjd		goto failed;
838258065Spjd
839272843Spjd	ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
840258065Spjd	if (ptr == NULL)
841258065Spjd		goto failed;
842258065Spjd
843258065Spjd	while (left > 0) {
844272843Spjd		ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
845258065Spjd		if (ptr == NULL)
846258065Spjd			goto failed;
847271579Spjd		switch (nvpair_type(nvp)) {
848271579Spjd		case NV_TYPE_NULL:
849272843Spjd			ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
850271579Spjd			break;
851271579Spjd		case NV_TYPE_BOOL:
852272843Spjd			ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
853271579Spjd			break;
854271579Spjd		case NV_TYPE_NUMBER:
855272843Spjd			ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
856271579Spjd			break;
857271579Spjd		case NV_TYPE_STRING:
858272843Spjd			ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
859271579Spjd			break;
860271579Spjd		case NV_TYPE_NVLIST:
861272843Spjd			ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
862272843Spjd			    &tmpnvl);
863271579Spjd			nvlist_set_parent(tmpnvl, nvp);
864271579Spjd			break;
865279438Srstone#ifndef _KERNEL
866271579Spjd		case NV_TYPE_DESCRIPTOR:
867272843Spjd			ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
868271579Spjd			    fds, nfds);
869271579Spjd			break;
870279438Srstone#endif
871271579Spjd		case NV_TYPE_BINARY:
872272843Spjd			ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
873271579Spjd			break;
874271579Spjd		case NV_TYPE_NVLIST_UP:
875271579Spjd			if (nvl->nvl_parent == NULL)
876271579Spjd				goto failed;
877271579Spjd			nvl = nvpair_nvlist(nvl->nvl_parent);
878271579Spjd			continue;
879271579Spjd		default:
880271579Spjd			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
881271579Spjd		}
882271579Spjd		if (ptr == NULL)
883271579Spjd			goto failed;
884258065Spjd		nvlist_move_nvpair(nvl, nvp);
885271579Spjd		if (tmpnvl != NULL) {
886271579Spjd			nvl = tmpnvl;
887271579Spjd			tmpnvl = NULL;
888271579Spjd		}
889258065Spjd	}
890258065Spjd
891271579Spjd	return (retnvl);
892258065Spjdfailed:
893271579Spjd	nvlist_destroy(retnvl);
894258065Spjd	return (NULL);
895258065Spjd}
896258065Spjd
897258065Spjdnvlist_t *
898258065Spjdnvlist_unpack(const void *buf, size_t size)
899258065Spjd{
900258065Spjd
901258065Spjd	return (nvlist_xunpack(buf, size, NULL, 0));
902258065Spjd}
903258065Spjd
904279438Srstone#ifndef _KERNEL
905258065Spjdint
906258065Spjdnvlist_send(int sock, const nvlist_t *nvl)
907258065Spjd{
908258065Spjd	size_t datasize, nfds;
909258065Spjd	int *fds;
910258065Spjd	void *data;
911258065Spjd	int64_t fdidx;
912258065Spjd	int serrno, ret;
913258065Spjd
914258065Spjd	if (nvlist_error(nvl) != 0) {
915258065Spjd		errno = nvlist_error(nvl);
916258065Spjd		return (-1);
917258065Spjd	}
918258065Spjd
919258065Spjd	fds = nvlist_descriptors(nvl, &nfds);
920258065Spjd	if (fds == NULL)
921258065Spjd		return (-1);
922258065Spjd
923258065Spjd	ret = -1;
924258065Spjd	data = NULL;
925258065Spjd	fdidx = 0;
926258065Spjd
927258065Spjd	data = nvlist_xpack(nvl, &fdidx, &datasize);
928258065Spjd	if (data == NULL)
929258065Spjd		goto out;
930258065Spjd
931258065Spjd	if (buf_send(sock, data, datasize) == -1)
932258065Spjd		goto out;
933258065Spjd
934258065Spjd	if (nfds > 0) {
935258065Spjd		if (fd_send(sock, fds, nfds) == -1)
936258065Spjd			goto out;
937258065Spjd	}
938258065Spjd
939258065Spjd	ret = 0;
940258065Spjdout:
941258065Spjd	serrno = errno;
942258065Spjd	free(fds);
943258065Spjd	free(data);
944258065Spjd	errno = serrno;
945258065Spjd	return (ret);
946258065Spjd}
947258065Spjd
948258065Spjdnvlist_t *
949258065Spjdnvlist_recv(int sock)
950258065Spjd{
951258065Spjd	struct nvlist_header nvlhdr;
952258065Spjd	nvlist_t *nvl, *ret;
953259430Spjd	unsigned char *buf;
954271028Spjd	size_t nfds, size, i;
955271028Spjd	int serrno, *fds;
956258065Spjd
957259430Spjd	if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
958258065Spjd		return (NULL);
959258065Spjd
960258065Spjd	if (!nvlist_check_header(&nvlhdr))
961258065Spjd		return (NULL);
962258065Spjd
963258065Spjd	nfds = (size_t)nvlhdr.nvlh_descriptors;
964258065Spjd	size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
965258065Spjd
966258065Spjd	buf = malloc(size);
967258065Spjd	if (buf == NULL)
968258065Spjd		return (NULL);
969258065Spjd
970259430Spjd	memcpy(buf, &nvlhdr, sizeof(nvlhdr));
971259430Spjd
972258065Spjd	ret = NULL;
973258065Spjd	fds = NULL;
974258065Spjd
975259430Spjd	if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
976258065Spjd		goto out;
977258065Spjd
978258065Spjd	if (nfds > 0) {
979258065Spjd		fds = malloc(nfds * sizeof(fds[0]));
980258065Spjd		if (fds == NULL)
981258065Spjd			goto out;
982258065Spjd		if (fd_recv(sock, fds, nfds) == -1)
983258065Spjd			goto out;
984258065Spjd	}
985258065Spjd
986258065Spjd	nvl = nvlist_xunpack(buf, size, fds, nfds);
987271026Spjd	if (nvl == NULL) {
988271026Spjd		for (i = 0; i < nfds; i++)
989271026Spjd			close(fds[i]);
990258065Spjd		goto out;
991271026Spjd	}
992258065Spjd
993258065Spjd	ret = nvl;
994258065Spjdout:
995258065Spjd	serrno = errno;
996258065Spjd	free(buf);
997258065Spjd	free(fds);
998258065Spjd	errno = serrno;
999258065Spjd
1000258065Spjd	return (ret);
1001258065Spjd}
1002258065Spjd
1003258065Spjdnvlist_t *
1004258065Spjdnvlist_xfer(int sock, nvlist_t *nvl)
1005258065Spjd{
1006258065Spjd
1007258065Spjd	if (nvlist_send(sock, nvl) < 0) {
1008258065Spjd		nvlist_destroy(nvl);
1009258065Spjd		return (NULL);
1010258065Spjd	}
1011258065Spjd	nvlist_destroy(nvl);
1012258065Spjd	return (nvlist_recv(sock));
1013258065Spjd}
1014279438Srstone#endif
1015258065Spjd
1016258065Spjdnvpair_t *
1017258065Spjdnvlist_first_nvpair(const nvlist_t *nvl)
1018258065Spjd{
1019258065Spjd
1020258065Spjd	NVLIST_ASSERT(nvl);
1021258065Spjd
1022258065Spjd	return (TAILQ_FIRST(&nvl->nvl_head));
1023258065Spjd}
1024258065Spjd
1025258065Spjdnvpair_t *
1026258065Spjdnvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1027258065Spjd{
1028258065Spjd	nvpair_t *retnvp;
1029258065Spjd
1030258065Spjd	NVLIST_ASSERT(nvl);
1031258065Spjd	NVPAIR_ASSERT(nvp);
1032258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1033258065Spjd
1034258065Spjd	retnvp = nvpair_next(nvp);
1035258065Spjd	PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1036258065Spjd
1037258065Spjd	return (retnvp);
1038258065Spjd
1039258065Spjd}
1040258065Spjd
1041258065Spjdnvpair_t *
1042258065Spjdnvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1043258065Spjd{
1044258065Spjd	nvpair_t *retnvp;
1045258065Spjd
1046258065Spjd	NVLIST_ASSERT(nvl);
1047258065Spjd	NVPAIR_ASSERT(nvp);
1048258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1049258065Spjd
1050258065Spjd	retnvp = nvpair_prev(nvp);
1051258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1052258065Spjd
1053258065Spjd	return (retnvp);
1054258065Spjd}
1055258065Spjd
1056258065Spjdconst char *
1057258065Spjdnvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1058258065Spjd{
1059258065Spjd	nvpair_t *nvp;
1060258065Spjd
1061258065Spjd	NVLIST_ASSERT(nvl);
1062258065Spjd	PJDLOG_ASSERT(cookiep != NULL);
1063258065Spjd
1064258065Spjd	if (*cookiep == NULL)
1065258065Spjd		nvp = nvlist_first_nvpair(nvl);
1066258065Spjd	else
1067258065Spjd		nvp = nvlist_next_nvpair(nvl, *cookiep);
1068258065Spjd	if (nvp == NULL)
1069258065Spjd		return (NULL);
1070258065Spjd	if (typep != NULL)
1071258065Spjd		*typep = nvpair_type(nvp);
1072258065Spjd	*cookiep = nvp;
1073258065Spjd	return (nvpair_name(nvp));
1074258065Spjd}
1075258065Spjd
1076258065Spjdbool
1077258065Spjdnvlist_exists(const nvlist_t *nvl, const char *name)
1078258065Spjd{
1079258065Spjd
1080279435Srstone	return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1081258065Spjd}
1082258065Spjd
1083279435Srstone#define	NVLIST_EXISTS(type, TYPE)					\
1084258065Spjdbool									\
1085258065Spjdnvlist_exists_##type(const nvlist_t *nvl, const char *name)		\
1086258065Spjd{									\
1087258065Spjd									\
1088279435Srstone	return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL);	\
1089258065Spjd}
1090258065Spjd
1091279435SrstoneNVLIST_EXISTS(null, NULL)
1092279435SrstoneNVLIST_EXISTS(bool, BOOL)
1093279435SrstoneNVLIST_EXISTS(number, NUMBER)
1094279435SrstoneNVLIST_EXISTS(string, STRING)
1095279435SrstoneNVLIST_EXISTS(nvlist, NVLIST)
1096279438Srstone#ifndef _KERNEL
1097279435SrstoneNVLIST_EXISTS(descriptor, DESCRIPTOR)
1098279438Srstone#endif
1099279435SrstoneNVLIST_EXISTS(binary, BINARY)
1100258065Spjd
1101258065Spjd#undef	NVLIST_EXISTS
1102258065Spjd
1103279438Srstone#ifndef _KERNEL
1104258065Spjdbool
1105258065Spjdnvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...)
1106258065Spjd{
1107258065Spjd	va_list nameap;
1108258065Spjd	bool ret;
1109258065Spjd
1110258065Spjd	va_start(nameap, namefmt);
1111258065Spjd	ret = nvlist_existsv(nvl, namefmt, nameap);
1112258065Spjd	va_end(nameap);
1113258065Spjd	return (ret);
1114258065Spjd}
1115258065Spjd
1116258065Spjd#define	NVLIST_EXISTSF(type)						\
1117258065Spjdbool									\
1118258065Spjdnvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...)	\
1119258065Spjd{									\
1120258065Spjd	va_list nameap;							\
1121258065Spjd	bool ret;							\
1122258065Spjd									\
1123258065Spjd	va_start(nameap, namefmt);					\
1124258065Spjd	ret = nvlist_existsv_##type(nvl, namefmt, nameap);		\
1125258065Spjd	va_end(nameap);							\
1126258065Spjd	return (ret);							\
1127258065Spjd}
1128258065Spjd
1129258065SpjdNVLIST_EXISTSF(null)
1130258065SpjdNVLIST_EXISTSF(bool)
1131258065SpjdNVLIST_EXISTSF(number)
1132258065SpjdNVLIST_EXISTSF(string)
1133258065SpjdNVLIST_EXISTSF(nvlist)
1134279438Srstone#ifndef _KERNEL
1135258065SpjdNVLIST_EXISTSF(descriptor)
1136279438Srstone#endif
1137258065SpjdNVLIST_EXISTSF(binary)
1138258065Spjd
1139258065Spjd#undef	NVLIST_EXISTSF
1140258065Spjd
1141258065Spjdbool
1142258065Spjdnvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap)
1143258065Spjd{
1144279435Srstone	char *name;
1145279435Srstone	bool exists;
1146258065Spjd
1147279438Srstone	nv_vasprintf(&name, namefmt, nameap);
1148279435Srstone	if (name == NULL)
1149279435Srstone		return (false);
1150279435Srstone
1151279435Srstone	exists = nvlist_exists(nvl, name);
1152279438Srstone	nv_free(name);
1153279435Srstone	return (exists);
1154258065Spjd}
1155258065Spjd
1156279435Srstone#define	NVLIST_EXISTSV(type)						\
1157258065Spjdbool									\
1158258065Spjdnvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt,		\
1159258065Spjd    va_list nameap)							\
1160258065Spjd{									\
1161279435Srstone	char *name;							\
1162279435Srstone	bool exists;							\
1163258065Spjd									\
1164279435Srstone	vasprintf(&name, namefmt, nameap);				\
1165279435Srstone	if (name == NULL)						\
1166279435Srstone		return (false);						\
1167279435Srstone	exists = nvlist_exists_##type(nvl, name);			\
1168279435Srstone	free(name);							\
1169279435Srstone	return (exists);						\
1170258065Spjd}
1171258065Spjd
1172279435SrstoneNVLIST_EXISTSV(null)
1173279435SrstoneNVLIST_EXISTSV(bool)
1174279435SrstoneNVLIST_EXISTSV(number)
1175279435SrstoneNVLIST_EXISTSV(string)
1176279435SrstoneNVLIST_EXISTSV(nvlist)
1177279435SrstoneNVLIST_EXISTSV(descriptor)
1178279435SrstoneNVLIST_EXISTSV(binary)
1179258065Spjd
1180258065Spjd#undef	NVLIST_EXISTSV
1181279438Srstone#endif
1182258065Spjd
1183258065Spjdvoid
1184258065Spjdnvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1185258065Spjd{
1186258065Spjd	nvpair_t *newnvp;
1187258065Spjd
1188258065Spjd	NVPAIR_ASSERT(nvp);
1189258065Spjd
1190258065Spjd	if (nvlist_error(nvl) != 0) {
1191279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1192258065Spjd		return;
1193258065Spjd	}
1194258065Spjd	if (nvlist_exists(nvl, nvpair_name(nvp))) {
1195279438Srstone		nvl->nvl_error = EEXIST;
1196279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1197258065Spjd		return;
1198258065Spjd	}
1199258065Spjd
1200258065Spjd	newnvp = nvpair_clone(nvp);
1201258065Spjd	if (newnvp == NULL) {
1202279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1203279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1204258065Spjd		return;
1205258065Spjd	}
1206258065Spjd
1207258065Spjd	nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1208258065Spjd}
1209258065Spjd
1210258065Spjdvoid
1211258065Spjdnvlist_add_null(nvlist_t *nvl, const char *name)
1212258065Spjd{
1213258065Spjd
1214258065Spjd	nvlist_addf_null(nvl, "%s", name);
1215258065Spjd}
1216258065Spjd
1217258065Spjdvoid
1218258065Spjdnvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
1219258065Spjd{
1220258065Spjd
1221258065Spjd	nvlist_addf_bool(nvl, value, "%s", name);
1222258065Spjd}
1223258065Spjd
1224258065Spjdvoid
1225258065Spjdnvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
1226258065Spjd{
1227258065Spjd
1228258065Spjd	nvlist_addf_number(nvl, value, "%s", name);
1229258065Spjd}
1230258065Spjd
1231258065Spjdvoid
1232258065Spjdnvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
1233258065Spjd{
1234258065Spjd
1235258065Spjd	nvlist_addf_string(nvl, value, "%s", name);
1236258065Spjd}
1237258065Spjd
1238258065Spjdvoid
1239258065Spjdnvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1240258065Spjd{
1241258065Spjd	va_list valueap;
1242258065Spjd
1243258065Spjd	va_start(valueap, valuefmt);
1244258065Spjd	nvlist_add_stringv(nvl, name, valuefmt, valueap);
1245258065Spjd	va_end(valueap);
1246258065Spjd}
1247258065Spjd
1248258065Spjdvoid
1249258065Spjdnvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1250258065Spjd    va_list valueap)
1251258065Spjd{
1252258065Spjd	nvpair_t *nvp;
1253258065Spjd
1254258065Spjd	if (nvlist_error(nvl) != 0) {
1255279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1256258065Spjd		return;
1257258065Spjd	}
1258258065Spjd
1259258065Spjd	nvp = nvpair_create_stringv(name, valuefmt, valueap);
1260279438Srstone	if (nvp == NULL) {
1261279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1262279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1263279438Srstone	} else
1264258065Spjd		nvlist_move_nvpair(nvl, nvp);
1265258065Spjd}
1266258065Spjd
1267258065Spjdvoid
1268258065Spjdnvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1269258065Spjd{
1270258065Spjd
1271258065Spjd	nvlist_addf_nvlist(nvl, value, "%s", name);
1272258065Spjd}
1273258065Spjd
1274279438Srstone#ifndef _KERNEL
1275258065Spjdvoid
1276258065Spjdnvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1277258065Spjd{
1278258065Spjd
1279258065Spjd	nvlist_addf_descriptor(nvl, value, "%s", name);
1280258065Spjd}
1281279438Srstone#endif
1282258065Spjd
1283258065Spjdvoid
1284258065Spjdnvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1285258065Spjd    size_t size)
1286258065Spjd{
1287258065Spjd
1288258065Spjd	nvlist_addf_binary(nvl, value, size, "%s", name);
1289258065Spjd}
1290258065Spjd
1291258065Spjdvoid
1292258065Spjdnvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...)
1293258065Spjd{
1294258065Spjd	va_list nameap;
1295258065Spjd
1296258065Spjd	va_start(nameap, namefmt);
1297258065Spjd	nvlist_addv_null(nvl, namefmt, nameap);
1298258065Spjd	va_end(nameap);
1299258065Spjd}
1300258065Spjd
1301258065Spjdvoid
1302258065Spjdnvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...)
1303258065Spjd{
1304258065Spjd	va_list nameap;
1305258065Spjd
1306258065Spjd	va_start(nameap, namefmt);
1307258065Spjd	nvlist_addv_bool(nvl, value, namefmt, nameap);
1308258065Spjd	va_end(nameap);
1309258065Spjd}
1310258065Spjd
1311258065Spjdvoid
1312258065Spjdnvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1313258065Spjd{
1314258065Spjd	va_list nameap;
1315258065Spjd
1316258065Spjd	va_start(nameap, namefmt);
1317258065Spjd	nvlist_addv_number(nvl, value, namefmt, nameap);
1318258065Spjd	va_end(nameap);
1319258065Spjd}
1320258065Spjd
1321258065Spjdvoid
1322258065Spjdnvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...)
1323258065Spjd{
1324258065Spjd	va_list nameap;
1325258065Spjd
1326258065Spjd	va_start(nameap, namefmt);
1327258065Spjd	nvlist_addv_string(nvl, value, namefmt, nameap);
1328258065Spjd	va_end(nameap);
1329258065Spjd}
1330258065Spjd
1331258065Spjdvoid
1332258065Spjdnvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1333258065Spjd    ...)
1334258065Spjd{
1335258065Spjd	va_list nameap;
1336258065Spjd
1337258065Spjd	va_start(nameap, namefmt);
1338258065Spjd	nvlist_addv_nvlist(nvl, value, namefmt, nameap);
1339258065Spjd	va_end(nameap);
1340258065Spjd}
1341258065Spjd
1342279438Srstone#ifndef _KERNEL
1343258065Spjdvoid
1344258065Spjdnvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...)
1345258065Spjd{
1346258065Spjd	va_list nameap;
1347258065Spjd
1348258065Spjd	va_start(nameap, namefmt);
1349258065Spjd	nvlist_addv_descriptor(nvl, value, namefmt, nameap);
1350258065Spjd	va_end(nameap);
1351258065Spjd}
1352279438Srstone#endif
1353258065Spjd
1354258065Spjdvoid
1355258065Spjdnvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size,
1356258065Spjd    const char *namefmt, ...)
1357258065Spjd{
1358258065Spjd	va_list nameap;
1359258065Spjd
1360258065Spjd	va_start(nameap, namefmt);
1361258065Spjd	nvlist_addv_binary(nvl, value, size, namefmt, nameap);
1362258065Spjd	va_end(nameap);
1363258065Spjd}
1364258065Spjd
1365258065Spjdvoid
1366258065Spjdnvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap)
1367258065Spjd{
1368258065Spjd	nvpair_t *nvp;
1369258065Spjd
1370258065Spjd	if (nvlist_error(nvl) != 0) {
1371279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1372258065Spjd		return;
1373258065Spjd	}
1374258065Spjd
1375258065Spjd	nvp = nvpair_createv_null(namefmt, nameap);
1376279438Srstone	if (nvp == NULL) {
1377279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1378279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1379279438Srstone	} else
1380258065Spjd		nvlist_move_nvpair(nvl, nvp);
1381258065Spjd}
1382258065Spjd
1383258065Spjdvoid
1384258065Spjdnvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap)
1385258065Spjd{
1386258065Spjd	nvpair_t *nvp;
1387258065Spjd
1388258065Spjd	if (nvlist_error(nvl) != 0) {
1389279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1390258065Spjd		return;
1391258065Spjd	}
1392258065Spjd
1393258065Spjd	nvp = nvpair_createv_bool(value, namefmt, nameap);
1394279438Srstone	if (nvp == NULL) {
1395279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1396279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1397279438Srstone	} else
1398258065Spjd		nvlist_move_nvpair(nvl, nvp);
1399258065Spjd}
1400258065Spjd
1401258065Spjdvoid
1402258065Spjdnvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt,
1403258065Spjd    va_list nameap)
1404258065Spjd{
1405258065Spjd	nvpair_t *nvp;
1406258065Spjd
1407258065Spjd	if (nvlist_error(nvl) != 0) {
1408279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1409258065Spjd		return;
1410258065Spjd	}
1411258065Spjd
1412258065Spjd	nvp = nvpair_createv_number(value, namefmt, nameap);
1413279438Srstone	if (nvp == NULL) {
1414279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1415279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1416279438Srstone	} else
1417258065Spjd		nvlist_move_nvpair(nvl, nvp);
1418258065Spjd}
1419258065Spjd
1420258065Spjdvoid
1421258065Spjdnvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt,
1422258065Spjd    va_list nameap)
1423258065Spjd{
1424258065Spjd	nvpair_t *nvp;
1425258065Spjd
1426258065Spjd	if (nvlist_error(nvl) != 0) {
1427279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1428258065Spjd		return;
1429258065Spjd	}
1430258065Spjd
1431258065Spjd	nvp = nvpair_createv_string(value, namefmt, nameap);
1432279438Srstone	if (nvp == NULL) {
1433279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1434279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1435279438Srstone	} else
1436258065Spjd		nvlist_move_nvpair(nvl, nvp);
1437258065Spjd}
1438258065Spjd
1439258065Spjdvoid
1440258065Spjdnvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1441258065Spjd    va_list nameap)
1442258065Spjd{
1443258065Spjd	nvpair_t *nvp;
1444258065Spjd
1445258065Spjd	if (nvlist_error(nvl) != 0) {
1446279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1447258065Spjd		return;
1448258065Spjd	}
1449258065Spjd
1450258065Spjd	nvp = nvpair_createv_nvlist(value, namefmt, nameap);
1451279438Srstone	if (nvp == NULL) {
1452279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1453279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1454279438Srstone	} else
1455258065Spjd		nvlist_move_nvpair(nvl, nvp);
1456258065Spjd}
1457258065Spjd
1458279438Srstone#ifndef _KERNEL
1459258065Spjdvoid
1460258065Spjdnvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1461258065Spjd    va_list nameap)
1462258065Spjd{
1463258065Spjd	nvpair_t *nvp;
1464258065Spjd
1465258065Spjd	if (nvlist_error(nvl) != 0) {
1466258065Spjd		errno = nvlist_error(nvl);
1467258065Spjd		return;
1468258065Spjd	}
1469258065Spjd
1470258065Spjd	nvp = nvpair_createv_descriptor(value, namefmt, nameap);
1471258065Spjd	if (nvp == NULL)
1472258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1473258065Spjd	else
1474258065Spjd		nvlist_move_nvpair(nvl, nvp);
1475258065Spjd}
1476279438Srstone#endif
1477258065Spjd
1478258065Spjdvoid
1479258065Spjdnvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size,
1480258065Spjd    const char *namefmt, va_list nameap)
1481258065Spjd{
1482258065Spjd	nvpair_t *nvp;
1483258065Spjd
1484258065Spjd	if (nvlist_error(nvl) != 0) {
1485279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1486258065Spjd		return;
1487258065Spjd	}
1488258065Spjd
1489258065Spjd	nvp = nvpair_createv_binary(value, size, namefmt, nameap);
1490279438Srstone	if (nvp == NULL) {
1491279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1492279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1493279438Srstone	} else
1494258065Spjd		nvlist_move_nvpair(nvl, nvp);
1495258065Spjd}
1496258065Spjd
1497258065Spjdvoid
1498258065Spjdnvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1499258065Spjd{
1500258065Spjd
1501258065Spjd	NVPAIR_ASSERT(nvp);
1502258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1503258065Spjd
1504258065Spjd	if (nvlist_error(nvl) != 0) {
1505258065Spjd		nvpair_free(nvp);
1506279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1507258065Spjd		return;
1508258065Spjd	}
1509258065Spjd	if (nvlist_exists(nvl, nvpair_name(nvp))) {
1510258065Spjd		nvpair_free(nvp);
1511279438Srstone		nvl->nvl_error = EEXIST;
1512279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1513258065Spjd		return;
1514258065Spjd	}
1515258065Spjd
1516258065Spjd	nvpair_insert(&nvl->nvl_head, nvp, nvl);
1517258065Spjd}
1518258065Spjd
1519258065Spjd#define	NVLIST_MOVE(vtype, type)					\
1520258065Spjdvoid									\
1521258065Spjdnvlist_move_##type(nvlist_t *nvl, const char *name, vtype value)	\
1522258065Spjd{									\
1523258065Spjd									\
1524258065Spjd	nvlist_movef_##type(nvl, value, "%s", name);			\
1525258065Spjd}
1526258065Spjd
1527258065SpjdNVLIST_MOVE(char *, string)
1528258065SpjdNVLIST_MOVE(nvlist_t *, nvlist)
1529279438Srstone#ifndef _KERNEL
1530258065SpjdNVLIST_MOVE(int, descriptor)
1531279438Srstone#endif
1532258065Spjd
1533258065Spjd#undef	NVLIST_MOVE
1534258065Spjd
1535258065Spjdvoid
1536258065Spjdnvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1537258065Spjd{
1538258065Spjd
1539258065Spjd	nvlist_movef_binary(nvl, value, size, "%s", name);
1540258065Spjd}
1541258065Spjd
1542258065Spjd#define	NVLIST_MOVEF(vtype, type)					\
1543258065Spjdvoid									\
1544258065Spjdnvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt,	\
1545258065Spjd    ...)								\
1546258065Spjd{									\
1547258065Spjd	va_list nameap;							\
1548258065Spjd									\
1549258065Spjd	va_start(nameap, namefmt);					\
1550258065Spjd	nvlist_movev_##type(nvl, value, namefmt, nameap);		\
1551258065Spjd	va_end(nameap);							\
1552258065Spjd}
1553258065Spjd
1554258065SpjdNVLIST_MOVEF(char *, string)
1555258065SpjdNVLIST_MOVEF(nvlist_t *, nvlist)
1556279438Srstone#ifndef _KERNEL
1557258065SpjdNVLIST_MOVEF(int, descriptor)
1558279438Srstone#endif
1559258065Spjd
1560258065Spjd#undef	NVLIST_MOVEF
1561258065Spjd
1562258065Spjdvoid
1563258065Spjdnvlist_movef_binary(nvlist_t *nvl, void *value, size_t size,
1564258065Spjd    const char *namefmt, ...)
1565258065Spjd{
1566258065Spjd	va_list nameap;
1567258065Spjd
1568258065Spjd	va_start(nameap, namefmt);
1569258065Spjd	nvlist_movev_binary(nvl, value, size, namefmt, nameap);
1570258065Spjd	va_end(nameap);
1571258065Spjd}
1572258065Spjd
1573258065Spjdvoid
1574258065Spjdnvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt,
1575258065Spjd    va_list nameap)
1576258065Spjd{
1577258065Spjd	nvpair_t *nvp;
1578258065Spjd
1579258065Spjd	if (nvlist_error(nvl) != 0) {
1580279438Srstone		nv_free(value);
1581279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1582258065Spjd		return;
1583258065Spjd	}
1584258065Spjd
1585258065Spjd	nvp = nvpair_movev_string(value, namefmt, nameap);
1586279438Srstone	if (nvp == NULL) {
1587279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1588279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1589279438Srstone	} else
1590258065Spjd		nvlist_move_nvpair(nvl, nvp);
1591258065Spjd}
1592258065Spjd
1593258065Spjdvoid
1594258065Spjdnvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
1595258065Spjd    va_list nameap)
1596258065Spjd{
1597258065Spjd	nvpair_t *nvp;
1598258065Spjd
1599258065Spjd	if (nvlist_error(nvl) != 0) {
1600271579Spjd		if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1601271579Spjd			nvlist_destroy(value);
1602279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1603258065Spjd		return;
1604258065Spjd	}
1605258065Spjd
1606258065Spjd	nvp = nvpair_movev_nvlist(value, namefmt, nameap);
1607279438Srstone	if (nvp == NULL) {
1608279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1609279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1610279438Srstone	} else
1611258065Spjd		nvlist_move_nvpair(nvl, nvp);
1612258065Spjd}
1613258065Spjd
1614279438Srstone#ifndef _KERNEL
1615258065Spjdvoid
1616258065Spjdnvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1617258065Spjd    va_list nameap)
1618258065Spjd{
1619258065Spjd	nvpair_t *nvp;
1620258065Spjd
1621258065Spjd	if (nvlist_error(nvl) != 0) {
1622258065Spjd		close(value);
1623258065Spjd		errno = nvlist_error(nvl);
1624258065Spjd		return;
1625258065Spjd	}
1626258065Spjd
1627258065Spjd	nvp = nvpair_movev_descriptor(value, namefmt, nameap);
1628258065Spjd	if (nvp == NULL)
1629258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1630258065Spjd	else
1631258065Spjd		nvlist_move_nvpair(nvl, nvp);
1632258065Spjd}
1633279438Srstone#endif
1634258065Spjd
1635258065Spjdvoid
1636258065Spjdnvlist_movev_binary(nvlist_t *nvl, void *value, size_t size,
1637258065Spjd    const char *namefmt, va_list nameap)
1638258065Spjd{
1639258065Spjd	nvpair_t *nvp;
1640258065Spjd
1641258065Spjd	if (nvlist_error(nvl) != 0) {
1642279438Srstone		nv_free(value);
1643279438Srstone		RESTORE_ERRNO(nvlist_error(nvl));
1644258065Spjd		return;
1645258065Spjd	}
1646258065Spjd
1647258065Spjd	nvp = nvpair_movev_binary(value, size, namefmt, nameap);
1648279438Srstone	if (nvp == NULL) {
1649279438Srstone		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1650279438Srstone		RESTORE_ERRNO(nvl->nvl_error);
1651279438Srstone	} else
1652258065Spjd		nvlist_move_nvpair(nvl, nvp);
1653258065Spjd}
1654258065Spjd
1655279435Srstoneconst nvpair_t *
1656279435Srstonenvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1657279435Srstone{
1658279435Srstone
1659279435Srstone	return (nvlist_find(nvl, NV_TYPE_NONE, name));
1660279435Srstone}
1661279435Srstone
1662279435Srstone#define	NVLIST_GET(ftype, type, TYPE)					\
1663258065Spjdftype									\
1664258065Spjdnvlist_get_##type(const nvlist_t *nvl, const char *name)		\
1665258065Spjd{									\
1666279435Srstone	const nvpair_t *nvp;						\
1667258065Spjd									\
1668279435Srstone	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
1669279435Srstone	if (nvp == NULL)						\
1670279435Srstone		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
1671279435Srstone	return (nvpair_get_##type(nvp));				\
1672258065Spjd}
1673258065Spjd
1674279435SrstoneNVLIST_GET(bool, bool, BOOL)
1675279435SrstoneNVLIST_GET(uint64_t, number, NUMBER)
1676279435SrstoneNVLIST_GET(const char *, string, STRING)
1677279435SrstoneNVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1678279438Srstone#ifndef _KERNEL
1679279435SrstoneNVLIST_GET(int, descriptor, DESCRIPTOR)
1680279438Srstone#endif
1681258065Spjd
1682258065Spjd#undef	NVLIST_GET
1683258065Spjd
1684258065Spjdconst void *
1685258065Spjdnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1686258065Spjd{
1687279435Srstone	nvpair_t *nvp;
1688258065Spjd
1689279435Srstone	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1690279435Srstone	if (nvp == NULL)
1691279435Srstone		nvlist_report_missing(NV_TYPE_BINARY, name);
1692279435Srstone
1693279435Srstone	return (nvpair_get_binary(nvp, sizep));
1694258065Spjd}
1695258065Spjd
1696258065Spjd#define	NVLIST_GETF(ftype, type)					\
1697258065Spjdftype									\
1698258065Spjdnvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...)	\
1699258065Spjd{									\
1700258065Spjd	va_list nameap;							\
1701258065Spjd	ftype value;							\
1702258065Spjd									\
1703258065Spjd	va_start(nameap, namefmt);					\
1704258065Spjd	value = nvlist_getv_##type(nvl, namefmt, nameap);		\
1705258065Spjd	va_end(nameap);							\
1706258065Spjd									\
1707258065Spjd	return (value);							\
1708258065Spjd}
1709258065Spjd
1710279438Srstone#ifndef _KERNEL
1711258065SpjdNVLIST_GETF(bool, bool)
1712258065SpjdNVLIST_GETF(uint64_t, number)
1713258065SpjdNVLIST_GETF(const char *, string)
1714258065SpjdNVLIST_GETF(const nvlist_t *, nvlist)
1715258065SpjdNVLIST_GETF(int, descriptor)
1716258065Spjd
1717258065Spjd#undef	NVLIST_GETF
1718258065Spjd
1719258065Spjdconst void *
1720258065Spjdnvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1721258065Spjd{
1722258065Spjd	va_list nameap;
1723258065Spjd	const void *value;
1724258065Spjd
1725258065Spjd	va_start(nameap, namefmt);
1726258065Spjd	value = nvlist_getv_binary(nvl, sizep, namefmt, nameap);
1727258065Spjd	va_end(nameap);
1728258065Spjd
1729258065Spjd	return (value);
1730258065Spjd}
1731258065Spjd
1732258065Spjd#define	NVLIST_GETV(ftype, type, TYPE)					\
1733258065Spjdftype									\
1734258065Spjdnvlist_getv_##type(const nvlist_t *nvl, const char *namefmt,		\
1735258065Spjd    va_list nameap)							\
1736258065Spjd{									\
1737279435Srstone	char *name;							\
1738279435Srstone	ftype value;							\
1739258065Spjd									\
1740279435Srstone	vasprintf(&name, namefmt, nameap);				\
1741279435Srstone	if (name == NULL)						\
1742279435Srstone		nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>");	\
1743279435Srstone	value = nvlist_get_##type(nvl, name);				\
1744279435Srstone	free(name);							\
1745279435Srstone									\
1746279435Srstone	return (value);							\
1747258065Spjd}
1748258065Spjd
1749258065SpjdNVLIST_GETV(bool, bool, BOOL)
1750258065SpjdNVLIST_GETV(uint64_t, number, NUMBER)
1751258065SpjdNVLIST_GETV(const char *, string, STRING)
1752258065SpjdNVLIST_GETV(const nvlist_t *, nvlist, NVLIST)
1753258065SpjdNVLIST_GETV(int, descriptor, DESCRIPTOR)
1754258065Spjd
1755258065Spjd#undef	NVLIST_GETV
1756258065Spjd
1757258065Spjdconst void *
1758258065Spjdnvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt,
1759258065Spjd    va_list nameap)
1760258065Spjd{
1761279435Srstone	char *name;
1762279435Srstone	const void *binary;
1763258065Spjd
1764279438Srstone	nv_vasprintf(&name, namefmt, nameap);
1765279435Srstone	if (name == NULL)
1766279435Srstone		nvlist_report_missing(NV_TYPE_BINARY, "<unknown>");
1767258065Spjd
1768279435Srstone	binary = nvlist_get_binary(nvl, name, sizep);
1769279438Srstone	nv_free(name);
1770279435Srstone	return (binary);
1771258065Spjd}
1772279438Srstone#endif
1773258065Spjd
1774279435Srstone#define	NVLIST_TAKE(ftype, type, TYPE)					\
1775258065Spjdftype									\
1776258065Spjdnvlist_take_##type(nvlist_t *nvl, const char *name)			\
1777258065Spjd{									\
1778279435Srstone	nvpair_t *nvp;							\
1779279435Srstone	ftype value;							\
1780258065Spjd									\
1781279435Srstone	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
1782279435Srstone	if (nvp == NULL)						\
1783279435Srstone		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
1784279435Srstone	value = (ftype)(intptr_t)nvpair_get_##type(nvp);		\
1785279435Srstone	nvlist_remove_nvpair(nvl, nvp);					\
1786279435Srstone	nvpair_free_structure(nvp);					\
1787279435Srstone	return (value);							\
1788258065Spjd}
1789258065Spjd
1790279435SrstoneNVLIST_TAKE(bool, bool, BOOL)
1791279435SrstoneNVLIST_TAKE(uint64_t, number, NUMBER)
1792279435SrstoneNVLIST_TAKE(char *, string, STRING)
1793279435SrstoneNVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1794279438Srstone#ifndef _KERNEL
1795279435SrstoneNVLIST_TAKE(int, descriptor, DESCRIPTOR)
1796279438Srstone#endif
1797258065Spjd
1798258065Spjd#undef	NVLIST_TAKE
1799258065Spjd
1800258065Spjdvoid *
1801258065Spjdnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1802258065Spjd{
1803279435Srstone	nvpair_t *nvp;
1804279435Srstone	void *value;
1805258065Spjd
1806279435Srstone	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1807279435Srstone	if (nvp == NULL)
1808279435Srstone		nvlist_report_missing(NV_TYPE_BINARY, name);
1809279435Srstone
1810279435Srstone	value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1811279435Srstone	nvlist_remove_nvpair(nvl, nvp);
1812279435Srstone	nvpair_free_structure(nvp);
1813279435Srstone	return (value);
1814258065Spjd}
1815258065Spjd
1816258065Spjd#define	NVLIST_TAKEF(ftype, type)					\
1817258065Spjdftype									\
1818258065Spjdnvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...)		\
1819258065Spjd{									\
1820258065Spjd	va_list nameap;							\
1821258065Spjd	ftype value;							\
1822258065Spjd									\
1823258065Spjd	va_start(nameap, namefmt);					\
1824258065Spjd	value = nvlist_takev_##type(nvl, namefmt, nameap);		\
1825258065Spjd	va_end(nameap);							\
1826258065Spjd									\
1827258065Spjd	return (value);							\
1828258065Spjd}
1829258065Spjd
1830279438Srstone#ifndef _KERNEL
1831258065SpjdNVLIST_TAKEF(bool, bool)
1832258065SpjdNVLIST_TAKEF(uint64_t, number)
1833258065SpjdNVLIST_TAKEF(char *, string)
1834258065SpjdNVLIST_TAKEF(nvlist_t *, nvlist)
1835258065SpjdNVLIST_TAKEF(int, descriptor)
1836258065Spjd
1837258065Spjd#undef	NVLIST_TAKEF
1838258065Spjd
1839258065Spjdvoid *
1840258065Spjdnvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1841258065Spjd{
1842258065Spjd	va_list nameap;
1843258065Spjd	void *value;
1844258065Spjd
1845258065Spjd	va_start(nameap, namefmt);
1846258065Spjd	value = nvlist_takev_binary(nvl, sizep, namefmt, nameap);
1847258065Spjd	va_end(nameap);
1848258065Spjd
1849258065Spjd	return (value);
1850258065Spjd}
1851258065Spjd
1852258065Spjd#define	NVLIST_TAKEV(ftype, type, TYPE)					\
1853258065Spjdftype									\
1854258065Spjdnvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap)	\
1855258065Spjd{									\
1856279435Srstone	char *name;							\
1857258065Spjd	ftype value;							\
1858258065Spjd									\
1859279435Srstone	vasprintf(&name, namefmt, nameap);				\
1860279435Srstone	if (name == NULL)						\
1861279435Srstone		nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>");	\
1862279435Srstone	value = nvlist_take_##type(nvl, name);				\
1863279435Srstone	free(name);							\
1864258065Spjd	return (value);							\
1865258065Spjd}
1866258065Spjd
1867258065SpjdNVLIST_TAKEV(bool, bool, BOOL)
1868258065SpjdNVLIST_TAKEV(uint64_t, number, NUMBER)
1869258065SpjdNVLIST_TAKEV(char *, string, STRING)
1870258065SpjdNVLIST_TAKEV(nvlist_t *, nvlist, NVLIST)
1871258065SpjdNVLIST_TAKEV(int, descriptor, DESCRIPTOR)
1872258065Spjd
1873258065Spjd#undef	NVLIST_TAKEV
1874258065Spjd
1875258065Spjdvoid *
1876258065Spjdnvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt,
1877258065Spjd    va_list nameap)
1878258065Spjd{
1879279435Srstone	char *name;
1880279435Srstone	void *binary;
1881258065Spjd
1882279438Srstone	nv_vasprintf(&name, namefmt, nameap);
1883279435Srstone	if (name == NULL)
1884279435Srstone		nvlist_report_missing(NV_TYPE_BINARY, "<unknown>");
1885258065Spjd
1886279435Srstone	binary = nvlist_take_binary(nvl, name, sizep);
1887279438Srstone	nv_free(name);
1888279435Srstone	return (binary);
1889258065Spjd}
1890279438Srstone#endif
1891258065Spjd
1892258065Spjdvoid
1893258065Spjdnvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1894258065Spjd{
1895258065Spjd
1896258065Spjd	NVLIST_ASSERT(nvl);
1897258065Spjd	NVPAIR_ASSERT(nvp);
1898258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1899258065Spjd
1900258065Spjd	nvpair_remove(&nvl->nvl_head, nvp, nvl);
1901258065Spjd}
1902258065Spjd
1903258065Spjdvoid
1904258065Spjdnvlist_free(nvlist_t *nvl, const char *name)
1905258065Spjd{
1906258065Spjd
1907279435Srstone	nvlist_free_type(nvl, name, NV_TYPE_NONE);
1908258065Spjd}
1909258065Spjd
1910279435Srstone#define	NVLIST_FREE(type, TYPE)						\
1911258065Spjdvoid									\
1912258065Spjdnvlist_free_##type(nvlist_t *nvl, const char *name)			\
1913258065Spjd{									\
1914258065Spjd									\
1915279435Srstone	nvlist_free_type(nvl, name, NV_TYPE_##TYPE);			\
1916258065Spjd}
1917258065Spjd
1918279435SrstoneNVLIST_FREE(null, NULL)
1919279435SrstoneNVLIST_FREE(bool, BOOL)
1920279435SrstoneNVLIST_FREE(number, NUMBER)
1921279435SrstoneNVLIST_FREE(string, STRING)
1922279435SrstoneNVLIST_FREE(nvlist, NVLIST)
1923279438Srstone#ifndef _KERNEL
1924279435SrstoneNVLIST_FREE(descriptor, DESCRIPTOR)
1925279438Srstone#endif
1926279435SrstoneNVLIST_FREE(binary, BINARY)
1927258065Spjd
1928258065Spjd#undef	NVLIST_FREE
1929258065Spjd
1930279438Srstone#ifndef _KERNEL
1931258065Spjdvoid
1932258065Spjdnvlist_freef(nvlist_t *nvl, const char *namefmt, ...)
1933258065Spjd{
1934258065Spjd	va_list nameap;
1935258065Spjd
1936258065Spjd	va_start(nameap, namefmt);
1937258065Spjd	nvlist_freev(nvl, namefmt, nameap);
1938258065Spjd	va_end(nameap);
1939258065Spjd}
1940258065Spjd
1941258065Spjd#define	NVLIST_FREEF(type)						\
1942258065Spjdvoid									\
1943258065Spjdnvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...)		\
1944258065Spjd{									\
1945258065Spjd	va_list nameap;							\
1946258065Spjd									\
1947258065Spjd	va_start(nameap, namefmt);					\
1948258065Spjd	nvlist_freev_##type(nvl, namefmt, nameap);			\
1949258065Spjd	va_end(nameap);							\
1950258065Spjd}
1951258065Spjd
1952258065SpjdNVLIST_FREEF(null)
1953258065SpjdNVLIST_FREEF(bool)
1954258065SpjdNVLIST_FREEF(number)
1955258065SpjdNVLIST_FREEF(string)
1956258065SpjdNVLIST_FREEF(nvlist)
1957258065SpjdNVLIST_FREEF(descriptor)
1958258065SpjdNVLIST_FREEF(binary)
1959258065Spjd
1960258065Spjd#undef	NVLIST_FREEF
1961258065Spjd
1962258065Spjdvoid
1963258065Spjdnvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap)
1964258065Spjd{
1965258065Spjd
1966258065Spjd	nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap);
1967258065Spjd}
1968258065Spjd
1969258065Spjd#define	NVLIST_FREEV(type, TYPE)					\
1970258065Spjdvoid									\
1971258065Spjdnvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap)	\
1972258065Spjd{									\
1973279435Srstone	char *name;							\
1974258065Spjd									\
1975279435Srstone	vasprintf(&name, namefmt, nameap);				\
1976279435Srstone	if (name == NULL)						\
1977279435Srstone		nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>");	\
1978279435Srstone	nvlist_free_##type(nvl, name);					\
1979279435Srstone	free(name);							\
1980258065Spjd}
1981258065Spjd
1982258065SpjdNVLIST_FREEV(null, NULL)
1983258065SpjdNVLIST_FREEV(bool, BOOL)
1984258065SpjdNVLIST_FREEV(number, NUMBER)
1985258065SpjdNVLIST_FREEV(string, STRING)
1986258065SpjdNVLIST_FREEV(nvlist, NVLIST)
1987258065SpjdNVLIST_FREEV(descriptor, DESCRIPTOR)
1988258065SpjdNVLIST_FREEV(binary, BINARY)
1989258065Spjd#undef	NVLIST_FREEV
1990279438Srstone#endif
1991258065Spjd
1992258065Spjdvoid
1993258065Spjdnvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1994258065Spjd{
1995258065Spjd
1996258065Spjd	NVLIST_ASSERT(nvl);
1997258065Spjd	NVPAIR_ASSERT(nvp);
1998258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1999258065Spjd
2000258065Spjd	nvlist_remove_nvpair(nvl, nvp);
2001258065Spjd	nvpair_free(nvp);
2002258065Spjd}
2003