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