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>
70 #include "nvlist_impl.h"
71 #include "nvpair_impl.h"
75 #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
76 #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
77 #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
80 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
81 #define PJDLOG_RASSERT(expr, ...) assert(expr)
82 #define PJDLOG_ABORT(...) do { \
83 fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \
84 fprintf(stderr, __VA_ARGS__); \
85 fprintf(stderr, "\n"); \
91 #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN)
92 #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE)
93 #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
95 #define NVLIST_MAGIC 0x6e766c /* "nvl" */
100 nvpair_t *nvl_parent;
101 struct nvl_head nvl_head;
104 #define NVLIST_ASSERT(nvl) do { \
105 PJDLOG_ASSERT((nvl) != NULL); \
106 PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \
110 MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
113 #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp)
115 #define NVLIST_HEADER_MAGIC 0x6c
116 #define NVLIST_HEADER_VERSION 0x00
117 struct nvlist_header {
119 uint8_t nvlh_version;
121 uint64_t nvlh_descriptors;
126 nvlist_create(int flags)
130 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
132 nvl = nv_malloc(sizeof(*nvl));
136 nvl->nvl_flags = flags;
137 nvl->nvl_parent = NULL;
138 TAILQ_INIT(&nvl->nvl_head);
139 nvl->nvl_magic = NVLIST_MAGIC;
145 nvlist_destroy(nvlist_t *nvl)
156 while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
157 nvlist_remove_nvpair(nvl, nvp);
167 nvlist_set_error(nvlist_t *nvl, int error)
170 PJDLOG_ASSERT(error != 0);
173 * Check for error != 0 so that we don't do the wrong thing if somebody
174 * tries to abuse this API when asserts are disabled.
176 if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
177 nvl->nvl_error = error;
181 nvlist_error(const nvlist_t *nvl)
189 return (nvl->nvl_error);
193 nvlist_get_nvpair_parent(const nvlist_t *nvl)
198 return (nvl->nvl_parent);
202 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
208 nvp = nvl->nvl_parent;
214 return (nvpair_nvlist(nvp));
218 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
223 nvl->nvl_parent = parent;
227 nvlist_empty(const nvlist_t *nvl)
231 PJDLOG_ASSERT(nvl->nvl_error == 0);
233 return (nvlist_first_nvpair(nvl) == NULL);
237 nvlist_flags(const nvlist_t *nvl)
241 PJDLOG_ASSERT(nvl->nvl_error == 0);
242 PJDLOG_ASSERT((nvl->nvl_flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
244 return (nvl->nvl_flags);
248 nvlist_report_missing(int type, const char *name)
251 PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
252 name, nvpair_type_string(type));
256 nvlist_find(const nvlist_t *nvl, int type, const char *name)
261 PJDLOG_ASSERT(nvl->nvl_error == 0);
262 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
263 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
265 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
266 nvp = nvlist_next_nvpair(nvl, nvp)) {
267 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
269 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
270 if (strcasecmp(nvpair_name(nvp), name) != 0)
273 if (strcmp(nvpair_name(nvp), name) != 0)
286 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
290 PJDLOG_ASSERT(nvl->nvl_error == 0);
291 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
292 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
294 return (nvlist_find(nvl, type, name) != NULL);
298 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
303 PJDLOG_ASSERT(nvl->nvl_error == 0);
304 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
305 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
307 nvp = nvlist_find(nvl, type, name);
309 nvlist_free_nvpair(nvl, nvp);
311 nvlist_report_missing(type, name);
315 nvlist_clone(const nvlist_t *nvl)
318 nvpair_t *nvp, *newnvp;
322 if (nvl->nvl_error != 0) {
323 ERRNO_SET(nvl->nvl_error);
327 newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
328 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
329 nvp = nvlist_next_nvpair(nvl, nvp)) {
330 newnvp = nvpair_clone(nvp);
333 nvlist_move_nvpair(newnvl, newnvp);
336 nvlist_destroy(newnvl);
344 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
347 if (nvlist_error(nvl) != 0) {
348 dprintf(fd, "%*serror: %d\n", level * 4, "",
357 * Dump content of nvlist.
360 nvlist_dump(const nvlist_t *nvl, int fd)
362 const nvlist_t *tmpnvl;
363 nvpair_t *nvp, *tmpnvp;
368 if (nvlist_dump_error_check(nvl, fd, level))
371 nvp = nvlist_first_nvpair(nvl);
372 while (nvp != NULL) {
373 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
374 nvpair_type_string(nvpair_type(nvp)));
375 switch (nvpair_type(nvp)) {
377 dprintf(fd, " null\n");
380 dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
384 dprintf(fd, " %ju (%jd) (0x%jx)\n",
385 (uintmax_t)nvpair_get_number(nvp),
386 (intmax_t)nvpair_get_number(nvp),
387 (uintmax_t)nvpair_get_number(nvp));
390 dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
394 tmpnvl = nvpair_get_nvlist(nvp);
395 if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
397 tmpnvp = nvlist_first_nvpair(tmpnvl);
398 if (tmpnvp != NULL) {
405 case NV_TYPE_DESCRIPTOR:
406 dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
410 const unsigned char *binary;
414 binary = nvpair_get_binary(nvp, &size);
415 dprintf(fd, " %zu ", size);
416 for (ii = 0; ii < size; ii++)
417 dprintf(fd, "%02hhx", binary[ii]);
422 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
425 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
427 nvl = nvlist_get_parent(nvl, &cookie);
437 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
441 nvlist_dump(nvl, fileno(fp));
446 * The function obtains size of the nvlist after nvlist_pack().
449 nvlist_size(const nvlist_t *nvl)
451 const nvlist_t *tmpnvl;
452 const nvpair_t *nvp, *tmpnvp;
457 PJDLOG_ASSERT(nvl->nvl_error == 0);
459 size = sizeof(struct nvlist_header);
460 nvp = nvlist_first_nvpair(nvl);
461 while (nvp != NULL) {
462 size += nvpair_header_size();
463 size += strlen(nvpair_name(nvp)) + 1;
464 if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
465 size += sizeof(struct nvlist_header);
466 size += nvpair_header_size() + 1;
467 tmpnvl = nvpair_get_nvlist(nvp);
468 PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
469 tmpnvp = nvlist_first_nvpair(tmpnvl);
470 if (tmpnvp != NULL) {
476 size += nvpair_size(nvp);
479 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
481 nvl = nvlist_get_parent(nvl, &cookie);
494 nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
501 PJDLOG_ASSERT(nvl->nvl_error == 0);
505 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
507 case NV_TYPE_DESCRIPTOR:
508 *descs = nvpair_get_descriptor(nvp);
512 nvl = nvpair_get_nvlist(nvp);
517 } while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
525 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
530 nitems = nvlist_ndescriptors(nvl);
531 fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
535 nvlist_xdescriptors(nvl, fds);
544 nvlist_ndescriptors(const nvlist_t *nvl)
553 PJDLOG_ASSERT(nvl->nvl_error == 0);
558 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
560 case NV_TYPE_DESCRIPTOR:
564 nvl = nvpair_get_nvlist(nvp);
569 } while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
577 static unsigned char *
578 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
580 struct nvlist_header nvlhdr;
584 nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
585 nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
586 nvlhdr.nvlh_flags = nvl->nvl_flags;
587 #if BYTE_ORDER == BIG_ENDIAN
588 nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
590 nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
591 nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
592 PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
593 memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
594 ptr += sizeof(nvlhdr);
595 *leftp -= sizeof(nvlhdr);
601 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
603 unsigned char *buf, *ptr;
605 const nvlist_t *tmpnvl;
606 nvpair_t *nvp, *tmpnvp;
611 if (nvl->nvl_error != 0) {
612 ERRNO_SET(nvl->nvl_error);
616 size = nvlist_size(nvl);
617 buf = nv_malloc(size);
624 ptr = nvlist_pack_header(nvl, ptr, &left);
626 nvp = nvlist_first_nvpair(nvl);
627 while (nvp != NULL) {
630 nvpair_init_datasize(nvp);
631 ptr = nvpair_pack_header(nvp, ptr, &left);
636 switch (nvpair_type(nvp)) {
638 ptr = nvpair_pack_null(nvp, ptr, &left);
641 ptr = nvpair_pack_bool(nvp, ptr, &left);
644 ptr = nvpair_pack_number(nvp, ptr, &left);
647 ptr = nvpair_pack_string(nvp, ptr, &left);
650 tmpnvl = nvpair_get_nvlist(nvp);
651 ptr = nvlist_pack_header(tmpnvl, ptr, &left);
654 tmpnvp = nvlist_first_nvpair(tmpnvl);
655 if (tmpnvp != NULL) {
660 ptr = nvpair_pack_nvlist_up(ptr, &left);
663 case NV_TYPE_DESCRIPTOR:
664 ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
668 ptr = nvpair_pack_binary(nvp, ptr, &left);
671 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
677 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
679 nvl = nvlist_get_parent(nvl, &cookie);
683 ptr = nvpair_pack_nvlist_up(ptr, &left);
696 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
701 if (nvl->nvl_error != 0) {
702 ERRNO_SET(nvl->nvl_error);
706 if (nvlist_ndescriptors(nvl) > 0) {
707 ERRNO_SET(EOPNOTSUPP);
711 return (nvlist_xpack(nvl, NULL, sizep));
715 nvlist_check_header(struct nvlist_header *nvlhdrp)
718 if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
722 if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
726 #if BYTE_ORDER == BIG_ENDIAN
727 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
728 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
729 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
732 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
733 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
734 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
740 const unsigned char *
741 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
742 bool *isbep, size_t *leftp)
744 struct nvlist_header nvlhdr;
746 if (*leftp < sizeof(nvlhdr))
749 memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
751 if (!nvlist_check_header(&nvlhdr))
754 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
758 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
760 if (nvlhdr.nvlh_descriptors > nfds)
763 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
766 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
768 ptr += sizeof(nvlhdr);
770 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
771 *leftp -= sizeof(nvlhdr);
780 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
783 const unsigned char *ptr;
784 nvlist_t *nvl, *retnvl, *tmpnvl;
789 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
795 nvl = retnvl = nvlist_create(0);
799 ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
802 if (nvl->nvl_flags != flags) {
808 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
811 switch (nvpair_type(nvp)) {
813 ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
816 ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
819 ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
822 ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
825 ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
827 nvlist_set_parent(tmpnvl, nvp);
830 case NV_TYPE_DESCRIPTOR:
831 ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
836 ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
838 case NV_TYPE_NVLIST_UP:
839 if (nvl->nvl_parent == NULL)
841 nvl = nvpair_nvlist(nvl->nvl_parent);
842 nvpair_free_structure(nvp);
845 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
849 nvlist_move_nvpair(nvl, nvp);
850 if (tmpnvl != NULL) {
858 nvlist_destroy(retnvl);
863 nvlist_unpack(const void *buf, size_t size, int flags)
866 return (nvlist_xunpack(buf, size, NULL, 0, flags));
871 nvlist_send(int sock, const nvlist_t *nvl)
873 size_t datasize, nfds;
879 if (nvlist_error(nvl) != 0) {
880 ERRNO_SET(nvlist_error(nvl));
884 fds = nvlist_descriptors(nvl, &nfds);
892 data = nvlist_xpack(nvl, &fdidx, &datasize);
896 if (buf_send(sock, data, datasize) == -1)
900 if (fd_send(sock, fds, nfds) == -1)
914 nvlist_recv(int sock, int flags)
916 struct nvlist_header nvlhdr;
919 size_t nfds, size, i;
922 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
925 if (!nvlist_check_header(&nvlhdr))
928 nfds = (size_t)nvlhdr.nvlh_descriptors;
929 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
931 buf = nv_malloc(size);
935 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
940 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
944 fds = nv_malloc(nfds * sizeof(fds[0]));
947 if (fd_recv(sock, fds, nfds) == -1)
951 nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
954 for (i = 0; i < nfds; i++)
971 nvlist_xfer(int sock, nvlist_t *nvl, int flags)
974 if (nvlist_send(sock, nvl) < 0) {
979 return (nvlist_recv(sock, flags));
984 nvlist_first_nvpair(const nvlist_t *nvl)
989 return (TAILQ_FIRST(&nvl->nvl_head));
993 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
999 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1001 retnvp = nvpair_next(nvp);
1002 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1009 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1015 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1017 retnvp = nvpair_prev(nvp);
1018 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1024 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1029 PJDLOG_ASSERT(cookiep != NULL);
1031 if (*cookiep == NULL)
1032 nvp = nvlist_first_nvpair(nvl);
1034 nvp = nvlist_next_nvpair(nvl, *cookiep);
1038 *typep = nvpair_type(nvp);
1040 return (nvpair_name(nvp));
1044 nvlist_exists(const nvlist_t *nvl, const char *name)
1047 return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1050 #define NVLIST_EXISTS(type, TYPE) \
1052 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
1055 return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \
1058 NVLIST_EXISTS(null, NULL)
1059 NVLIST_EXISTS(bool, BOOL)
1060 NVLIST_EXISTS(number, NUMBER)
1061 NVLIST_EXISTS(string, STRING)
1062 NVLIST_EXISTS(nvlist, NVLIST)
1064 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1066 NVLIST_EXISTS(binary, BINARY)
1068 #undef NVLIST_EXISTS
1071 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1077 if (nvlist_error(nvl) != 0) {
1078 ERRNO_SET(nvlist_error(nvl));
1081 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1082 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1083 nvl->nvl_error = EEXIST;
1084 ERRNO_SET(nvlist_error(nvl));
1089 newnvp = nvpair_clone(nvp);
1090 if (newnvp == NULL) {
1091 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1092 ERRNO_SET(nvlist_error(nvl));
1096 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1100 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1104 va_start(valueap, valuefmt);
1105 nvlist_add_stringv(nvl, name, valuefmt, valueap);
1110 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1115 if (nvlist_error(nvl) != 0) {
1116 ERRNO_SET(nvlist_error(nvl));
1120 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1122 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1123 ERRNO_SET(nvl->nvl_error);
1125 nvlist_move_nvpair(nvl, nvp);
1130 nvlist_add_null(nvlist_t *nvl, const char *name)
1134 if (nvlist_error(nvl) != 0) {
1135 ERRNO_SET(nvlist_error(nvl));
1139 nvp = nvpair_create_null(name);
1141 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1142 ERRNO_SET(nvl->nvl_error);
1144 nvlist_move_nvpair(nvl, nvp);
1149 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1154 if (nvlist_error(nvl) != 0) {
1155 ERRNO_SET(nvlist_error(nvl));
1159 nvp = nvpair_create_binary(name, value, size);
1161 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1162 ERRNO_SET(nvl->nvl_error);
1164 nvlist_move_nvpair(nvl, nvp);
1169 #define NVLIST_ADD(vtype, type) \
1171 nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \
1175 if (nvlist_error(nvl) != 0) { \
1176 ERRNO_SET(nvlist_error(nvl)); \
1180 nvp = nvpair_create_##type(name, value); \
1181 if (nvp == NULL) { \
1182 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1183 ERRNO_SET(nvl->nvl_error); \
1185 nvlist_move_nvpair(nvl, nvp); \
1189 NVLIST_ADD(bool, bool)
1190 NVLIST_ADD(uint64_t, number)
1191 NVLIST_ADD(const char *, string)
1192 NVLIST_ADD(const nvlist_t *, nvlist)
1194 NVLIST_ADD(int, descriptor);
1200 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1204 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1206 if (nvlist_error(nvl) != 0) {
1208 ERRNO_SET(nvlist_error(nvl));
1211 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1212 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1214 nvl->nvl_error = EEXIST;
1215 ERRNO_SET(nvl->nvl_error);
1220 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1224 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1228 if (nvlist_error(nvl) != 0) {
1230 ERRNO_SET(nvlist_error(nvl));
1234 nvp = nvpair_move_string(name, value);
1236 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1237 ERRNO_SET(nvl->nvl_error);
1239 nvlist_move_nvpair(nvl, nvp);
1244 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1248 if (nvlist_error(nvl) != 0) {
1249 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1250 nvlist_destroy(value);
1251 ERRNO_SET(nvlist_error(nvl));
1255 nvp = nvpair_move_nvlist(name, value);
1257 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1258 ERRNO_SET(nvl->nvl_error);
1260 nvlist_move_nvpair(nvl, nvp);
1266 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1270 if (nvlist_error(nvl) != 0) {
1272 ERRNO_SET(nvlist_error(nvl));
1276 nvp = nvpair_move_descriptor(name, value);
1278 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1279 ERRNO_SET(nvl->nvl_error);
1281 nvlist_move_nvpair(nvl, nvp);
1287 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1291 if (nvlist_error(nvl) != 0) {
1293 ERRNO_SET(nvlist_error(nvl));
1297 nvp = nvpair_move_binary(name, value, size);
1299 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1300 ERRNO_SET(nvl->nvl_error);
1302 nvlist_move_nvpair(nvl, nvp);
1307 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1310 return (nvlist_find(nvl, NV_TYPE_NONE, name));
1313 #define NVLIST_GET(ftype, type, TYPE) \
1315 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1317 const nvpair_t *nvp; \
1319 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1321 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1322 return (nvpair_get_##type(nvp)); \
1325 NVLIST_GET(bool, bool, BOOL)
1326 NVLIST_GET(uint64_t, number, NUMBER)
1327 NVLIST_GET(const char *, string, STRING)
1328 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1330 NVLIST_GET(int, descriptor, DESCRIPTOR)
1336 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1340 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1342 nvlist_report_missing(NV_TYPE_BINARY, name);
1344 return (nvpair_get_binary(nvp, sizep));
1347 #define NVLIST_TAKE(ftype, type, TYPE) \
1349 nvlist_take_##type(nvlist_t *nvl, const char *name) \
1354 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1356 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1357 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1358 nvlist_remove_nvpair(nvl, nvp); \
1359 nvpair_free_structure(nvp); \
1363 NVLIST_TAKE(bool, bool, BOOL)
1364 NVLIST_TAKE(uint64_t, number, NUMBER)
1365 NVLIST_TAKE(char *, string, STRING)
1366 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1368 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1374 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1379 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1381 nvlist_report_missing(NV_TYPE_BINARY, name);
1383 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1384 nvlist_remove_nvpair(nvl, nvp);
1385 nvpair_free_structure(nvp);
1390 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1395 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1397 nvpair_remove(&nvl->nvl_head, nvp, nvl);
1401 nvlist_free(nvlist_t *nvl, const char *name)
1404 nvlist_free_type(nvl, name, NV_TYPE_NONE);
1407 #define NVLIST_FREE(type, TYPE) \
1409 nvlist_free_##type(nvlist_t *nvl, const char *name) \
1412 nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \
1415 NVLIST_FREE(null, NULL)
1416 NVLIST_FREE(bool, BOOL)
1417 NVLIST_FREE(number, NUMBER)
1418 NVLIST_FREE(string, STRING)
1419 NVLIST_FREE(nvlist, NVLIST)
1421 NVLIST_FREE(descriptor, DESCRIPTOR)
1423 NVLIST_FREE(binary, BINARY)
1428 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1433 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1435 nvlist_remove_nvpair(nvl, nvp);