2 * Copyright (c) 2009-2013 The FreeBSD Foundation
3 * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
35 #include <sys/endian.h>
36 #include <sys/queue.h>
40 #include <sys/errno.h>
41 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #include <sys/systm.h>
46 #include <machine/stdarg.h>
49 #include <sys/socket.h>
71 #include "nvlist_impl.h"
72 #include "nvpair_impl.h"
76 #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
77 #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
78 #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
81 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
82 #define PJDLOG_RASSERT(expr, ...) assert(expr)
83 #define PJDLOG_ABORT(...) do { \
84 fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \
85 fprintf(stderr, __VA_ARGS__); \
86 fprintf(stderr, "\n"); \
92 #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN | NV_FLAG_IN_ARRAY)
93 #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE)
94 #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
96 #define NVLIST_MAGIC 0x6e766c /* "nvl" */
101 nvpair_t *nvl_parent;
102 nvpair_t *nvl_array_next;
103 struct nvl_head nvl_head;
106 #define NVLIST_ASSERT(nvl) do { \
107 PJDLOG_ASSERT((nvl) != NULL); \
108 PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \
112 MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
115 #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp)
117 #define NVLIST_HEADER_MAGIC 0x6c
118 #define NVLIST_HEADER_VERSION 0x00
119 struct nvlist_header {
121 uint8_t nvlh_version;
123 uint64_t nvlh_descriptors;
128 nvlist_create(int flags)
132 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
134 nvl = nv_malloc(sizeof(*nvl));
138 nvl->nvl_flags = flags;
139 nvl->nvl_parent = NULL;
140 nvl->nvl_array_next = NULL;
141 TAILQ_INIT(&nvl->nvl_head);
142 nvl->nvl_magic = NVLIST_MAGIC;
148 nvlist_destroy(nvlist_t *nvl)
159 while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
160 nvlist_remove_nvpair(nvl, nvp);
163 if (nvl->nvl_array_next != NULL)
164 nvpair_free_structure(nvl->nvl_array_next);
165 nvl->nvl_array_next = NULL;
166 nvl->nvl_parent = NULL;
174 nvlist_set_error(nvlist_t *nvl, int error)
177 PJDLOG_ASSERT(error != 0);
180 * Check for error != 0 so that we don't do the wrong thing if somebody
181 * tries to abuse this API when asserts are disabled.
183 if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
184 nvl->nvl_error = error;
188 nvlist_error(const nvlist_t *nvl)
196 return (nvl->nvl_error);
200 nvlist_get_nvpair_parent(const nvlist_t *nvl)
205 return (nvl->nvl_parent);
209 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
215 nvp = nvl->nvl_parent;
221 return (nvpair_nvlist(nvp));
225 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
230 nvl->nvl_parent = parent;
234 nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele)
240 nvl->nvl_flags |= NV_FLAG_IN_ARRAY;
242 nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY;
243 nv_free(nvl->nvl_array_next);
246 nvl->nvl_array_next = ele;
250 nvlist_in_array(const nvlist_t *nvl)
255 return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0);
259 nvlist_get_array_next(const nvlist_t *nvl)
265 nvp = nvl->nvl_array_next;
269 return (nvpair_get_nvlist(nvp));
273 nvlist_get_pararr(const nvlist_t *nvl, void **cookiep)
277 ret = nvlist_get_array_next(nvl);
284 ret = nvlist_get_parent(nvl, cookiep);
289 nvlist_empty(const nvlist_t *nvl)
293 PJDLOG_ASSERT(nvl->nvl_error == 0);
295 return (nvlist_first_nvpair(nvl) == NULL);
299 nvlist_flags(const nvlist_t *nvl)
303 PJDLOG_ASSERT(nvl->nvl_error == 0);
305 return (nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
309 nvlist_set_flags(nvlist_t *nvl, int flags)
313 PJDLOG_ASSERT(nvl->nvl_error == 0);
315 nvl->nvl_flags = flags;
319 nvlist_report_missing(int type, const char *name)
322 PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
323 name, nvpair_type_string(type));
327 nvlist_find(const nvlist_t *nvl, int type, const char *name)
332 PJDLOG_ASSERT(nvl->nvl_error == 0);
333 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
334 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
336 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
337 nvp = nvlist_next_nvpair(nvl, nvp)) {
338 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
340 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
341 if (strcasecmp(nvpair_name(nvp), name) != 0)
344 if (strcmp(nvpair_name(nvp), name) != 0)
357 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
361 PJDLOG_ASSERT(nvl->nvl_error == 0);
362 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
363 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
365 return (nvlist_find(nvl, type, name) != NULL);
369 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
374 PJDLOG_ASSERT(nvl->nvl_error == 0);
375 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
376 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
378 nvp = nvlist_find(nvl, type, name);
380 nvlist_free_nvpair(nvl, nvp);
382 nvlist_report_missing(type, name);
386 nvlist_clone(const nvlist_t *nvl)
389 nvpair_t *nvp, *newnvp;
393 if (nvl->nvl_error != 0) {
394 ERRNO_SET(nvl->nvl_error);
398 newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
399 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
400 nvp = nvlist_next_nvpair(nvl, nvp)) {
401 newnvp = nvpair_clone(nvp);
404 (void)nvlist_move_nvpair(newnvl, newnvp);
407 nvlist_destroy(newnvl);
415 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
418 if (nvlist_error(nvl) != 0) {
419 dprintf(fd, "%*serror: %d\n", level * 4, "",
428 * Dump content of nvlist.
431 nvlist_dump(const nvlist_t *nvl, int fd)
433 const nvlist_t *tmpnvl;
434 nvpair_t *nvp, *tmpnvp;
439 if (nvlist_dump_error_check(nvl, fd, level))
442 nvp = nvlist_first_nvpair(nvl);
443 while (nvp != NULL) {
444 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
445 nvpair_type_string(nvpair_type(nvp)));
446 switch (nvpair_type(nvp)) {
448 dprintf(fd, " null\n");
451 dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
455 dprintf(fd, " %ju (%jd) (0x%jx)\n",
456 (uintmax_t)nvpair_get_number(nvp),
457 (intmax_t)nvpair_get_number(nvp),
458 (uintmax_t)nvpair_get_number(nvp));
461 dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
465 tmpnvl = nvpair_get_nvlist(nvp);
466 if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
468 tmpnvp = nvlist_first_nvpair(tmpnvl);
469 if (tmpnvp != NULL) {
476 case NV_TYPE_DESCRIPTOR:
477 dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
481 const unsigned char *binary;
485 binary = nvpair_get_binary(nvp, &size);
486 dprintf(fd, " %zu ", size);
487 for (ii = 0; ii < size; ii++)
488 dprintf(fd, "%02hhx", binary[ii]);
492 case NV_TYPE_BOOL_ARRAY:
498 value = nvpair_get_bool_array(nvp, &nitems);
500 for (ii = 0; ii < nitems; ii++) {
501 dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE");
502 if (ii != nitems - 1)
508 case NV_TYPE_STRING_ARRAY:
510 const char * const *value;
514 value = nvpair_get_string_array(nvp, &nitems);
516 for (ii = 0; ii < nitems; ii++) {
517 if (value[ii] == NULL)
520 dprintf(fd, "\"%s\"", value[ii]);
521 if (ii != nitems - 1)
527 case NV_TYPE_NUMBER_ARRAY:
529 const uint64_t *value;
533 value = nvpair_get_number_array(nvp, &nitems);
535 for (ii = 0; ii < nitems; ii++) {
536 dprintf(fd, "%ju (%jd) (0x%jx)",
537 value[ii], value[ii], value[ii]);
538 if (ii != nitems - 1)
544 case NV_TYPE_DESCRIPTOR_ARRAY:
550 value = nvpair_get_descriptor_array(nvp, &nitems);
552 for (ii = 0; ii < nitems; ii++) {
553 dprintf(fd, "%d", value[ii]);
554 if (ii != nitems - 1)
560 case NV_TYPE_NVLIST_ARRAY:
562 const nvlist_t * const *value;
566 value = nvpair_get_nvlist_array(nvp, &nitems);
567 dprintf(fd, " %zu\n", nitems);
570 for (ii = 0; ii < nitems; ii++) {
571 if (nvlist_dump_error_check(value[ii], fd,
576 if (tmpnvl == NULL) {
577 tmpnvp = nvlist_first_nvpair(value[ii]);
578 if (tmpnvp != NULL) {
581 dprintf(fd, "%*s,\n",
582 (level + 1) * 4, "");
586 if (tmpnvp != NULL) {
595 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
598 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
601 if (nvlist_in_array(nvl))
602 dprintf(fd, "%*s,\n", level * 4, "");
603 nvl = nvlist_get_pararr(nvl, &cookie);
606 if (nvlist_in_array(nvl) && cookie == NULL) {
607 nvp = nvlist_first_nvpair(nvl);
612 } while (nvp == NULL);
613 if (nvlist_in_array(nvl) && cookie == NULL)
620 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
624 nvlist_dump(nvl, fileno(fp));
629 * The function obtains size of the nvlist after nvlist_pack().
632 nvlist_size(const nvlist_t *nvl)
634 const nvlist_t *tmpnvl;
635 const nvlist_t * const *nvlarray;
636 const nvpair_t *nvp, *tmpnvp;
642 PJDLOG_ASSERT(nvl->nvl_error == 0);
644 size = sizeof(struct nvlist_header);
645 nvp = nvlist_first_nvpair(nvl);
646 while (nvp != NULL) {
647 size += nvpair_header_size();
648 size += strlen(nvpair_name(nvp)) + 1;
649 if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
650 size += sizeof(struct nvlist_header);
651 size += nvpair_header_size() + 1;
652 tmpnvl = nvpair_get_nvlist(nvp);
653 PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
654 tmpnvp = nvlist_first_nvpair(tmpnvl);
655 if (tmpnvp != NULL) {
660 } else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) {
661 nvlarray = nvpair_get_nvlist_array(nvp, &nitems);
662 PJDLOG_ASSERT(nitems > 0);
664 size += (nvpair_header_size() + 1) * nitems;
665 size += sizeof(struct nvlist_header) * nitems;
669 for (ii = 0; ii < nitems; ii++) {
670 PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0);
671 tmpnvp = nvlist_first_nvpair(nvlarray[ii]);
672 if (tmpnvp != NULL) {
673 tmpnvl = nvlarray[ii];
677 if (tmpnvp != NULL) {
684 size += nvpair_size(nvp);
687 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
690 nvl = nvlist_get_pararr(nvl, &cookie);
693 if (nvlist_in_array(nvl) && cookie == NULL) {
694 nvp = nvlist_first_nvpair(nvl);
698 } while (nvp == NULL);
699 if (nvlist_in_array(nvl) && cookie == NULL)
710 nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
717 PJDLOG_ASSERT(nvl->nvl_error == 0);
721 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
723 case NV_TYPE_DESCRIPTOR:
724 *descs = nvpair_get_descriptor(nvp);
727 case NV_TYPE_DESCRIPTOR_ARRAY:
733 value = nvpair_get_descriptor_array(nvp,
735 for (ii = 0; ii < nitems; ii++) {
742 nvl = nvpair_get_nvlist(nvp);
745 case NV_TYPE_NVLIST_ARRAY:
747 const nvlist_t * const *value;
750 value = nvpair_get_nvlist_array(nvp, &nitems);
751 PJDLOG_ASSERT(value != NULL);
752 PJDLOG_ASSERT(nitems > 0);
760 } while ((nvl = nvlist_get_pararr(nvl, (void**)&nvp)) != NULL);
768 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
773 nitems = nvlist_ndescriptors(nvl);
774 fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
778 nvlist_xdescriptors(nvl, fds);
787 nvlist_ndescriptors(const nvlist_t *nvl)
796 PJDLOG_ASSERT(nvl->nvl_error == 0);
801 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
803 case NV_TYPE_DESCRIPTOR:
807 nvl = nvpair_get_nvlist(nvp);
810 case NV_TYPE_NVLIST_ARRAY:
812 const nvlist_t * const *value;
815 value = nvpair_get_nvlist_array(nvp, &nitems);
816 PJDLOG_ASSERT(value != NULL);
817 PJDLOG_ASSERT(nitems > 0);
823 case NV_TYPE_DESCRIPTOR_ARRAY:
827 (void)nvpair_get_descriptor_array(nvp,
834 } while ((nvl = nvlist_get_pararr(nvl, (void**)&nvp)) != NULL);
842 static unsigned char *
843 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
845 struct nvlist_header nvlhdr;
849 nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
850 nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
851 nvlhdr.nvlh_flags = nvl->nvl_flags;
852 #if BYTE_ORDER == BIG_ENDIAN
853 nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
855 nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
856 nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
857 PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
858 memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
859 ptr += sizeof(nvlhdr);
860 *leftp -= sizeof(nvlhdr);
866 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
868 unsigned char *buf, *ptr;
870 const nvlist_t *tmpnvl;
871 nvpair_t *nvp, *tmpnvp;
876 if (nvl->nvl_error != 0) {
877 ERRNO_SET(nvl->nvl_error);
881 size = nvlist_size(nvl);
882 buf = nv_malloc(size);
889 ptr = nvlist_pack_header(nvl, ptr, &left);
891 nvp = nvlist_first_nvpair(nvl);
892 while (nvp != NULL) {
895 nvpair_init_datasize(nvp);
896 ptr = nvpair_pack_header(nvp, ptr, &left);
899 switch (nvpair_type(nvp)) {
901 ptr = nvpair_pack_null(nvp, ptr, &left);
904 ptr = nvpair_pack_bool(nvp, ptr, &left);
907 ptr = nvpair_pack_number(nvp, ptr, &left);
910 ptr = nvpair_pack_string(nvp, ptr, &left);
913 tmpnvl = nvpair_get_nvlist(nvp);
914 ptr = nvlist_pack_header(tmpnvl, ptr, &left);
917 tmpnvp = nvlist_first_nvpair(tmpnvl);
918 if (tmpnvp != NULL) {
923 ptr = nvpair_pack_nvlist_up(ptr, &left);
926 case NV_TYPE_DESCRIPTOR:
927 ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
929 case NV_TYPE_DESCRIPTOR_ARRAY:
930 ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp,
935 ptr = nvpair_pack_binary(nvp, ptr, &left);
937 case NV_TYPE_BOOL_ARRAY:
938 ptr = nvpair_pack_bool_array(nvp, ptr, &left);
940 case NV_TYPE_NUMBER_ARRAY:
941 ptr = nvpair_pack_number_array(nvp, ptr, &left);
943 case NV_TYPE_STRING_ARRAY:
944 ptr = nvpair_pack_string_array(nvp, ptr, &left);
946 case NV_TYPE_NVLIST_ARRAY:
948 const nvlist_t * const * value;
953 value = nvpair_get_nvlist_array(nvp, &nitems);
954 for (ii = 0; ii < nitems; ii++) {
955 ptr = nvlist_pack_header(value[ii], ptr, &left);
958 tmpnvp = nvlist_first_nvpair(value[ii]);
959 if (tmpnvp != NULL) {
963 ptr = nvpair_pack_nvlist_array_next(ptr, &left);
967 if (tmpnvl != NULL) {
975 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
979 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
982 if (nvlist_in_array(nvl)) {
983 ptr = nvpair_pack_nvlist_array_next(ptr,
988 nvl = nvlist_get_pararr(nvl, &cookie);
991 if (nvlist_in_array(nvl) && cookie == NULL) {
992 nvp = nvlist_first_nvpair(nvl);
993 ptr = nvlist_pack_header(nvl, ptr,
997 } else if (nvpair_type((nvpair_t *)cookie) !=
998 NV_TYPE_NVLIST_ARRAY) {
999 ptr = nvpair_pack_nvlist_up(ptr, &left);
1006 } while (nvp == NULL);
1007 if (nvlist_in_array(nvl) && cookie == NULL)
1022 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
1027 if (nvl->nvl_error != 0) {
1028 ERRNO_SET(nvl->nvl_error);
1032 if (nvlist_ndescriptors(nvl) > 0) {
1033 ERRNO_SET(EOPNOTSUPP);
1037 return (nvlist_xpack(nvl, NULL, sizep));
1041 nvlist_check_header(struct nvlist_header *nvlhdrp)
1044 if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
1048 if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
1052 #if BYTE_ORDER == BIG_ENDIAN
1053 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
1054 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
1055 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
1058 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
1059 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
1060 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
1066 const unsigned char *
1067 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
1068 bool *isbep, size_t *leftp)
1070 struct nvlist_header nvlhdr;
1073 if (*leftp < sizeof(nvlhdr))
1076 memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
1078 if (!nvlist_check_header(&nvlhdr))
1081 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
1085 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
1087 if (nvlhdr.nvlh_descriptors > nfds)
1090 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
1093 inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY);
1094 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf;
1096 ptr += sizeof(nvlhdr);
1098 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
1099 *leftp -= sizeof(nvlhdr);
1108 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
1111 const unsigned char *ptr;
1112 nvlist_t *nvl, *retnvl, *tmpnvl, *array;
1117 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
1122 tmpnvl = array = NULL;
1123 nvl = retnvl = nvlist_create(0);
1127 ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
1130 if (nvl->nvl_flags != flags) {
1136 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
1139 switch (nvpair_type(nvp)) {
1141 ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
1144 ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
1146 case NV_TYPE_NUMBER:
1147 ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
1149 case NV_TYPE_STRING:
1150 ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
1152 case NV_TYPE_NVLIST:
1153 ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
1155 if (tmpnvl == NULL || ptr == NULL)
1157 nvlist_set_parent(tmpnvl, nvp);
1160 case NV_TYPE_DESCRIPTOR:
1161 ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
1164 case NV_TYPE_DESCRIPTOR_ARRAY:
1165 ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr,
1169 case NV_TYPE_BINARY:
1170 ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
1172 case NV_TYPE_NVLIST_UP:
1173 if (nvl->nvl_parent == NULL)
1175 nvl = nvpair_nvlist(nvl->nvl_parent);
1176 nvpair_free_structure(nvp);
1178 case NV_TYPE_NVLIST_ARRAY_NEXT:
1179 if (nvl->nvl_array_next == NULL) {
1180 if (nvl->nvl_parent == NULL)
1182 nvl = nvpair_nvlist(nvl->nvl_parent);
1184 nvl = __DECONST(nvlist_t *,
1185 nvlist_get_array_next(nvl));
1186 ptr = nvlist_unpack_header(nvl, ptr, nfds,
1191 nvpair_free_structure(nvp);
1193 case NV_TYPE_BOOL_ARRAY:
1194 ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left);
1196 case NV_TYPE_NUMBER_ARRAY:
1197 ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left);
1199 case NV_TYPE_STRING_ARRAY:
1200 ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left);
1202 case NV_TYPE_NVLIST_ARRAY:
1203 ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left,
1208 while (array != NULL) {
1209 nvlist_set_parent(array, nvp);
1210 array = __DECONST(nvlist_t *,
1211 nvlist_get_array_next(array));
1213 ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe,
1217 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
1221 if (!nvlist_move_nvpair(nvl, nvp))
1223 if (tmpnvl != NULL) {
1231 nvlist_destroy(retnvl);
1236 nvlist_unpack(const void *buf, size_t size, int flags)
1239 return (nvlist_xunpack(buf, size, NULL, 0, flags));
1244 nvlist_send(int sock, const nvlist_t *nvl)
1246 size_t datasize, nfds;
1252 if (nvlist_error(nvl) != 0) {
1253 ERRNO_SET(nvlist_error(nvl));
1257 fds = nvlist_descriptors(nvl, &nfds);
1265 data = nvlist_xpack(nvl, &fdidx, &datasize);
1269 if (buf_send(sock, data, datasize) == -1)
1273 if (fd_send(sock, fds, nfds) == -1)
1287 nvlist_recv(int sock, int flags)
1289 struct nvlist_header nvlhdr;
1290 nvlist_t *nvl, *ret;
1292 size_t nfds, size, i;
1295 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
1298 if (!nvlist_check_header(&nvlhdr))
1301 nfds = (size_t)nvlhdr.nvlh_descriptors;
1302 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
1304 buf = nv_malloc(size);
1308 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
1313 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
1317 fds = nv_malloc(nfds * sizeof(fds[0]));
1320 if (fd_recv(sock, fds, nfds) == -1)
1324 nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
1327 for (i = 0; i < nfds; i++)
1344 nvlist_xfer(int sock, nvlist_t *nvl, int flags)
1347 if (nvlist_send(sock, nvl) < 0) {
1348 nvlist_destroy(nvl);
1351 nvlist_destroy(nvl);
1352 return (nvlist_recv(sock, flags));
1357 nvlist_first_nvpair(const nvlist_t *nvl)
1362 return (TAILQ_FIRST(&nvl->nvl_head));
1366 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1372 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1374 retnvp = nvpair_next(nvp);
1375 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1382 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1388 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1390 retnvp = nvpair_prev(nvp);
1391 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1397 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1403 if (cookiep == NULL || *cookiep == NULL)
1404 nvp = nvlist_first_nvpair(nvl);
1406 nvp = nvlist_next_nvpair(nvl, *cookiep);
1410 *typep = nvpair_type(nvp);
1411 if (cookiep != NULL)
1413 return (nvpair_name(nvp));
1417 nvlist_exists(const nvlist_t *nvl, const char *name)
1420 return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1423 #define NVLIST_EXISTS(type, TYPE) \
1425 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
1428 return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \
1431 NVLIST_EXISTS(null, NULL)
1432 NVLIST_EXISTS(bool, BOOL)
1433 NVLIST_EXISTS(number, NUMBER)
1434 NVLIST_EXISTS(string, STRING)
1435 NVLIST_EXISTS(nvlist, NVLIST)
1436 NVLIST_EXISTS(binary, BINARY)
1437 NVLIST_EXISTS(bool_array, BOOL_ARRAY)
1438 NVLIST_EXISTS(number_array, NUMBER_ARRAY)
1439 NVLIST_EXISTS(string_array, STRING_ARRAY)
1440 NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY)
1442 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1443 NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY)
1446 #undef NVLIST_EXISTS
1449 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1455 if (nvlist_error(nvl) != 0) {
1456 ERRNO_SET(nvlist_error(nvl));
1459 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1460 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1461 nvl->nvl_error = EEXIST;
1462 ERRNO_SET(nvlist_error(nvl));
1467 newnvp = nvpair_clone(nvp);
1468 if (newnvp == NULL) {
1469 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1470 ERRNO_SET(nvlist_error(nvl));
1474 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1478 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1482 va_start(valueap, valuefmt);
1483 nvlist_add_stringv(nvl, name, valuefmt, valueap);
1488 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1493 if (nvlist_error(nvl) != 0) {
1494 ERRNO_SET(nvlist_error(nvl));
1498 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1500 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1501 ERRNO_SET(nvl->nvl_error);
1503 (void)nvlist_move_nvpair(nvl, nvp);
1508 nvlist_add_null(nvlist_t *nvl, const char *name)
1512 if (nvlist_error(nvl) != 0) {
1513 ERRNO_SET(nvlist_error(nvl));
1517 nvp = nvpair_create_null(name);
1519 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1520 ERRNO_SET(nvl->nvl_error);
1522 (void)nvlist_move_nvpair(nvl, nvp);
1527 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1532 if (nvlist_error(nvl) != 0) {
1533 ERRNO_SET(nvlist_error(nvl));
1537 nvp = nvpair_create_binary(name, value, size);
1539 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1540 ERRNO_SET(nvl->nvl_error);
1542 (void)nvlist_move_nvpair(nvl, nvp);
1547 #define NVLIST_ADD(vtype, type) \
1549 nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \
1553 if (nvlist_error(nvl) != 0) { \
1554 ERRNO_SET(nvlist_error(nvl)); \
1558 nvp = nvpair_create_##type(name, value); \
1559 if (nvp == NULL) { \
1560 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1561 ERRNO_SET(nvl->nvl_error); \
1563 (void)nvlist_move_nvpair(nvl, nvp); \
1567 NVLIST_ADD(bool, bool)
1568 NVLIST_ADD(uint64_t, number)
1569 NVLIST_ADD(const char *, string)
1570 NVLIST_ADD(const nvlist_t *, nvlist)
1572 NVLIST_ADD(int, descriptor);
1577 #define NVLIST_ADD_ARRAY(vtype, type) \
1579 nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value, \
1584 if (nvlist_error(nvl) != 0) { \
1585 ERRNO_SET(nvlist_error(nvl)); \
1589 nvp = nvpair_create_##type##_array(name, value, nitems); \
1590 if (nvp == NULL) { \
1591 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1592 ERRNO_SET(nvl->nvl_error); \
1594 (void)nvlist_move_nvpair(nvl, nvp); \
1598 NVLIST_ADD_ARRAY(const bool *, bool)
1599 NVLIST_ADD_ARRAY(const uint64_t *, number)
1600 NVLIST_ADD_ARRAY(const char * const *, string)
1601 NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist)
1603 NVLIST_ADD_ARRAY(const int *, descriptor)
1606 #undef NVLIST_ADD_ARRAY
1609 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1613 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1615 if (nvlist_error(nvl) != 0) {
1617 ERRNO_SET(nvlist_error(nvl));
1620 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1621 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1623 nvl->nvl_error = EEXIST;
1624 ERRNO_SET(nvl->nvl_error);
1629 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1634 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1638 if (nvlist_error(nvl) != 0) {
1640 ERRNO_SET(nvlist_error(nvl));
1644 nvp = nvpair_move_string(name, value);
1646 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1647 ERRNO_SET(nvl->nvl_error);
1649 (void)nvlist_move_nvpair(nvl, nvp);
1654 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1658 if (nvlist_error(nvl) != 0) {
1659 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1660 nvlist_destroy(value);
1661 ERRNO_SET(nvlist_error(nvl));
1665 nvp = nvpair_move_nvlist(name, value);
1667 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1668 ERRNO_SET(nvl->nvl_error);
1670 (void)nvlist_move_nvpair(nvl, nvp);
1676 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1680 if (nvlist_error(nvl) != 0) {
1682 ERRNO_SET(nvlist_error(nvl));
1686 nvp = nvpair_move_descriptor(name, value);
1688 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1689 ERRNO_SET(nvl->nvl_error);
1691 (void)nvlist_move_nvpair(nvl, nvp);
1697 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1701 if (nvlist_error(nvl) != 0) {
1703 ERRNO_SET(nvlist_error(nvl));
1707 nvp = nvpair_move_binary(name, value, size);
1709 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1710 ERRNO_SET(nvl->nvl_error);
1712 (void)nvlist_move_nvpair(nvl, nvp);
1717 nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value,
1722 if (nvlist_error(nvl) != 0) {
1724 ERRNO_SET(nvlist_error(nvl));
1728 nvp = nvpair_move_bool_array(name, value, nitems);
1730 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1731 ERRNO_SET(nvl->nvl_error);
1733 (void)nvlist_move_nvpair(nvl, nvp);
1738 nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value,
1744 if (nvlist_error(nvl) != 0) {
1745 if (value != NULL) {
1746 for (i = 0; i < nitems; i++)
1750 ERRNO_SET(nvlist_error(nvl));
1754 nvp = nvpair_move_string_array(name, value, nitems);
1756 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1757 ERRNO_SET(nvl->nvl_error);
1759 (void)nvlist_move_nvpair(nvl, nvp);
1764 nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value,
1770 if (nvlist_error(nvl) != 0) {
1771 if (value != NULL) {
1772 for (i = 0; i < nitems; i++) {
1773 if (nvlist_get_pararr(value[i], NULL) == NULL)
1774 nvlist_destroy(value[i]);
1778 ERRNO_SET(nvlist_error(nvl));
1782 nvp = nvpair_move_nvlist_array(name, value, nitems);
1784 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1785 ERRNO_SET(nvl->nvl_error);
1787 (void)nvlist_move_nvpair(nvl, nvp);
1792 nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value,
1797 if (nvlist_error(nvl) != 0) {
1799 ERRNO_SET(nvlist_error(nvl));
1803 nvp = nvpair_move_number_array(name, value, nitems);
1805 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1806 ERRNO_SET(nvl->nvl_error);
1808 (void)nvlist_move_nvpair(nvl, nvp);
1814 nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value,
1820 if (nvlist_error(nvl) != 0) {
1822 for (i = 0; i < nitems; i++)
1827 ERRNO_SET(nvlist_error(nvl));
1831 nvp = nvpair_move_descriptor_array(name, value, nitems);
1833 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1834 ERRNO_SET(nvl->nvl_error);
1836 (void)nvlist_move_nvpair(nvl, nvp);
1842 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1845 return (nvlist_find(nvl, NV_TYPE_NONE, name));
1848 #define NVLIST_GET(ftype, type, TYPE) \
1850 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1852 const nvpair_t *nvp; \
1854 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1856 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1857 return (nvpair_get_##type(nvp)); \
1860 NVLIST_GET(bool, bool, BOOL)
1861 NVLIST_GET(uint64_t, number, NUMBER)
1862 NVLIST_GET(const char *, string, STRING)
1863 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1865 NVLIST_GET(int, descriptor, DESCRIPTOR)
1871 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1875 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1877 nvlist_report_missing(NV_TYPE_BINARY, name);
1879 return (nvpair_get_binary(nvp, sizep));
1882 #define NVLIST_GET_ARRAY(ftype, type, TYPE) \
1884 nvlist_get_##type##_array(const nvlist_t *nvl, const char *name, \
1887 const nvpair_t *nvp; \
1889 nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \
1891 nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \
1892 return (nvpair_get_##type##_array(nvp, nitems)); \
1895 NVLIST_GET_ARRAY(const bool *, bool, BOOL)
1896 NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER)
1897 NVLIST_GET_ARRAY(const char * const *, string, STRING)
1898 NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST)
1900 NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR)
1903 #undef NVLIST_GET_ARRAY
1905 #define NVLIST_TAKE(ftype, type, TYPE) \
1907 nvlist_take_##type(nvlist_t *nvl, const char *name) \
1912 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1914 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1915 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1916 nvlist_remove_nvpair(nvl, nvp); \
1917 nvpair_free_structure(nvp); \
1921 NVLIST_TAKE(bool, bool, BOOL)
1922 NVLIST_TAKE(uint64_t, number, NUMBER)
1923 NVLIST_TAKE(char *, string, STRING)
1924 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1926 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1932 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1937 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1939 nvlist_report_missing(NV_TYPE_BINARY, name);
1941 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1942 nvlist_remove_nvpair(nvl, nvp);
1943 nvpair_free_structure(nvp);
1947 #define NVLIST_TAKE_ARRAY(ftype, type, TYPE) \
1949 nvlist_take_##type##_array(nvlist_t *nvl, const char *name, \
1955 nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \
1957 nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \
1958 value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\
1959 nvlist_remove_nvpair(nvl, nvp); \
1960 nvpair_free_structure(nvp); \
1964 NVLIST_TAKE_ARRAY(bool *, bool, BOOL)
1965 NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER)
1966 NVLIST_TAKE_ARRAY(char **, string, STRING)
1967 NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST)
1969 NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR)
1973 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1978 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1980 nvpair_remove(&nvl->nvl_head, nvp, nvl);
1984 nvlist_free(nvlist_t *nvl, const char *name)
1987 nvlist_free_type(nvl, name, NV_TYPE_NONE);
1990 #define NVLIST_FREE(type, TYPE) \
1992 nvlist_free_##type(nvlist_t *nvl, const char *name) \
1995 nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \
1998 NVLIST_FREE(null, NULL)
1999 NVLIST_FREE(bool, BOOL)
2000 NVLIST_FREE(number, NUMBER)
2001 NVLIST_FREE(string, STRING)
2002 NVLIST_FREE(nvlist, NVLIST)
2003 NVLIST_FREE(binary, BINARY)
2004 NVLIST_FREE(bool_array, BOOL_ARRAY)
2005 NVLIST_FREE(number_array, NUMBER_ARRAY)
2006 NVLIST_FREE(string_array, STRING_ARRAY)
2007 NVLIST_FREE(nvlist_array, NVLIST_ARRAY)
2009 NVLIST_FREE(descriptor, DESCRIPTOR)
2010 NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY)
2016 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
2021 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
2023 nvlist_remove_nvpair(nvl, nvp);