subr_nvlist.c revision 260222
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/lib/libnv/nvlist.c 260222 2014-01-03 09:07:03Z pjd $");
32258065Spjd
33258065Spjd#include <sys/param.h>
34258065Spjd#include <sys/endian.h>
35258065Spjd#include <sys/queue.h>
36258065Spjd#include <sys/socket.h>
37258065Spjd
38258065Spjd#include <errno.h>
39258065Spjd#include <stdarg.h>
40258065Spjd#include <stdbool.h>
41258065Spjd#include <stdint.h>
42258065Spjd#define	_WITH_DPRINTF
43258065Spjd#include <stdio.h>
44258065Spjd#include <stdlib.h>
45258065Spjd#include <string.h>
46258065Spjd#include <unistd.h>
47258065Spjd
48258065Spjd#ifdef HAVE_PJDLOG
49258065Spjd#include <pjdlog.h>
50258065Spjd#endif
51258065Spjd
52258065Spjd#include "msgio.h"
53258065Spjd#include "nv.h"
54258065Spjd#include "nv_impl.h"
55258065Spjd#include "nvlist_impl.h"
56258065Spjd#include "nvpair_impl.h"
57258065Spjd
58258065Spjd#ifndef	HAVE_PJDLOG
59258065Spjd#include <assert.h>
60258065Spjd#define	PJDLOG_ASSERT(...)		assert(__VA_ARGS__)
61258065Spjd#define	PJDLOG_RASSERT(expr, ...)	assert(expr)
62258065Spjd#define	PJDLOG_ABORT(...)		do {				\
63258065Spjd	fprintf(stderr, "%s:%u: ", __FILE__, __LINE__);			\
64258065Spjd	fprintf(stderr, __VA_ARGS__);					\
65258065Spjd	fprintf(stderr, "\n");						\
66258065Spjd	abort();							\
67258065Spjd} while (0)
68258065Spjd#endif
69258065Spjd
70258065Spjd#define	NV_FLAG_PRIVATE_MASK	(NV_FLAG_BIG_ENDIAN)
71258065Spjd#define	NV_FLAG_PUBLIC_MASK	(NV_FLAG_IGNORE_CASE)
72258065Spjd#define	NV_FLAG_ALL_MASK	(NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
73258065Spjd
74258065Spjd#define	NVLIST_MAGIC	0x6e766c	/* "nvl" */
75258065Spjdstruct nvlist {
76258065Spjd	int		nvl_magic;
77258065Spjd	int		nvl_error;
78258065Spjd	int		nvl_flags;
79258065Spjd	struct nvl_head	nvl_head;
80258065Spjd};
81258065Spjd
82258065Spjd#define	NVLIST_ASSERT(nvl)	do {					\
83258065Spjd	PJDLOG_ASSERT((nvl) != NULL);					\
84258065Spjd	PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);		\
85258065Spjd} while (0)
86258065Spjd
87258065Spjd#define	NVPAIR_ASSERT(nvp)	nvpair_assert(nvp)
88258065Spjd
89258065Spjd#define	NVLIST_HEADER_MAGIC	0x6c
90258065Spjd#define	NVLIST_HEADER_VERSION	0x00
91258065Spjdstruct nvlist_header {
92258065Spjd	uint8_t		nvlh_magic;
93258065Spjd	uint8_t		nvlh_version;
94258065Spjd	uint8_t		nvlh_flags;
95258065Spjd	uint64_t	nvlh_descriptors;
96258065Spjd	uint64_t	nvlh_size;
97258065Spjd} __packed;
98258065Spjd
99258065Spjdnvlist_t *
100258065Spjdnvlist_create(int flags)
101258065Spjd{
102258065Spjd	nvlist_t *nvl;
103258065Spjd
104258065Spjd	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
105258065Spjd
106258065Spjd	nvl = malloc(sizeof(*nvl));
107258065Spjd	nvl->nvl_error = 0;
108258065Spjd	nvl->nvl_flags = flags;
109258065Spjd	TAILQ_INIT(&nvl->nvl_head);
110258065Spjd	nvl->nvl_magic = NVLIST_MAGIC;
111258065Spjd
112258065Spjd	return (nvl);
113258065Spjd}
114258065Spjd
115258065Spjdvoid
116258065Spjdnvlist_destroy(nvlist_t *nvl)
117258065Spjd{
118258065Spjd	nvpair_t *nvp;
119258065Spjd	int serrno;
120258065Spjd
121258065Spjd	if (nvl == NULL)
122258065Spjd		return;
123258065Spjd
124258065Spjd	serrno = errno;
125258065Spjd
126258065Spjd	NVLIST_ASSERT(nvl);
127258065Spjd
128260222Spjd	while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
129258065Spjd		nvlist_remove_nvpair(nvl, nvp);
130260222Spjd		nvpair_free(nvp);
131260222Spjd	}
132258065Spjd	nvl->nvl_magic = 0;
133258065Spjd	free(nvl);
134258065Spjd
135258065Spjd	errno = serrno;
136258065Spjd}
137258065Spjd
138258065Spjdint
139258065Spjdnvlist_error(const nvlist_t *nvl)
140258065Spjd{
141258065Spjd
142258065Spjd	if (nvl == NULL)
143258065Spjd		return (ENOMEM);
144258065Spjd
145258065Spjd	NVLIST_ASSERT(nvl);
146258065Spjd
147258065Spjd	return (nvl->nvl_error);
148258065Spjd}
149258065Spjd
150258065Spjdbool
151258065Spjdnvlist_empty(const nvlist_t *nvl)
152258065Spjd{
153258065Spjd
154258065Spjd	NVLIST_ASSERT(nvl);
155258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
156258065Spjd
157258065Spjd	return (nvlist_first_nvpair(nvl) == NULL);
158258065Spjd}
159258065Spjd
160258065Spjdstatic void
161258065Spjdnvlist_report_missing(int type, const char *namefmt, va_list nameap)
162258065Spjd{
163258065Spjd	char *name;
164258065Spjd
165258065Spjd	vasprintf(&name, namefmt, nameap);
166258065Spjd	PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
167258065Spjd	    name != NULL ? name : "N/A", nvpair_type_string(type));
168258065Spjd}
169258065Spjd
170258065Spjdstatic nvpair_t *
171258065Spjdnvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
172258065Spjd{
173258065Spjd	nvpair_t *nvp;
174258065Spjd	char *name;
175258065Spjd
176258065Spjd	NVLIST_ASSERT(nvl);
177258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
178258065Spjd	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
179258065Spjd	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
180258065Spjd
181258065Spjd	if (vasprintf(&name, namefmt, nameap) < 0)
182258065Spjd		return (NULL);
183258065Spjd
184258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
185258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
186258065Spjd		if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
187258065Spjd			continue;
188258065Spjd		if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
189258065Spjd			if (strcasecmp(nvpair_name(nvp), name) != 0)
190258065Spjd				continue;
191258065Spjd		} else {
192258065Spjd			if (strcmp(nvpair_name(nvp), name) != 0)
193258065Spjd				continue;
194258065Spjd		}
195258065Spjd		break;
196258065Spjd	}
197258065Spjd
198258065Spjd	free(name);
199258065Spjd
200258065Spjd	if (nvp == NULL)
201258065Spjd		errno = ENOENT;
202258065Spjd
203258065Spjd	return (nvp);
204258065Spjd}
205258065Spjd
206258065Spjdbool
207258065Spjdnvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
208258065Spjd{
209258065Spjd
210258065Spjd	return (nvlist_existsf_type(nvl, type, "%s", name));
211258065Spjd}
212258065Spjd
213258065Spjdbool
214258065Spjdnvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...)
215258065Spjd{
216258065Spjd	va_list nameap;
217258065Spjd	bool ret;
218258065Spjd
219258065Spjd	va_start(nameap, namefmt);
220258065Spjd	ret = nvlist_existsv_type(nvl, type, namefmt, nameap);
221258065Spjd	va_end(nameap);
222258065Spjd
223258065Spjd	return (ret);
224258065Spjd}
225258065Spjd
226258065Spjdbool
227258065Spjdnvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt,
228258065Spjd    va_list nameap)
229258065Spjd{
230258065Spjd
231258065Spjd	NVLIST_ASSERT(nvl);
232258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
233258065Spjd	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
234258065Spjd	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
235258065Spjd
236258065Spjd	return (nvlist_findv(nvl, type, namefmt, nameap) != NULL);
237258065Spjd}
238258065Spjd
239258065Spjdvoid
240258065Spjdnvlist_free_type(nvlist_t *nvl, const char *name, int type)
241258065Spjd{
242258065Spjd
243258065Spjd	nvlist_freef_type(nvl, type, "%s", name);
244258065Spjd}
245258065Spjd
246258065Spjdvoid
247258065Spjdnvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...)
248258065Spjd{
249258065Spjd	va_list nameap;
250258065Spjd
251258065Spjd	va_start(nameap, namefmt);
252258065Spjd	nvlist_freev_type(nvl, type, namefmt, nameap);
253258065Spjd	va_end(nameap);
254258065Spjd}
255258065Spjd
256258065Spjdvoid
257258065Spjdnvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
258258065Spjd{
259258065Spjd	va_list cnameap;
260258065Spjd	nvpair_t *nvp;
261258065Spjd
262258065Spjd	NVLIST_ASSERT(nvl);
263258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
264258065Spjd	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
265258065Spjd	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
266258065Spjd
267258065Spjd	va_copy(cnameap, nameap);
268258065Spjd	nvp = nvlist_findv(nvl, type, namefmt, cnameap);
269258065Spjd	va_end(cnameap);
270258065Spjd	if (nvp != NULL)
271258065Spjd		nvlist_free_nvpair(nvl, nvp);
272258065Spjd	else
273258065Spjd		nvlist_report_missing(type, namefmt, nameap);
274258065Spjd}
275258065Spjd
276258065Spjdnvlist_t *
277258065Spjdnvlist_clone(const nvlist_t *nvl)
278258065Spjd{
279258065Spjd	nvlist_t *newnvl;
280258065Spjd	nvpair_t *nvp, *newnvp;
281258065Spjd
282258065Spjd	NVLIST_ASSERT(nvl);
283258065Spjd
284258065Spjd	if (nvl->nvl_error != 0) {
285258065Spjd		errno = nvl->nvl_error;
286258065Spjd		return (NULL);
287258065Spjd	}
288258065Spjd
289258065Spjd	newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
290258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
291258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
292258065Spjd		newnvp = nvpair_clone(nvp);
293258065Spjd		if (newnvp == NULL)
294258065Spjd			break;
295258065Spjd		nvlist_move_nvpair(newnvl, newnvp);
296258065Spjd	}
297258065Spjd	if (nvp != NULL) {
298258065Spjd		nvlist_destroy(newnvl);
299258065Spjd		return (NULL);
300258065Spjd	}
301258065Spjd	return (newnvl);
302258065Spjd}
303258065Spjd
304258065Spjd/*
305258065Spjd * Dump content of nvlist.
306258065Spjd */
307258065Spjdstatic void
308258065Spjdnvlist_xdump(const nvlist_t *nvl, int fd, int level)
309258065Spjd{
310258065Spjd	nvpair_t *nvp;
311258065Spjd
312258065Spjd	PJDLOG_ASSERT(level < 3);
313258065Spjd
314258065Spjd	if (nvlist_error(nvl) != 0) {
315258065Spjd		dprintf(fd, "%*serror: %d\n", level * 4, "",
316258065Spjd		    nvlist_error(nvl));
317258065Spjd		return;
318258065Spjd	}
319258065Spjd
320258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
321258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
322258065Spjd		dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
323258065Spjd		    nvpair_type_string(nvpair_type(nvp)));
324258065Spjd		switch (nvpair_type(nvp)) {
325258065Spjd		case NV_TYPE_NULL:
326258065Spjd			dprintf(fd, " null\n");
327258065Spjd			break;
328258065Spjd		case NV_TYPE_BOOL:
329258065Spjd			dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
330258065Spjd			    "TRUE" : "FALSE");
331258065Spjd			break;
332258065Spjd		case NV_TYPE_NUMBER:
333258065Spjd			dprintf(fd, " %ju (%jd) (0x%jx)\n",
334258065Spjd			    (uintmax_t)nvpair_get_number(nvp),
335258065Spjd			    (intmax_t)nvpair_get_number(nvp),
336258065Spjd			    (uintmax_t)nvpair_get_number(nvp));
337258065Spjd			break;
338258065Spjd		case NV_TYPE_STRING:
339258065Spjd			dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
340258065Spjd			break;
341258065Spjd		case NV_TYPE_NVLIST:
342258065Spjd			dprintf(fd, "\n");
343258065Spjd			nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1);
344258065Spjd			break;
345258065Spjd		case NV_TYPE_DESCRIPTOR:
346258065Spjd			dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
347258065Spjd			break;
348258065Spjd		case NV_TYPE_BINARY:
349258065Spjd		    {
350258065Spjd			const unsigned char *binary;
351258065Spjd			unsigned int ii;
352258065Spjd			size_t size;
353258065Spjd
354258065Spjd			binary = nvpair_get_binary(nvp, &size);
355258065Spjd			dprintf(fd, " %zu ", size);
356258065Spjd			for (ii = 0; ii < size; ii++)
357258065Spjd				dprintf(fd, "%02hhx", binary[ii]);
358258065Spjd			dprintf(fd, "\n");
359258065Spjd			break;
360258065Spjd		    }
361258065Spjd		default:
362258065Spjd			PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
363258065Spjd		}
364258065Spjd	}
365258065Spjd}
366258065Spjd
367258065Spjdvoid
368258065Spjdnvlist_dump(const nvlist_t *nvl, int fd)
369258065Spjd{
370258065Spjd
371258065Spjd	nvlist_xdump(nvl, fd, 0);
372258065Spjd}
373258065Spjd
374258065Spjdvoid
375258065Spjdnvlist_fdump(const nvlist_t *nvl, FILE *fp)
376258065Spjd{
377258065Spjd
378258065Spjd	fflush(fp);
379258065Spjd	nvlist_dump(nvl, fileno(fp));
380258065Spjd}
381258065Spjd
382258065Spjd/*
383258065Spjd * The function obtains size of the nvlist after nvlist_pack().
384258065Spjd * Additional argument 'level' allows to track how deep are we as we obtain
385258065Spjd * size of the NV_TYPE_NVLIST elements using recursion. We allow at most
386258065Spjd * three levels of recursion.
387258065Spjd */
388258065Spjdstatic size_t
389258065Spjdnvlist_xsize(const nvlist_t *nvl, int level)
390258065Spjd{
391258065Spjd	const nvpair_t *nvp;
392258065Spjd	size_t size;
393258065Spjd
394258065Spjd	NVLIST_ASSERT(nvl);
395258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
396258065Spjd	PJDLOG_ASSERT(level < 3);
397258065Spjd
398258065Spjd	size = sizeof(struct nvlist_header);
399258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
400258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
401258065Spjd		size += nvpair_header_size();
402258065Spjd		size += strlen(nvpair_name(nvp)) + 1;
403258065Spjd		if (nvpair_type(nvp) == NV_TYPE_NVLIST)
404258065Spjd			size += nvlist_xsize(nvpair_get_nvlist(nvp), level + 1);
405258065Spjd		else
406258065Spjd			size += nvpair_size(nvp);
407258065Spjd	}
408258065Spjd
409258065Spjd	return (size);
410258065Spjd}
411258065Spjd
412258065Spjdsize_t
413258065Spjdnvlist_size(const nvlist_t *nvl)
414258065Spjd{
415258065Spjd
416258065Spjd	return (nvlist_xsize(nvl, 0));
417258065Spjd}
418258065Spjd
419258065Spjdstatic int *
420258065Spjdnvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
421258065Spjd{
422258065Spjd	const nvpair_t *nvp;
423258065Spjd
424258065Spjd	NVLIST_ASSERT(nvl);
425258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
426258065Spjd	PJDLOG_ASSERT(level < 3);
427258065Spjd
428258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
429258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
430258065Spjd		switch (nvpair_type(nvp)) {
431258065Spjd		case NV_TYPE_DESCRIPTOR:
432258065Spjd			*descs = nvpair_get_descriptor(nvp);
433258065Spjd			descs++;
434258065Spjd			break;
435258065Spjd		case NV_TYPE_NVLIST:
436258065Spjd			descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
437258065Spjd			    descs, level + 1);
438258065Spjd			break;
439258065Spjd		}
440258065Spjd	}
441258065Spjd
442258065Spjd	return (descs);
443258065Spjd}
444258065Spjd
445258065Spjdint *
446258065Spjdnvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
447258065Spjd{
448258065Spjd	size_t nitems;
449258065Spjd	int *fds;
450258065Spjd
451258065Spjd	nitems = nvlist_ndescriptors(nvl);
452258065Spjd	fds = malloc(sizeof(fds[0]) * (nitems + 1));
453258065Spjd	if (fds == NULL)
454258065Spjd		return (NULL);
455258065Spjd	if (nitems > 0)
456258065Spjd		nvlist_xdescriptors(nvl, fds, 0);
457258065Spjd	fds[nitems] = -1;
458258065Spjd	if (nitemsp != NULL)
459258065Spjd		*nitemsp = nitems;
460258065Spjd	return (fds);
461258065Spjd}
462258065Spjd
463258065Spjdstatic size_t
464258065Spjdnvlist_xndescriptors(const nvlist_t *nvl, int level)
465258065Spjd{
466258065Spjd	const nvpair_t *nvp;
467258065Spjd	size_t ndescs;
468258065Spjd
469258065Spjd	NVLIST_ASSERT(nvl);
470258065Spjd	PJDLOG_ASSERT(nvl->nvl_error == 0);
471258065Spjd	PJDLOG_ASSERT(level < 3);
472258065Spjd
473258065Spjd	ndescs = 0;
474258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
475258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
476258065Spjd		switch (nvpair_type(nvp)) {
477258065Spjd		case NV_TYPE_DESCRIPTOR:
478258065Spjd			ndescs++;
479258065Spjd			break;
480258065Spjd		case NV_TYPE_NVLIST:
481258065Spjd			ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
482258065Spjd			    level + 1);
483258065Spjd			break;
484258065Spjd		}
485258065Spjd	}
486258065Spjd
487258065Spjd	return (ndescs);
488258065Spjd}
489258065Spjd
490258065Spjdsize_t
491258065Spjdnvlist_ndescriptors(const nvlist_t *nvl)
492258065Spjd{
493258065Spjd
494258065Spjd	return (nvlist_xndescriptors(nvl, 0));
495258065Spjd}
496258065Spjd
497258065Spjdstatic unsigned char *
498258065Spjdnvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
499258065Spjd{
500258065Spjd	struct nvlist_header nvlhdr;
501258065Spjd
502258065Spjd	NVLIST_ASSERT(nvl);
503258065Spjd
504258065Spjd	nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
505258065Spjd	nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
506258065Spjd	nvlhdr.nvlh_flags = nvl->nvl_flags;
507258065Spjd#if BYTE_ORDER == BIG_ENDIAN
508258065Spjd	nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
509258065Spjd#endif
510258065Spjd	nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
511258065Spjd	nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
512258065Spjd	PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
513258065Spjd	memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
514258065Spjd	ptr += sizeof(nvlhdr);
515258065Spjd	*leftp -= sizeof(nvlhdr);
516258065Spjd
517258065Spjd	return (ptr);
518258065Spjd}
519258065Spjd
520258065Spjdvoid *
521258065Spjdnvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
522258065Spjd{
523258065Spjd	unsigned char *buf, *ptr;
524258065Spjd	size_t left, size;
525258065Spjd	nvpair_t *nvp;
526258065Spjd
527258065Spjd	NVLIST_ASSERT(nvl);
528258065Spjd
529258065Spjd	if (nvl->nvl_error != 0) {
530258065Spjd		errno = nvl->nvl_error;
531258065Spjd		return (NULL);
532258065Spjd	}
533258065Spjd
534258065Spjd	size = nvlist_size(nvl);
535258065Spjd	buf = malloc(size);
536258065Spjd	if (buf == NULL)
537258065Spjd		return (NULL);
538258065Spjd
539258065Spjd	ptr = buf;
540258065Spjd	left = size;
541258065Spjd
542258065Spjd	ptr = nvlist_pack_header(nvl, ptr, &left);
543258065Spjd
544258065Spjd	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
545258065Spjd	    nvp = nvlist_next_nvpair(nvl, nvp)) {
546258065Spjd		ptr = nvpair_pack(nvp, ptr, fdidxp, &left);
547258065Spjd		if (ptr == NULL) {
548258065Spjd			free(buf);
549258065Spjd			return (NULL);
550258065Spjd		}
551258065Spjd	}
552258065Spjd
553258065Spjd	if (sizep != NULL)
554258065Spjd		*sizep = size;
555258065Spjd	return (buf);
556258065Spjd}
557258065Spjd
558258065Spjdvoid *
559258065Spjdnvlist_pack(const nvlist_t *nvl, size_t *sizep)
560258065Spjd{
561258065Spjd
562258065Spjd	NVLIST_ASSERT(nvl);
563258065Spjd
564258065Spjd	if (nvl->nvl_error != 0) {
565258065Spjd		errno = nvl->nvl_error;
566258065Spjd		return (NULL);
567258065Spjd	}
568258065Spjd
569258065Spjd	if (nvlist_ndescriptors(nvl) > 0) {
570258065Spjd		errno = EOPNOTSUPP;
571258065Spjd		return (NULL);
572258065Spjd	}
573258065Spjd
574258065Spjd	return (nvlist_xpack(nvl, NULL, sizep));
575258065Spjd}
576258065Spjd
577258065Spjdstatic bool
578258065Spjdnvlist_check_header(struct nvlist_header *nvlhdrp)
579258065Spjd{
580258065Spjd
581258065Spjd	if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
582258065Spjd		errno = EINVAL;
583258065Spjd		return (false);
584258065Spjd	}
585258065Spjd	if ((nvlhdrp->nvlh_flags &= ~NV_FLAG_ALL_MASK) != 0) {
586258065Spjd		errno = EINVAL;
587258065Spjd		return (false);
588258065Spjd	}
589258065Spjd#if BYTE_ORDER == BIG_ENDIAN
590258065Spjd	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
591258065Spjd		nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
592258065Spjd		nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
593258065Spjd	}
594258065Spjd#else
595258065Spjd	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
596258065Spjd		nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
597258065Spjd		nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
598258065Spjd	}
599258065Spjd#endif
600258065Spjd	return (true);
601258065Spjd}
602258065Spjd
603258065Spjdstatic const unsigned char *
604258065Spjdnvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
605258065Spjd    int *flagsp, size_t *leftp)
606258065Spjd{
607258065Spjd	struct nvlist_header nvlhdr;
608258065Spjd
609258065Spjd	if (*leftp < sizeof(nvlhdr))
610258065Spjd		goto failed;
611258065Spjd
612258065Spjd	memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
613258065Spjd
614258065Spjd	if (!nvlist_check_header(&nvlhdr))
615258065Spjd		goto failed;
616258065Spjd
617258065Spjd	if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
618258065Spjd		goto failed;
619258065Spjd
620258065Spjd	/*
621258065Spjd	 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
622258065Spjd	 */
623258065Spjd	if (nvlhdr.nvlh_descriptors > nfds)
624258065Spjd		goto failed;
625258065Spjd
626258065Spjd	if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
627258065Spjd		goto failed;
628258065Spjd
629258065Spjd	nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
630258065Spjd
631258065Spjd	ptr += sizeof(nvlhdr);
632258065Spjd	*flagsp = (int)nvlhdr.nvlh_flags;
633258065Spjd	*leftp -= sizeof(nvlhdr);
634258065Spjd
635258065Spjd	return (ptr);
636258065Spjdfailed:
637258065Spjd	errno = EINVAL;
638258065Spjd	return (NULL);
639258065Spjd}
640258065Spjd
641258065Spjdnvlist_t *
642258065Spjdnvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
643258065Spjd{
644258065Spjd	const unsigned char *ptr;
645258065Spjd	nvlist_t *nvl;
646258065Spjd	nvpair_t *nvp;
647258065Spjd	size_t left;
648258065Spjd	int flags;
649258065Spjd
650258065Spjd	left = size;
651258065Spjd	ptr = buf;
652258065Spjd
653258065Spjd	nvl = nvlist_create(0);
654258065Spjd	if (nvl == NULL)
655258065Spjd		goto failed;
656258065Spjd
657258065Spjd	ptr = nvlist_unpack_header(nvl, ptr, nfds, &flags, &left);
658258065Spjd	if (ptr == NULL)
659258065Spjd		goto failed;
660258065Spjd
661258065Spjd	while (left > 0) {
662258065Spjd		ptr = nvpair_unpack(flags, ptr, &left, fds, nfds, &nvp);
663258065Spjd		if (ptr == NULL)
664258065Spjd			goto failed;
665258065Spjd		nvlist_move_nvpair(nvl, nvp);
666258065Spjd	}
667258065Spjd
668258065Spjd	return (nvl);
669258065Spjdfailed:
670258065Spjd	nvlist_destroy(nvl);
671258065Spjd	return (NULL);
672258065Spjd}
673258065Spjd
674258065Spjdnvlist_t *
675258065Spjdnvlist_unpack(const void *buf, size_t size)
676258065Spjd{
677258065Spjd
678258065Spjd	return (nvlist_xunpack(buf, size, NULL, 0));
679258065Spjd}
680258065Spjd
681258065Spjdint
682258065Spjdnvlist_send(int sock, const nvlist_t *nvl)
683258065Spjd{
684258065Spjd	size_t datasize, nfds;
685258065Spjd	int *fds;
686258065Spjd	void *data;
687258065Spjd	int64_t fdidx;
688258065Spjd	int serrno, ret;
689258065Spjd
690258065Spjd	if (nvlist_error(nvl) != 0) {
691258065Spjd		errno = nvlist_error(nvl);
692258065Spjd		return (-1);
693258065Spjd	}
694258065Spjd
695258065Spjd	fds = nvlist_descriptors(nvl, &nfds);
696258065Spjd	if (fds == NULL)
697258065Spjd		return (-1);
698258065Spjd
699258065Spjd	ret = -1;
700258065Spjd	data = NULL;
701258065Spjd	fdidx = 0;
702258065Spjd
703258065Spjd	data = nvlist_xpack(nvl, &fdidx, &datasize);
704258065Spjd	if (data == NULL)
705258065Spjd		goto out;
706258065Spjd
707258065Spjd	if (buf_send(sock, data, datasize) == -1)
708258065Spjd		goto out;
709258065Spjd
710258065Spjd	if (nfds > 0) {
711258065Spjd		if (fd_send(sock, fds, nfds) == -1)
712258065Spjd			goto out;
713258065Spjd	}
714258065Spjd
715258065Spjd	ret = 0;
716258065Spjdout:
717258065Spjd	serrno = errno;
718258065Spjd	free(fds);
719258065Spjd	free(data);
720258065Spjd	errno = serrno;
721258065Spjd	return (ret);
722258065Spjd}
723258065Spjd
724258065Spjdnvlist_t *
725258065Spjdnvlist_recv(int sock)
726258065Spjd{
727258065Spjd	struct nvlist_header nvlhdr;
728258065Spjd	nvlist_t *nvl, *ret;
729259430Spjd	unsigned char *buf;
730258065Spjd	size_t nfds, size;
731258065Spjd	int serrno, *fds;
732258065Spjd
733259430Spjd	if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
734258065Spjd		return (NULL);
735258065Spjd
736258065Spjd	if (!nvlist_check_header(&nvlhdr))
737258065Spjd		return (NULL);
738258065Spjd
739258065Spjd	nfds = (size_t)nvlhdr.nvlh_descriptors;
740258065Spjd	size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
741258065Spjd
742258065Spjd	buf = malloc(size);
743258065Spjd	if (buf == NULL)
744258065Spjd		return (NULL);
745258065Spjd
746259430Spjd	memcpy(buf, &nvlhdr, sizeof(nvlhdr));
747259430Spjd
748258065Spjd	ret = NULL;
749258065Spjd	fds = NULL;
750258065Spjd
751259430Spjd	if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
752258065Spjd		goto out;
753258065Spjd
754258065Spjd	if (nfds > 0) {
755258065Spjd		fds = malloc(nfds * sizeof(fds[0]));
756258065Spjd		if (fds == NULL)
757258065Spjd			goto out;
758258065Spjd		if (fd_recv(sock, fds, nfds) == -1)
759258065Spjd			goto out;
760258065Spjd	}
761258065Spjd
762258065Spjd	nvl = nvlist_xunpack(buf, size, fds, nfds);
763258065Spjd	if (nvl == NULL)
764258065Spjd		goto out;
765258065Spjd
766258065Spjd	ret = nvl;
767258065Spjdout:
768258065Spjd	serrno = errno;
769258065Spjd	free(buf);
770258065Spjd	free(fds);
771258065Spjd	errno = serrno;
772258065Spjd
773258065Spjd	return (ret);
774258065Spjd}
775258065Spjd
776258065Spjdnvlist_t *
777258065Spjdnvlist_xfer(int sock, nvlist_t *nvl)
778258065Spjd{
779258065Spjd
780258065Spjd	if (nvlist_send(sock, nvl) < 0) {
781258065Spjd		nvlist_destroy(nvl);
782258065Spjd		return (NULL);
783258065Spjd	}
784258065Spjd	nvlist_destroy(nvl);
785258065Spjd	return (nvlist_recv(sock));
786258065Spjd}
787258065Spjd
788258065Spjdnvpair_t *
789258065Spjdnvlist_first_nvpair(const nvlist_t *nvl)
790258065Spjd{
791258065Spjd
792258065Spjd	NVLIST_ASSERT(nvl);
793258065Spjd
794258065Spjd	return (TAILQ_FIRST(&nvl->nvl_head));
795258065Spjd}
796258065Spjd
797258065Spjdnvpair_t *
798258065Spjdnvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
799258065Spjd{
800258065Spjd	nvpair_t *retnvp;
801258065Spjd
802258065Spjd	NVLIST_ASSERT(nvl);
803258065Spjd	NVPAIR_ASSERT(nvp);
804258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
805258065Spjd
806258065Spjd	retnvp = nvpair_next(nvp);
807258065Spjd	PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
808258065Spjd
809258065Spjd	return (retnvp);
810258065Spjd
811258065Spjd}
812258065Spjd
813258065Spjdnvpair_t *
814258065Spjdnvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
815258065Spjd{
816258065Spjd	nvpair_t *retnvp;
817258065Spjd
818258065Spjd	NVLIST_ASSERT(nvl);
819258065Spjd	NVPAIR_ASSERT(nvp);
820258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
821258065Spjd
822258065Spjd	retnvp = nvpair_prev(nvp);
823258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
824258065Spjd
825258065Spjd	return (retnvp);
826258065Spjd}
827258065Spjd
828258065Spjdconst char *
829258065Spjdnvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
830258065Spjd{
831258065Spjd	nvpair_t *nvp;
832258065Spjd
833258065Spjd	NVLIST_ASSERT(nvl);
834258065Spjd	PJDLOG_ASSERT(cookiep != NULL);
835258065Spjd
836258065Spjd	if (*cookiep == NULL)
837258065Spjd		nvp = nvlist_first_nvpair(nvl);
838258065Spjd	else
839258065Spjd		nvp = nvlist_next_nvpair(nvl, *cookiep);
840258065Spjd	if (nvp == NULL)
841258065Spjd		return (NULL);
842258065Spjd	if (typep != NULL)
843258065Spjd		*typep = nvpair_type(nvp);
844258065Spjd	*cookiep = nvp;
845258065Spjd	return (nvpair_name(nvp));
846258065Spjd}
847258065Spjd
848258065Spjdbool
849258065Spjdnvlist_exists(const nvlist_t *nvl, const char *name)
850258065Spjd{
851258065Spjd
852258065Spjd	return (nvlist_existsf(nvl, "%s", name));
853258065Spjd}
854258065Spjd
855258065Spjd#define	NVLIST_EXISTS(type)						\
856258065Spjdbool									\
857258065Spjdnvlist_exists_##type(const nvlist_t *nvl, const char *name)		\
858258065Spjd{									\
859258065Spjd									\
860258065Spjd	return (nvlist_existsf_##type(nvl, "%s", name));		\
861258065Spjd}
862258065Spjd
863258065SpjdNVLIST_EXISTS(null)
864258065SpjdNVLIST_EXISTS(bool)
865258065SpjdNVLIST_EXISTS(number)
866258065SpjdNVLIST_EXISTS(string)
867258065SpjdNVLIST_EXISTS(nvlist)
868258065SpjdNVLIST_EXISTS(descriptor)
869258065SpjdNVLIST_EXISTS(binary)
870258065Spjd
871258065Spjd#undef	NVLIST_EXISTS
872258065Spjd
873258065Spjdbool
874258065Spjdnvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...)
875258065Spjd{
876258065Spjd	va_list nameap;
877258065Spjd	bool ret;
878258065Spjd
879258065Spjd	va_start(nameap, namefmt);
880258065Spjd	ret = nvlist_existsv(nvl, namefmt, nameap);
881258065Spjd	va_end(nameap);
882258065Spjd	return (ret);
883258065Spjd}
884258065Spjd
885258065Spjd#define	NVLIST_EXISTSF(type)						\
886258065Spjdbool									\
887258065Spjdnvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...)	\
888258065Spjd{									\
889258065Spjd	va_list nameap;							\
890258065Spjd	bool ret;							\
891258065Spjd									\
892258065Spjd	va_start(nameap, namefmt);					\
893258065Spjd	ret = nvlist_existsv_##type(nvl, namefmt, nameap);		\
894258065Spjd	va_end(nameap);							\
895258065Spjd	return (ret);							\
896258065Spjd}
897258065Spjd
898258065SpjdNVLIST_EXISTSF(null)
899258065SpjdNVLIST_EXISTSF(bool)
900258065SpjdNVLIST_EXISTSF(number)
901258065SpjdNVLIST_EXISTSF(string)
902258065SpjdNVLIST_EXISTSF(nvlist)
903258065SpjdNVLIST_EXISTSF(descriptor)
904258065SpjdNVLIST_EXISTSF(binary)
905258065Spjd
906258065Spjd#undef	NVLIST_EXISTSF
907258065Spjd
908258065Spjdbool
909258065Spjdnvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap)
910258065Spjd{
911258065Spjd
912258065Spjd	return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap) != NULL);
913258065Spjd}
914258065Spjd
915258065Spjd#define	NVLIST_EXISTSV(type, TYPE)					\
916258065Spjdbool									\
917258065Spjdnvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt,		\
918258065Spjd    va_list nameap)							\
919258065Spjd{									\
920258065Spjd									\
921258065Spjd	return (nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, nameap) !=	\
922258065Spjd	    NULL);							\
923258065Spjd}
924258065Spjd
925258065SpjdNVLIST_EXISTSV(null, NULL)
926258065SpjdNVLIST_EXISTSV(bool, BOOL)
927258065SpjdNVLIST_EXISTSV(number, NUMBER)
928258065SpjdNVLIST_EXISTSV(string, STRING)
929258065SpjdNVLIST_EXISTSV(nvlist, NVLIST)
930258065SpjdNVLIST_EXISTSV(descriptor, DESCRIPTOR)
931258065SpjdNVLIST_EXISTSV(binary, BINARY)
932258065Spjd
933258065Spjd#undef	NVLIST_EXISTSV
934258065Spjd
935258065Spjdvoid
936258065Spjdnvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
937258065Spjd{
938258065Spjd	nvpair_t *newnvp;
939258065Spjd
940258065Spjd	NVPAIR_ASSERT(nvp);
941258065Spjd
942258065Spjd	if (nvlist_error(nvl) != 0) {
943258065Spjd		errno = nvlist_error(nvl);
944258065Spjd		return;
945258065Spjd	}
946258065Spjd	if (nvlist_exists(nvl, nvpair_name(nvp))) {
947258065Spjd		nvl->nvl_error = errno = EEXIST;
948258065Spjd		return;
949258065Spjd	}
950258065Spjd
951258065Spjd	newnvp = nvpair_clone(nvp);
952258065Spjd	if (newnvp == NULL) {
953258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
954258065Spjd		return;
955258065Spjd	}
956258065Spjd
957258065Spjd	nvpair_insert(&nvl->nvl_head, newnvp, nvl);
958258065Spjd}
959258065Spjd
960258065Spjdvoid
961258065Spjdnvlist_add_null(nvlist_t *nvl, const char *name)
962258065Spjd{
963258065Spjd
964258065Spjd	nvlist_addf_null(nvl, "%s", name);
965258065Spjd}
966258065Spjd
967258065Spjdvoid
968258065Spjdnvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
969258065Spjd{
970258065Spjd
971258065Spjd	nvlist_addf_bool(nvl, value, "%s", name);
972258065Spjd}
973258065Spjd
974258065Spjdvoid
975258065Spjdnvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
976258065Spjd{
977258065Spjd
978258065Spjd	nvlist_addf_number(nvl, value, "%s", name);
979258065Spjd}
980258065Spjd
981258065Spjdvoid
982258065Spjdnvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
983258065Spjd{
984258065Spjd
985258065Spjd	nvlist_addf_string(nvl, value, "%s", name);
986258065Spjd}
987258065Spjd
988258065Spjdvoid
989258065Spjdnvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
990258065Spjd{
991258065Spjd	va_list valueap;
992258065Spjd
993258065Spjd	va_start(valueap, valuefmt);
994258065Spjd	nvlist_add_stringv(nvl, name, valuefmt, valueap);
995258065Spjd	va_end(valueap);
996258065Spjd}
997258065Spjd
998258065Spjdvoid
999258065Spjdnvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1000258065Spjd    va_list valueap)
1001258065Spjd{
1002258065Spjd	nvpair_t *nvp;
1003258065Spjd
1004258065Spjd	if (nvlist_error(nvl) != 0) {
1005258065Spjd		errno = nvlist_error(nvl);
1006258065Spjd		return;
1007258065Spjd	}
1008258065Spjd
1009258065Spjd	nvp = nvpair_create_stringv(name, valuefmt, valueap);
1010258065Spjd	if (nvp == NULL)
1011258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1012258065Spjd	else
1013258065Spjd		nvlist_move_nvpair(nvl, nvp);
1014258065Spjd}
1015258065Spjd
1016258065Spjdvoid
1017258065Spjdnvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1018258065Spjd{
1019258065Spjd
1020258065Spjd	nvlist_addf_nvlist(nvl, value, "%s", name);
1021258065Spjd}
1022258065Spjd
1023258065Spjdvoid
1024258065Spjdnvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1025258065Spjd{
1026258065Spjd
1027258065Spjd	nvlist_addf_descriptor(nvl, value, "%s", name);
1028258065Spjd}
1029258065Spjd
1030258065Spjdvoid
1031258065Spjdnvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1032258065Spjd    size_t size)
1033258065Spjd{
1034258065Spjd
1035258065Spjd	nvlist_addf_binary(nvl, value, size, "%s", name);
1036258065Spjd}
1037258065Spjd
1038258065Spjdvoid
1039258065Spjdnvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...)
1040258065Spjd{
1041258065Spjd	va_list nameap;
1042258065Spjd
1043258065Spjd	va_start(nameap, namefmt);
1044258065Spjd	nvlist_addv_null(nvl, namefmt, nameap);
1045258065Spjd	va_end(nameap);
1046258065Spjd}
1047258065Spjd
1048258065Spjdvoid
1049258065Spjdnvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...)
1050258065Spjd{
1051258065Spjd	va_list nameap;
1052258065Spjd
1053258065Spjd	va_start(nameap, namefmt);
1054258065Spjd	nvlist_addv_bool(nvl, value, namefmt, nameap);
1055258065Spjd	va_end(nameap);
1056258065Spjd}
1057258065Spjd
1058258065Spjdvoid
1059258065Spjdnvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1060258065Spjd{
1061258065Spjd	va_list nameap;
1062258065Spjd
1063258065Spjd	va_start(nameap, namefmt);
1064258065Spjd	nvlist_addv_number(nvl, value, namefmt, nameap);
1065258065Spjd	va_end(nameap);
1066258065Spjd}
1067258065Spjd
1068258065Spjdvoid
1069258065Spjdnvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...)
1070258065Spjd{
1071258065Spjd	va_list nameap;
1072258065Spjd
1073258065Spjd	va_start(nameap, namefmt);
1074258065Spjd	nvlist_addv_string(nvl, value, namefmt, nameap);
1075258065Spjd	va_end(nameap);
1076258065Spjd}
1077258065Spjd
1078258065Spjdvoid
1079258065Spjdnvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1080258065Spjd    ...)
1081258065Spjd{
1082258065Spjd	va_list nameap;
1083258065Spjd
1084258065Spjd	va_start(nameap, namefmt);
1085258065Spjd	nvlist_addv_nvlist(nvl, value, namefmt, nameap);
1086258065Spjd	va_end(nameap);
1087258065Spjd}
1088258065Spjd
1089258065Spjdvoid
1090258065Spjdnvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...)
1091258065Spjd{
1092258065Spjd	va_list nameap;
1093258065Spjd
1094258065Spjd	va_start(nameap, namefmt);
1095258065Spjd	nvlist_addv_descriptor(nvl, value, namefmt, nameap);
1096258065Spjd	va_end(nameap);
1097258065Spjd}
1098258065Spjd
1099258065Spjdvoid
1100258065Spjdnvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size,
1101258065Spjd    const char *namefmt, ...)
1102258065Spjd{
1103258065Spjd	va_list nameap;
1104258065Spjd
1105258065Spjd	va_start(nameap, namefmt);
1106258065Spjd	nvlist_addv_binary(nvl, value, size, namefmt, nameap);
1107258065Spjd	va_end(nameap);
1108258065Spjd}
1109258065Spjd
1110258065Spjdvoid
1111258065Spjdnvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap)
1112258065Spjd{
1113258065Spjd	nvpair_t *nvp;
1114258065Spjd
1115258065Spjd	if (nvlist_error(nvl) != 0) {
1116258065Spjd		errno = nvlist_error(nvl);
1117258065Spjd		return;
1118258065Spjd	}
1119258065Spjd
1120258065Spjd	nvp = nvpair_createv_null(namefmt, nameap);
1121258065Spjd	if (nvp == NULL)
1122258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1123258065Spjd	else
1124258065Spjd		nvlist_move_nvpair(nvl, nvp);
1125258065Spjd}
1126258065Spjd
1127258065Spjdvoid
1128258065Spjdnvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap)
1129258065Spjd{
1130258065Spjd	nvpair_t *nvp;
1131258065Spjd
1132258065Spjd	if (nvlist_error(nvl) != 0) {
1133258065Spjd		errno = nvlist_error(nvl);
1134258065Spjd		return;
1135258065Spjd	}
1136258065Spjd
1137258065Spjd	nvp = nvpair_createv_bool(value, namefmt, nameap);
1138258065Spjd	if (nvp == NULL)
1139258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1140258065Spjd	else
1141258065Spjd		nvlist_move_nvpair(nvl, nvp);
1142258065Spjd}
1143258065Spjd
1144258065Spjdvoid
1145258065Spjdnvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt,
1146258065Spjd    va_list nameap)
1147258065Spjd{
1148258065Spjd	nvpair_t *nvp;
1149258065Spjd
1150258065Spjd	if (nvlist_error(nvl) != 0) {
1151258065Spjd		errno = nvlist_error(nvl);
1152258065Spjd		return;
1153258065Spjd	}
1154258065Spjd
1155258065Spjd	nvp = nvpair_createv_number(value, namefmt, nameap);
1156258065Spjd	if (nvp == NULL)
1157258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1158258065Spjd	else
1159258065Spjd		nvlist_move_nvpair(nvl, nvp);
1160258065Spjd}
1161258065Spjd
1162258065Spjdvoid
1163258065Spjdnvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt,
1164258065Spjd    va_list nameap)
1165258065Spjd{
1166258065Spjd	nvpair_t *nvp;
1167258065Spjd
1168258065Spjd	if (nvlist_error(nvl) != 0) {
1169258065Spjd		errno = nvlist_error(nvl);
1170258065Spjd		return;
1171258065Spjd	}
1172258065Spjd
1173258065Spjd	nvp = nvpair_createv_string(value, namefmt, nameap);
1174258065Spjd	if (nvp == NULL)
1175258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1176258065Spjd	else
1177258065Spjd		nvlist_move_nvpair(nvl, nvp);
1178258065Spjd}
1179258065Spjd
1180258065Spjdvoid
1181258065Spjdnvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1182258065Spjd    va_list nameap)
1183258065Spjd{
1184258065Spjd	nvpair_t *nvp;
1185258065Spjd
1186258065Spjd	if (nvlist_error(nvl) != 0) {
1187258065Spjd		errno = nvlist_error(nvl);
1188258065Spjd		return;
1189258065Spjd	}
1190258065Spjd
1191258065Spjd	nvp = nvpair_createv_nvlist(value, namefmt, nameap);
1192258065Spjd	if (nvp == NULL)
1193258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1194258065Spjd	else
1195258065Spjd		nvlist_move_nvpair(nvl, nvp);
1196258065Spjd}
1197258065Spjd
1198258065Spjdvoid
1199258065Spjdnvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1200258065Spjd    va_list nameap)
1201258065Spjd{
1202258065Spjd	nvpair_t *nvp;
1203258065Spjd
1204258065Spjd	if (nvlist_error(nvl) != 0) {
1205258065Spjd		errno = nvlist_error(nvl);
1206258065Spjd		return;
1207258065Spjd	}
1208258065Spjd
1209258065Spjd	nvp = nvpair_createv_descriptor(value, namefmt, nameap);
1210258065Spjd	if (nvp == NULL)
1211258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1212258065Spjd	else
1213258065Spjd		nvlist_move_nvpair(nvl, nvp);
1214258065Spjd}
1215258065Spjd
1216258065Spjdvoid
1217258065Spjdnvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size,
1218258065Spjd    const char *namefmt, va_list nameap)
1219258065Spjd{
1220258065Spjd	nvpair_t *nvp;
1221258065Spjd
1222258065Spjd	if (nvlist_error(nvl) != 0) {
1223258065Spjd		errno = nvlist_error(nvl);
1224258065Spjd		return;
1225258065Spjd	}
1226258065Spjd
1227258065Spjd	nvp = nvpair_createv_binary(value, size, namefmt, nameap);
1228258065Spjd	if (nvp == NULL)
1229258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1230258065Spjd	else
1231258065Spjd		nvlist_move_nvpair(nvl, nvp);
1232258065Spjd}
1233258065Spjd
1234258065Spjdvoid
1235258065Spjdnvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1236258065Spjd{
1237258065Spjd
1238258065Spjd	NVPAIR_ASSERT(nvp);
1239258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1240258065Spjd
1241258065Spjd	if (nvlist_error(nvl) != 0) {
1242258065Spjd		nvpair_free(nvp);
1243258065Spjd		errno = nvlist_error(nvl);
1244258065Spjd		return;
1245258065Spjd	}
1246258065Spjd	if (nvlist_exists(nvl, nvpair_name(nvp))) {
1247258065Spjd		nvpair_free(nvp);
1248258065Spjd		nvl->nvl_error = errno = EEXIST;
1249258065Spjd		return;
1250258065Spjd	}
1251258065Spjd
1252258065Spjd	nvpair_insert(&nvl->nvl_head, nvp, nvl);
1253258065Spjd}
1254258065Spjd
1255258065Spjd#define	NVLIST_MOVE(vtype, type)					\
1256258065Spjdvoid									\
1257258065Spjdnvlist_move_##type(nvlist_t *nvl, const char *name, vtype value)	\
1258258065Spjd{									\
1259258065Spjd									\
1260258065Spjd	nvlist_movef_##type(nvl, value, "%s", name);			\
1261258065Spjd}
1262258065Spjd
1263258065SpjdNVLIST_MOVE(char *, string)
1264258065SpjdNVLIST_MOVE(nvlist_t *, nvlist)
1265258065SpjdNVLIST_MOVE(int, descriptor)
1266258065Spjd
1267258065Spjd#undef	NVLIST_MOVE
1268258065Spjd
1269258065Spjdvoid
1270258065Spjdnvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1271258065Spjd{
1272258065Spjd
1273258065Spjd	nvlist_movef_binary(nvl, value, size, "%s", name);
1274258065Spjd}
1275258065Spjd
1276258065Spjd#define	NVLIST_MOVEF(vtype, type)					\
1277258065Spjdvoid									\
1278258065Spjdnvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt,	\
1279258065Spjd    ...)								\
1280258065Spjd{									\
1281258065Spjd	va_list nameap;							\
1282258065Spjd									\
1283258065Spjd	va_start(nameap, namefmt);					\
1284258065Spjd	nvlist_movev_##type(nvl, value, namefmt, nameap);		\
1285258065Spjd	va_end(nameap);							\
1286258065Spjd}
1287258065Spjd
1288258065SpjdNVLIST_MOVEF(char *, string)
1289258065SpjdNVLIST_MOVEF(nvlist_t *, nvlist)
1290258065SpjdNVLIST_MOVEF(int, descriptor)
1291258065Spjd
1292258065Spjd#undef	NVLIST_MOVEF
1293258065Spjd
1294258065Spjdvoid
1295258065Spjdnvlist_movef_binary(nvlist_t *nvl, void *value, size_t size,
1296258065Spjd    const char *namefmt, ...)
1297258065Spjd{
1298258065Spjd	va_list nameap;
1299258065Spjd
1300258065Spjd	va_start(nameap, namefmt);
1301258065Spjd	nvlist_movev_binary(nvl, value, size, namefmt, nameap);
1302258065Spjd	va_end(nameap);
1303258065Spjd}
1304258065Spjd
1305258065Spjdvoid
1306258065Spjdnvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt,
1307258065Spjd    va_list nameap)
1308258065Spjd{
1309258065Spjd	nvpair_t *nvp;
1310258065Spjd
1311258065Spjd	if (nvlist_error(nvl) != 0) {
1312258065Spjd		free(value);
1313258065Spjd		errno = nvlist_error(nvl);
1314258065Spjd		return;
1315258065Spjd	}
1316258065Spjd
1317258065Spjd	nvp = nvpair_movev_string(value, namefmt, nameap);
1318258065Spjd	if (nvp == NULL)
1319258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1320258065Spjd	else
1321258065Spjd		nvlist_move_nvpair(nvl, nvp);
1322258065Spjd}
1323258065Spjd
1324258065Spjdvoid
1325258065Spjdnvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
1326258065Spjd    va_list nameap)
1327258065Spjd{
1328258065Spjd	nvpair_t *nvp;
1329258065Spjd
1330258065Spjd	if (nvlist_error(nvl) != 0) {
1331258065Spjd		nvlist_destroy(value);
1332258065Spjd		errno = nvlist_error(nvl);
1333258065Spjd		return;
1334258065Spjd	}
1335258065Spjd
1336258065Spjd	nvp = nvpair_movev_nvlist(value, namefmt, nameap);
1337258065Spjd	if (nvp == NULL)
1338258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1339258065Spjd	else
1340258065Spjd		nvlist_move_nvpair(nvl, nvp);
1341258065Spjd}
1342258065Spjd
1343258065Spjdvoid
1344258065Spjdnvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1345258065Spjd    va_list nameap)
1346258065Spjd{
1347258065Spjd	nvpair_t *nvp;
1348258065Spjd
1349258065Spjd	if (nvlist_error(nvl) != 0) {
1350258065Spjd		close(value);
1351258065Spjd		errno = nvlist_error(nvl);
1352258065Spjd		return;
1353258065Spjd	}
1354258065Spjd
1355258065Spjd	nvp = nvpair_movev_descriptor(value, namefmt, nameap);
1356258065Spjd	if (nvp == NULL)
1357258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1358258065Spjd	else
1359258065Spjd		nvlist_move_nvpair(nvl, nvp);
1360258065Spjd}
1361258065Spjd
1362258065Spjdvoid
1363258065Spjdnvlist_movev_binary(nvlist_t *nvl, void *value, size_t size,
1364258065Spjd    const char *namefmt, va_list nameap)
1365258065Spjd{
1366258065Spjd	nvpair_t *nvp;
1367258065Spjd
1368258065Spjd	if (nvlist_error(nvl) != 0) {
1369258065Spjd		free(value);
1370258065Spjd		errno = nvlist_error(nvl);
1371258065Spjd		return;
1372258065Spjd	}
1373258065Spjd
1374258065Spjd	nvp = nvpair_movev_binary(value, size, namefmt, nameap);
1375258065Spjd	if (nvp == NULL)
1376258065Spjd		nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1377258065Spjd	else
1378258065Spjd		nvlist_move_nvpair(nvl, nvp);
1379258065Spjd}
1380258065Spjd
1381258065Spjd#define	NVLIST_GET(ftype, type)						\
1382258065Spjdftype									\
1383258065Spjdnvlist_get_##type(const nvlist_t *nvl, const char *name)		\
1384258065Spjd{									\
1385258065Spjd									\
1386258065Spjd	return (nvlist_getf_##type(nvl, "%s", name));			\
1387258065Spjd}
1388258065Spjd
1389258065SpjdNVLIST_GET(const nvpair_t *, nvpair)
1390258065SpjdNVLIST_GET(bool, bool)
1391258065SpjdNVLIST_GET(uint64_t, number)
1392258065SpjdNVLIST_GET(const char *, string)
1393258065SpjdNVLIST_GET(const nvlist_t *, nvlist)
1394258065SpjdNVLIST_GET(int, descriptor)
1395258065Spjd
1396258065Spjd#undef	NVLIST_GET
1397258065Spjd
1398258065Spjdconst void *
1399258065Spjdnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1400258065Spjd{
1401258065Spjd
1402258065Spjd	return (nvlist_getf_binary(nvl, sizep, "%s", name));
1403258065Spjd}
1404258065Spjd
1405258065Spjd#define	NVLIST_GETF(ftype, type)					\
1406258065Spjdftype									\
1407258065Spjdnvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...)	\
1408258065Spjd{									\
1409258065Spjd	va_list nameap;							\
1410258065Spjd	ftype value;							\
1411258065Spjd									\
1412258065Spjd	va_start(nameap, namefmt);					\
1413258065Spjd	value = nvlist_getv_##type(nvl, namefmt, nameap);		\
1414258065Spjd	va_end(nameap);							\
1415258065Spjd									\
1416258065Spjd	return (value);							\
1417258065Spjd}
1418258065Spjd
1419258065SpjdNVLIST_GETF(const nvpair_t *, nvpair)
1420258065SpjdNVLIST_GETF(bool, bool)
1421258065SpjdNVLIST_GETF(uint64_t, number)
1422258065SpjdNVLIST_GETF(const char *, string)
1423258065SpjdNVLIST_GETF(const nvlist_t *, nvlist)
1424258065SpjdNVLIST_GETF(int, descriptor)
1425258065Spjd
1426258065Spjd#undef	NVLIST_GETF
1427258065Spjd
1428258065Spjdconst void *
1429258065Spjdnvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1430258065Spjd{
1431258065Spjd	va_list nameap;
1432258065Spjd	const void *value;
1433258065Spjd
1434258065Spjd	va_start(nameap, namefmt);
1435258065Spjd	value = nvlist_getv_binary(nvl, sizep, namefmt, nameap);
1436258065Spjd	va_end(nameap);
1437258065Spjd
1438258065Spjd	return (value);
1439258065Spjd}
1440258065Spjd
1441258065Spjdconst nvpair_t *
1442258065Spjdnvlist_getv_nvpair(const nvlist_t *nvl, const char *namefmt, va_list nameap)
1443258065Spjd{
1444258065Spjd
1445258065Spjd	return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap));
1446258065Spjd}
1447258065Spjd
1448258065Spjd#define	NVLIST_GETV(ftype, type, TYPE)					\
1449258065Spjdftype									\
1450258065Spjdnvlist_getv_##type(const nvlist_t *nvl, const char *namefmt,		\
1451258065Spjd    va_list nameap)							\
1452258065Spjd{									\
1453258065Spjd	va_list cnameap;						\
1454258065Spjd	const nvpair_t *nvp;						\
1455258065Spjd									\
1456258065Spjd	va_copy(cnameap, nameap);					\
1457258065Spjd	nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap);	\
1458258065Spjd	va_end(cnameap);						\
1459258065Spjd	if (nvp == NULL)						\
1460258065Spjd		nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap);	\
1461258065Spjd	return (nvpair_get_##type(nvp));				\
1462258065Spjd}
1463258065Spjd
1464258065SpjdNVLIST_GETV(bool, bool, BOOL)
1465258065SpjdNVLIST_GETV(uint64_t, number, NUMBER)
1466258065SpjdNVLIST_GETV(const char *, string, STRING)
1467258065SpjdNVLIST_GETV(const nvlist_t *, nvlist, NVLIST)
1468258065SpjdNVLIST_GETV(int, descriptor, DESCRIPTOR)
1469258065Spjd
1470258065Spjd#undef	NVLIST_GETV
1471258065Spjd
1472258065Spjdconst void *
1473258065Spjdnvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt,
1474258065Spjd    va_list nameap)
1475258065Spjd{
1476258065Spjd	va_list cnameap;
1477258065Spjd	const nvpair_t *nvp;
1478258065Spjd
1479258065Spjd	va_copy(cnameap, nameap);
1480258065Spjd	nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap);
1481258065Spjd	va_end(cnameap);
1482258065Spjd	if (nvp == NULL)
1483258065Spjd		nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap);
1484258065Spjd
1485258065Spjd	return (nvpair_get_binary(nvp, sizep));
1486258065Spjd}
1487258065Spjd
1488258065Spjd#define	NVLIST_TAKE(ftype, type)					\
1489258065Spjdftype									\
1490258065Spjdnvlist_take_##type(nvlist_t *nvl, const char *name)			\
1491258065Spjd{									\
1492258065Spjd									\
1493258065Spjd	return (nvlist_takef_##type(nvl, "%s", name));			\
1494258065Spjd}
1495258065Spjd
1496258065SpjdNVLIST_TAKE(nvpair_t *, nvpair)
1497258065SpjdNVLIST_TAKE(bool, bool)
1498258065SpjdNVLIST_TAKE(uint64_t, number)
1499258065SpjdNVLIST_TAKE(char *, string)
1500258065SpjdNVLIST_TAKE(nvlist_t *, nvlist)
1501258065SpjdNVLIST_TAKE(int, descriptor)
1502258065Spjd
1503258065Spjd#undef	NVLIST_TAKE
1504258065Spjd
1505258065Spjdvoid *
1506258065Spjdnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1507258065Spjd{
1508258065Spjd
1509258065Spjd	return (nvlist_takef_binary(nvl, sizep, "%s", name));
1510258065Spjd}
1511258065Spjd
1512258065Spjd#define	NVLIST_TAKEF(ftype, type)					\
1513258065Spjdftype									\
1514258065Spjdnvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...)		\
1515258065Spjd{									\
1516258065Spjd	va_list nameap;							\
1517258065Spjd	ftype value;							\
1518258065Spjd									\
1519258065Spjd	va_start(nameap, namefmt);					\
1520258065Spjd	value = nvlist_takev_##type(nvl, namefmt, nameap);		\
1521258065Spjd	va_end(nameap);							\
1522258065Spjd									\
1523258065Spjd	return (value);							\
1524258065Spjd}
1525258065Spjd
1526258065SpjdNVLIST_TAKEF(nvpair_t *, nvpair)
1527258065SpjdNVLIST_TAKEF(bool, bool)
1528258065SpjdNVLIST_TAKEF(uint64_t, number)
1529258065SpjdNVLIST_TAKEF(char *, string)
1530258065SpjdNVLIST_TAKEF(nvlist_t *, nvlist)
1531258065SpjdNVLIST_TAKEF(int, descriptor)
1532258065Spjd
1533258065Spjd#undef	NVLIST_TAKEF
1534258065Spjd
1535258065Spjdvoid *
1536258065Spjdnvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1537258065Spjd{
1538258065Spjd	va_list nameap;
1539258065Spjd	void *value;
1540258065Spjd
1541258065Spjd	va_start(nameap, namefmt);
1542258065Spjd	value = nvlist_takev_binary(nvl, sizep, namefmt, nameap);
1543258065Spjd	va_end(nameap);
1544258065Spjd
1545258065Spjd	return (value);
1546258065Spjd}
1547258065Spjd
1548258065Spjdnvpair_t *
1549258065Spjdnvlist_takev_nvpair(nvlist_t *nvl, const char *namefmt, va_list nameap)
1550258065Spjd{
1551258065Spjd	nvpair_t *nvp;
1552258065Spjd
1553258065Spjd	nvp = nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap);
1554258065Spjd	if (nvp != NULL)
1555258065Spjd		nvlist_remove_nvpair(nvl, nvp);
1556258065Spjd	return (nvp);
1557258065Spjd}
1558258065Spjd
1559258065Spjd#define	NVLIST_TAKEV(ftype, type, TYPE)					\
1560258065Spjdftype									\
1561258065Spjdnvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap)	\
1562258065Spjd{									\
1563258065Spjd	va_list cnameap;						\
1564258065Spjd	nvpair_t *nvp;							\
1565258065Spjd	ftype value;							\
1566258065Spjd									\
1567258065Spjd	va_copy(cnameap, nameap);					\
1568258065Spjd	nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap);	\
1569258065Spjd	va_end(cnameap);						\
1570258065Spjd	if (nvp == NULL)						\
1571258065Spjd		nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap);	\
1572258065Spjd	value = (ftype)(intptr_t)nvpair_get_##type(nvp);		\
1573258065Spjd	nvlist_remove_nvpair(nvl, nvp);					\
1574258065Spjd	nvpair_free_structure(nvp);					\
1575258065Spjd	return (value);							\
1576258065Spjd}
1577258065Spjd
1578258065SpjdNVLIST_TAKEV(bool, bool, BOOL)
1579258065SpjdNVLIST_TAKEV(uint64_t, number, NUMBER)
1580258065SpjdNVLIST_TAKEV(char *, string, STRING)
1581258065SpjdNVLIST_TAKEV(nvlist_t *, nvlist, NVLIST)
1582258065SpjdNVLIST_TAKEV(int, descriptor, DESCRIPTOR)
1583258065Spjd
1584258065Spjd#undef	NVLIST_TAKEV
1585258065Spjd
1586258065Spjdvoid *
1587258065Spjdnvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt,
1588258065Spjd    va_list nameap)
1589258065Spjd{
1590258065Spjd	va_list cnameap;
1591258065Spjd	nvpair_t *nvp;
1592258065Spjd	void *value;
1593258065Spjd
1594258065Spjd	va_copy(cnameap, nameap);
1595258065Spjd	nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap);
1596258065Spjd	va_end(cnameap);
1597258065Spjd	if (nvp == NULL)
1598258065Spjd		nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap);
1599258065Spjd
1600258065Spjd	value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1601258065Spjd	nvlist_remove_nvpair(nvl, nvp);
1602258065Spjd	nvpair_free_structure(nvp);
1603258065Spjd	return (value);
1604258065Spjd}
1605258065Spjd
1606258065Spjdvoid
1607258065Spjdnvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1608258065Spjd{
1609258065Spjd
1610258065Spjd	NVLIST_ASSERT(nvl);
1611258065Spjd	NVPAIR_ASSERT(nvp);
1612258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1613258065Spjd
1614258065Spjd	nvpair_remove(&nvl->nvl_head, nvp, nvl);
1615258065Spjd}
1616258065Spjd
1617258065Spjdvoid
1618258065Spjdnvlist_free(nvlist_t *nvl, const char *name)
1619258065Spjd{
1620258065Spjd
1621258065Spjd	nvlist_freef(nvl, "%s", name);
1622258065Spjd}
1623258065Spjd
1624258065Spjd#define	NVLIST_FREE(type)						\
1625258065Spjdvoid									\
1626258065Spjdnvlist_free_##type(nvlist_t *nvl, const char *name)			\
1627258065Spjd{									\
1628258065Spjd									\
1629258065Spjd	nvlist_freef_##type(nvl, "%s", name);				\
1630258065Spjd}
1631258065Spjd
1632258065SpjdNVLIST_FREE(null)
1633258065SpjdNVLIST_FREE(bool)
1634258065SpjdNVLIST_FREE(number)
1635258065SpjdNVLIST_FREE(string)
1636258065SpjdNVLIST_FREE(nvlist)
1637258065SpjdNVLIST_FREE(descriptor)
1638258065SpjdNVLIST_FREE(binary)
1639258065Spjd
1640258065Spjd#undef	NVLIST_FREE
1641258065Spjd
1642258065Spjdvoid
1643258065Spjdnvlist_freef(nvlist_t *nvl, const char *namefmt, ...)
1644258065Spjd{
1645258065Spjd	va_list nameap;
1646258065Spjd
1647258065Spjd	va_start(nameap, namefmt);
1648258065Spjd	nvlist_freev(nvl, namefmt, nameap);
1649258065Spjd	va_end(nameap);
1650258065Spjd}
1651258065Spjd
1652258065Spjd#define	NVLIST_FREEF(type)						\
1653258065Spjdvoid									\
1654258065Spjdnvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...)		\
1655258065Spjd{									\
1656258065Spjd	va_list nameap;							\
1657258065Spjd									\
1658258065Spjd	va_start(nameap, namefmt);					\
1659258065Spjd	nvlist_freev_##type(nvl, namefmt, nameap);			\
1660258065Spjd	va_end(nameap);							\
1661258065Spjd}
1662258065Spjd
1663258065SpjdNVLIST_FREEF(null)
1664258065SpjdNVLIST_FREEF(bool)
1665258065SpjdNVLIST_FREEF(number)
1666258065SpjdNVLIST_FREEF(string)
1667258065SpjdNVLIST_FREEF(nvlist)
1668258065SpjdNVLIST_FREEF(descriptor)
1669258065SpjdNVLIST_FREEF(binary)
1670258065Spjd
1671258065Spjd#undef	NVLIST_FREEF
1672258065Spjd
1673258065Spjdvoid
1674258065Spjdnvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap)
1675258065Spjd{
1676258065Spjd
1677258065Spjd	nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap);
1678258065Spjd}
1679258065Spjd
1680258065Spjd#define	NVLIST_FREEV(type, TYPE)					\
1681258065Spjdvoid									\
1682258065Spjdnvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap)	\
1683258065Spjd{									\
1684258065Spjd									\
1685258065Spjd	nvlist_freev_type(nvl, NV_TYPE_##TYPE, namefmt, nameap);	\
1686258065Spjd}
1687258065Spjd
1688258065SpjdNVLIST_FREEV(null, NULL)
1689258065SpjdNVLIST_FREEV(bool, BOOL)
1690258065SpjdNVLIST_FREEV(number, NUMBER)
1691258065SpjdNVLIST_FREEV(string, STRING)
1692258065SpjdNVLIST_FREEV(nvlist, NVLIST)
1693258065SpjdNVLIST_FREEV(descriptor, DESCRIPTOR)
1694258065SpjdNVLIST_FREEV(binary, BINARY)
1695258065Spjd#undef	NVLIST_FREEV
1696258065Spjd
1697258065Spjdvoid
1698258065Spjdnvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1699258065Spjd{
1700258065Spjd
1701258065Spjd	NVLIST_ASSERT(nvl);
1702258065Spjd	NVPAIR_ASSERT(nvp);
1703258065Spjd	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1704258065Spjd
1705258065Spjd	nvlist_remove_nvpair(nvl, nvp);
1706258065Spjd	nvpair_free(nvp);
1707258065Spjd}
1708