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>
42 #include <sys/malloc.h>
43 #include <sys/systm.h>
45 #include <machine/stdarg.h>
57 #include "common_impl.h"
67 #include "nvlist_impl.h"
68 #include "nvpair_impl.h"
72 #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
73 #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
74 #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
77 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
78 #define PJDLOG_RASSERT(expr, ...) assert(expr)
79 #define PJDLOG_ABORT(...) abort()
83 #define NVPAIR_MAGIC 0x6e7670 /* "nvp" */
90 size_t nvp_nitems; /* Used only for array types. */
92 TAILQ_ENTRY(nvpair) nvp_next;
95 #define NVPAIR_ASSERT(nvp) do { \
96 PJDLOG_ASSERT((nvp) != NULL); \
97 PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \
100 struct nvpair_header {
102 uint16_t nvph_namesize;
103 uint64_t nvph_datasize;
104 uint64_t nvph_nitems;
109 nvpair_assert(const nvpair_t *nvp)
116 nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize,
122 PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
124 namelen = strlen(name);
125 if (namelen >= NV_NAME_MAX) {
126 ERRNO_SET(ENAMETOOLONG);
130 nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
132 nvp->nvp_name = (char *)(nvp + 1);
133 memcpy(nvp->nvp_name, name, namelen);
134 nvp->nvp_name[namelen] = '\0';
135 nvp->nvp_type = type;
136 nvp->nvp_data = data;
137 nvp->nvp_datasize = datasize;
138 nvp->nvp_nitems = nitems;
139 nvp->nvp_magic = NVPAIR_MAGIC;
146 nvpair_nvlist(const nvpair_t *nvp)
151 return (nvp->nvp_list);
155 nvpair_next(const nvpair_t *nvp)
159 PJDLOG_ASSERT(nvp->nvp_list != NULL);
161 return (TAILQ_NEXT(nvp, nvp_next));
165 nvpair_prev(const nvpair_t *nvp)
169 PJDLOG_ASSERT(nvp->nvp_list != NULL);
171 return (TAILQ_PREV(nvp, nvl_head, nvp_next));
175 nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
179 PJDLOG_ASSERT(nvp->nvp_list == NULL);
180 PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 ||
181 !nvlist_exists(nvl, nvpair_name(nvp)));
183 TAILQ_INSERT_TAIL(head, nvp, nvp_next);
188 nvpair_remove_nvlist(nvpair_t *nvp)
192 /* XXX: DECONST is bad, mkay? */
193 nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
194 PJDLOG_ASSERT(nvl != NULL);
195 nvlist_set_parent(nvl, NULL);
199 nvpair_remove_nvlist_array(nvpair_t *nvp)
204 /* XXX: DECONST is bad, mkay? */
205 nvlarray = __DECONST(nvlist_t **,
206 nvpair_get_nvlist_array(nvp, &count));
207 for (i = 0; i < count; i++)
208 nvlist_set_array_next(nvlarray[i], NULL);
212 nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
216 PJDLOG_ASSERT(nvp->nvp_list == nvl);
218 if (nvpair_type(nvp) == NV_TYPE_NVLIST)
219 nvpair_remove_nvlist(nvp);
220 else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY)
221 nvpair_remove_nvlist_array(nvp);
223 TAILQ_REMOVE(head, nvp, nvp_next);
224 nvp->nvp_list = NULL;
228 nvpair_clone(const nvpair_t *nvp)
237 name = nvpair_name(nvp);
239 switch (nvpair_type(nvp)) {
241 newnvp = nvpair_create_null(name);
244 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
247 newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
250 newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
253 newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
256 data = nvpair_get_binary(nvp, &datasize);
257 newnvp = nvpair_create_binary(name, data, datasize);
259 case NV_TYPE_BOOL_ARRAY:
260 data = nvpair_get_bool_array(nvp, &datasize);
261 newnvp = nvpair_create_bool_array(name, data, datasize);
263 case NV_TYPE_NUMBER_ARRAY:
264 data = nvpair_get_number_array(nvp, &datasize);
265 newnvp = nvpair_create_number_array(name, data, datasize);
267 case NV_TYPE_STRING_ARRAY:
268 data = nvpair_get_string_array(nvp, &datasize);
269 newnvp = nvpair_create_string_array(name, data, datasize);
271 case NV_TYPE_NVLIST_ARRAY:
272 data = nvpair_get_nvlist_array(nvp, &datasize);
273 newnvp = nvpair_create_nvlist_array(name, data, datasize);
276 case NV_TYPE_DESCRIPTOR:
277 newnvp = nvpair_create_descriptor(name,
278 nvpair_get_descriptor(nvp));
280 case NV_TYPE_DESCRIPTOR_ARRAY:
281 data = nvpair_get_descriptor_array(nvp, &datasize);
282 newnvp = nvpair_create_descriptor_array(name, data, datasize);
286 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
293 nvpair_header_size(void)
296 return (sizeof(struct nvpair_header));
300 nvpair_size(const nvpair_t *nvp)
305 return (nvp->nvp_datasize);
309 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
311 struct nvpair_header nvphdr;
316 nvphdr.nvph_type = nvp->nvp_type;
317 namesize = strlen(nvp->nvp_name) + 1;
318 PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
319 nvphdr.nvph_namesize = namesize;
320 nvphdr.nvph_datasize = nvp->nvp_datasize;
321 nvphdr.nvph_nitems = nvp->nvp_nitems;
322 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
323 memcpy(ptr, &nvphdr, sizeof(nvphdr));
324 ptr += sizeof(nvphdr);
325 *leftp -= sizeof(nvphdr);
327 PJDLOG_ASSERT(*leftp >= namesize);
328 memcpy(ptr, nvp->nvp_name, namesize);
336 nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
337 size_t *leftp __unused)
341 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
347 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
352 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
354 value = (uint8_t)nvp->nvp_data;
356 PJDLOG_ASSERT(*leftp >= sizeof(value));
357 memcpy(ptr, &value, sizeof(value));
358 ptr += sizeof(value);
359 *leftp -= sizeof(value);
365 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
370 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
372 value = (uint64_t)nvp->nvp_data;
374 PJDLOG_ASSERT(*leftp >= sizeof(value));
375 memcpy(ptr, &value, sizeof(value));
376 ptr += sizeof(value);
377 *leftp -= sizeof(value);
383 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
387 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
389 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
390 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
391 ptr += nvp->nvp_datasize;
392 *leftp -= nvp->nvp_datasize;
398 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
400 struct nvpair_header nvphdr;
402 const char *name = "";
405 nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
406 nvphdr.nvph_namesize = namesize;
407 nvphdr.nvph_datasize = 0;
408 nvphdr.nvph_nitems = 0;
409 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
410 memcpy(ptr, &nvphdr, sizeof(nvphdr));
411 ptr += sizeof(nvphdr);
412 *leftp -= sizeof(nvphdr);
414 PJDLOG_ASSERT(*leftp >= namesize);
415 memcpy(ptr, name, namesize);
423 nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp)
425 struct nvpair_header nvphdr;
427 const char *name = "";
430 nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT;
431 nvphdr.nvph_namesize = namesize;
432 nvphdr.nvph_datasize = 0;
433 nvphdr.nvph_nitems = 0;
434 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
435 memcpy(ptr, &nvphdr, sizeof(nvphdr));
436 ptr += sizeof(nvphdr);
437 *leftp -= sizeof(nvphdr);
439 PJDLOG_ASSERT(*leftp >= namesize);
440 memcpy(ptr, name, namesize);
449 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
455 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
457 value = (int64_t)nvp->nvp_data;
460 * If there is a real descriptor here, we change its number
461 * to position in the array of descriptors send via control
464 PJDLOG_ASSERT(fdidxp != NULL);
470 PJDLOG_ASSERT(*leftp >= sizeof(value));
471 memcpy(ptr, &value, sizeof(value));
472 ptr += sizeof(value);
473 *leftp -= sizeof(value);
480 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
484 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
486 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
487 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
488 ptr += nvp->nvp_datasize;
489 *leftp -= nvp->nvp_datasize;
495 nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
499 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
500 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
502 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
503 ptr += nvp->nvp_datasize;
504 *leftp -= nvp->nvp_datasize;
510 nvpair_pack_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
514 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
515 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
517 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
518 ptr += nvp->nvp_datasize;
519 *leftp -= nvp->nvp_datasize;
525 nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
529 const char * const *array;
532 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
533 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
536 array = nvpair_get_string_array(nvp, NULL);
537 PJDLOG_ASSERT(array != NULL);
539 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
540 len = strlen(array[ii]) + 1;
541 PJDLOG_ASSERT(*leftp >= len);
543 memcpy(ptr, (const void *)array[ii], len);
549 PJDLOG_ASSERT(size == nvp->nvp_datasize);
556 nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr,
557 int64_t *fdidxp, size_t *leftp)
564 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
565 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
567 array = nvpair_get_descriptor_array(nvp, NULL);
568 PJDLOG_ASSERT(array != NULL);
570 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
571 PJDLOG_ASSERT(*leftp >= sizeof(value));
576 * If there is a real descriptor here, we change its
577 * number to position in the array of descriptors send
578 * via control message.
580 PJDLOG_ASSERT(fdidxp != NULL);
585 memcpy(ptr, &value, sizeof(value));
586 ptr += sizeof(value);
587 *leftp -= sizeof(value);
595 nvpair_init_datasize(nvpair_t *nvp)
600 if (nvp->nvp_type == NV_TYPE_NVLIST) {
601 if (nvp->nvp_data == 0) {
602 nvp->nvp_datasize = 0;
605 nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
610 const unsigned char *
611 nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
614 struct nvpair_header nvphdr;
616 if (*leftp < sizeof(nvphdr))
619 memcpy(&nvphdr, ptr, sizeof(nvphdr));
620 ptr += sizeof(nvphdr);
621 *leftp -= sizeof(nvphdr);
623 #if NV_TYPE_FIRST > 0
624 if (nvphdr.nvph_type < NV_TYPE_FIRST)
627 if (nvphdr.nvph_type > NV_TYPE_LAST &&
628 nvphdr.nvph_type != NV_TYPE_NVLIST_UP &&
629 nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) {
633 #if BYTE_ORDER == BIG_ENDIAN
635 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
636 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
640 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
641 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
645 if (nvphdr.nvph_namesize > NV_NAME_MAX)
647 if (*leftp < nvphdr.nvph_namesize)
649 if (nvphdr.nvph_namesize < 1)
651 if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
652 (size_t)(nvphdr.nvph_namesize - 1)) {
656 memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
657 ptr += nvphdr.nvph_namesize;
658 *leftp -= nvphdr.nvph_namesize;
660 if (*leftp < nvphdr.nvph_datasize)
663 nvp->nvp_type = nvphdr.nvph_type;
665 nvp->nvp_datasize = nvphdr.nvph_datasize;
666 nvp->nvp_nitems = nvphdr.nvph_nitems;
674 const unsigned char *
675 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
676 size_t *leftp __unused)
679 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
681 if (nvp->nvp_datasize != 0) {
689 const unsigned char *
690 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
695 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
697 if (nvp->nvp_datasize != sizeof(value)) {
701 if (*leftp < sizeof(value)) {
706 memcpy(&value, ptr, sizeof(value));
707 ptr += sizeof(value);
708 *leftp -= sizeof(value);
710 if (value != 0 && value != 1) {
715 nvp->nvp_data = (uint64_t)value;
720 const unsigned char *
721 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
725 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
727 if (nvp->nvp_datasize != sizeof(uint64_t)) {
731 if (*leftp < sizeof(uint64_t)) {
737 nvp->nvp_data = be64dec(ptr);
739 nvp->nvp_data = le64dec(ptr);
741 ptr += sizeof(uint64_t);
742 *leftp -= sizeof(uint64_t);
747 const unsigned char *
748 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
749 const unsigned char *ptr, size_t *leftp)
752 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
754 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
759 if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
760 nvp->nvp_datasize - 1) {
765 nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
766 if (nvp->nvp_data == 0)
769 ptr += nvp->nvp_datasize;
770 *leftp -= nvp->nvp_datasize;
775 const unsigned char *
776 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
777 const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
781 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
783 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
788 value = nvlist_create(0);
792 ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
796 nvp->nvp_data = (uint64_t)(uintptr_t)value;
803 const unsigned char *
804 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
805 size_t *leftp, const int *fds, size_t nfds)
809 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
811 if (nvp->nvp_datasize != sizeof(idx)) {
815 if (*leftp < sizeof(idx)) {
830 if ((size_t)idx >= nfds) {
835 nvp->nvp_data = (uint64_t)fds[idx];
838 *leftp -= sizeof(idx);
844 const unsigned char *
845 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
846 const unsigned char *ptr, size_t *leftp)
850 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
852 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
857 value = nv_malloc(nvp->nvp_datasize);
861 memcpy(value, ptr, nvp->nvp_datasize);
862 ptr += nvp->nvp_datasize;
863 *leftp -= nvp->nvp_datasize;
865 nvp->nvp_data = (uint64_t)(uintptr_t)value;
870 const unsigned char *
871 nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp,
872 const unsigned char *ptr, size_t *leftp)
878 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
880 size = sizeof(*value) * nvp->nvp_nitems;
881 if (nvp->nvp_datasize != size || *leftp < size ||
882 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
887 value = nv_malloc(size);
891 for (i = 0; i < nvp->nvp_nitems; i++) {
892 value[i] = *(const uint8_t *)ptr;
894 ptr += sizeof(*value);
895 *leftp -= sizeof(*value);
898 nvp->nvp_data = (uint64_t)(uintptr_t)value;
903 const unsigned char *
904 nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
911 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
913 size = sizeof(*value) * nvp->nvp_nitems;
914 if (nvp->nvp_datasize != size || *leftp < size ||
915 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
920 value = nv_malloc(size);
924 for (i = 0; i < nvp->nvp_nitems; i++) {
926 value[i] = be64dec(ptr);
928 value[i] = le64dec(ptr);
930 ptr += sizeof(*value);
931 *leftp -= sizeof(*value);
934 nvp->nvp_data = (uint64_t)(uintptr_t)value;
939 const unsigned char *
940 nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp,
941 const unsigned char *ptr, size_t *leftp)
949 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
951 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 ||
952 nvp->nvp_nitems == 0) {
957 size = nvp->nvp_datasize;
958 tmp = (const char *)ptr;
959 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
960 len = strnlen(tmp, size - 1) + 1;
973 value = nv_malloc(sizeof(*value) * nvp->nvp_nitems);
977 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
978 value[ii] = nv_strdup((const char *)ptr);
979 if (value[ii] == NULL)
981 len = strlen(value[ii]) + 1;
985 nvp->nvp_data = (uint64_t)(uintptr_t)value;
989 for (j = 0; j < ii; j++)
996 const unsigned char *
997 nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
998 const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
1005 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1007 size = sizeof(idx) * nvp->nvp_nitems;
1008 if (nvp->nvp_datasize != size || *leftp < size ||
1009 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
1014 array = (int *)nv_malloc(size);
1018 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1030 if ((size_t)idx >= nfds) {
1036 array[ii] = (uint64_t)fds[idx];
1039 *leftp -= sizeof(idx);
1042 nvp->nvp_data = (uint64_t)(uintptr_t)array;
1048 const unsigned char *
1049 nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
1050 const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
1057 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1059 sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
1060 if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
1066 value = nv_malloc(nvp->nvp_nitems * sizeof(*value));
1070 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1071 value[ii] = nvlist_create(0);
1072 if (value[ii] == NULL)
1075 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1076 (uint64_t)(uintptr_t)value[ii], 0, 0);
1079 nvlist_set_array_next(value[ii - 1], tmpnvp);
1082 nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
1084 nvp->nvp_data = (uint64_t)(uintptr_t)value;
1085 *firstel = value[0];
1090 for (j = 0; j <= ii; j++)
1091 nvlist_destroy(value[j]);
1098 const unsigned char *
1099 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
1102 nvpair_t *nvp, *tmp;
1104 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
1107 nvp->nvp_name = (char *)(nvp + 1);
1109 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
1112 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
1117 /* Update nvp_name after realloc(). */
1118 nvp->nvp_name = (char *)(nvp + 1);
1119 nvp->nvp_data = 0x00;
1120 nvp->nvp_magic = NVPAIR_MAGIC;
1129 nvpair_type(const nvpair_t *nvp)
1134 return (nvp->nvp_type);
1138 nvpair_name(const nvpair_t *nvp)
1143 return (nvp->nvp_name);
1147 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
1152 va_start(valueap, valuefmt);
1153 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1160 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
1166 len = nv_vasprintf(&str, valuefmt, valueap);
1169 nvp = nvpair_create_string(name, str);
1176 nvpair_create_null(const char *name)
1179 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1183 nvpair_create_bool(const char *name, bool value)
1186 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1187 sizeof(uint8_t), 0));
1191 nvpair_create_number(const char *name, uint64_t value)
1194 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1198 nvpair_create_string(const char *name, const char *value)
1204 if (value == NULL) {
1209 data = nv_strdup(value);
1212 size = strlen(value) + 1;
1214 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1223 nvpair_create_nvlist(const char *name, const nvlist_t *value)
1228 if (value == NULL) {
1233 nvl = nvlist_clone(value);
1237 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1240 nvlist_destroy(nvl);
1242 nvlist_set_parent(nvl, nvp);
1249 nvpair_create_descriptor(const char *name, int value)
1253 if (value < 0 || !fd_is_valid(value)) {
1258 value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1262 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1263 sizeof(int64_t), 0);
1275 nvpair_create_binary(const char *name, const void *value, size_t size)
1280 if (value == NULL || size == 0) {
1285 data = nv_malloc(size);
1288 memcpy(data, value, size);
1290 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1299 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1305 if (value == NULL || nitems == 0) {
1310 size = sizeof(value[0]) * nitems;
1311 data = nv_malloc(size);
1315 memcpy(data, value, size);
1316 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1328 nvpair_create_number_array(const char *name, const uint64_t *value,
1335 if (value == NULL || nitems == 0) {
1340 size = sizeof(value[0]) * nitems;
1341 data = nv_malloc(size);
1345 memcpy(data, value, size);
1346 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1347 (uint64_t)(uintptr_t)data, size, nitems);
1358 nvpair_create_string_array(const char *name, const char * const *value,
1363 size_t datasize, size;
1366 if (value == NULL || nitems == 0) {
1373 data = nv_malloc(sizeof(value[0]) * nitems);
1377 for (ii = 0; ii < nitems; ii++) {
1378 if (value[ii] == NULL) {
1383 size = strlen(value[ii]) + 1;
1385 data[ii] = nv_strdup(value[ii]);
1386 if (data[ii] == NULL)
1389 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1390 (uint64_t)(uintptr_t)data, datasize, nitems);
1395 for (; ii > 0; ii--)
1396 nv_free(data[ii - 1]);
1405 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1415 if (value == NULL || nitems == 0) {
1420 nvls = nv_malloc(sizeof(value[0]) * nitems);
1424 for (ii = 0; ii < nitems; ii++) {
1425 if (value[ii] == NULL) {
1430 nvls[ii] = nvlist_clone(value[ii]);
1431 if (nvls[ii] == NULL)
1437 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1438 (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1441 nvlist_destroy(nvls[ii]);
1445 nvlist_set_array_next(nvls[ii - 1], nvp);
1448 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1449 nvlist_set_flags(nvls[nitems - 1], flags);
1451 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1452 (uint64_t)(uintptr_t)nvls, 0, nitems);
1456 for (ii = 0; ii < nitems; ii++)
1457 nvlist_set_parent(nvls[ii], parent);
1463 for (; ii > 0; ii--)
1464 nvlist_destroy(nvls[ii - 1]);
1473 nvpair_create_descriptor_array(const char *name, const int *value,
1480 if (value == NULL) {
1487 fds = nv_malloc(sizeof(value[0]) * nitems);
1490 for (ii = 0; ii < nitems; ii++) {
1491 if (value[ii] == -1) {
1494 if (!fd_is_valid(value[ii])) {
1499 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1505 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1506 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1511 for (; ii > 0; ii--) {
1512 if (fds[ii - 1] != -1)
1524 nvpair_move_string(const char *name, char *value)
1528 if (value == NULL) {
1533 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1534 strlen(value) + 1, 0);
1545 nvpair_move_nvlist(const char *name, nvlist_t *value)
1549 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1554 if (nvlist_error(value) != 0) {
1555 ERRNO_SET(nvlist_error(value));
1556 nvlist_destroy(value);
1560 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1563 nvlist_destroy(value);
1565 nvlist_set_parent(value, nvp);
1572 nvpair_move_descriptor(const char *name, int value)
1576 if (value < 0 || !fd_is_valid(value)) {
1581 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1582 sizeof(int64_t), 0);
1594 nvpair_move_binary(const char *name, void *value, size_t size)
1598 if (value == NULL || size == 0) {
1603 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1615 nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1619 if (value == NULL || nitems == 0) {
1624 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1625 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1636 nvpair_move_string_array(const char *name, char **value, size_t nitems)
1641 if (value == NULL || nitems == 0) {
1647 for (i = 0; i < nitems; i++) {
1648 if (value[i] == NULL) {
1653 size += strlen(value[i]) + 1;
1656 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1657 (uint64_t)(uintptr_t)value, size, nitems);
1660 for (i = 0; i < nitems; i++)
1670 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1674 if (value == NULL || nitems == 0) {
1679 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1680 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1691 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1697 if (value == NULL || nitems == 0) {
1702 for (ii = 0; ii < nitems; ii++) {
1703 if (value == NULL || nvlist_error(value[ii]) != 0 ||
1704 nvlist_get_pararr(value[ii], NULL) != NULL) {
1711 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1712 (uint64_t)(uintptr_t)value[ii], 0, 0);
1715 nvlist_set_array_next(value[ii - 1], nvp);
1718 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1719 nvlist_set_flags(value[nitems - 1], flags);
1721 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1722 (uint64_t)(uintptr_t)value, 0, nitems);
1726 for (ii = 0; ii < nitems; ii++)
1727 nvlist_set_parent(value[ii], parent);
1732 for (ii = 0; ii < nitems; ii++) {
1733 if (value[ii] != NULL &&
1734 nvlist_get_pararr(value[ii], NULL) != NULL) {
1735 nvlist_destroy(value[ii]);
1746 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1751 if (value == NULL || nitems == 0) {
1756 for (i = 0; i < nitems; i++) {
1757 if (value[i] != -1 && !fd_is_valid(value[i])) {
1763 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1764 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1771 for (i = 0; i < nitems; i++) {
1772 if (fd_is_valid(value[i]))
1783 nvpair_get_bool(const nvpair_t *nvp)
1788 return (nvp->nvp_data == 1);
1792 nvpair_get_number(const nvpair_t *nvp)
1797 return (nvp->nvp_data);
1801 nvpair_get_string(const nvpair_t *nvp)
1805 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1807 return ((const char *)(intptr_t)nvp->nvp_data);
1811 nvpair_get_nvlist(const nvpair_t *nvp)
1815 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1817 return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1822 nvpair_get_descriptor(const nvpair_t *nvp)
1826 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1828 return ((int)nvp->nvp_data);
1833 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1837 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1840 *sizep = nvp->nvp_datasize;
1842 return ((const void *)(intptr_t)nvp->nvp_data);
1846 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1850 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1853 *nitems = nvp->nvp_nitems;
1855 return ((const bool *)(intptr_t)nvp->nvp_data);
1859 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1863 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1866 *nitems = nvp->nvp_nitems;
1868 return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1871 const char * const *
1872 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1876 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1879 *nitems = nvp->nvp_nitems;
1881 return ((const char * const *)(intptr_t)nvp->nvp_data);
1884 const nvlist_t * const *
1885 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1889 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1892 *nitems = nvp->nvp_nitems;
1894 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1899 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1903 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1906 *nitems = nvp->nvp_nitems;
1908 return ((const int *)(intptr_t)nvp->nvp_data);
1913 nvpair_free(nvpair_t *nvp)
1918 PJDLOG_ASSERT(nvp->nvp_list == NULL);
1921 switch (nvp->nvp_type) {
1923 case NV_TYPE_DESCRIPTOR:
1924 close((int)nvp->nvp_data);
1926 case NV_TYPE_DESCRIPTOR_ARRAY:
1927 for (i = 0; i < nvp->nvp_nitems; i++)
1928 close(((int *)(intptr_t)nvp->nvp_data)[i]);
1931 case NV_TYPE_NVLIST:
1932 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
1934 case NV_TYPE_STRING:
1935 nv_free((char *)(intptr_t)nvp->nvp_data);
1937 case NV_TYPE_BINARY:
1938 nv_free((void *)(intptr_t)nvp->nvp_data);
1940 case NV_TYPE_NVLIST_ARRAY:
1941 for (i = 0; i < nvp->nvp_nitems; i++) {
1943 ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
1945 nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
1947 case NV_TYPE_NUMBER_ARRAY:
1948 nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
1950 case NV_TYPE_BOOL_ARRAY:
1951 nv_free((bool *)(intptr_t)nvp->nvp_data);
1953 case NV_TYPE_STRING_ARRAY:
1954 for (i = 0; i < nvp->nvp_nitems; i++)
1955 nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
1956 nv_free((char **)(intptr_t)nvp->nvp_data);
1963 nvpair_free_structure(nvpair_t *nvp)
1967 PJDLOG_ASSERT(nvp->nvp_list == NULL);
1974 nvpair_type_string(int type)
1982 case NV_TYPE_NUMBER:
1984 case NV_TYPE_STRING:
1986 case NV_TYPE_NVLIST:
1988 case NV_TYPE_DESCRIPTOR:
1989 return ("DESCRIPTOR");
1990 case NV_TYPE_BINARY:
1992 case NV_TYPE_BOOL_ARRAY:
1993 return ("BOOL ARRAY");
1994 case NV_TYPE_NUMBER_ARRAY:
1995 return ("NUMBER ARRAY");
1996 case NV_TYPE_STRING_ARRAY:
1997 return ("STRING ARRAY");
1998 case NV_TYPE_NVLIST_ARRAY:
1999 return ("NVLIST ARRAY");
2000 case NV_TYPE_DESCRIPTOR_ARRAY:
2001 return ("DESCRIPTOR ARRAY");
2003 return ("<UNKNOWN>");