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)
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));
133 nvl->nvl_flags = flags;
134 nvl->nvl_parent = NULL;
135 TAILQ_INIT(&nvl->nvl_head);
136 nvl->nvl_magic = NVLIST_MAGIC;
142 nvlist_destroy(nvlist_t *nvl)
153 while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
154 nvlist_remove_nvpair(nvl, nvp);
164 nvlist_set_error(nvlist_t *nvl, int error)
167 PJDLOG_ASSERT(error != 0);
170 * Check for error != 0 so that we don't do the wrong thing if somebody
171 * tries to abuse this API when asserts are disabled.
173 if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
174 nvl->nvl_error = error;
178 nvlist_error(const nvlist_t *nvl)
186 return (nvl->nvl_error);
190 nvlist_get_nvpair_parent(const nvlist_t *nvl)
195 return (nvl->nvl_parent);
199 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
205 nvp = nvl->nvl_parent;
211 return (nvpair_nvlist(nvp));
215 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
220 nvl->nvl_parent = parent;
224 nvlist_empty(const nvlist_t *nvl)
228 PJDLOG_ASSERT(nvl->nvl_error == 0);
230 return (nvlist_first_nvpair(nvl) == NULL);
234 nvlist_report_missing(int type, const char *name)
237 PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
238 name, nvpair_type_string(type));
242 nvlist_find(const nvlist_t *nvl, int type, const char *name)
247 PJDLOG_ASSERT(nvl->nvl_error == 0);
248 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
249 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
251 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
252 nvp = nvlist_next_nvpair(nvl, nvp)) {
253 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
255 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
256 if (strcasecmp(nvpair_name(nvp), name) != 0)
259 if (strcmp(nvpair_name(nvp), name) != 0)
272 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
276 PJDLOG_ASSERT(nvl->nvl_error == 0);
277 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
278 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
280 return (nvlist_find(nvl, type, name) != NULL);
284 nvlist_free_type(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 nvp = nvlist_find(nvl, type, name);
295 nvlist_free_nvpair(nvl, nvp);
297 nvlist_report_missing(type, name);
301 nvlist_clone(const nvlist_t *nvl)
304 nvpair_t *nvp, *newnvp;
308 if (nvl->nvl_error != 0) {
309 ERRNO_SET(nvl->nvl_error);
313 newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
314 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
315 nvp = nvlist_next_nvpair(nvl, nvp)) {
316 newnvp = nvpair_clone(nvp);
319 nvlist_move_nvpair(newnvl, newnvp);
322 nvlist_destroy(newnvl);
330 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
333 if (nvlist_error(nvl) != 0) {
334 dprintf(fd, "%*serror: %d\n", level * 4, "",
343 * Dump content of nvlist.
346 nvlist_dump(const nvlist_t *nvl, int fd)
348 const nvlist_t *tmpnvl;
349 nvpair_t *nvp, *tmpnvp;
354 if (nvlist_dump_error_check(nvl, fd, level))
357 nvp = nvlist_first_nvpair(nvl);
358 while (nvp != NULL) {
359 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
360 nvpair_type_string(nvpair_type(nvp)));
361 switch (nvpair_type(nvp)) {
363 dprintf(fd, " null\n");
366 dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
370 dprintf(fd, " %ju (%jd) (0x%jx)\n",
371 (uintmax_t)nvpair_get_number(nvp),
372 (intmax_t)nvpair_get_number(nvp),
373 (uintmax_t)nvpair_get_number(nvp));
376 dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
380 tmpnvl = nvpair_get_nvlist(nvp);
381 if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
383 tmpnvp = nvlist_first_nvpair(tmpnvl);
384 if (tmpnvp != NULL) {
391 case NV_TYPE_DESCRIPTOR:
392 dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
396 const unsigned char *binary;
400 binary = nvpair_get_binary(nvp, &size);
401 dprintf(fd, " %zu ", size);
402 for (ii = 0; ii < size; ii++)
403 dprintf(fd, "%02hhx", binary[ii]);
408 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
411 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
413 nvl = nvlist_get_parent(nvl, &cookie);
423 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
427 nvlist_dump(nvl, fileno(fp));
432 * The function obtains size of the nvlist after nvlist_pack().
435 nvlist_size(const nvlist_t *nvl)
437 const nvlist_t *tmpnvl;
438 const nvpair_t *nvp, *tmpnvp;
443 PJDLOG_ASSERT(nvl->nvl_error == 0);
445 size = sizeof(struct nvlist_header);
446 nvp = nvlist_first_nvpair(nvl);
447 while (nvp != NULL) {
448 size += nvpair_header_size();
449 size += strlen(nvpair_name(nvp)) + 1;
450 if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
451 size += sizeof(struct nvlist_header);
452 size += nvpair_header_size() + 1;
453 tmpnvl = nvpair_get_nvlist(nvp);
454 PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
455 tmpnvp = nvlist_first_nvpair(tmpnvl);
456 if (tmpnvp != NULL) {
462 size += nvpair_size(nvp);
465 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
467 nvl = nvlist_get_parent(nvl, &cookie);
480 nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
487 PJDLOG_ASSERT(nvl->nvl_error == 0);
491 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
493 case NV_TYPE_DESCRIPTOR:
494 *descs = nvpair_get_descriptor(nvp);
498 nvl = nvpair_get_nvlist(nvp);
503 } while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
511 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
516 nitems = nvlist_ndescriptors(nvl);
517 fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
521 nvlist_xdescriptors(nvl, fds);
530 nvlist_ndescriptors(const nvlist_t *nvl)
539 PJDLOG_ASSERT(nvl->nvl_error == 0);
544 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
546 case NV_TYPE_DESCRIPTOR:
550 nvl = nvpair_get_nvlist(nvp);
555 } while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
563 static unsigned char *
564 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
566 struct nvlist_header nvlhdr;
570 nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
571 nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
572 nvlhdr.nvlh_flags = nvl->nvl_flags;
573 #if BYTE_ORDER == BIG_ENDIAN
574 nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
576 nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
577 nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
578 PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
579 memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
580 ptr += sizeof(nvlhdr);
581 *leftp -= sizeof(nvlhdr);
587 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
589 unsigned char *buf, *ptr;
591 const nvlist_t *tmpnvl;
592 nvpair_t *nvp, *tmpnvp;
597 if (nvl->nvl_error != 0) {
598 ERRNO_SET(nvl->nvl_error);
602 size = nvlist_size(nvl);
603 buf = nv_malloc(size);
610 ptr = nvlist_pack_header(nvl, ptr, &left);
612 nvp = nvlist_first_nvpair(nvl);
613 while (nvp != NULL) {
616 nvpair_init_datasize(nvp);
617 ptr = nvpair_pack_header(nvp, ptr, &left);
622 switch (nvpair_type(nvp)) {
624 ptr = nvpair_pack_null(nvp, ptr, &left);
627 ptr = nvpair_pack_bool(nvp, ptr, &left);
630 ptr = nvpair_pack_number(nvp, ptr, &left);
633 ptr = nvpair_pack_string(nvp, ptr, &left);
636 tmpnvl = nvpair_get_nvlist(nvp);
637 ptr = nvlist_pack_header(tmpnvl, ptr, &left);
640 tmpnvp = nvlist_first_nvpair(tmpnvl);
641 if (tmpnvp != NULL) {
646 ptr = nvpair_pack_nvlist_up(ptr, &left);
649 case NV_TYPE_DESCRIPTOR:
650 ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
654 ptr = nvpair_pack_binary(nvp, ptr, &left);
657 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
663 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
665 nvl = nvlist_get_parent(nvl, &cookie);
669 ptr = nvpair_pack_nvlist_up(ptr, &left);
682 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
687 if (nvl->nvl_error != 0) {
688 ERRNO_SET(nvl->nvl_error);
692 if (nvlist_ndescriptors(nvl) > 0) {
693 ERRNO_SET(EOPNOTSUPP);
697 return (nvlist_xpack(nvl, NULL, sizep));
701 nvlist_check_header(struct nvlist_header *nvlhdrp)
704 if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
708 if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
712 #if BYTE_ORDER == BIG_ENDIAN
713 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
714 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
715 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
718 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
719 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
720 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
726 const unsigned char *
727 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
728 bool *isbep, size_t *leftp)
730 struct nvlist_header nvlhdr;
732 if (*leftp < sizeof(nvlhdr))
735 memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
737 if (!nvlist_check_header(&nvlhdr))
740 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
744 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
746 if (nvlhdr.nvlh_descriptors > nfds)
749 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
752 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
754 ptr += sizeof(nvlhdr);
756 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
757 *leftp -= sizeof(nvlhdr);
766 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
768 const unsigned char *ptr;
769 nvlist_t *nvl, *retnvl, *tmpnvl;
778 nvl = retnvl = nvlist_create(0);
782 ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
787 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
790 switch (nvpair_type(nvp)) {
792 ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
795 ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
798 ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
801 ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
804 ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
806 nvlist_set_parent(tmpnvl, nvp);
809 case NV_TYPE_DESCRIPTOR:
810 ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
815 ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
817 case NV_TYPE_NVLIST_UP:
818 if (nvl->nvl_parent == NULL)
820 nvl = nvpair_nvlist(nvl->nvl_parent);
823 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
827 nvlist_move_nvpair(nvl, nvp);
828 if (tmpnvl != NULL) {
836 nvlist_destroy(retnvl);
841 nvlist_unpack(const void *buf, size_t size)
844 return (nvlist_xunpack(buf, size, NULL, 0));
849 nvlist_send(int sock, const nvlist_t *nvl)
851 size_t datasize, nfds;
857 if (nvlist_error(nvl) != 0) {
858 ERRNO_SET(nvlist_error(nvl));
862 fds = nvlist_descriptors(nvl, &nfds);
870 data = nvlist_xpack(nvl, &fdidx, &datasize);
874 if (buf_send(sock, data, datasize) == -1)
878 if (fd_send(sock, fds, nfds) == -1)
892 nvlist_recv(int sock)
894 struct nvlist_header nvlhdr;
897 size_t nfds, size, i;
900 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
903 if (!nvlist_check_header(&nvlhdr))
906 nfds = (size_t)nvlhdr.nvlh_descriptors;
907 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
909 buf = nv_malloc(size);
913 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
918 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
922 fds = nv_malloc(nfds * sizeof(fds[0]));
925 if (fd_recv(sock, fds, nfds) == -1)
929 nvl = nvlist_xunpack(buf, size, fds, nfds);
932 for (i = 0; i < nfds; i++)
949 nvlist_xfer(int sock, nvlist_t *nvl)
952 if (nvlist_send(sock, nvl) < 0) {
957 return (nvlist_recv(sock));
962 nvlist_first_nvpair(const nvlist_t *nvl)
967 return (TAILQ_FIRST(&nvl->nvl_head));
971 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
977 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
979 retnvp = nvpair_next(nvp);
980 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
987 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
993 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
995 retnvp = nvpair_prev(nvp);
996 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1002 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1007 PJDLOG_ASSERT(cookiep != NULL);
1009 if (*cookiep == NULL)
1010 nvp = nvlist_first_nvpair(nvl);
1012 nvp = nvlist_next_nvpair(nvl, *cookiep);
1016 *typep = nvpair_type(nvp);
1018 return (nvpair_name(nvp));
1022 nvlist_exists(const nvlist_t *nvl, const char *name)
1025 return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1028 #define NVLIST_EXISTS(type, TYPE) \
1030 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
1033 return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \
1036 NVLIST_EXISTS(null, NULL)
1037 NVLIST_EXISTS(bool, BOOL)
1038 NVLIST_EXISTS(number, NUMBER)
1039 NVLIST_EXISTS(string, STRING)
1040 NVLIST_EXISTS(nvlist, NVLIST)
1042 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1044 NVLIST_EXISTS(binary, BINARY)
1046 #undef NVLIST_EXISTS
1049 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1055 if (nvlist_error(nvl) != 0) {
1056 ERRNO_SET(nvlist_error(nvl));
1059 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1060 nvl->nvl_error = EEXIST;
1061 ERRNO_SET(nvlist_error(nvl));
1065 newnvp = nvpair_clone(nvp);
1066 if (newnvp == NULL) {
1067 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1068 ERRNO_SET(nvlist_error(nvl));
1072 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1076 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1080 va_start(valueap, valuefmt);
1081 nvlist_add_stringv(nvl, name, valuefmt, valueap);
1086 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1091 if (nvlist_error(nvl) != 0) {
1092 ERRNO_SET(nvlist_error(nvl));
1096 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1098 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1099 ERRNO_SET(nvl->nvl_error);
1101 nvlist_move_nvpair(nvl, nvp);
1106 nvlist_add_null(nvlist_t *nvl, const char *name)
1110 if (nvlist_error(nvl) != 0) {
1111 ERRNO_SET(nvlist_error(nvl));
1115 nvp = nvpair_create_null(name);
1117 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1118 ERRNO_SET(nvl->nvl_error);
1120 nvlist_move_nvpair(nvl, nvp);
1125 nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
1129 if (nvlist_error(nvl) != 0) {
1130 ERRNO_SET(nvlist_error(nvl));
1134 nvp = nvpair_create_bool(name, value);
1136 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1137 ERRNO_SET(nvl->nvl_error);
1139 nvlist_move_nvpair(nvl, nvp);
1144 nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
1148 if (nvlist_error(nvl) != 0) {
1149 ERRNO_SET(nvlist_error(nvl));
1153 nvp = nvpair_create_number(name, value);
1155 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1156 ERRNO_SET(nvl->nvl_error);
1158 nvlist_move_nvpair(nvl, nvp);
1163 nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
1167 if (nvlist_error(nvl) != 0) {
1168 ERRNO_SET(nvlist_error(nvl));
1172 nvp = nvpair_create_string(name, value);
1174 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1175 ERRNO_SET(nvl->nvl_error);
1177 nvlist_move_nvpair(nvl, nvp);
1182 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1186 if (nvlist_error(nvl) != 0) {
1187 ERRNO_SET(nvlist_error(nvl));
1191 nvp = nvpair_create_nvlist(name, value);
1193 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1194 ERRNO_SET(nvl->nvl_error);
1196 nvlist_move_nvpair(nvl, nvp);
1202 nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1206 if (nvlist_error(nvl) != 0) {
1207 errno = nvlist_error(nvl);
1211 nvp = nvpair_create_descriptor(name, value);
1213 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1215 nvlist_move_nvpair(nvl, nvp);
1220 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1225 if (nvlist_error(nvl) != 0) {
1226 ERRNO_SET(nvlist_error(nvl));
1230 nvp = nvpair_create_binary(name, value, size);
1232 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1233 ERRNO_SET(nvl->nvl_error);
1235 nvlist_move_nvpair(nvl, nvp);
1240 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1244 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1246 if (nvlist_error(nvl) != 0) {
1248 ERRNO_SET(nvlist_error(nvl));
1251 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1253 nvl->nvl_error = EEXIST;
1254 ERRNO_SET(nvl->nvl_error);
1258 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1262 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1266 if (nvlist_error(nvl) != 0) {
1268 ERRNO_SET(nvlist_error(nvl));
1272 nvp = nvpair_move_string(name, value);
1274 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1275 ERRNO_SET(nvl->nvl_error);
1277 nvlist_move_nvpair(nvl, nvp);
1282 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1286 if (nvlist_error(nvl) != 0) {
1287 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1288 nvlist_destroy(value);
1289 ERRNO_SET(nvlist_error(nvl));
1293 nvp = nvpair_move_nvlist(name, value);
1295 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1296 ERRNO_SET(nvl->nvl_error);
1298 nvlist_move_nvpair(nvl, nvp);
1304 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1308 if (nvlist_error(nvl) != 0) {
1310 ERRNO_SET(nvlist_error(nvl));
1314 nvp = nvpair_move_descriptor(name, value);
1316 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1317 ERRNO_SET(nvl->nvl_error);
1319 nvlist_move_nvpair(nvl, nvp);
1325 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1329 if (nvlist_error(nvl) != 0) {
1331 ERRNO_SET(nvlist_error(nvl));
1335 nvp = nvpair_move_binary(name, value, size);
1337 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1338 ERRNO_SET(nvl->nvl_error);
1340 nvlist_move_nvpair(nvl, nvp);
1345 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1348 return (nvlist_find(nvl, NV_TYPE_NONE, name));
1351 #define NVLIST_GET(ftype, type, TYPE) \
1353 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1355 const nvpair_t *nvp; \
1357 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1359 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1360 return (nvpair_get_##type(nvp)); \
1363 NVLIST_GET(bool, bool, BOOL)
1364 NVLIST_GET(uint64_t, number, NUMBER)
1365 NVLIST_GET(const char *, string, STRING)
1366 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1368 NVLIST_GET(int, descriptor, DESCRIPTOR)
1374 nvlist_get_binary(const 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 return (nvpair_get_binary(nvp, sizep));
1385 #define NVLIST_TAKE(ftype, type, TYPE) \
1387 nvlist_take_##type(nvlist_t *nvl, const char *name) \
1392 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1394 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1395 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1396 nvlist_remove_nvpair(nvl, nvp); \
1397 nvpair_free_structure(nvp); \
1401 NVLIST_TAKE(bool, bool, BOOL)
1402 NVLIST_TAKE(uint64_t, number, NUMBER)
1403 NVLIST_TAKE(char *, string, STRING)
1404 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1406 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1412 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1417 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1419 nvlist_report_missing(NV_TYPE_BINARY, name);
1421 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1422 nvlist_remove_nvpair(nvl, nvp);
1423 nvpair_free_structure(nvp);
1428 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1433 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1435 nvpair_remove(&nvl->nvl_head, nvp, nvl);
1439 nvlist_free(nvlist_t *nvl, const char *name)
1442 nvlist_free_type(nvl, name, NV_TYPE_NONE);
1445 #define NVLIST_FREE(type, TYPE) \
1447 nvlist_free_##type(nvlist_t *nvl, const char *name) \
1450 nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \
1453 NVLIST_FREE(null, NULL)
1454 NVLIST_FREE(bool, BOOL)
1455 NVLIST_FREE(number, NUMBER)
1456 NVLIST_FREE(string, STRING)
1457 NVLIST_FREE(nvlist, NVLIST)
1459 NVLIST_FREE(descriptor, DESCRIPTOR)
1461 NVLIST_FREE(binary, BINARY)
1466 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1471 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1473 nvlist_remove_nvpair(nvl, nvp);