2 * Copyright (c) 2009-2013 The FreeBSD Foundation
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/endian.h>
35 #include <sys/queue.h>
39 #include <sys/errno.h>
40 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/systm.h>
45 #include <machine/stdarg.h>
48 #include <sys/socket.h>
68 #include <sys/nv_impl.h>
69 #include <sys/nvlist_impl.h>
70 #include <sys/nvpair_impl.h>
74 #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
75 #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
76 #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
79 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
80 #define PJDLOG_RASSERT(expr, ...) assert(expr)
81 #define PJDLOG_ABORT(...) do { \
82 fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \
83 fprintf(stderr, __VA_ARGS__); \
84 fprintf(stderr, "\n"); \
90 #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN)
91 #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE)
92 #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
94 #define NVLIST_MAGIC 0x6e766c /* "nvl" */
100 struct nvl_head nvl_head;
103 #define NVLIST_ASSERT(nvl) do { \
104 PJDLOG_ASSERT((nvl) != NULL); \
105 PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \
109 MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
112 #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp)
114 #define NVLIST_HEADER_MAGIC 0x6c
115 #define NVLIST_HEADER_VERSION 0x00
116 struct nvlist_header {
118 uint8_t nvlh_version;
120 uint64_t nvlh_descriptors;
125 nvlist_create(int flags)
129 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
131 nvl = nv_malloc(sizeof(*nvl));
135 nvl->nvl_flags = flags;
136 nvl->nvl_parent = NULL;
137 TAILQ_INIT(&nvl->nvl_head);
138 nvl->nvl_magic = NVLIST_MAGIC;
144 nvlist_destroy(nvlist_t *nvl)
155 while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
156 nvlist_remove_nvpair(nvl, nvp);
166 nvlist_set_error(nvlist_t *nvl, int error)
169 PJDLOG_ASSERT(error != 0);
172 * Check for error != 0 so that we don't do the wrong thing if somebody
173 * tries to abuse this API when asserts are disabled.
175 if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
176 nvl->nvl_error = error;
180 nvlist_error(const nvlist_t *nvl)
188 return (nvl->nvl_error);
192 nvlist_get_nvpair_parent(const nvlist_t *nvl)
197 return (nvl->nvl_parent);
201 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
207 nvp = nvl->nvl_parent;
213 return (nvpair_nvlist(nvp));
217 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
222 nvl->nvl_parent = parent;
226 nvlist_empty(const nvlist_t *nvl)
230 PJDLOG_ASSERT(nvl->nvl_error == 0);
232 return (nvlist_first_nvpair(nvl) == NULL);
236 nvlist_flags(const nvlist_t *nvl)
240 PJDLOG_ASSERT(nvl->nvl_error == 0);
241 PJDLOG_ASSERT((nvl->nvl_flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
243 return (nvl->nvl_flags);
247 nvlist_report_missing(int type, const char *name)
250 PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
251 name, nvpair_type_string(type));
255 nvlist_find(const nvlist_t *nvl, int type, const char *name)
260 PJDLOG_ASSERT(nvl->nvl_error == 0);
261 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
262 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
264 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
265 nvp = nvlist_next_nvpair(nvl, nvp)) {
266 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
268 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
269 if (strcasecmp(nvpair_name(nvp), name) != 0)
272 if (strcmp(nvpair_name(nvp), name) != 0)
285 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
289 PJDLOG_ASSERT(nvl->nvl_error == 0);
290 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
291 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
293 return (nvlist_find(nvl, type, name) != NULL);
297 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
302 PJDLOG_ASSERT(nvl->nvl_error == 0);
303 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
304 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
306 nvp = nvlist_find(nvl, type, name);
308 nvlist_free_nvpair(nvl, nvp);
310 nvlist_report_missing(type, name);
314 nvlist_clone(const nvlist_t *nvl)
317 nvpair_t *nvp, *newnvp;
321 if (nvl->nvl_error != 0) {
322 ERRNO_SET(nvl->nvl_error);
326 newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
327 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
328 nvp = nvlist_next_nvpair(nvl, nvp)) {
329 newnvp = nvpair_clone(nvp);
332 nvlist_move_nvpair(newnvl, newnvp);
335 nvlist_destroy(newnvl);
343 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
346 if (nvlist_error(nvl) != 0) {
347 dprintf(fd, "%*serror: %d\n", level * 4, "",
356 * Dump content of nvlist.
359 nvlist_dump(const nvlist_t *nvl, int fd)
361 const nvlist_t *tmpnvl;
362 nvpair_t *nvp, *tmpnvp;
367 if (nvlist_dump_error_check(nvl, fd, level))
370 nvp = nvlist_first_nvpair(nvl);
371 while (nvp != NULL) {
372 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
373 nvpair_type_string(nvpair_type(nvp)));
374 switch (nvpair_type(nvp)) {
376 dprintf(fd, " null\n");
379 dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
383 dprintf(fd, " %ju (%jd) (0x%jx)\n",
384 (uintmax_t)nvpair_get_number(nvp),
385 (intmax_t)nvpair_get_number(nvp),
386 (uintmax_t)nvpair_get_number(nvp));
389 dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
393 tmpnvl = nvpair_get_nvlist(nvp);
394 if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
396 tmpnvp = nvlist_first_nvpair(tmpnvl);
397 if (tmpnvp != NULL) {
404 case NV_TYPE_DESCRIPTOR:
405 dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
409 const unsigned char *binary;
413 binary = nvpair_get_binary(nvp, &size);
414 dprintf(fd, " %zu ", size);
415 for (ii = 0; ii < size; ii++)
416 dprintf(fd, "%02hhx", binary[ii]);
421 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
424 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
426 nvl = nvlist_get_parent(nvl, &cookie);
436 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
440 nvlist_dump(nvl, fileno(fp));
445 * The function obtains size of the nvlist after nvlist_pack().
448 nvlist_size(const nvlist_t *nvl)
450 const nvlist_t *tmpnvl;
451 const nvpair_t *nvp, *tmpnvp;
456 PJDLOG_ASSERT(nvl->nvl_error == 0);
458 size = sizeof(struct nvlist_header);
459 nvp = nvlist_first_nvpair(nvl);
460 while (nvp != NULL) {
461 size += nvpair_header_size();
462 size += strlen(nvpair_name(nvp)) + 1;
463 if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
464 size += sizeof(struct nvlist_header);
465 size += nvpair_header_size() + 1;
466 tmpnvl = nvpair_get_nvlist(nvp);
467 PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
468 tmpnvp = nvlist_first_nvpair(tmpnvl);
469 if (tmpnvp != NULL) {
475 size += nvpair_size(nvp);
478 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
480 nvl = nvlist_get_parent(nvl, &cookie);
493 nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
500 PJDLOG_ASSERT(nvl->nvl_error == 0);
504 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
506 case NV_TYPE_DESCRIPTOR:
507 *descs = nvpair_get_descriptor(nvp);
511 nvl = nvpair_get_nvlist(nvp);
516 } while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
524 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
529 nitems = nvlist_ndescriptors(nvl);
530 fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
534 nvlist_xdescriptors(nvl, fds);
543 nvlist_ndescriptors(const nvlist_t *nvl)
552 PJDLOG_ASSERT(nvl->nvl_error == 0);
557 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
559 case NV_TYPE_DESCRIPTOR:
563 nvl = nvpair_get_nvlist(nvp);
568 } while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
576 static unsigned char *
577 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
579 struct nvlist_header nvlhdr;
583 nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
584 nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
585 nvlhdr.nvlh_flags = nvl->nvl_flags;
586 #if BYTE_ORDER == BIG_ENDIAN
587 nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
589 nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
590 nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
591 PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
592 memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
593 ptr += sizeof(nvlhdr);
594 *leftp -= sizeof(nvlhdr);
600 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
602 unsigned char *buf, *ptr;
604 const nvlist_t *tmpnvl;
605 nvpair_t *nvp, *tmpnvp;
610 if (nvl->nvl_error != 0) {
611 ERRNO_SET(nvl->nvl_error);
615 size = nvlist_size(nvl);
616 buf = nv_malloc(size);
623 ptr = nvlist_pack_header(nvl, ptr, &left);
625 nvp = nvlist_first_nvpair(nvl);
626 while (nvp != NULL) {
629 nvpair_init_datasize(nvp);
630 ptr = nvpair_pack_header(nvp, ptr, &left);
635 switch (nvpair_type(nvp)) {
637 ptr = nvpair_pack_null(nvp, ptr, &left);
640 ptr = nvpair_pack_bool(nvp, ptr, &left);
643 ptr = nvpair_pack_number(nvp, ptr, &left);
646 ptr = nvpair_pack_string(nvp, ptr, &left);
649 tmpnvl = nvpair_get_nvlist(nvp);
650 ptr = nvlist_pack_header(tmpnvl, ptr, &left);
653 tmpnvp = nvlist_first_nvpair(tmpnvl);
654 if (tmpnvp != NULL) {
659 ptr = nvpair_pack_nvlist_up(ptr, &left);
662 case NV_TYPE_DESCRIPTOR:
663 ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
667 ptr = nvpair_pack_binary(nvp, ptr, &left);
670 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
676 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
678 nvl = nvlist_get_parent(nvl, &cookie);
682 ptr = nvpair_pack_nvlist_up(ptr, &left);
695 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
700 if (nvl->nvl_error != 0) {
701 ERRNO_SET(nvl->nvl_error);
705 if (nvlist_ndescriptors(nvl) > 0) {
706 ERRNO_SET(EOPNOTSUPP);
710 return (nvlist_xpack(nvl, NULL, sizep));
714 nvlist_check_header(struct nvlist_header *nvlhdrp)
717 if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
721 if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
725 #if BYTE_ORDER == BIG_ENDIAN
726 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
727 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
728 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
731 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
732 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
733 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
739 const unsigned char *
740 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
741 bool *isbep, size_t *leftp)
743 struct nvlist_header nvlhdr;
745 if (*leftp < sizeof(nvlhdr))
748 memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
750 if (!nvlist_check_header(&nvlhdr))
753 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
757 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
759 if (nvlhdr.nvlh_descriptors > nfds)
762 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
765 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
767 ptr += sizeof(nvlhdr);
769 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
770 *leftp -= sizeof(nvlhdr);
779 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
782 const unsigned char *ptr;
783 nvlist_t *nvl, *retnvl, *tmpnvl;
788 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
794 nvl = retnvl = nvlist_create(0);
798 ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
801 if (nvl->nvl_flags != flags) {
807 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
810 switch (nvpair_type(nvp)) {
812 ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
815 ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
818 ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
821 ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
824 ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
826 nvlist_set_parent(tmpnvl, nvp);
829 case NV_TYPE_DESCRIPTOR:
830 ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
835 ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
837 case NV_TYPE_NVLIST_UP:
838 if (nvl->nvl_parent == NULL)
840 nvl = nvpair_nvlist(nvl->nvl_parent);
841 nvpair_free_structure(nvp);
844 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
848 nvlist_move_nvpair(nvl, nvp);
849 if (tmpnvl != NULL) {
857 nvlist_destroy(retnvl);
862 nvlist_unpack(const void *buf, size_t size, int flags)
865 return (nvlist_xunpack(buf, size, NULL, 0, flags));
870 nvlist_send(int sock, const nvlist_t *nvl)
872 size_t datasize, nfds;
878 if (nvlist_error(nvl) != 0) {
879 ERRNO_SET(nvlist_error(nvl));
883 fds = nvlist_descriptors(nvl, &nfds);
891 data = nvlist_xpack(nvl, &fdidx, &datasize);
895 if (buf_send(sock, data, datasize) == -1)
899 if (fd_send(sock, fds, nfds) == -1)
913 nvlist_recv(int sock, int flags)
915 struct nvlist_header nvlhdr;
918 size_t nfds, size, i;
921 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
924 if (!nvlist_check_header(&nvlhdr))
927 nfds = (size_t)nvlhdr.nvlh_descriptors;
928 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
930 buf = nv_malloc(size);
934 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
939 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
943 fds = nv_malloc(nfds * sizeof(fds[0]));
946 if (fd_recv(sock, fds, nfds) == -1)
950 nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
953 for (i = 0; i < nfds; i++)
970 nvlist_xfer(int sock, nvlist_t *nvl, int flags)
973 if (nvlist_send(sock, nvl) < 0) {
978 return (nvlist_recv(sock, flags));
983 nvlist_first_nvpair(const nvlist_t *nvl)
988 return (TAILQ_FIRST(&nvl->nvl_head));
992 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
998 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1000 retnvp = nvpair_next(nvp);
1001 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1008 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1014 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1016 retnvp = nvpair_prev(nvp);
1017 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1023 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1028 PJDLOG_ASSERT(cookiep != NULL);
1030 if (*cookiep == NULL)
1031 nvp = nvlist_first_nvpair(nvl);
1033 nvp = nvlist_next_nvpair(nvl, *cookiep);
1037 *typep = nvpair_type(nvp);
1039 return (nvpair_name(nvp));
1043 nvlist_exists(const nvlist_t *nvl, const char *name)
1046 return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1049 #define NVLIST_EXISTS(type, TYPE) \
1051 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
1054 return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \
1057 NVLIST_EXISTS(null, NULL)
1058 NVLIST_EXISTS(bool, BOOL)
1059 NVLIST_EXISTS(number, NUMBER)
1060 NVLIST_EXISTS(string, STRING)
1061 NVLIST_EXISTS(nvlist, NVLIST)
1063 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1065 NVLIST_EXISTS(binary, BINARY)
1067 #undef NVLIST_EXISTS
1070 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1076 if (nvlist_error(nvl) != 0) {
1077 ERRNO_SET(nvlist_error(nvl));
1080 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1081 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1082 nvl->nvl_error = EEXIST;
1083 ERRNO_SET(nvlist_error(nvl));
1088 newnvp = nvpair_clone(nvp);
1089 if (newnvp == NULL) {
1090 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1091 ERRNO_SET(nvlist_error(nvl));
1095 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1099 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1103 va_start(valueap, valuefmt);
1104 nvlist_add_stringv(nvl, name, valuefmt, valueap);
1109 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1114 if (nvlist_error(nvl) != 0) {
1115 ERRNO_SET(nvlist_error(nvl));
1119 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1121 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1122 ERRNO_SET(nvl->nvl_error);
1124 nvlist_move_nvpair(nvl, nvp);
1129 nvlist_add_null(nvlist_t *nvl, const char *name)
1133 if (nvlist_error(nvl) != 0) {
1134 ERRNO_SET(nvlist_error(nvl));
1138 nvp = nvpair_create_null(name);
1140 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1141 ERRNO_SET(nvl->nvl_error);
1143 nvlist_move_nvpair(nvl, nvp);
1148 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1153 if (nvlist_error(nvl) != 0) {
1154 ERRNO_SET(nvlist_error(nvl));
1158 nvp = nvpair_create_binary(name, value, size);
1160 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1161 ERRNO_SET(nvl->nvl_error);
1163 nvlist_move_nvpair(nvl, nvp);
1168 #define NVLIST_ADD(vtype, type) \
1170 nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \
1174 if (nvlist_error(nvl) != 0) { \
1175 ERRNO_SET(nvlist_error(nvl)); \
1179 nvp = nvpair_create_##type(name, value); \
1180 if (nvp == NULL) { \
1181 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1182 ERRNO_SET(nvl->nvl_error); \
1184 nvlist_move_nvpair(nvl, nvp); \
1188 NVLIST_ADD(bool, bool)
1189 NVLIST_ADD(uint64_t, number)
1190 NVLIST_ADD(const char *, string)
1191 NVLIST_ADD(const nvlist_t *, nvlist)
1193 NVLIST_ADD(int, descriptor);
1199 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1203 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1205 if (nvlist_error(nvl) != 0) {
1207 ERRNO_SET(nvlist_error(nvl));
1210 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1211 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1213 nvl->nvl_error = EEXIST;
1214 ERRNO_SET(nvl->nvl_error);
1219 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1223 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1227 if (nvlist_error(nvl) != 0) {
1229 ERRNO_SET(nvlist_error(nvl));
1233 nvp = nvpair_move_string(name, value);
1235 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1236 ERRNO_SET(nvl->nvl_error);
1238 nvlist_move_nvpair(nvl, nvp);
1243 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1247 if (nvlist_error(nvl) != 0) {
1248 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1249 nvlist_destroy(value);
1250 ERRNO_SET(nvlist_error(nvl));
1254 nvp = nvpair_move_nvlist(name, value);
1256 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1257 ERRNO_SET(nvl->nvl_error);
1259 nvlist_move_nvpair(nvl, nvp);
1265 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1269 if (nvlist_error(nvl) != 0) {
1271 ERRNO_SET(nvlist_error(nvl));
1275 nvp = nvpair_move_descriptor(name, value);
1277 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1278 ERRNO_SET(nvl->nvl_error);
1280 nvlist_move_nvpair(nvl, nvp);
1286 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1290 if (nvlist_error(nvl) != 0) {
1292 ERRNO_SET(nvlist_error(nvl));
1296 nvp = nvpair_move_binary(name, value, size);
1298 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1299 ERRNO_SET(nvl->nvl_error);
1301 nvlist_move_nvpair(nvl, nvp);
1306 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1309 return (nvlist_find(nvl, NV_TYPE_NONE, name));
1312 #define NVLIST_GET(ftype, type, TYPE) \
1314 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1316 const nvpair_t *nvp; \
1318 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1320 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1321 return (nvpair_get_##type(nvp)); \
1324 NVLIST_GET(bool, bool, BOOL)
1325 NVLIST_GET(uint64_t, number, NUMBER)
1326 NVLIST_GET(const char *, string, STRING)
1327 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1329 NVLIST_GET(int, descriptor, DESCRIPTOR)
1335 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1339 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1341 nvlist_report_missing(NV_TYPE_BINARY, name);
1343 return (nvpair_get_binary(nvp, sizep));
1346 #define NVLIST_TAKE(ftype, type, TYPE) \
1348 nvlist_take_##type(nvlist_t *nvl, const char *name) \
1353 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1355 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1356 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1357 nvlist_remove_nvpair(nvl, nvp); \
1358 nvpair_free_structure(nvp); \
1362 NVLIST_TAKE(bool, bool, BOOL)
1363 NVLIST_TAKE(uint64_t, number, NUMBER)
1364 NVLIST_TAKE(char *, string, STRING)
1365 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1367 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1373 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1378 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1380 nvlist_report_missing(NV_TYPE_BINARY, name);
1382 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1383 nvlist_remove_nvpair(nvl, nvp);
1384 nvpair_free_structure(nvp);
1389 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1394 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1396 nvpair_remove(&nvl->nvl_head, nvp, nvl);
1400 nvlist_free(nvlist_t *nvl, const char *name)
1403 nvlist_free_type(nvl, name, NV_TYPE_NONE);
1406 #define NVLIST_FREE(type, TYPE) \
1408 nvlist_free_##type(nvlist_t *nvl, const char *name) \
1411 nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \
1414 NVLIST_FREE(null, NULL)
1415 NVLIST_FREE(bool, BOOL)
1416 NVLIST_FREE(number, NUMBER)
1417 NVLIST_FREE(string, STRING)
1418 NVLIST_FREE(nvlist, NVLIST)
1420 NVLIST_FREE(descriptor, DESCRIPTOR)
1422 NVLIST_FREE(binary, BINARY)
1427 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1432 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1434 nvlist_remove_nvpair(nvl, nvp);