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_flags(const nvlist_t *nvl)
239 PJDLOG_ASSERT(nvl->nvl_error == 0);
240 PJDLOG_ASSERT((nvl->nvl_flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
242 return (nvl->nvl_flags);
246 nvlist_report_missing(int type, const char *name)
249 PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
250 name, nvpair_type_string(type));
254 nvlist_find(const nvlist_t *nvl, int type, const char *name)
259 PJDLOG_ASSERT(nvl->nvl_error == 0);
260 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
261 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
263 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
264 nvp = nvlist_next_nvpair(nvl, nvp)) {
265 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
267 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
268 if (strcasecmp(nvpair_name(nvp), name) != 0)
271 if (strcmp(nvpair_name(nvp), name) != 0)
278 RESTORE_ERRNO(ENOENT);
284 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
288 PJDLOG_ASSERT(nvl->nvl_error == 0);
289 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
290 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
292 return (nvlist_find(nvl, type, name) != NULL);
296 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
301 PJDLOG_ASSERT(nvl->nvl_error == 0);
302 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
303 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
305 nvp = nvlist_find(nvl, type, name);
307 nvlist_free_nvpair(nvl, nvp);
309 nvlist_report_missing(type, name);
313 nvlist_clone(const nvlist_t *nvl)
316 nvpair_t *nvp, *newnvp;
320 if (nvl->nvl_error != 0) {
321 RESTORE_ERRNO(nvl->nvl_error);
325 newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
326 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
327 nvp = nvlist_next_nvpair(nvl, nvp)) {
328 newnvp = nvpair_clone(nvp);
331 nvlist_move_nvpair(newnvl, newnvp);
334 nvlist_destroy(newnvl);
342 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
345 if (nvlist_error(nvl) != 0) {
346 dprintf(fd, "%*serror: %d\n", level * 4, "",
355 * Dump content of nvlist.
358 nvlist_dump(const nvlist_t *nvl, int fd)
360 const nvlist_t *tmpnvl;
361 nvpair_t *nvp, *tmpnvp;
366 if (nvlist_dump_error_check(nvl, fd, level))
369 nvp = nvlist_first_nvpair(nvl);
370 while (nvp != NULL) {
371 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
372 nvpair_type_string(nvpair_type(nvp)));
373 switch (nvpair_type(nvp)) {
375 dprintf(fd, " null\n");
378 dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
382 dprintf(fd, " %ju (%jd) (0x%jx)\n",
383 (uintmax_t)nvpair_get_number(nvp),
384 (intmax_t)nvpair_get_number(nvp),
385 (uintmax_t)nvpair_get_number(nvp));
388 dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
392 tmpnvl = nvpair_get_nvlist(nvp);
393 if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
395 tmpnvp = nvlist_first_nvpair(tmpnvl);
396 if (tmpnvp != NULL) {
403 case NV_TYPE_DESCRIPTOR:
404 dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
408 const unsigned char *binary;
412 binary = nvpair_get_binary(nvp, &size);
413 dprintf(fd, " %zu ", size);
414 for (ii = 0; ii < size; ii++)
415 dprintf(fd, "%02hhx", binary[ii]);
420 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
423 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
425 nvl = nvlist_get_parent(nvl, &cookie);
435 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
439 nvlist_dump(nvl, fileno(fp));
444 * The function obtains size of the nvlist after nvlist_pack().
447 nvlist_size(const nvlist_t *nvl)
449 const nvlist_t *tmpnvl;
450 const nvpair_t *nvp, *tmpnvp;
455 PJDLOG_ASSERT(nvl->nvl_error == 0);
457 size = sizeof(struct nvlist_header);
458 nvp = nvlist_first_nvpair(nvl);
459 while (nvp != NULL) {
460 size += nvpair_header_size();
461 size += strlen(nvpair_name(nvp)) + 1;
462 if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
463 size += sizeof(struct nvlist_header);
464 size += nvpair_header_size() + 1;
465 tmpnvl = nvpair_get_nvlist(nvp);
466 PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
467 tmpnvp = nvlist_first_nvpair(tmpnvl);
468 if (tmpnvp != NULL) {
474 size += nvpair_size(nvp);
477 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
479 nvl = nvlist_get_parent(nvl, &cookie);
492 nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
497 PJDLOG_ASSERT(nvl->nvl_error == 0);
498 PJDLOG_ASSERT(level < 3);
500 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
501 nvp = nvlist_next_nvpair(nvl, nvp)) {
502 switch (nvpair_type(nvp)) {
503 case NV_TYPE_DESCRIPTOR:
504 *descs = nvpair_get_descriptor(nvp);
508 descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
520 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
525 nitems = nvlist_ndescriptors(nvl);
526 fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
530 nvlist_xdescriptors(nvl, fds, 0);
539 nvlist_xndescriptors(const nvlist_t *nvl, int level)
546 PJDLOG_ASSERT(nvl->nvl_error == 0);
547 PJDLOG_ASSERT(level < 3);
550 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
551 nvp = nvlist_next_nvpair(nvl, nvp)) {
552 switch (nvpair_type(nvp)) {
553 case NV_TYPE_DESCRIPTOR:
557 ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
570 nvlist_ndescriptors(const nvlist_t *nvl)
573 return (nvlist_xndescriptors(nvl, 0));
576 static unsigned char *
577 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
579 struct nvlist_header nvlhdr;
583 nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
584 nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
585 nvlhdr.nvlh_flags = nvl->nvl_flags;
586 #if BYTE_ORDER == BIG_ENDIAN
587 nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
589 nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
590 nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
591 PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
592 memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
593 ptr += sizeof(nvlhdr);
594 *leftp -= sizeof(nvlhdr);
600 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
602 unsigned char *buf, *ptr;
604 const nvlist_t *tmpnvl;
605 nvpair_t *nvp, *tmpnvp;
610 if (nvl->nvl_error != 0) {
611 RESTORE_ERRNO(nvl->nvl_error);
615 size = nvlist_size(nvl);
616 buf = nv_malloc(size);
623 ptr = nvlist_pack_header(nvl, ptr, &left);
625 nvp = nvlist_first_nvpair(nvl);
626 while (nvp != NULL) {
629 nvpair_init_datasize(nvp);
630 ptr = nvpair_pack_header(nvp, ptr, &left);
635 switch (nvpair_type(nvp)) {
637 ptr = nvpair_pack_null(nvp, ptr, &left);
640 ptr = nvpair_pack_bool(nvp, ptr, &left);
643 ptr = nvpair_pack_number(nvp, ptr, &left);
646 ptr = nvpair_pack_string(nvp, ptr, &left);
649 tmpnvl = nvpair_get_nvlist(nvp);
650 ptr = nvlist_pack_header(tmpnvl, ptr, &left);
653 tmpnvp = nvlist_first_nvpair(tmpnvl);
654 if (tmpnvp != NULL) {
659 ptr = nvpair_pack_nvlist_up(ptr, &left);
662 case NV_TYPE_DESCRIPTOR:
663 ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
667 ptr = nvpair_pack_binary(nvp, ptr, &left);
670 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
676 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
678 nvl = nvlist_get_parent(nvl, &cookie);
682 ptr = nvpair_pack_nvlist_up(ptr, &left);
695 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
700 if (nvl->nvl_error != 0) {
701 RESTORE_ERRNO(nvl->nvl_error);
705 if (nvlist_ndescriptors(nvl) > 0) {
706 RESTORE_ERRNO(EOPNOTSUPP);
710 return (nvlist_xpack(nvl, NULL, sizep));
714 nvlist_check_header(struct nvlist_header *nvlhdrp)
717 if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
718 RESTORE_ERRNO(EINVAL);
721 if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
722 RESTORE_ERRNO(EINVAL);
725 #if BYTE_ORDER == BIG_ENDIAN
726 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
727 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
728 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
731 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
732 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
733 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
739 const unsigned char *
740 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
741 bool *isbep, size_t *leftp)
743 struct nvlist_header nvlhdr;
745 if (*leftp < sizeof(nvlhdr))
748 memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
750 if (!nvlist_check_header(&nvlhdr))
753 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
757 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
759 if (nvlhdr.nvlh_descriptors > nfds)
762 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
765 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
767 ptr += sizeof(nvlhdr);
769 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
770 *leftp -= sizeof(nvlhdr);
774 RESTORE_ERRNO(EINVAL);
779 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
781 const unsigned char *ptr;
782 nvlist_t *nvl, *retnvl, *tmpnvl;
791 nvl = retnvl = nvlist_create(0);
795 ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
800 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
803 switch (nvpair_type(nvp)) {
805 ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
808 ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
811 ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
814 ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
817 ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
819 nvlist_set_parent(tmpnvl, nvp);
822 case NV_TYPE_DESCRIPTOR:
823 ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
828 ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
830 case NV_TYPE_NVLIST_UP:
831 if (nvl->nvl_parent == NULL)
833 nvl = nvpair_nvlist(nvl->nvl_parent);
836 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
840 nvlist_move_nvpair(nvl, nvp);
841 if (tmpnvl != NULL) {
849 nvlist_destroy(retnvl);
854 nvlist_unpack(const void *buf, size_t size)
857 return (nvlist_xunpack(buf, size, NULL, 0));
862 nvlist_send(int sock, const nvlist_t *nvl)
864 size_t datasize, nfds;
870 if (nvlist_error(nvl) != 0) {
871 errno = nvlist_error(nvl);
875 fds = nvlist_descriptors(nvl, &nfds);
883 data = nvlist_xpack(nvl, &fdidx, &datasize);
887 if (buf_send(sock, data, datasize) == -1)
891 if (fd_send(sock, fds, nfds) == -1)
905 nvlist_recv(int sock)
907 struct nvlist_header nvlhdr;
910 size_t nfds, size, i;
913 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
916 if (!nvlist_check_header(&nvlhdr))
919 nfds = (size_t)nvlhdr.nvlh_descriptors;
920 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
926 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
931 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
935 fds = malloc(nfds * sizeof(fds[0]));
938 if (fd_recv(sock, fds, nfds) == -1)
942 nvl = nvlist_xunpack(buf, size, fds, nfds);
944 for (i = 0; i < nfds; i++)
960 nvlist_xfer(int sock, nvlist_t *nvl)
963 if (nvlist_send(sock, nvl) < 0) {
968 return (nvlist_recv(sock));
973 nvlist_first_nvpair(const nvlist_t *nvl)
978 return (TAILQ_FIRST(&nvl->nvl_head));
982 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
988 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
990 retnvp = nvpair_next(nvp);
991 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
998 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1004 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1006 retnvp = nvpair_prev(nvp);
1007 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1013 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1018 PJDLOG_ASSERT(cookiep != NULL);
1020 if (*cookiep == NULL)
1021 nvp = nvlist_first_nvpair(nvl);
1023 nvp = nvlist_next_nvpair(nvl, *cookiep);
1027 *typep = nvpair_type(nvp);
1029 return (nvpair_name(nvp));
1033 nvlist_exists(const nvlist_t *nvl, const char *name)
1036 return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1039 #define NVLIST_EXISTS(type, TYPE) \
1041 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
1044 return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \
1047 NVLIST_EXISTS(null, NULL)
1048 NVLIST_EXISTS(bool, BOOL)
1049 NVLIST_EXISTS(number, NUMBER)
1050 NVLIST_EXISTS(string, STRING)
1051 NVLIST_EXISTS(nvlist, NVLIST)
1053 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1055 NVLIST_EXISTS(binary, BINARY)
1057 #undef NVLIST_EXISTS
1060 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1066 if (nvlist_error(nvl) != 0) {
1067 RESTORE_ERRNO(nvlist_error(nvl));
1070 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1071 nvl->nvl_error = EEXIST;
1072 RESTORE_ERRNO(nvlist_error(nvl));
1076 newnvp = nvpair_clone(nvp);
1077 if (newnvp == NULL) {
1078 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1079 RESTORE_ERRNO(nvlist_error(nvl));
1083 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1087 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1091 va_start(valueap, valuefmt);
1092 nvlist_add_stringv(nvl, name, valuefmt, valueap);
1097 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1102 if (nvlist_error(nvl) != 0) {
1103 RESTORE_ERRNO(nvlist_error(nvl));
1107 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1109 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1110 RESTORE_ERRNO(nvl->nvl_error);
1112 nvlist_move_nvpair(nvl, nvp);
1116 nvlist_add_null(nvlist_t *nvl, const char *name)
1120 if (nvlist_error(nvl) != 0) {
1121 RESTORE_ERRNO(nvlist_error(nvl));
1125 nvp = nvpair_create_null(name);
1127 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1128 RESTORE_ERRNO(nvl->nvl_error);
1130 nvlist_move_nvpair(nvl, nvp);
1134 nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
1138 if (nvlist_error(nvl) != 0) {
1139 RESTORE_ERRNO(nvlist_error(nvl));
1143 nvp = nvpair_create_bool(name, value);
1145 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1146 RESTORE_ERRNO(nvl->nvl_error);
1148 nvlist_move_nvpair(nvl, nvp);
1152 nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
1156 if (nvlist_error(nvl) != 0) {
1157 RESTORE_ERRNO(nvlist_error(nvl));
1161 nvp = nvpair_create_number(name, value);
1163 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1164 RESTORE_ERRNO(nvl->nvl_error);
1166 nvlist_move_nvpair(nvl, nvp);
1170 nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
1174 if (nvlist_error(nvl) != 0) {
1175 RESTORE_ERRNO(nvlist_error(nvl));
1179 nvp = nvpair_create_string(name, value);
1181 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1182 RESTORE_ERRNO(nvl->nvl_error);
1184 nvlist_move_nvpair(nvl, nvp);
1188 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1192 if (nvlist_error(nvl) != 0) {
1193 RESTORE_ERRNO(nvlist_error(nvl));
1197 nvp = nvpair_create_nvlist(name, value);
1199 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1200 RESTORE_ERRNO(nvl->nvl_error);
1202 nvlist_move_nvpair(nvl, nvp);
1207 nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1211 if (nvlist_error(nvl) != 0) {
1212 errno = nvlist_error(nvl);
1216 nvp = nvpair_create_descriptor(name, value);
1218 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1220 nvlist_move_nvpair(nvl, nvp);
1225 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1230 if (nvlist_error(nvl) != 0) {
1231 RESTORE_ERRNO(nvlist_error(nvl));
1235 nvp = nvpair_create_binary(name, value, size);
1237 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1238 RESTORE_ERRNO(nvl->nvl_error);
1240 nvlist_move_nvpair(nvl, nvp);
1244 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1248 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1250 if (nvlist_error(nvl) != 0) {
1252 RESTORE_ERRNO(nvlist_error(nvl));
1255 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1257 nvl->nvl_error = EEXIST;
1258 RESTORE_ERRNO(nvl->nvl_error);
1262 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1266 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1270 if (nvlist_error(nvl) != 0) {
1272 RESTORE_ERRNO(nvlist_error(nvl));
1276 nvp = nvpair_move_string(name, value);
1278 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1279 RESTORE_ERRNO(nvl->nvl_error);
1281 nvlist_move_nvpair(nvl, nvp);
1285 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1289 if (nvlist_error(nvl) != 0) {
1290 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1291 nvlist_destroy(value);
1292 RESTORE_ERRNO(nvlist_error(nvl));
1296 nvp = nvpair_move_nvlist(name, value);
1298 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1299 RESTORE_ERRNO(nvl->nvl_error);
1301 nvlist_move_nvpair(nvl, nvp);
1306 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1310 if (nvlist_error(nvl) != 0) {
1312 errno = nvlist_error(nvl);
1316 nvp = nvpair_move_descriptor(name, value);
1318 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1320 nvlist_move_nvpair(nvl, nvp);
1325 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1329 if (nvlist_error(nvl) != 0) {
1331 RESTORE_ERRNO(nvlist_error(nvl));
1335 nvp = nvpair_move_binary(name, value, size);
1337 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1338 RESTORE_ERRNO(nvl->nvl_error);
1340 nvlist_move_nvpair(nvl, nvp);
1344 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1347 return (nvlist_find(nvl, NV_TYPE_NONE, name));
1350 #define NVLIST_GET(ftype, type, TYPE) \
1352 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1354 const nvpair_t *nvp; \
1356 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1358 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1359 return (nvpair_get_##type(nvp)); \
1362 NVLIST_GET(bool, bool, BOOL)
1363 NVLIST_GET(uint64_t, number, NUMBER)
1364 NVLIST_GET(const char *, string, STRING)
1365 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1367 NVLIST_GET(int, descriptor, DESCRIPTOR)
1373 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1377 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1379 nvlist_report_missing(NV_TYPE_BINARY, name);
1381 return (nvpair_get_binary(nvp, sizep));
1384 #define NVLIST_TAKE(ftype, type, TYPE) \
1386 nvlist_take_##type(nvlist_t *nvl, const char *name) \
1391 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1393 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1394 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1395 nvlist_remove_nvpair(nvl, nvp); \
1396 nvpair_free_structure(nvp); \
1400 NVLIST_TAKE(bool, bool, BOOL)
1401 NVLIST_TAKE(uint64_t, number, NUMBER)
1402 NVLIST_TAKE(char *, string, STRING)
1403 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1405 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1411 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1416 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1418 nvlist_report_missing(NV_TYPE_BINARY, name);
1420 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1421 nvlist_remove_nvpair(nvl, nvp);
1422 nvpair_free_structure(nvp);
1427 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1432 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1434 nvpair_remove(&nvl->nvl_head, nvp, nvl);
1438 nvlist_free(nvlist_t *nvl, const char *name)
1441 nvlist_free_type(nvl, name, NV_TYPE_NONE);
1444 #define NVLIST_FREE(type, TYPE) \
1446 nvlist_free_##type(nvlist_t *nvl, const char *name) \
1449 nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \
1452 NVLIST_FREE(null, NULL)
1453 NVLIST_FREE(bool, BOOL)
1454 NVLIST_FREE(number, NUMBER)
1455 NVLIST_FREE(string, STRING)
1456 NVLIST_FREE(nvlist, NVLIST)
1458 NVLIST_FREE(descriptor, DESCRIPTOR)
1460 NVLIST_FREE(binary, BINARY)
1465 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1470 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1472 nvlist_remove_nvpair(nvl, nvp);