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);
843 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
847 nvlist_move_nvpair(nvl, nvp);
848 if (tmpnvl != NULL) {
856 nvlist_destroy(retnvl);
861 nvlist_unpack(const void *buf, size_t size, int flags)
864 return (nvlist_xunpack(buf, size, NULL, 0, flags));
869 nvlist_send(int sock, const nvlist_t *nvl)
871 size_t datasize, nfds;
877 if (nvlist_error(nvl) != 0) {
878 ERRNO_SET(nvlist_error(nvl));
882 fds = nvlist_descriptors(nvl, &nfds);
890 data = nvlist_xpack(nvl, &fdidx, &datasize);
894 if (buf_send(sock, data, datasize) == -1)
898 if (fd_send(sock, fds, nfds) == -1)
912 nvlist_recv(int sock, int flags)
914 struct nvlist_header nvlhdr;
917 size_t nfds, size, i;
920 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
923 if (!nvlist_check_header(&nvlhdr))
926 nfds = (size_t)nvlhdr.nvlh_descriptors;
927 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
929 buf = nv_malloc(size);
933 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
938 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
942 fds = nv_malloc(nfds * sizeof(fds[0]));
945 if (fd_recv(sock, fds, nfds) == -1)
949 nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
952 for (i = 0; i < nfds; i++)
969 nvlist_xfer(int sock, nvlist_t *nvl, int flags)
972 if (nvlist_send(sock, nvl) < 0) {
977 return (nvlist_recv(sock, flags));
982 nvlist_first_nvpair(const nvlist_t *nvl)
987 return (TAILQ_FIRST(&nvl->nvl_head));
991 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
997 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
999 retnvp = nvpair_next(nvp);
1000 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1007 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1013 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1015 retnvp = nvpair_prev(nvp);
1016 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1022 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1027 PJDLOG_ASSERT(cookiep != NULL);
1029 if (*cookiep == NULL)
1030 nvp = nvlist_first_nvpair(nvl);
1032 nvp = nvlist_next_nvpair(nvl, *cookiep);
1036 *typep = nvpair_type(nvp);
1038 return (nvpair_name(nvp));
1042 nvlist_exists(const nvlist_t *nvl, const char *name)
1045 return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1048 #define NVLIST_EXISTS(type, TYPE) \
1050 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
1053 return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \
1056 NVLIST_EXISTS(null, NULL)
1057 NVLIST_EXISTS(bool, BOOL)
1058 NVLIST_EXISTS(number, NUMBER)
1059 NVLIST_EXISTS(string, STRING)
1060 NVLIST_EXISTS(nvlist, NVLIST)
1062 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1064 NVLIST_EXISTS(binary, BINARY)
1066 #undef NVLIST_EXISTS
1069 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1075 if (nvlist_error(nvl) != 0) {
1076 ERRNO_SET(nvlist_error(nvl));
1079 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1080 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1081 nvl->nvl_error = EEXIST;
1082 ERRNO_SET(nvlist_error(nvl));
1087 newnvp = nvpair_clone(nvp);
1088 if (newnvp == NULL) {
1089 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1090 ERRNO_SET(nvlist_error(nvl));
1094 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1098 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1102 va_start(valueap, valuefmt);
1103 nvlist_add_stringv(nvl, name, valuefmt, valueap);
1108 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1113 if (nvlist_error(nvl) != 0) {
1114 ERRNO_SET(nvlist_error(nvl));
1118 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1120 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1121 ERRNO_SET(nvl->nvl_error);
1123 nvlist_move_nvpair(nvl, nvp);
1128 nvlist_add_null(nvlist_t *nvl, const char *name)
1132 if (nvlist_error(nvl) != 0) {
1133 ERRNO_SET(nvlist_error(nvl));
1137 nvp = nvpair_create_null(name);
1139 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1140 ERRNO_SET(nvl->nvl_error);
1142 nvlist_move_nvpair(nvl, nvp);
1147 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1152 if (nvlist_error(nvl) != 0) {
1153 ERRNO_SET(nvlist_error(nvl));
1157 nvp = nvpair_create_binary(name, value, size);
1159 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1160 ERRNO_SET(nvl->nvl_error);
1162 nvlist_move_nvpair(nvl, nvp);
1167 #define NVLIST_ADD(vtype, type) \
1169 nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \
1173 if (nvlist_error(nvl) != 0) { \
1174 ERRNO_SET(nvlist_error(nvl)); \
1178 nvp = nvpair_create_##type(name, value); \
1179 if (nvp == NULL) { \
1180 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1181 ERRNO_SET(nvl->nvl_error); \
1183 nvlist_move_nvpair(nvl, nvp); \
1187 NVLIST_ADD(bool, bool)
1188 NVLIST_ADD(uint64_t, number)
1189 NVLIST_ADD(const char *, string)
1190 NVLIST_ADD(const nvlist_t *, nvlist)
1192 NVLIST_ADD(int, descriptor);
1198 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1202 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1204 if (nvlist_error(nvl) != 0) {
1206 ERRNO_SET(nvlist_error(nvl));
1209 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1210 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1212 nvl->nvl_error = EEXIST;
1213 ERRNO_SET(nvl->nvl_error);
1218 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1222 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1226 if (nvlist_error(nvl) != 0) {
1228 ERRNO_SET(nvlist_error(nvl));
1232 nvp = nvpair_move_string(name, value);
1234 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1235 ERRNO_SET(nvl->nvl_error);
1237 nvlist_move_nvpair(nvl, nvp);
1242 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1246 if (nvlist_error(nvl) != 0) {
1247 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1248 nvlist_destroy(value);
1249 ERRNO_SET(nvlist_error(nvl));
1253 nvp = nvpair_move_nvlist(name, value);
1255 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1256 ERRNO_SET(nvl->nvl_error);
1258 nvlist_move_nvpair(nvl, nvp);
1264 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1268 if (nvlist_error(nvl) != 0) {
1270 ERRNO_SET(nvlist_error(nvl));
1274 nvp = nvpair_move_descriptor(name, value);
1276 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1277 ERRNO_SET(nvl->nvl_error);
1279 nvlist_move_nvpair(nvl, nvp);
1285 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1289 if (nvlist_error(nvl) != 0) {
1291 ERRNO_SET(nvlist_error(nvl));
1295 nvp = nvpair_move_binary(name, value, size);
1297 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1298 ERRNO_SET(nvl->nvl_error);
1300 nvlist_move_nvpair(nvl, nvp);
1305 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1308 return (nvlist_find(nvl, NV_TYPE_NONE, name));
1311 #define NVLIST_GET(ftype, type, TYPE) \
1313 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1315 const nvpair_t *nvp; \
1317 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1319 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1320 return (nvpair_get_##type(nvp)); \
1323 NVLIST_GET(bool, bool, BOOL)
1324 NVLIST_GET(uint64_t, number, NUMBER)
1325 NVLIST_GET(const char *, string, STRING)
1326 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1328 NVLIST_GET(int, descriptor, DESCRIPTOR)
1334 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1338 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1340 nvlist_report_missing(NV_TYPE_BINARY, name);
1342 return (nvpair_get_binary(nvp, sizep));
1345 #define NVLIST_TAKE(ftype, type, TYPE) \
1347 nvlist_take_##type(nvlist_t *nvl, const char *name) \
1352 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1354 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1355 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1356 nvlist_remove_nvpair(nvl, nvp); \
1357 nvpair_free_structure(nvp); \
1361 NVLIST_TAKE(bool, bool, BOOL)
1362 NVLIST_TAKE(uint64_t, number, NUMBER)
1363 NVLIST_TAKE(char *, string, STRING)
1364 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1366 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1372 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1377 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1379 nvlist_report_missing(NV_TYPE_BINARY, name);
1381 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1382 nvlist_remove_nvpair(nvl, nvp);
1383 nvpair_free_structure(nvp);
1388 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1393 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1395 nvpair_remove(&nvl->nvl_head, nvp, nvl);
1399 nvlist_free(nvlist_t *nvl, const char *name)
1402 nvlist_free_type(nvl, name, NV_TYPE_NONE);
1405 #define NVLIST_FREE(type, TYPE) \
1407 nvlist_free_##type(nvlist_t *nvl, const char *name) \
1410 nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \
1413 NVLIST_FREE(null, NULL)
1414 NVLIST_FREE(bool, BOOL)
1415 NVLIST_FREE(number, NUMBER)
1416 NVLIST_FREE(string, STRING)
1417 NVLIST_FREE(nvlist, NVLIST)
1419 NVLIST_FREE(descriptor, DESCRIPTOR)
1421 NVLIST_FREE(binary, BINARY)
1426 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1431 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1433 nvlist_remove_nvpair(nvl, nvp);