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);
139 nvlist_error(const nvlist_t *nvl)
147 return (nvl->nvl_error);
151 nvlist_empty(const nvlist_t *nvl)
155 PJDLOG_ASSERT(nvl->nvl_error == 0);
157 return (nvlist_first_nvpair(nvl) == NULL);
161 nvlist_report_missing(int type, const char *namefmt, va_list nameap)
165 vasprintf(&name, namefmt, nameap);
166 PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
167 name != NULL ? name : "N/A", nvpair_type_string(type));
171 nvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
177 PJDLOG_ASSERT(nvl->nvl_error == 0);
178 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
179 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
181 if (vasprintf(&name, namefmt, nameap) < 0)
184 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
185 nvp = nvlist_next_nvpair(nvl, nvp)) {
186 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
188 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
189 if (strcasecmp(nvpair_name(nvp), name) != 0)
192 if (strcmp(nvpair_name(nvp), name) != 0)
207 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
210 return (nvlist_existsf_type(nvl, type, "%s", name));
214 nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...)
219 va_start(nameap, namefmt);
220 ret = nvlist_existsv_type(nvl, type, namefmt, nameap);
227 nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt,
232 PJDLOG_ASSERT(nvl->nvl_error == 0);
233 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
234 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
236 return (nvlist_findv(nvl, type, namefmt, nameap) != NULL);
240 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
243 nvlist_freef_type(nvl, type, "%s", name);
247 nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...)
251 va_start(nameap, namefmt);
252 nvlist_freev_type(nvl, type, namefmt, nameap);
257 nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
263 PJDLOG_ASSERT(nvl->nvl_error == 0);
264 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
265 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
267 va_copy(cnameap, nameap);
268 nvp = nvlist_findv(nvl, type, namefmt, cnameap);
271 nvlist_free_nvpair(nvl, nvp);
273 nvlist_report_missing(type, namefmt, nameap);
277 nvlist_clone(const nvlist_t *nvl)
280 nvpair_t *nvp, *newnvp;
284 if (nvl->nvl_error != 0) {
285 errno = nvl->nvl_error;
289 newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
290 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
291 nvp = nvlist_next_nvpair(nvl, nvp)) {
292 newnvp = nvpair_clone(nvp);
295 nvlist_move_nvpair(newnvl, newnvp);
298 nvlist_destroy(newnvl);
305 * Dump content of nvlist.
308 nvlist_xdump(const nvlist_t *nvl, int fd, int level)
312 PJDLOG_ASSERT(level < 3);
314 if (nvlist_error(nvl) != 0) {
315 dprintf(fd, "%*serror: %d\n", level * 4, "",
320 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
321 nvp = nvlist_next_nvpair(nvl, nvp)) {
322 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
323 nvpair_type_string(nvpair_type(nvp)));
324 switch (nvpair_type(nvp)) {
326 dprintf(fd, " null\n");
329 dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
333 dprintf(fd, " %ju (%jd) (0x%jx)\n",
334 (uintmax_t)nvpair_get_number(nvp),
335 (intmax_t)nvpair_get_number(nvp),
336 (uintmax_t)nvpair_get_number(nvp));
339 dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
343 nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1);
345 case NV_TYPE_DESCRIPTOR:
346 dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
350 const unsigned char *binary;
354 binary = nvpair_get_binary(nvp, &size);
355 dprintf(fd, " %zu ", size);
356 for (ii = 0; ii < size; ii++)
357 dprintf(fd, "%02hhx", binary[ii]);
362 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
368 nvlist_dump(const nvlist_t *nvl, int fd)
371 nvlist_xdump(nvl, fd, 0);
375 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
379 nvlist_dump(nvl, fileno(fp));
383 * The function obtains size of the nvlist after nvlist_pack().
384 * Additional argument 'level' allows to track how deep are we as we obtain
385 * size of the NV_TYPE_NVLIST elements using recursion. We allow at most
386 * three levels of recursion.
389 nvlist_xsize(const nvlist_t *nvl, int level)
395 PJDLOG_ASSERT(nvl->nvl_error == 0);
396 PJDLOG_ASSERT(level < 3);
398 size = sizeof(struct nvlist_header);
399 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
400 nvp = nvlist_next_nvpair(nvl, nvp)) {
401 size += nvpair_header_size();
402 size += strlen(nvpair_name(nvp)) + 1;
403 if (nvpair_type(nvp) == NV_TYPE_NVLIST)
404 size += nvlist_xsize(nvpair_get_nvlist(nvp), level + 1);
406 size += nvpair_size(nvp);
413 nvlist_size(const nvlist_t *nvl)
416 return (nvlist_xsize(nvl, 0));
420 nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
425 PJDLOG_ASSERT(nvl->nvl_error == 0);
426 PJDLOG_ASSERT(level < 3);
428 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
429 nvp = nvlist_next_nvpair(nvl, nvp)) {
430 switch (nvpair_type(nvp)) {
431 case NV_TYPE_DESCRIPTOR:
432 *descs = nvpair_get_descriptor(nvp);
436 descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
446 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
451 nitems = nvlist_ndescriptors(nvl);
452 fds = malloc(sizeof(fds[0]) * (nitems + 1));
456 nvlist_xdescriptors(nvl, fds, 0);
464 nvlist_xndescriptors(const nvlist_t *nvl, int level)
470 PJDLOG_ASSERT(nvl->nvl_error == 0);
471 PJDLOG_ASSERT(level < 3);
474 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
475 nvp = nvlist_next_nvpair(nvl, nvp)) {
476 switch (nvpair_type(nvp)) {
477 case NV_TYPE_DESCRIPTOR:
481 ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
491 nvlist_ndescriptors(const nvlist_t *nvl)
494 return (nvlist_xndescriptors(nvl, 0));
497 static unsigned char *
498 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
500 struct nvlist_header nvlhdr;
504 nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
505 nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
506 nvlhdr.nvlh_flags = nvl->nvl_flags;
507 #if BYTE_ORDER == BIG_ENDIAN
508 nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
510 nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
511 nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
512 PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
513 memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
514 ptr += sizeof(nvlhdr);
515 *leftp -= sizeof(nvlhdr);
521 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
523 unsigned char *buf, *ptr;
529 if (nvl->nvl_error != 0) {
530 errno = nvl->nvl_error;
534 size = nvlist_size(nvl);
542 ptr = nvlist_pack_header(nvl, ptr, &left);
544 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
545 nvp = nvlist_next_nvpair(nvl, nvp)) {
546 ptr = nvpair_pack(nvp, ptr, fdidxp, &left);
559 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
564 if (nvl->nvl_error != 0) {
565 errno = nvl->nvl_error;
569 if (nvlist_ndescriptors(nvl) > 0) {
574 return (nvlist_xpack(nvl, NULL, sizep));
578 nvlist_check_header(struct nvlist_header *nvlhdrp)
581 if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
585 if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
589 #if BYTE_ORDER == BIG_ENDIAN
590 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
591 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
592 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
595 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
596 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
597 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
603 static const unsigned char *
604 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
605 int *flagsp, size_t *leftp)
607 struct nvlist_header nvlhdr;
609 if (*leftp < sizeof(nvlhdr))
612 memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
614 if (!nvlist_check_header(&nvlhdr))
617 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
621 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
623 if (nvlhdr.nvlh_descriptors > nfds)
626 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
629 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
631 ptr += sizeof(nvlhdr);
632 *flagsp = (int)nvlhdr.nvlh_flags;
633 *leftp -= sizeof(nvlhdr);
642 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
644 const unsigned char *ptr;
653 nvl = nvlist_create(0);
657 ptr = nvlist_unpack_header(nvl, ptr, nfds, &flags, &left);
662 ptr = nvpair_unpack(flags, ptr, &left, fds, nfds, &nvp);
665 nvlist_move_nvpair(nvl, nvp);
675 nvlist_unpack(const void *buf, size_t size)
678 return (nvlist_xunpack(buf, size, NULL, 0));
682 nvlist_send(int sock, const nvlist_t *nvl)
684 size_t datasize, nfds;
690 if (nvlist_error(nvl) != 0) {
691 errno = nvlist_error(nvl);
695 fds = nvlist_descriptors(nvl, &nfds);
703 data = nvlist_xpack(nvl, &fdidx, &datasize);
707 if (buf_send(sock, data, datasize) == -1)
711 if (fd_send(sock, fds, nfds) == -1)
725 nvlist_recv(int sock)
727 struct nvlist_header nvlhdr;
733 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
736 if (!nvlist_check_header(&nvlhdr))
739 nfds = (size_t)nvlhdr.nvlh_descriptors;
740 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
746 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
751 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
755 fds = malloc(nfds * sizeof(fds[0]));
758 if (fd_recv(sock, fds, nfds) == -1)
762 nvl = nvlist_xunpack(buf, size, fds, nfds);
764 for (i = 0; i < nfds; i++)
780 nvlist_xfer(int sock, nvlist_t *nvl)
783 if (nvlist_send(sock, nvl) < 0) {
788 return (nvlist_recv(sock));
792 nvlist_first_nvpair(const nvlist_t *nvl)
797 return (TAILQ_FIRST(&nvl->nvl_head));
801 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
807 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
809 retnvp = nvpair_next(nvp);
810 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
817 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
823 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
825 retnvp = nvpair_prev(nvp);
826 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
832 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
837 PJDLOG_ASSERT(cookiep != NULL);
839 if (*cookiep == NULL)
840 nvp = nvlist_first_nvpair(nvl);
842 nvp = nvlist_next_nvpair(nvl, *cookiep);
846 *typep = nvpair_type(nvp);
848 return (nvpair_name(nvp));
852 nvlist_exists(const nvlist_t *nvl, const char *name)
855 return (nvlist_existsf(nvl, "%s", name));
858 #define NVLIST_EXISTS(type) \
860 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
863 return (nvlist_existsf_##type(nvl, "%s", name)); \
868 NVLIST_EXISTS(number)
869 NVLIST_EXISTS(string)
870 NVLIST_EXISTS(nvlist)
871 NVLIST_EXISTS(descriptor)
872 NVLIST_EXISTS(binary)
877 nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...)
882 va_start(nameap, namefmt);
883 ret = nvlist_existsv(nvl, namefmt, nameap);
888 #define NVLIST_EXISTSF(type) \
890 nvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...) \
895 va_start(nameap, namefmt); \
896 ret = nvlist_existsv_##type(nvl, namefmt, nameap); \
903 NVLIST_EXISTSF(number)
904 NVLIST_EXISTSF(string)
905 NVLIST_EXISTSF(nvlist)
906 NVLIST_EXISTSF(descriptor)
907 NVLIST_EXISTSF(binary)
909 #undef NVLIST_EXISTSF
912 nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap)
915 return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap) != NULL);
918 #define NVLIST_EXISTSV(type, TYPE) \
920 nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \
924 return (nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, nameap) != \
928 NVLIST_EXISTSV(null, NULL)
929 NVLIST_EXISTSV(bool, BOOL)
930 NVLIST_EXISTSV(number, NUMBER)
931 NVLIST_EXISTSV(string, STRING)
932 NVLIST_EXISTSV(nvlist, NVLIST)
933 NVLIST_EXISTSV(descriptor, DESCRIPTOR)
934 NVLIST_EXISTSV(binary, BINARY)
936 #undef NVLIST_EXISTSV
939 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
945 if (nvlist_error(nvl) != 0) {
946 errno = nvlist_error(nvl);
949 if (nvlist_exists(nvl, nvpair_name(nvp))) {
950 nvl->nvl_error = errno = EEXIST;
954 newnvp = nvpair_clone(nvp);
955 if (newnvp == NULL) {
956 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
960 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
964 nvlist_add_null(nvlist_t *nvl, const char *name)
967 nvlist_addf_null(nvl, "%s", name);
971 nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
974 nvlist_addf_bool(nvl, value, "%s", name);
978 nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
981 nvlist_addf_number(nvl, value, "%s", name);
985 nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
988 nvlist_addf_string(nvl, value, "%s", name);
992 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
996 va_start(valueap, valuefmt);
997 nvlist_add_stringv(nvl, name, valuefmt, valueap);
1002 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1007 if (nvlist_error(nvl) != 0) {
1008 errno = nvlist_error(nvl);
1012 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1014 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1016 nvlist_move_nvpair(nvl, nvp);
1020 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1023 nvlist_addf_nvlist(nvl, value, "%s", name);
1027 nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1030 nvlist_addf_descriptor(nvl, value, "%s", name);
1034 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1038 nvlist_addf_binary(nvl, value, size, "%s", name);
1042 nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...)
1046 va_start(nameap, namefmt);
1047 nvlist_addv_null(nvl, namefmt, nameap);
1052 nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...)
1056 va_start(nameap, namefmt);
1057 nvlist_addv_bool(nvl, value, namefmt, nameap);
1062 nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1066 va_start(nameap, namefmt);
1067 nvlist_addv_number(nvl, value, namefmt, nameap);
1072 nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...)
1076 va_start(nameap, namefmt);
1077 nvlist_addv_string(nvl, value, namefmt, nameap);
1082 nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1087 va_start(nameap, namefmt);
1088 nvlist_addv_nvlist(nvl, value, namefmt, nameap);
1093 nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...)
1097 va_start(nameap, namefmt);
1098 nvlist_addv_descriptor(nvl, value, namefmt, nameap);
1103 nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size,
1104 const char *namefmt, ...)
1108 va_start(nameap, namefmt);
1109 nvlist_addv_binary(nvl, value, size, namefmt, nameap);
1114 nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap)
1118 if (nvlist_error(nvl) != 0) {
1119 errno = nvlist_error(nvl);
1123 nvp = nvpair_createv_null(namefmt, nameap);
1125 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1127 nvlist_move_nvpair(nvl, nvp);
1131 nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap)
1135 if (nvlist_error(nvl) != 0) {
1136 errno = nvlist_error(nvl);
1140 nvp = nvpair_createv_bool(value, namefmt, nameap);
1142 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1144 nvlist_move_nvpair(nvl, nvp);
1148 nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt,
1153 if (nvlist_error(nvl) != 0) {
1154 errno = nvlist_error(nvl);
1158 nvp = nvpair_createv_number(value, namefmt, nameap);
1160 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1162 nvlist_move_nvpair(nvl, nvp);
1166 nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt,
1171 if (nvlist_error(nvl) != 0) {
1172 errno = nvlist_error(nvl);
1176 nvp = nvpair_createv_string(value, namefmt, nameap);
1178 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1180 nvlist_move_nvpair(nvl, nvp);
1184 nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1189 if (nvlist_error(nvl) != 0) {
1190 errno = nvlist_error(nvl);
1194 nvp = nvpair_createv_nvlist(value, namefmt, nameap);
1196 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1198 nvlist_move_nvpair(nvl, nvp);
1202 nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1207 if (nvlist_error(nvl) != 0) {
1208 errno = nvlist_error(nvl);
1212 nvp = nvpair_createv_descriptor(value, namefmt, nameap);
1214 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1216 nvlist_move_nvpair(nvl, nvp);
1220 nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size,
1221 const char *namefmt, va_list nameap)
1225 if (nvlist_error(nvl) != 0) {
1226 errno = nvlist_error(nvl);
1230 nvp = nvpair_createv_binary(value, size, namefmt, nameap);
1232 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1234 nvlist_move_nvpair(nvl, nvp);
1238 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1242 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1244 if (nvlist_error(nvl) != 0) {
1246 errno = nvlist_error(nvl);
1249 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1251 nvl->nvl_error = errno = EEXIST;
1255 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1258 #define NVLIST_MOVE(vtype, type) \
1260 nvlist_move_##type(nvlist_t *nvl, const char *name, vtype value) \
1263 nvlist_movef_##type(nvl, value, "%s", name); \
1266 NVLIST_MOVE(char *, string)
1267 NVLIST_MOVE(nvlist_t *, nvlist)
1268 NVLIST_MOVE(int, descriptor)
1273 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1276 nvlist_movef_binary(nvl, value, size, "%s", name);
1279 #define NVLIST_MOVEF(vtype, type) \
1281 nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt, \
1286 va_start(nameap, namefmt); \
1287 nvlist_movev_##type(nvl, value, namefmt, nameap); \
1291 NVLIST_MOVEF(char *, string)
1292 NVLIST_MOVEF(nvlist_t *, nvlist)
1293 NVLIST_MOVEF(int, descriptor)
1298 nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size,
1299 const char *namefmt, ...)
1303 va_start(nameap, namefmt);
1304 nvlist_movev_binary(nvl, value, size, namefmt, nameap);
1309 nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt,
1314 if (nvlist_error(nvl) != 0) {
1316 errno = nvlist_error(nvl);
1320 nvp = nvpair_movev_string(value, namefmt, nameap);
1322 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1324 nvlist_move_nvpair(nvl, nvp);
1328 nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
1333 if (nvlist_error(nvl) != 0) {
1334 nvlist_destroy(value);
1335 errno = nvlist_error(nvl);
1339 nvp = nvpair_movev_nvlist(value, namefmt, nameap);
1341 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1343 nvlist_move_nvpair(nvl, nvp);
1347 nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1352 if (nvlist_error(nvl) != 0) {
1354 errno = nvlist_error(nvl);
1358 nvp = nvpair_movev_descriptor(value, namefmt, nameap);
1360 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1362 nvlist_move_nvpair(nvl, nvp);
1366 nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size,
1367 const char *namefmt, va_list nameap)
1371 if (nvlist_error(nvl) != 0) {
1373 errno = nvlist_error(nvl);
1377 nvp = nvpair_movev_binary(value, size, namefmt, nameap);
1379 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1381 nvlist_move_nvpair(nvl, nvp);
1384 #define NVLIST_GET(ftype, type) \
1386 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1389 return (nvlist_getf_##type(nvl, "%s", name)); \
1392 NVLIST_GET(const nvpair_t *, nvpair)
1393 NVLIST_GET(bool, bool)
1394 NVLIST_GET(uint64_t, number)
1395 NVLIST_GET(const char *, string)
1396 NVLIST_GET(const nvlist_t *, nvlist)
1397 NVLIST_GET(int, descriptor)
1402 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1405 return (nvlist_getf_binary(nvl, sizep, "%s", name));
1408 #define NVLIST_GETF(ftype, type) \
1410 nvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...) \
1415 va_start(nameap, namefmt); \
1416 value = nvlist_getv_##type(nvl, namefmt, nameap); \
1422 NVLIST_GETF(const nvpair_t *, nvpair)
1423 NVLIST_GETF(bool, bool)
1424 NVLIST_GETF(uint64_t, number)
1425 NVLIST_GETF(const char *, string)
1426 NVLIST_GETF(const nvlist_t *, nvlist)
1427 NVLIST_GETF(int, descriptor)
1432 nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1437 va_start(nameap, namefmt);
1438 value = nvlist_getv_binary(nvl, sizep, namefmt, nameap);
1445 nvlist_getv_nvpair(const nvlist_t *nvl, const char *namefmt, va_list nameap)
1448 return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap));
1451 #define NVLIST_GETV(ftype, type, TYPE) \
1453 nvlist_getv_##type(const nvlist_t *nvl, const char *namefmt, \
1457 const nvpair_t *nvp; \
1459 va_copy(cnameap, nameap); \
1460 nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \
1463 nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \
1464 return (nvpair_get_##type(nvp)); \
1467 NVLIST_GETV(bool, bool, BOOL)
1468 NVLIST_GETV(uint64_t, number, NUMBER)
1469 NVLIST_GETV(const char *, string, STRING)
1470 NVLIST_GETV(const nvlist_t *, nvlist, NVLIST)
1471 NVLIST_GETV(int, descriptor, DESCRIPTOR)
1476 nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt,
1480 const nvpair_t *nvp;
1482 va_copy(cnameap, nameap);
1483 nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap);
1486 nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap);
1488 return (nvpair_get_binary(nvp, sizep));
1491 #define NVLIST_TAKE(ftype, type) \
1493 nvlist_take_##type(nvlist_t *nvl, const char *name) \
1496 return (nvlist_takef_##type(nvl, "%s", name)); \
1499 NVLIST_TAKE(nvpair_t *, nvpair)
1500 NVLIST_TAKE(bool, bool)
1501 NVLIST_TAKE(uint64_t, number)
1502 NVLIST_TAKE(char *, string)
1503 NVLIST_TAKE(nvlist_t *, nvlist)
1504 NVLIST_TAKE(int, descriptor)
1509 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1512 return (nvlist_takef_binary(nvl, sizep, "%s", name));
1515 #define NVLIST_TAKEF(ftype, type) \
1517 nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...) \
1522 va_start(nameap, namefmt); \
1523 value = nvlist_takev_##type(nvl, namefmt, nameap); \
1529 NVLIST_TAKEF(nvpair_t *, nvpair)
1530 NVLIST_TAKEF(bool, bool)
1531 NVLIST_TAKEF(uint64_t, number)
1532 NVLIST_TAKEF(char *, string)
1533 NVLIST_TAKEF(nvlist_t *, nvlist)
1534 NVLIST_TAKEF(int, descriptor)
1539 nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1544 va_start(nameap, namefmt);
1545 value = nvlist_takev_binary(nvl, sizep, namefmt, nameap);
1552 nvlist_takev_nvpair(nvlist_t *nvl, const char *namefmt, va_list nameap)
1556 nvp = nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap);
1558 nvlist_remove_nvpair(nvl, nvp);
1562 #define NVLIST_TAKEV(ftype, type, TYPE) \
1564 nvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
1570 va_copy(cnameap, nameap); \
1571 nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \
1574 nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \
1575 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1576 nvlist_remove_nvpair(nvl, nvp); \
1577 nvpair_free_structure(nvp); \
1581 NVLIST_TAKEV(bool, bool, BOOL)
1582 NVLIST_TAKEV(uint64_t, number, NUMBER)
1583 NVLIST_TAKEV(char *, string, STRING)
1584 NVLIST_TAKEV(nvlist_t *, nvlist, NVLIST)
1585 NVLIST_TAKEV(int, descriptor, DESCRIPTOR)
1590 nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt,
1597 va_copy(cnameap, nameap);
1598 nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap);
1601 nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap);
1603 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1604 nvlist_remove_nvpair(nvl, nvp);
1605 nvpair_free_structure(nvp);
1610 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1615 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1617 nvpair_remove(&nvl->nvl_head, nvp, nvl);
1621 nvlist_free(nvlist_t *nvl, const char *name)
1624 nvlist_freef(nvl, "%s", name);
1627 #define NVLIST_FREE(type) \
1629 nvlist_free_##type(nvlist_t *nvl, const char *name) \
1632 nvlist_freef_##type(nvl, "%s", name); \
1640 NVLIST_FREE(descriptor)
1646 nvlist_freef(nvlist_t *nvl, const char *namefmt, ...)
1650 va_start(nameap, namefmt);
1651 nvlist_freev(nvl, namefmt, nameap);
1655 #define NVLIST_FREEF(type) \
1657 nvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...) \
1661 va_start(nameap, namefmt); \
1662 nvlist_freev_##type(nvl, namefmt, nameap); \
1668 NVLIST_FREEF(number)
1669 NVLIST_FREEF(string)
1670 NVLIST_FREEF(nvlist)
1671 NVLIST_FREEF(descriptor)
1672 NVLIST_FREEF(binary)
1677 nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap)
1680 nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap);
1683 #define NVLIST_FREEV(type, TYPE) \
1685 nvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
1688 nvlist_freev_type(nvl, NV_TYPE_##TYPE, namefmt, nameap); \
1691 NVLIST_FREEV(null, NULL)
1692 NVLIST_FREEV(bool, BOOL)
1693 NVLIST_FREEV(number, NUMBER)
1694 NVLIST_FREEV(string, STRING)
1695 NVLIST_FREEV(nvlist, NVLIST)
1696 NVLIST_FREEV(descriptor, DESCRIPTOR)
1697 NVLIST_FREEV(binary, BINARY)
1701 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1706 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1708 nvlist_remove_nvpair(nvl, nvp);