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)
154 while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
155 nvlist_remove_nvpair(nvl, nvp);
161 RESTORE_ERRNO(serrno);
165 nvlist_set_error(nvlist_t *nvl, int error)
168 PJDLOG_ASSERT(error != 0);
171 * Check for error != 0 so that we don't do the wrong thing if somebody
172 * tries to abuse this API when asserts are disabled.
174 if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
175 nvl->nvl_error = error;
179 nvlist_error(const nvlist_t *nvl)
187 return (nvl->nvl_error);
191 nvlist_get_nvpair_parent(const nvlist_t *nvl)
196 return (nvl->nvl_parent);
200 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
206 nvp = nvl->nvl_parent;
212 return (nvpair_nvlist(nvp));
216 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
221 nvl->nvl_parent = parent;
225 nvlist_empty(const nvlist_t *nvl)
229 PJDLOG_ASSERT(nvl->nvl_error == 0);
231 return (nvlist_first_nvpair(nvl) == NULL);
235 nvlist_report_missing(int type, const char *name)
238 PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
239 name, nvpair_type_string(type));
243 nvlist_find(const nvlist_t *nvl, int type, const char *name)
248 PJDLOG_ASSERT(nvl->nvl_error == 0);
249 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
250 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
252 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
253 nvp = nvlist_next_nvpair(nvl, nvp)) {
254 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
256 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
257 if (strcasecmp(nvpair_name(nvp), name) != 0)
260 if (strcmp(nvpair_name(nvp), name) != 0)
267 RESTORE_ERRNO(ENOENT);
273 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
277 PJDLOG_ASSERT(nvl->nvl_error == 0);
278 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
279 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
281 return (nvlist_find(nvl, type, name) != NULL);
286 nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...)
291 va_start(nameap, namefmt);
292 ret = nvlist_existsv_type(nvl, type, namefmt, nameap);
299 nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt,
305 nv_vasprintf(&name, namefmt, nameap);
309 exists = nvlist_exists_type(nvl, name, type);
316 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
321 PJDLOG_ASSERT(nvl->nvl_error == 0);
322 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
323 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
325 nvp = nvlist_find(nvl, type, name);
327 nvlist_free_nvpair(nvl, nvp);
329 nvlist_report_missing(type, name);
334 nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...)
338 va_start(nameap, namefmt);
339 nvlist_freev_type(nvl, type, namefmt, nameap);
344 nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
348 nv_vasprintf(&name, namefmt, nameap);
350 nvlist_report_missing(type, "<unknown>");
351 nvlist_free_type(nvl, name, type);
357 nvlist_clone(const nvlist_t *nvl)
360 nvpair_t *nvp, *newnvp;
364 if (nvl->nvl_error != 0) {
365 RESTORE_ERRNO(nvl->nvl_error);
369 newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
370 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
371 nvp = nvlist_next_nvpair(nvl, nvp)) {
372 newnvp = nvpair_clone(nvp);
375 nvlist_move_nvpair(newnvl, newnvp);
378 nvlist_destroy(newnvl);
386 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
389 if (nvlist_error(nvl) != 0) {
390 dprintf(fd, "%*serror: %d\n", level * 4, "",
399 * Dump content of nvlist.
402 nvlist_dump(const nvlist_t *nvl, int fd)
404 const nvlist_t *tmpnvl;
405 nvpair_t *nvp, *tmpnvp;
410 if (nvlist_dump_error_check(nvl, fd, level))
413 nvp = nvlist_first_nvpair(nvl);
414 while (nvp != NULL) {
415 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
416 nvpair_type_string(nvpair_type(nvp)));
417 switch (nvpair_type(nvp)) {
419 dprintf(fd, " null\n");
422 dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
426 dprintf(fd, " %ju (%jd) (0x%jx)\n",
427 (uintmax_t)nvpair_get_number(nvp),
428 (intmax_t)nvpair_get_number(nvp),
429 (uintmax_t)nvpair_get_number(nvp));
432 dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
436 tmpnvl = nvpair_get_nvlist(nvp);
437 if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
439 tmpnvp = nvlist_first_nvpair(tmpnvl);
440 if (tmpnvp != NULL) {
447 case NV_TYPE_DESCRIPTOR:
448 dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
452 const unsigned char *binary;
456 binary = nvpair_get_binary(nvp, &size);
457 dprintf(fd, " %zu ", size);
458 for (ii = 0; ii < size; ii++)
459 dprintf(fd, "%02hhx", binary[ii]);
464 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
467 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
469 nvl = nvlist_get_parent(nvl, &cookie);
479 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
483 nvlist_dump(nvl, fileno(fp));
488 * The function obtains size of the nvlist after nvlist_pack().
491 nvlist_size(const nvlist_t *nvl)
493 const nvlist_t *tmpnvl;
494 const nvpair_t *nvp, *tmpnvp;
499 PJDLOG_ASSERT(nvl->nvl_error == 0);
501 size = sizeof(struct nvlist_header);
502 nvp = nvlist_first_nvpair(nvl);
503 while (nvp != NULL) {
504 size += nvpair_header_size();
505 size += strlen(nvpair_name(nvp)) + 1;
506 if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
507 size += sizeof(struct nvlist_header);
508 size += nvpair_header_size() + 1;
509 tmpnvl = nvpair_get_nvlist(nvp);
510 PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
511 tmpnvp = nvlist_first_nvpair(tmpnvl);
512 if (tmpnvp != NULL) {
518 size += nvpair_size(nvp);
521 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
523 nvl = nvlist_get_parent(nvl, &cookie);
536 nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
541 PJDLOG_ASSERT(nvl->nvl_error == 0);
542 PJDLOG_ASSERT(level < 3);
544 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
545 nvp = nvlist_next_nvpair(nvl, nvp)) {
546 switch (nvpair_type(nvp)) {
547 case NV_TYPE_DESCRIPTOR:
548 *descs = nvpair_get_descriptor(nvp);
552 descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
564 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
569 nitems = nvlist_ndescriptors(nvl);
570 fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
574 nvlist_xdescriptors(nvl, fds, 0);
583 nvlist_xndescriptors(const nvlist_t *nvl, int level)
590 PJDLOG_ASSERT(nvl->nvl_error == 0);
591 PJDLOG_ASSERT(level < 3);
594 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
595 nvp = nvlist_next_nvpair(nvl, nvp)) {
596 switch (nvpair_type(nvp)) {
597 case NV_TYPE_DESCRIPTOR:
601 ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
614 nvlist_ndescriptors(const nvlist_t *nvl)
617 return (nvlist_xndescriptors(nvl, 0));
620 static unsigned char *
621 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
623 struct nvlist_header nvlhdr;
627 nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
628 nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
629 nvlhdr.nvlh_flags = nvl->nvl_flags;
630 #if BYTE_ORDER == BIG_ENDIAN
631 nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
633 nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
634 nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
635 PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
636 memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
637 ptr += sizeof(nvlhdr);
638 *leftp -= sizeof(nvlhdr);
644 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
646 unsigned char *buf, *ptr;
648 const nvlist_t *tmpnvl;
649 nvpair_t *nvp, *tmpnvp;
654 if (nvl->nvl_error != 0) {
655 RESTORE_ERRNO(nvl->nvl_error);
659 size = nvlist_size(nvl);
660 buf = nv_malloc(size);
667 ptr = nvlist_pack_header(nvl, ptr, &left);
669 nvp = nvlist_first_nvpair(nvl);
670 while (nvp != NULL) {
673 nvpair_init_datasize(nvp);
674 ptr = nvpair_pack_header(nvp, ptr, &left);
679 switch (nvpair_type(nvp)) {
681 ptr = nvpair_pack_null(nvp, ptr, &left);
684 ptr = nvpair_pack_bool(nvp, ptr, &left);
687 ptr = nvpair_pack_number(nvp, ptr, &left);
690 ptr = nvpair_pack_string(nvp, ptr, &left);
693 tmpnvl = nvpair_get_nvlist(nvp);
694 ptr = nvlist_pack_header(tmpnvl, ptr, &left);
697 tmpnvp = nvlist_first_nvpair(tmpnvl);
698 if (tmpnvp != NULL) {
703 ptr = nvpair_pack_nvlist_up(ptr, &left);
706 case NV_TYPE_DESCRIPTOR:
707 ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
711 ptr = nvpair_pack_binary(nvp, ptr, &left);
714 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
720 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
722 nvl = nvlist_get_parent(nvl, &cookie);
726 ptr = nvpair_pack_nvlist_up(ptr, &left);
739 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
744 if (nvl->nvl_error != 0) {
745 RESTORE_ERRNO(nvl->nvl_error);
749 if (nvlist_ndescriptors(nvl) > 0) {
750 RESTORE_ERRNO(EOPNOTSUPP);
754 return (nvlist_xpack(nvl, NULL, sizep));
758 nvlist_check_header(struct nvlist_header *nvlhdrp)
761 if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
762 RESTORE_ERRNO(EINVAL);
765 if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
766 RESTORE_ERRNO(EINVAL);
769 #if BYTE_ORDER == BIG_ENDIAN
770 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
771 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
772 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
775 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
776 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
777 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
783 const unsigned char *
784 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
785 bool *isbep, size_t *leftp)
787 struct nvlist_header nvlhdr;
789 if (*leftp < sizeof(nvlhdr))
792 memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
794 if (!nvlist_check_header(&nvlhdr))
797 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
801 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
803 if (nvlhdr.nvlh_descriptors > nfds)
806 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
809 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
811 ptr += sizeof(nvlhdr);
813 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
814 *leftp -= sizeof(nvlhdr);
818 RESTORE_ERRNO(EINVAL);
823 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
825 const unsigned char *ptr;
826 nvlist_t *nvl, *retnvl, *tmpnvl;
835 nvl = retnvl = nvlist_create(0);
839 ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
844 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
847 switch (nvpair_type(nvp)) {
849 ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
852 ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
855 ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
858 ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
861 ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
863 nvlist_set_parent(tmpnvl, nvp);
866 case NV_TYPE_DESCRIPTOR:
867 ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
872 ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
874 case NV_TYPE_NVLIST_UP:
875 if (nvl->nvl_parent == NULL)
877 nvl = nvpair_nvlist(nvl->nvl_parent);
880 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
884 nvlist_move_nvpair(nvl, nvp);
885 if (tmpnvl != NULL) {
893 nvlist_destroy(retnvl);
898 nvlist_unpack(const void *buf, size_t size)
901 return (nvlist_xunpack(buf, size, NULL, 0));
906 nvlist_send(int sock, const nvlist_t *nvl)
908 size_t datasize, nfds;
914 if (nvlist_error(nvl) != 0) {
915 errno = nvlist_error(nvl);
919 fds = nvlist_descriptors(nvl, &nfds);
927 data = nvlist_xpack(nvl, &fdidx, &datasize);
931 if (buf_send(sock, data, datasize) == -1)
935 if (fd_send(sock, fds, nfds) == -1)
949 nvlist_recv(int sock)
951 struct nvlist_header nvlhdr;
954 size_t nfds, size, i;
957 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
960 if (!nvlist_check_header(&nvlhdr))
963 nfds = (size_t)nvlhdr.nvlh_descriptors;
964 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
970 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
975 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
979 fds = malloc(nfds * sizeof(fds[0]));
982 if (fd_recv(sock, fds, nfds) == -1)
986 nvl = nvlist_xunpack(buf, size, fds, nfds);
988 for (i = 0; i < nfds; i++)
1004 nvlist_xfer(int sock, nvlist_t *nvl)
1007 if (nvlist_send(sock, nvl) < 0) {
1008 nvlist_destroy(nvl);
1011 nvlist_destroy(nvl);
1012 return (nvlist_recv(sock));
1017 nvlist_first_nvpair(const nvlist_t *nvl)
1022 return (TAILQ_FIRST(&nvl->nvl_head));
1026 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1032 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1034 retnvp = nvpair_next(nvp);
1035 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1042 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1048 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1050 retnvp = nvpair_prev(nvp);
1051 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1057 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1062 PJDLOG_ASSERT(cookiep != NULL);
1064 if (*cookiep == NULL)
1065 nvp = nvlist_first_nvpair(nvl);
1067 nvp = nvlist_next_nvpair(nvl, *cookiep);
1071 *typep = nvpair_type(nvp);
1073 return (nvpair_name(nvp));
1077 nvlist_exists(const nvlist_t *nvl, const char *name)
1080 return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1083 #define NVLIST_EXISTS(type, TYPE) \
1085 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
1088 return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \
1091 NVLIST_EXISTS(null, NULL)
1092 NVLIST_EXISTS(bool, BOOL)
1093 NVLIST_EXISTS(number, NUMBER)
1094 NVLIST_EXISTS(string, STRING)
1095 NVLIST_EXISTS(nvlist, NVLIST)
1097 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1099 NVLIST_EXISTS(binary, BINARY)
1101 #undef NVLIST_EXISTS
1105 nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...)
1110 va_start(nameap, namefmt);
1111 ret = nvlist_existsv(nvl, namefmt, nameap);
1116 #define NVLIST_EXISTSF(type) \
1118 nvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...) \
1123 va_start(nameap, namefmt); \
1124 ret = nvlist_existsv_##type(nvl, namefmt, nameap); \
1129 NVLIST_EXISTSF(null)
1130 NVLIST_EXISTSF(bool)
1131 NVLIST_EXISTSF(number)
1132 NVLIST_EXISTSF(string)
1133 NVLIST_EXISTSF(nvlist)
1135 NVLIST_EXISTSF(descriptor)
1137 NVLIST_EXISTSF(binary)
1139 #undef NVLIST_EXISTSF
1142 nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap)
1147 nv_vasprintf(&name, namefmt, nameap);
1151 exists = nvlist_exists(nvl, name);
1156 #define NVLIST_EXISTSV(type) \
1158 nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \
1164 vasprintf(&name, namefmt, nameap); \
1167 exists = nvlist_exists_##type(nvl, name); \
1172 NVLIST_EXISTSV(null)
1173 NVLIST_EXISTSV(bool)
1174 NVLIST_EXISTSV(number)
1175 NVLIST_EXISTSV(string)
1176 NVLIST_EXISTSV(nvlist)
1177 NVLIST_EXISTSV(descriptor)
1178 NVLIST_EXISTSV(binary)
1180 #undef NVLIST_EXISTSV
1184 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1190 if (nvlist_error(nvl) != 0) {
1191 RESTORE_ERRNO(nvlist_error(nvl));
1194 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1195 nvl->nvl_error = EEXIST;
1196 RESTORE_ERRNO(nvlist_error(nvl));
1200 newnvp = nvpair_clone(nvp);
1201 if (newnvp == NULL) {
1202 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1203 RESTORE_ERRNO(nvlist_error(nvl));
1207 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1211 nvlist_add_null(nvlist_t *nvl, const char *name)
1214 nvlist_addf_null(nvl, "%s", name);
1218 nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
1221 nvlist_addf_bool(nvl, value, "%s", name);
1225 nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
1228 nvlist_addf_number(nvl, value, "%s", name);
1232 nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
1235 nvlist_addf_string(nvl, value, "%s", name);
1239 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1243 va_start(valueap, valuefmt);
1244 nvlist_add_stringv(nvl, name, valuefmt, valueap);
1249 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1254 if (nvlist_error(nvl) != 0) {
1255 RESTORE_ERRNO(nvlist_error(nvl));
1259 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1261 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1262 RESTORE_ERRNO(nvl->nvl_error);
1264 nvlist_move_nvpair(nvl, nvp);
1268 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1271 nvlist_addf_nvlist(nvl, value, "%s", name);
1276 nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1279 nvlist_addf_descriptor(nvl, value, "%s", name);
1284 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1288 nvlist_addf_binary(nvl, value, size, "%s", name);
1292 nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...)
1296 va_start(nameap, namefmt);
1297 nvlist_addv_null(nvl, namefmt, nameap);
1302 nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...)
1306 va_start(nameap, namefmt);
1307 nvlist_addv_bool(nvl, value, namefmt, nameap);
1312 nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1316 va_start(nameap, namefmt);
1317 nvlist_addv_number(nvl, value, namefmt, nameap);
1322 nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...)
1326 va_start(nameap, namefmt);
1327 nvlist_addv_string(nvl, value, namefmt, nameap);
1332 nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1337 va_start(nameap, namefmt);
1338 nvlist_addv_nvlist(nvl, value, namefmt, nameap);
1344 nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...)
1348 va_start(nameap, namefmt);
1349 nvlist_addv_descriptor(nvl, value, namefmt, nameap);
1355 nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size,
1356 const char *namefmt, ...)
1360 va_start(nameap, namefmt);
1361 nvlist_addv_binary(nvl, value, size, namefmt, nameap);
1366 nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap)
1370 if (nvlist_error(nvl) != 0) {
1371 RESTORE_ERRNO(nvlist_error(nvl));
1375 nvp = nvpair_createv_null(namefmt, nameap);
1377 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1378 RESTORE_ERRNO(nvl->nvl_error);
1380 nvlist_move_nvpair(nvl, nvp);
1384 nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap)
1388 if (nvlist_error(nvl) != 0) {
1389 RESTORE_ERRNO(nvlist_error(nvl));
1393 nvp = nvpair_createv_bool(value, namefmt, nameap);
1395 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1396 RESTORE_ERRNO(nvl->nvl_error);
1398 nvlist_move_nvpair(nvl, nvp);
1402 nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt,
1407 if (nvlist_error(nvl) != 0) {
1408 RESTORE_ERRNO(nvlist_error(nvl));
1412 nvp = nvpair_createv_number(value, namefmt, nameap);
1414 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1415 RESTORE_ERRNO(nvl->nvl_error);
1417 nvlist_move_nvpair(nvl, nvp);
1421 nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt,
1426 if (nvlist_error(nvl) != 0) {
1427 RESTORE_ERRNO(nvlist_error(nvl));
1431 nvp = nvpair_createv_string(value, namefmt, nameap);
1433 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1434 RESTORE_ERRNO(nvl->nvl_error);
1436 nvlist_move_nvpair(nvl, nvp);
1440 nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1445 if (nvlist_error(nvl) != 0) {
1446 RESTORE_ERRNO(nvlist_error(nvl));
1450 nvp = nvpair_createv_nvlist(value, namefmt, nameap);
1452 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1453 RESTORE_ERRNO(nvl->nvl_error);
1455 nvlist_move_nvpair(nvl, nvp);
1460 nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1465 if (nvlist_error(nvl) != 0) {
1466 errno = nvlist_error(nvl);
1470 nvp = nvpair_createv_descriptor(value, namefmt, nameap);
1472 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1474 nvlist_move_nvpair(nvl, nvp);
1479 nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size,
1480 const char *namefmt, va_list nameap)
1484 if (nvlist_error(nvl) != 0) {
1485 RESTORE_ERRNO(nvlist_error(nvl));
1489 nvp = nvpair_createv_binary(value, size, namefmt, nameap);
1491 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1492 RESTORE_ERRNO(nvl->nvl_error);
1494 nvlist_move_nvpair(nvl, nvp);
1498 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1502 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1504 if (nvlist_error(nvl) != 0) {
1506 RESTORE_ERRNO(nvlist_error(nvl));
1509 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1511 nvl->nvl_error = EEXIST;
1512 RESTORE_ERRNO(nvl->nvl_error);
1516 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1519 #define NVLIST_MOVE(vtype, type) \
1521 nvlist_move_##type(nvlist_t *nvl, const char *name, vtype value) \
1524 nvlist_movef_##type(nvl, value, "%s", name); \
1527 NVLIST_MOVE(char *, string)
1528 NVLIST_MOVE(nvlist_t *, nvlist)
1530 NVLIST_MOVE(int, descriptor)
1536 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1539 nvlist_movef_binary(nvl, value, size, "%s", name);
1542 #define NVLIST_MOVEF(vtype, type) \
1544 nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt, \
1549 va_start(nameap, namefmt); \
1550 nvlist_movev_##type(nvl, value, namefmt, nameap); \
1554 NVLIST_MOVEF(char *, string)
1555 NVLIST_MOVEF(nvlist_t *, nvlist)
1557 NVLIST_MOVEF(int, descriptor)
1563 nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size,
1564 const char *namefmt, ...)
1568 va_start(nameap, namefmt);
1569 nvlist_movev_binary(nvl, value, size, namefmt, nameap);
1574 nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt,
1579 if (nvlist_error(nvl) != 0) {
1581 RESTORE_ERRNO(nvlist_error(nvl));
1585 nvp = nvpair_movev_string(value, namefmt, nameap);
1587 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1588 RESTORE_ERRNO(nvl->nvl_error);
1590 nvlist_move_nvpair(nvl, nvp);
1594 nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
1599 if (nvlist_error(nvl) != 0) {
1600 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1601 nvlist_destroy(value);
1602 RESTORE_ERRNO(nvlist_error(nvl));
1606 nvp = nvpair_movev_nvlist(value, namefmt, nameap);
1608 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1609 RESTORE_ERRNO(nvl->nvl_error);
1611 nvlist_move_nvpair(nvl, nvp);
1616 nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1621 if (nvlist_error(nvl) != 0) {
1623 errno = nvlist_error(nvl);
1627 nvp = nvpair_movev_descriptor(value, namefmt, nameap);
1629 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1631 nvlist_move_nvpair(nvl, nvp);
1636 nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size,
1637 const char *namefmt, va_list nameap)
1641 if (nvlist_error(nvl) != 0) {
1643 RESTORE_ERRNO(nvlist_error(nvl));
1647 nvp = nvpair_movev_binary(value, size, namefmt, nameap);
1649 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1650 RESTORE_ERRNO(nvl->nvl_error);
1652 nvlist_move_nvpair(nvl, nvp);
1656 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1659 return (nvlist_find(nvl, NV_TYPE_NONE, name));
1662 #define NVLIST_GET(ftype, type, TYPE) \
1664 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1666 const nvpair_t *nvp; \
1668 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1670 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1671 return (nvpair_get_##type(nvp)); \
1674 NVLIST_GET(bool, bool, BOOL)
1675 NVLIST_GET(uint64_t, number, NUMBER)
1676 NVLIST_GET(const char *, string, STRING)
1677 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1679 NVLIST_GET(int, descriptor, DESCRIPTOR)
1685 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1689 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1691 nvlist_report_missing(NV_TYPE_BINARY, name);
1693 return (nvpair_get_binary(nvp, sizep));
1696 #define NVLIST_GETF(ftype, type) \
1698 nvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...) \
1703 va_start(nameap, namefmt); \
1704 value = nvlist_getv_##type(nvl, namefmt, nameap); \
1711 NVLIST_GETF(bool, bool)
1712 NVLIST_GETF(uint64_t, number)
1713 NVLIST_GETF(const char *, string)
1714 NVLIST_GETF(const nvlist_t *, nvlist)
1715 NVLIST_GETF(int, descriptor)
1720 nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1725 va_start(nameap, namefmt);
1726 value = nvlist_getv_binary(nvl, sizep, namefmt, nameap);
1732 #define NVLIST_GETV(ftype, type, TYPE) \
1734 nvlist_getv_##type(const nvlist_t *nvl, const char *namefmt, \
1740 vasprintf(&name, namefmt, nameap); \
1742 nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \
1743 value = nvlist_get_##type(nvl, name); \
1749 NVLIST_GETV(bool, bool, BOOL)
1750 NVLIST_GETV(uint64_t, number, NUMBER)
1751 NVLIST_GETV(const char *, string, STRING)
1752 NVLIST_GETV(const nvlist_t *, nvlist, NVLIST)
1753 NVLIST_GETV(int, descriptor, DESCRIPTOR)
1758 nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt,
1764 nv_vasprintf(&name, namefmt, nameap);
1766 nvlist_report_missing(NV_TYPE_BINARY, "<unknown>");
1768 binary = nvlist_get_binary(nvl, name, sizep);
1774 #define NVLIST_TAKE(ftype, type, TYPE) \
1776 nvlist_take_##type(nvlist_t *nvl, const char *name) \
1781 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1783 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1784 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1785 nvlist_remove_nvpair(nvl, nvp); \
1786 nvpair_free_structure(nvp); \
1790 NVLIST_TAKE(bool, bool, BOOL)
1791 NVLIST_TAKE(uint64_t, number, NUMBER)
1792 NVLIST_TAKE(char *, string, STRING)
1793 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1795 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1801 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1806 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1808 nvlist_report_missing(NV_TYPE_BINARY, name);
1810 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1811 nvlist_remove_nvpair(nvl, nvp);
1812 nvpair_free_structure(nvp);
1816 #define NVLIST_TAKEF(ftype, type) \
1818 nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...) \
1823 va_start(nameap, namefmt); \
1824 value = nvlist_takev_##type(nvl, namefmt, nameap); \
1831 NVLIST_TAKEF(bool, bool)
1832 NVLIST_TAKEF(uint64_t, number)
1833 NVLIST_TAKEF(char *, string)
1834 NVLIST_TAKEF(nvlist_t *, nvlist)
1835 NVLIST_TAKEF(int, descriptor)
1840 nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1845 va_start(nameap, namefmt);
1846 value = nvlist_takev_binary(nvl, sizep, namefmt, nameap);
1852 #define NVLIST_TAKEV(ftype, type, TYPE) \
1854 nvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
1859 vasprintf(&name, namefmt, nameap); \
1861 nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \
1862 value = nvlist_take_##type(nvl, name); \
1867 NVLIST_TAKEV(bool, bool, BOOL)
1868 NVLIST_TAKEV(uint64_t, number, NUMBER)
1869 NVLIST_TAKEV(char *, string, STRING)
1870 NVLIST_TAKEV(nvlist_t *, nvlist, NVLIST)
1871 NVLIST_TAKEV(int, descriptor, DESCRIPTOR)
1876 nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt,
1882 nv_vasprintf(&name, namefmt, nameap);
1884 nvlist_report_missing(NV_TYPE_BINARY, "<unknown>");
1886 binary = nvlist_take_binary(nvl, name, sizep);
1893 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1898 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1900 nvpair_remove(&nvl->nvl_head, nvp, nvl);
1904 nvlist_free(nvlist_t *nvl, const char *name)
1907 nvlist_free_type(nvl, name, NV_TYPE_NONE);
1910 #define NVLIST_FREE(type, TYPE) \
1912 nvlist_free_##type(nvlist_t *nvl, const char *name) \
1915 nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \
1918 NVLIST_FREE(null, NULL)
1919 NVLIST_FREE(bool, BOOL)
1920 NVLIST_FREE(number, NUMBER)
1921 NVLIST_FREE(string, STRING)
1922 NVLIST_FREE(nvlist, NVLIST)
1924 NVLIST_FREE(descriptor, DESCRIPTOR)
1926 NVLIST_FREE(binary, BINARY)
1932 nvlist_freef(nvlist_t *nvl, const char *namefmt, ...)
1936 va_start(nameap, namefmt);
1937 nvlist_freev(nvl, namefmt, nameap);
1941 #define NVLIST_FREEF(type) \
1943 nvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...) \
1947 va_start(nameap, namefmt); \
1948 nvlist_freev_##type(nvl, namefmt, nameap); \
1954 NVLIST_FREEF(number)
1955 NVLIST_FREEF(string)
1956 NVLIST_FREEF(nvlist)
1957 NVLIST_FREEF(descriptor)
1958 NVLIST_FREEF(binary)
1963 nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap)
1966 nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap);
1969 #define NVLIST_FREEV(type, TYPE) \
1971 nvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
1975 vasprintf(&name, namefmt, nameap); \
1977 nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \
1978 nvlist_free_##type(nvl, name); \
1982 NVLIST_FREEV(null, NULL)
1983 NVLIST_FREEV(bool, BOOL)
1984 NVLIST_FREEV(number, NUMBER)
1985 NVLIST_FREEV(string, STRING)
1986 NVLIST_FREEV(nvlist, NVLIST)
1987 NVLIST_FREEV(descriptor, DESCRIPTOR)
1988 NVLIST_FREEV(binary, BINARY)
1993 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1998 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
2000 nvlist_remove_nvpair(nvl, nvp);