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>
36 #include <sys/socket.h>
55 #include "nvlist_impl.h"
56 #include "nvpair_impl.h"
60 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
61 #define PJDLOG_RASSERT(expr, ...) assert(expr)
62 #define PJDLOG_ABORT(...) do { \
63 fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \
64 fprintf(stderr, __VA_ARGS__); \
65 fprintf(stderr, "\n"); \
70 #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN)
71 #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE)
72 #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
74 #define NVLIST_MAGIC 0x6e766c /* "nvl" */
79 struct nvl_head nvl_head;
82 #define NVLIST_ASSERT(nvl) do { \
83 PJDLOG_ASSERT((nvl) != NULL); \
84 PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \
87 #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp)
89 #define NVLIST_HEADER_MAGIC 0x6c
90 #define NVLIST_HEADER_VERSION 0x00
91 struct nvlist_header {
95 uint64_t nvlh_descriptors;
100 nvlist_create(int flags)
104 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
106 nvl = malloc(sizeof(*nvl));
108 nvl->nvl_flags = flags;
109 TAILQ_INIT(&nvl->nvl_head);
110 nvl->nvl_magic = NVLIST_MAGIC;
116 nvlist_destroy(nvlist_t *nvl)
128 while ((nvp = nvlist_first_nvpair(nvl)) != NULL)
129 nvlist_remove_nvpair(nvl, nvp);
137 nvlist_error(const nvlist_t *nvl)
145 return (nvl->nvl_error);
149 nvlist_empty(const nvlist_t *nvl)
153 PJDLOG_ASSERT(nvl->nvl_error == 0);
155 return (nvlist_first_nvpair(nvl) == NULL);
159 nvlist_report_missing(int type, const char *namefmt, va_list nameap)
163 vasprintf(&name, namefmt, nameap);
164 PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
165 name != NULL ? name : "N/A", nvpair_type_string(type));
169 nvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
175 PJDLOG_ASSERT(nvl->nvl_error == 0);
176 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
177 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
179 if (vasprintf(&name, namefmt, nameap) < 0)
182 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
183 nvp = nvlist_next_nvpair(nvl, nvp)) {
184 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
186 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
187 if (strcasecmp(nvpair_name(nvp), name) != 0)
190 if (strcmp(nvpair_name(nvp), name) != 0)
205 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
208 return (nvlist_existsf_type(nvl, type, "%s", name));
212 nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...)
217 va_start(nameap, namefmt);
218 ret = nvlist_existsv_type(nvl, type, namefmt, nameap);
225 nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt,
230 PJDLOG_ASSERT(nvl->nvl_error == 0);
231 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
232 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
234 return (nvlist_findv(nvl, type, namefmt, nameap) != NULL);
238 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
241 nvlist_freef_type(nvl, type, "%s", name);
245 nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...)
249 va_start(nameap, namefmt);
250 nvlist_freev_type(nvl, type, namefmt, nameap);
255 nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
261 PJDLOG_ASSERT(nvl->nvl_error == 0);
262 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
263 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
265 va_copy(cnameap, nameap);
266 nvp = nvlist_findv(nvl, type, namefmt, cnameap);
269 nvlist_free_nvpair(nvl, nvp);
271 nvlist_report_missing(type, namefmt, nameap);
275 nvlist_clone(const nvlist_t *nvl)
278 nvpair_t *nvp, *newnvp;
282 if (nvl->nvl_error != 0) {
283 errno = nvl->nvl_error;
287 newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
288 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
289 nvp = nvlist_next_nvpair(nvl, nvp)) {
290 newnvp = nvpair_clone(nvp);
293 nvlist_move_nvpair(newnvl, newnvp);
296 nvlist_destroy(newnvl);
303 * Dump content of nvlist.
306 nvlist_xdump(const nvlist_t *nvl, int fd, int level)
310 PJDLOG_ASSERT(level < 3);
312 if (nvlist_error(nvl) != 0) {
313 dprintf(fd, "%*serror: %d\n", level * 4, "",
318 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
319 nvp = nvlist_next_nvpair(nvl, nvp)) {
320 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
321 nvpair_type_string(nvpair_type(nvp)));
322 switch (nvpair_type(nvp)) {
324 dprintf(fd, " null\n");
327 dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
331 dprintf(fd, " %ju (%jd) (0x%jx)\n",
332 (uintmax_t)nvpair_get_number(nvp),
333 (intmax_t)nvpair_get_number(nvp),
334 (uintmax_t)nvpair_get_number(nvp));
337 dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
341 nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1);
343 case NV_TYPE_DESCRIPTOR:
344 dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
348 const unsigned char *binary;
352 binary = nvpair_get_binary(nvp, &size);
353 dprintf(fd, " %zu ", size);
354 for (ii = 0; ii < size; ii++)
355 dprintf(fd, "%02hhx", binary[ii]);
360 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
366 nvlist_dump(const nvlist_t *nvl, int fd)
369 nvlist_xdump(nvl, fd, 0);
373 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
377 nvlist_dump(nvl, fileno(fp));
381 * The function obtains size of the nvlist after nvlist_pack().
382 * Additional argument 'level' allows to track how deep are we as we obtain
383 * size of the NV_TYPE_NVLIST elements using recursion. We allow at most
384 * three levels of recursion.
387 nvlist_xsize(const nvlist_t *nvl, int level)
393 PJDLOG_ASSERT(nvl->nvl_error == 0);
394 PJDLOG_ASSERT(level < 3);
396 size = sizeof(struct nvlist_header);
397 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
398 nvp = nvlist_next_nvpair(nvl, nvp)) {
399 size += nvpair_header_size();
400 size += strlen(nvpair_name(nvp)) + 1;
401 if (nvpair_type(nvp) == NV_TYPE_NVLIST)
402 size += nvlist_xsize(nvpair_get_nvlist(nvp), level + 1);
404 size += nvpair_size(nvp);
411 nvlist_size(const nvlist_t *nvl)
414 return (nvlist_xsize(nvl, 0));
418 nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
423 PJDLOG_ASSERT(nvl->nvl_error == 0);
424 PJDLOG_ASSERT(level < 3);
426 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
427 nvp = nvlist_next_nvpair(nvl, nvp)) {
428 switch (nvpair_type(nvp)) {
429 case NV_TYPE_DESCRIPTOR:
430 *descs = nvpair_get_descriptor(nvp);
434 descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
444 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
449 nitems = nvlist_ndescriptors(nvl);
450 fds = malloc(sizeof(fds[0]) * (nitems + 1));
454 nvlist_xdescriptors(nvl, fds, 0);
462 nvlist_xndescriptors(const nvlist_t *nvl, int level)
468 PJDLOG_ASSERT(nvl->nvl_error == 0);
469 PJDLOG_ASSERT(level < 3);
472 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
473 nvp = nvlist_next_nvpair(nvl, nvp)) {
474 switch (nvpair_type(nvp)) {
475 case NV_TYPE_DESCRIPTOR:
479 ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
489 nvlist_ndescriptors(const nvlist_t *nvl)
492 return (nvlist_xndescriptors(nvl, 0));
495 static unsigned char *
496 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
498 struct nvlist_header nvlhdr;
502 nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
503 nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
504 nvlhdr.nvlh_flags = nvl->nvl_flags;
505 #if BYTE_ORDER == BIG_ENDIAN
506 nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
508 nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
509 nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
510 PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
511 memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
512 ptr += sizeof(nvlhdr);
513 *leftp -= sizeof(nvlhdr);
519 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
521 unsigned char *buf, *ptr;
527 if (nvl->nvl_error != 0) {
528 errno = nvl->nvl_error;
532 size = nvlist_size(nvl);
540 ptr = nvlist_pack_header(nvl, ptr, &left);
542 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
543 nvp = nvlist_next_nvpair(nvl, nvp)) {
544 ptr = nvpair_pack(nvp, ptr, fdidxp, &left);
557 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
562 if (nvl->nvl_error != 0) {
563 errno = nvl->nvl_error;
567 if (nvlist_ndescriptors(nvl) > 0) {
572 return (nvlist_xpack(nvl, NULL, sizep));
576 nvlist_check_header(struct nvlist_header *nvlhdrp)
579 if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
583 if ((nvlhdrp->nvlh_flags &= ~NV_FLAG_ALL_MASK) != 0) {
587 #if BYTE_ORDER == BIG_ENDIAN
588 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
589 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
590 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
593 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
594 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
595 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
601 static const unsigned char *
602 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
603 int *flagsp, size_t *leftp)
605 struct nvlist_header nvlhdr;
607 if (*leftp < sizeof(nvlhdr))
610 memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
612 if (!nvlist_check_header(&nvlhdr))
615 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
619 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
621 if (nvlhdr.nvlh_descriptors > nfds)
624 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
627 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
629 ptr += sizeof(nvlhdr);
630 *flagsp = (int)nvlhdr.nvlh_flags;
631 *leftp -= sizeof(nvlhdr);
640 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
642 const unsigned char *ptr;
651 nvl = nvlist_create(0);
655 ptr = nvlist_unpack_header(nvl, ptr, nfds, &flags, &left);
660 ptr = nvpair_unpack(flags, ptr, &left, fds, nfds, &nvp);
663 nvlist_move_nvpair(nvl, nvp);
673 nvlist_unpack(const void *buf, size_t size)
676 return (nvlist_xunpack(buf, size, NULL, 0));
680 nvlist_send(int sock, const nvlist_t *nvl)
682 size_t datasize, nfds;
688 if (nvlist_error(nvl) != 0) {
689 errno = nvlist_error(nvl);
693 fds = nvlist_descriptors(nvl, &nfds);
701 data = nvlist_xpack(nvl, &fdidx, &datasize);
705 if (buf_send(sock, data, datasize) == -1)
709 if (fd_send(sock, fds, nfds) == -1)
723 nvlist_recv(int sock)
725 struct nvlist_header nvlhdr;
731 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
734 if (!nvlist_check_header(&nvlhdr))
737 nfds = (size_t)nvlhdr.nvlh_descriptors;
738 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
744 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
749 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
753 fds = malloc(nfds * sizeof(fds[0]));
756 if (fd_recv(sock, fds, nfds) == -1)
760 nvl = nvlist_xunpack(buf, size, fds, nfds);
775 nvlist_xfer(int sock, nvlist_t *nvl)
778 if (nvlist_send(sock, nvl) < 0) {
783 return (nvlist_recv(sock));
787 nvlist_first_nvpair(const nvlist_t *nvl)
792 return (TAILQ_FIRST(&nvl->nvl_head));
796 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
802 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
804 retnvp = nvpair_next(nvp);
805 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
812 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
818 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
820 retnvp = nvpair_prev(nvp);
821 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
827 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
832 PJDLOG_ASSERT(cookiep != NULL);
834 if (*cookiep == NULL)
835 nvp = nvlist_first_nvpair(nvl);
837 nvp = nvlist_next_nvpair(nvl, *cookiep);
841 *typep = nvpair_type(nvp);
843 return (nvpair_name(nvp));
847 nvlist_exists(const nvlist_t *nvl, const char *name)
850 return (nvlist_existsf(nvl, "%s", name));
853 #define NVLIST_EXISTS(type) \
855 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
858 return (nvlist_existsf_##type(nvl, "%s", name)); \
863 NVLIST_EXISTS(number)
864 NVLIST_EXISTS(string)
865 NVLIST_EXISTS(nvlist)
866 NVLIST_EXISTS(descriptor)
867 NVLIST_EXISTS(binary)
872 nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...)
877 va_start(nameap, namefmt);
878 ret = nvlist_existsv(nvl, namefmt, nameap);
883 #define NVLIST_EXISTSF(type) \
885 nvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...) \
890 va_start(nameap, namefmt); \
891 ret = nvlist_existsv_##type(nvl, namefmt, nameap); \
898 NVLIST_EXISTSF(number)
899 NVLIST_EXISTSF(string)
900 NVLIST_EXISTSF(nvlist)
901 NVLIST_EXISTSF(descriptor)
902 NVLIST_EXISTSF(binary)
904 #undef NVLIST_EXISTSF
907 nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap)
910 return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap) != NULL);
913 #define NVLIST_EXISTSV(type, TYPE) \
915 nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \
919 return (nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, nameap) != \
923 NVLIST_EXISTSV(null, NULL)
924 NVLIST_EXISTSV(bool, BOOL)
925 NVLIST_EXISTSV(number, NUMBER)
926 NVLIST_EXISTSV(string, STRING)
927 NVLIST_EXISTSV(nvlist, NVLIST)
928 NVLIST_EXISTSV(descriptor, DESCRIPTOR)
929 NVLIST_EXISTSV(binary, BINARY)
931 #undef NVLIST_EXISTSV
934 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
940 if (nvlist_error(nvl) != 0) {
941 errno = nvlist_error(nvl);
944 if (nvlist_exists(nvl, nvpair_name(nvp))) {
945 nvl->nvl_error = errno = EEXIST;
949 newnvp = nvpair_clone(nvp);
950 if (newnvp == NULL) {
951 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
955 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
959 nvlist_add_null(nvlist_t *nvl, const char *name)
962 nvlist_addf_null(nvl, "%s", name);
966 nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
969 nvlist_addf_bool(nvl, value, "%s", name);
973 nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
976 nvlist_addf_number(nvl, value, "%s", name);
980 nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
983 nvlist_addf_string(nvl, value, "%s", name);
987 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
991 va_start(valueap, valuefmt);
992 nvlist_add_stringv(nvl, name, valuefmt, valueap);
997 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1002 if (nvlist_error(nvl) != 0) {
1003 errno = nvlist_error(nvl);
1007 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1009 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1011 nvlist_move_nvpair(nvl, nvp);
1015 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1018 nvlist_addf_nvlist(nvl, value, "%s", name);
1022 nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1025 nvlist_addf_descriptor(nvl, value, "%s", name);
1029 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1033 nvlist_addf_binary(nvl, value, size, "%s", name);
1037 nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...)
1041 va_start(nameap, namefmt);
1042 nvlist_addv_null(nvl, namefmt, nameap);
1047 nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...)
1051 va_start(nameap, namefmt);
1052 nvlist_addv_bool(nvl, value, namefmt, nameap);
1057 nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1061 va_start(nameap, namefmt);
1062 nvlist_addv_number(nvl, value, namefmt, nameap);
1067 nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...)
1071 va_start(nameap, namefmt);
1072 nvlist_addv_string(nvl, value, namefmt, nameap);
1077 nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1082 va_start(nameap, namefmt);
1083 nvlist_addv_nvlist(nvl, value, namefmt, nameap);
1088 nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...)
1092 va_start(nameap, namefmt);
1093 nvlist_addv_descriptor(nvl, value, namefmt, nameap);
1098 nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size,
1099 const char *namefmt, ...)
1103 va_start(nameap, namefmt);
1104 nvlist_addv_binary(nvl, value, size, namefmt, nameap);
1109 nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap)
1113 if (nvlist_error(nvl) != 0) {
1114 errno = nvlist_error(nvl);
1118 nvp = nvpair_createv_null(namefmt, nameap);
1120 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1122 nvlist_move_nvpair(nvl, nvp);
1126 nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap)
1130 if (nvlist_error(nvl) != 0) {
1131 errno = nvlist_error(nvl);
1135 nvp = nvpair_createv_bool(value, namefmt, nameap);
1137 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1139 nvlist_move_nvpair(nvl, nvp);
1143 nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt,
1148 if (nvlist_error(nvl) != 0) {
1149 errno = nvlist_error(nvl);
1153 nvp = nvpair_createv_number(value, namefmt, nameap);
1155 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1157 nvlist_move_nvpair(nvl, nvp);
1161 nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt,
1166 if (nvlist_error(nvl) != 0) {
1167 errno = nvlist_error(nvl);
1171 nvp = nvpair_createv_string(value, namefmt, nameap);
1173 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1175 nvlist_move_nvpair(nvl, nvp);
1179 nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1184 if (nvlist_error(nvl) != 0) {
1185 errno = nvlist_error(nvl);
1189 nvp = nvpair_createv_nvlist(value, namefmt, nameap);
1191 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1193 nvlist_move_nvpair(nvl, nvp);
1197 nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1202 if (nvlist_error(nvl) != 0) {
1203 errno = nvlist_error(nvl);
1207 nvp = nvpair_createv_descriptor(value, namefmt, nameap);
1209 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1211 nvlist_move_nvpair(nvl, nvp);
1215 nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size,
1216 const char *namefmt, va_list nameap)
1220 if (nvlist_error(nvl) != 0) {
1221 errno = nvlist_error(nvl);
1225 nvp = nvpair_createv_binary(value, size, namefmt, nameap);
1227 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1229 nvlist_move_nvpair(nvl, nvp);
1233 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1237 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1239 if (nvlist_error(nvl) != 0) {
1241 errno = nvlist_error(nvl);
1244 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1246 nvl->nvl_error = errno = EEXIST;
1250 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1253 #define NVLIST_MOVE(vtype, type) \
1255 nvlist_move_##type(nvlist_t *nvl, const char *name, vtype value) \
1258 nvlist_movef_##type(nvl, value, "%s", name); \
1261 NVLIST_MOVE(char *, string)
1262 NVLIST_MOVE(nvlist_t *, nvlist)
1263 NVLIST_MOVE(int, descriptor)
1268 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1271 nvlist_movef_binary(nvl, value, size, "%s", name);
1274 #define NVLIST_MOVEF(vtype, type) \
1276 nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt, \
1281 va_start(nameap, namefmt); \
1282 nvlist_movev_##type(nvl, value, namefmt, nameap); \
1286 NVLIST_MOVEF(char *, string)
1287 NVLIST_MOVEF(nvlist_t *, nvlist)
1288 NVLIST_MOVEF(int, descriptor)
1293 nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size,
1294 const char *namefmt, ...)
1298 va_start(nameap, namefmt);
1299 nvlist_movev_binary(nvl, value, size, namefmt, nameap);
1304 nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt,
1309 if (nvlist_error(nvl) != 0) {
1311 errno = nvlist_error(nvl);
1315 nvp = nvpair_movev_string(value, namefmt, nameap);
1317 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1319 nvlist_move_nvpair(nvl, nvp);
1323 nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
1328 if (nvlist_error(nvl) != 0) {
1329 nvlist_destroy(value);
1330 errno = nvlist_error(nvl);
1334 nvp = nvpair_movev_nvlist(value, namefmt, nameap);
1336 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1338 nvlist_move_nvpair(nvl, nvp);
1342 nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1347 if (nvlist_error(nvl) != 0) {
1349 errno = nvlist_error(nvl);
1353 nvp = nvpair_movev_descriptor(value, namefmt, nameap);
1355 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1357 nvlist_move_nvpair(nvl, nvp);
1361 nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size,
1362 const char *namefmt, va_list nameap)
1366 if (nvlist_error(nvl) != 0) {
1368 errno = nvlist_error(nvl);
1372 nvp = nvpair_movev_binary(value, size, namefmt, nameap);
1374 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1376 nvlist_move_nvpair(nvl, nvp);
1379 #define NVLIST_GET(ftype, type) \
1381 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1384 return (nvlist_getf_##type(nvl, "%s", name)); \
1387 NVLIST_GET(const nvpair_t *, nvpair)
1388 NVLIST_GET(bool, bool)
1389 NVLIST_GET(uint64_t, number)
1390 NVLIST_GET(const char *, string)
1391 NVLIST_GET(const nvlist_t *, nvlist)
1392 NVLIST_GET(int, descriptor)
1397 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1400 return (nvlist_getf_binary(nvl, sizep, "%s", name));
1403 #define NVLIST_GETF(ftype, type) \
1405 nvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...) \
1410 va_start(nameap, namefmt); \
1411 value = nvlist_getv_##type(nvl, namefmt, nameap); \
1417 NVLIST_GETF(const nvpair_t *, nvpair)
1418 NVLIST_GETF(bool, bool)
1419 NVLIST_GETF(uint64_t, number)
1420 NVLIST_GETF(const char *, string)
1421 NVLIST_GETF(const nvlist_t *, nvlist)
1422 NVLIST_GETF(int, descriptor)
1427 nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1432 va_start(nameap, namefmt);
1433 value = nvlist_getv_binary(nvl, sizep, namefmt, nameap);
1440 nvlist_getv_nvpair(const nvlist_t *nvl, const char *namefmt, va_list nameap)
1443 return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap));
1446 #define NVLIST_GETV(ftype, type, TYPE) \
1448 nvlist_getv_##type(const nvlist_t *nvl, const char *namefmt, \
1452 const nvpair_t *nvp; \
1454 va_copy(cnameap, nameap); \
1455 nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \
1458 nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \
1459 return (nvpair_get_##type(nvp)); \
1462 NVLIST_GETV(bool, bool, BOOL)
1463 NVLIST_GETV(uint64_t, number, NUMBER)
1464 NVLIST_GETV(const char *, string, STRING)
1465 NVLIST_GETV(const nvlist_t *, nvlist, NVLIST)
1466 NVLIST_GETV(int, descriptor, DESCRIPTOR)
1471 nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt,
1475 const nvpair_t *nvp;
1477 va_copy(cnameap, nameap);
1478 nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap);
1481 nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap);
1483 return (nvpair_get_binary(nvp, sizep));
1486 #define NVLIST_TAKE(ftype, type) \
1488 nvlist_take_##type(nvlist_t *nvl, const char *name) \
1491 return (nvlist_takef_##type(nvl, "%s", name)); \
1494 NVLIST_TAKE(nvpair_t *, nvpair)
1495 NVLIST_TAKE(bool, bool)
1496 NVLIST_TAKE(uint64_t, number)
1497 NVLIST_TAKE(char *, string)
1498 NVLIST_TAKE(nvlist_t *, nvlist)
1499 NVLIST_TAKE(int, descriptor)
1504 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1507 return (nvlist_takef_binary(nvl, sizep, "%s", name));
1510 #define NVLIST_TAKEF(ftype, type) \
1512 nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...) \
1517 va_start(nameap, namefmt); \
1518 value = nvlist_takev_##type(nvl, namefmt, nameap); \
1524 NVLIST_TAKEF(nvpair_t *, nvpair)
1525 NVLIST_TAKEF(bool, bool)
1526 NVLIST_TAKEF(uint64_t, number)
1527 NVLIST_TAKEF(char *, string)
1528 NVLIST_TAKEF(nvlist_t *, nvlist)
1529 NVLIST_TAKEF(int, descriptor)
1534 nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1539 va_start(nameap, namefmt);
1540 value = nvlist_takev_binary(nvl, sizep, namefmt, nameap);
1547 nvlist_takev_nvpair(nvlist_t *nvl, const char *namefmt, va_list nameap)
1551 nvp = nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap);
1553 nvlist_remove_nvpair(nvl, nvp);
1557 #define NVLIST_TAKEV(ftype, type, TYPE) \
1559 nvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
1565 va_copy(cnameap, nameap); \
1566 nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \
1569 nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \
1570 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1571 nvlist_remove_nvpair(nvl, nvp); \
1572 nvpair_free_structure(nvp); \
1576 NVLIST_TAKEV(bool, bool, BOOL)
1577 NVLIST_TAKEV(uint64_t, number, NUMBER)
1578 NVLIST_TAKEV(char *, string, STRING)
1579 NVLIST_TAKEV(nvlist_t *, nvlist, NVLIST)
1580 NVLIST_TAKEV(int, descriptor, DESCRIPTOR)
1585 nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt,
1592 va_copy(cnameap, nameap);
1593 nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap);
1596 nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap);
1598 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1599 nvlist_remove_nvpair(nvl, nvp);
1600 nvpair_free_structure(nvp);
1605 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1610 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1612 nvpair_remove(&nvl->nvl_head, nvp, nvl);
1616 nvlist_free(nvlist_t *nvl, const char *name)
1619 nvlist_freef(nvl, "%s", name);
1622 #define NVLIST_FREE(type) \
1624 nvlist_free_##type(nvlist_t *nvl, const char *name) \
1627 nvlist_freef_##type(nvl, "%s", name); \
1635 NVLIST_FREE(descriptor)
1641 nvlist_freef(nvlist_t *nvl, const char *namefmt, ...)
1645 va_start(nameap, namefmt);
1646 nvlist_freev(nvl, namefmt, nameap);
1650 #define NVLIST_FREEF(type) \
1652 nvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...) \
1656 va_start(nameap, namefmt); \
1657 nvlist_freev_##type(nvl, namefmt, nameap); \
1663 NVLIST_FREEF(number)
1664 NVLIST_FREEF(string)
1665 NVLIST_FREEF(nvlist)
1666 NVLIST_FREEF(descriptor)
1667 NVLIST_FREEF(binary)
1672 nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap)
1675 nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap);
1678 #define NVLIST_FREEV(type, TYPE) \
1680 nvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
1683 nvlist_freev_type(nvl, NV_TYPE_##TYPE, namefmt, nameap); \
1686 NVLIST_FREEV(null, NULL)
1687 NVLIST_FREEV(bool, BOOL)
1688 NVLIST_FREEV(number, NUMBER)
1689 NVLIST_FREEV(string, STRING)
1690 NVLIST_FREEV(nvlist, NVLIST)
1691 NVLIST_FREEV(descriptor, DESCRIPTOR)
1692 NVLIST_FREEV(binary, BINARY)
1696 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1701 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1703 nvlist_remove_nvpair(nvl, nvp);