xref: /freebsd/sys/contrib/libnv/bsd_nvpair.c (revision 1f474190)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2009-2013 The FreeBSD Foundation
5  * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
6  * All rights reserved.
7  *
8  * This software was developed by Pawel Jakub Dawidek under sponsorship from
9  * the FreeBSD Foundation.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include <sys/param.h>
37 #include <sys/endian.h>
38 #include <sys/queue.h>
39 
40 #ifdef _KERNEL
41 
42 #include <sys/errno.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/systm.h>
46 
47 #include <machine/stdarg.h>
48 
49 #else
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <stdarg.h>
53 #include <stdbool.h>
54 #include <stdint.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <unistd.h>
58 
59 #include "common_impl.h"
60 #endif
61 
62 #ifdef HAVE_PJDLOG
63 #include <pjdlog.h>
64 #endif
65 
66 #include <sys/nv.h>
67 
68 #include "nv_impl.h"
69 #include "nvlist_impl.h"
70 #include "nvpair_impl.h"
71 
72 #ifndef	HAVE_PJDLOG
73 #ifdef _KERNEL
74 #define	PJDLOG_ASSERT(...)		MPASS(__VA_ARGS__)
75 #define	PJDLOG_RASSERT(expr, ...)	KASSERT(expr, (__VA_ARGS__))
76 #define	PJDLOG_ABORT(...)		panic(__VA_ARGS__)
77 #else
78 #include <assert.h>
79 #define	PJDLOG_ASSERT(...)		assert(__VA_ARGS__)
80 #define	PJDLOG_RASSERT(expr, ...)	assert(expr)
81 #define	PJDLOG_ABORT(...)		abort()
82 #endif
83 #endif
84 
85 #define	NVPAIR_MAGIC	0x6e7670	/* "nvp" */
86 struct nvpair {
87 	int		 nvp_magic;
88 	char		*nvp_name;
89 	int		 nvp_type;
90 	uint64_t	 nvp_data;
91 	size_t		 nvp_datasize;
92 	size_t		 nvp_nitems;	/* Used only for array types. */
93 	nvlist_t	*nvp_list;
94 	TAILQ_ENTRY(nvpair) nvp_next;
95 };
96 
97 #define	NVPAIR_ASSERT(nvp)	do {					\
98 	PJDLOG_ASSERT((nvp) != NULL);					\
99 	PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC);		\
100 } while (0)
101 
102 struct nvpair_header {
103 	uint8_t		nvph_type;
104 	uint16_t	nvph_namesize;
105 	uint64_t	nvph_datasize;
106 	uint64_t	nvph_nitems;
107 } __packed;
108 
109 
110 void
111 nvpair_assert(const nvpair_t *nvp __unused)
112 {
113 
114 	NVPAIR_ASSERT(nvp);
115 }
116 
117 static nvpair_t *
118 nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize,
119     size_t nitems)
120 {
121 	nvpair_t *nvp;
122 	size_t namelen;
123 
124 	PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
125 
126 	namelen = strlen(name);
127 	if (namelen >= NV_NAME_MAX) {
128 		ERRNO_SET(ENAMETOOLONG);
129 		return (NULL);
130 	}
131 
132 	nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
133 	if (nvp != NULL) {
134 		nvp->nvp_name = (char *)(nvp + 1);
135 		memcpy(nvp->nvp_name, name, namelen);
136 		nvp->nvp_name[namelen] = '\0';
137 		nvp->nvp_type = type;
138 		nvp->nvp_data = data;
139 		nvp->nvp_datasize = datasize;
140 		nvp->nvp_nitems = nitems;
141 		nvp->nvp_magic = NVPAIR_MAGIC;
142 	}
143 
144 	return (nvp);
145 }
146 
147 static int
148 nvpair_append(nvpair_t *nvp, const void *value, size_t valsize, size_t datasize)
149 {
150 	void *olddata, *data, *valp;
151 	size_t oldlen;
152 
153 	oldlen = nvp->nvp_nitems * valsize;
154 	olddata = (void *)(uintptr_t)nvp->nvp_data;
155 	data = nv_realloc(olddata, oldlen + valsize);
156 	if (data == NULL) {
157 		ERRNO_SET(ENOMEM);
158 		return (-1);
159 	}
160 	valp = (unsigned char *)data + oldlen;
161 	memcpy(valp, value, valsize);
162 
163 	nvp->nvp_data = (uint64_t)(uintptr_t)data;
164 	nvp->nvp_datasize += datasize;
165 	nvp->nvp_nitems++;
166 	return (0);
167 }
168 
169 nvlist_t *
170 nvpair_nvlist(const nvpair_t *nvp)
171 {
172 
173 	NVPAIR_ASSERT(nvp);
174 
175 	return (nvp->nvp_list);
176 }
177 
178 nvpair_t *
179 nvpair_next(const nvpair_t *nvp)
180 {
181 
182 	NVPAIR_ASSERT(nvp);
183 	PJDLOG_ASSERT(nvp->nvp_list != NULL);
184 
185 	return (TAILQ_NEXT(nvp, nvp_next));
186 }
187 
188 nvpair_t *
189 nvpair_prev(const nvpair_t *nvp)
190 {
191 
192 	NVPAIR_ASSERT(nvp);
193 	PJDLOG_ASSERT(nvp->nvp_list != NULL);
194 
195 	return (TAILQ_PREV(nvp, nvl_head, nvp_next));
196 }
197 
198 void
199 nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
200 {
201 
202 	NVPAIR_ASSERT(nvp);
203 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
204 	PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 ||
205 	    !nvlist_exists(nvl, nvpair_name(nvp)));
206 
207 	TAILQ_INSERT_TAIL(head, nvp, nvp_next);
208 	nvp->nvp_list = nvl;
209 }
210 
211 static void
212 nvpair_remove_nvlist(nvpair_t *nvp)
213 {
214 	nvlist_t *nvl;
215 
216 	/* XXX: DECONST is bad, mkay? */
217 	nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
218 	PJDLOG_ASSERT(nvl != NULL);
219 	nvlist_set_parent(nvl, NULL);
220 }
221 
222 static void
223 nvpair_remove_nvlist_array(nvpair_t *nvp)
224 {
225 	nvlist_t **nvlarray;
226 	size_t count, i;
227 
228 	/* XXX: DECONST is bad, mkay? */
229 	nvlarray = __DECONST(nvlist_t **,
230 	    nvpair_get_nvlist_array(nvp, &count));
231 	for (i = 0; i < count; i++) {
232 		nvlist_set_array_next(nvlarray[i], NULL);
233 		nvlist_set_parent(nvlarray[i], NULL);
234 	}
235 }
236 
237 void
238 nvpair_remove(struct nvl_head *head, nvpair_t *nvp,
239     const nvlist_t *nvl __unused)
240 {
241 
242 	NVPAIR_ASSERT(nvp);
243 	PJDLOG_ASSERT(nvp->nvp_list == nvl);
244 
245 	if (nvpair_type(nvp) == NV_TYPE_NVLIST)
246 		nvpair_remove_nvlist(nvp);
247 	else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY)
248 		nvpair_remove_nvlist_array(nvp);
249 
250 	TAILQ_REMOVE(head, nvp, nvp_next);
251 	nvp->nvp_list = NULL;
252 }
253 
254 nvpair_t *
255 nvpair_clone(const nvpair_t *nvp)
256 {
257 	nvpair_t *newnvp;
258 	const char *name;
259 	const void *data;
260 	size_t datasize;
261 
262 	NVPAIR_ASSERT(nvp);
263 
264 	name = nvpair_name(nvp);
265 
266 	switch (nvpair_type(nvp)) {
267 	case NV_TYPE_NULL:
268 		newnvp = nvpair_create_null(name);
269 		break;
270 	case NV_TYPE_BOOL:
271 		newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
272 		break;
273 	case NV_TYPE_NUMBER:
274 		newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
275 		break;
276 	case NV_TYPE_STRING:
277 		newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
278 		break;
279 	case NV_TYPE_NVLIST:
280 		newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
281 		break;
282 	case NV_TYPE_BINARY:
283 		data = nvpair_get_binary(nvp, &datasize);
284 		newnvp = nvpair_create_binary(name, data, datasize);
285 		break;
286 	case NV_TYPE_BOOL_ARRAY:
287 		data = nvpair_get_bool_array(nvp, &datasize);
288 		newnvp = nvpair_create_bool_array(name, data, datasize);
289 		break;
290 	case NV_TYPE_NUMBER_ARRAY:
291 		data = nvpair_get_number_array(nvp, &datasize);
292 		newnvp = nvpair_create_number_array(name, data, datasize);
293 		break;
294 	case NV_TYPE_STRING_ARRAY:
295 		data = nvpair_get_string_array(nvp, &datasize);
296 		newnvp = nvpair_create_string_array(name, data, datasize);
297 		break;
298 	case NV_TYPE_NVLIST_ARRAY:
299 		data = nvpair_get_nvlist_array(nvp, &datasize);
300 		newnvp = nvpair_create_nvlist_array(name, data, datasize);
301 		break;
302 #ifndef _KERNEL
303 	case NV_TYPE_DESCRIPTOR:
304 		newnvp = nvpair_create_descriptor(name,
305 		    nvpair_get_descriptor(nvp));
306 		break;
307 	case NV_TYPE_DESCRIPTOR_ARRAY:
308 		data = nvpair_get_descriptor_array(nvp, &datasize);
309 		newnvp = nvpair_create_descriptor_array(name, data, datasize);
310 		break;
311 #endif
312 	default:
313 		PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
314 	}
315 
316 	return (newnvp);
317 }
318 
319 size_t
320 nvpair_header_size(void)
321 {
322 
323 	return (sizeof(struct nvpair_header));
324 }
325 
326 size_t
327 nvpair_size(const nvpair_t *nvp)
328 {
329 
330 	NVPAIR_ASSERT(nvp);
331 
332 	return (nvp->nvp_datasize);
333 }
334 
335 unsigned char *
336 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
337 {
338 	struct nvpair_header nvphdr;
339 	size_t namesize;
340 
341 	NVPAIR_ASSERT(nvp);
342 
343 	nvphdr.nvph_type = nvp->nvp_type;
344 	namesize = strlen(nvp->nvp_name) + 1;
345 	PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
346 	nvphdr.nvph_namesize = namesize;
347 	nvphdr.nvph_datasize = nvp->nvp_datasize;
348 	nvphdr.nvph_nitems = nvp->nvp_nitems;
349 	PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
350 	memcpy(ptr, &nvphdr, sizeof(nvphdr));
351 	ptr += sizeof(nvphdr);
352 	*leftp -= sizeof(nvphdr);
353 
354 	PJDLOG_ASSERT(*leftp >= namesize);
355 	memcpy(ptr, nvp->nvp_name, namesize);
356 	ptr += namesize;
357 	*leftp -= namesize;
358 
359 	return (ptr);
360 }
361 
362 unsigned char *
363 nvpair_pack_null(const nvpair_t *nvp __unused, unsigned char *ptr,
364     size_t *leftp __unused)
365 {
366 
367 	NVPAIR_ASSERT(nvp);
368 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
369 
370 	return (ptr);
371 }
372 
373 unsigned char *
374 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
375 {
376 	uint8_t value;
377 
378 	NVPAIR_ASSERT(nvp);
379 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
380 
381 	value = (uint8_t)nvp->nvp_data;
382 
383 	PJDLOG_ASSERT(*leftp >= sizeof(value));
384 	memcpy(ptr, &value, sizeof(value));
385 	ptr += sizeof(value);
386 	*leftp -= sizeof(value);
387 
388 	return (ptr);
389 }
390 
391 unsigned char *
392 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
393 {
394 	uint64_t value;
395 
396 	NVPAIR_ASSERT(nvp);
397 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
398 
399 	value = (uint64_t)nvp->nvp_data;
400 
401 	PJDLOG_ASSERT(*leftp >= sizeof(value));
402 	memcpy(ptr, &value, sizeof(value));
403 	ptr += sizeof(value);
404 	*leftp -= sizeof(value);
405 
406 	return (ptr);
407 }
408 
409 unsigned char *
410 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
411 {
412 
413 	NVPAIR_ASSERT(nvp);
414 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
415 
416 	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
417 	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
418 	ptr += nvp->nvp_datasize;
419 	*leftp -= nvp->nvp_datasize;
420 
421 	return (ptr);
422 }
423 
424 unsigned char *
425 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
426 {
427 	struct nvpair_header nvphdr;
428 	size_t namesize;
429 	const char *name = "";
430 
431 	namesize = 1;
432 	nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
433 	nvphdr.nvph_namesize = namesize;
434 	nvphdr.nvph_datasize = 0;
435 	nvphdr.nvph_nitems = 0;
436 	PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
437 	memcpy(ptr, &nvphdr, sizeof(nvphdr));
438 	ptr += sizeof(nvphdr);
439 	*leftp -= sizeof(nvphdr);
440 
441 	PJDLOG_ASSERT(*leftp >= namesize);
442 	memcpy(ptr, name, namesize);
443 	ptr += namesize;
444 	*leftp -= namesize;
445 
446 	return (ptr);
447 }
448 
449 unsigned char *
450 nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp)
451 {
452 	struct nvpair_header nvphdr;
453 	size_t namesize;
454 	const char *name = "";
455 
456 	namesize = 1;
457 	nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT;
458 	nvphdr.nvph_namesize = namesize;
459 	nvphdr.nvph_datasize = 0;
460 	nvphdr.nvph_nitems = 0;
461 	PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
462 	memcpy(ptr, &nvphdr, sizeof(nvphdr));
463 	ptr += sizeof(nvphdr);
464 	*leftp -= sizeof(nvphdr);
465 
466 	PJDLOG_ASSERT(*leftp >= namesize);
467 	memcpy(ptr, name, namesize);
468 	ptr += namesize;
469 	*leftp -= namesize;
470 
471 	return (ptr);
472 }
473 
474 #ifndef _KERNEL
475 unsigned char *
476 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
477     size_t *leftp)
478 {
479 	int64_t value;
480 
481 	NVPAIR_ASSERT(nvp);
482 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
483 
484 	value = (int64_t)nvp->nvp_data;
485 	if (value != -1) {
486 		/*
487 		 * If there is a real descriptor here, we change its number
488 		 * to position in the array of descriptors send via control
489 		 * message.
490 		 */
491 		PJDLOG_ASSERT(fdidxp != NULL);
492 
493 		value = *fdidxp;
494 		(*fdidxp)++;
495 	}
496 
497 	PJDLOG_ASSERT(*leftp >= sizeof(value));
498 	memcpy(ptr, &value, sizeof(value));
499 	ptr += sizeof(value);
500 	*leftp -= sizeof(value);
501 
502 	return (ptr);
503 }
504 #endif
505 
506 unsigned char *
507 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
508 {
509 
510 	NVPAIR_ASSERT(nvp);
511 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
512 
513 	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
514 	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
515 	ptr += nvp->nvp_datasize;
516 	*leftp -= nvp->nvp_datasize;
517 
518 	return (ptr);
519 }
520 
521 unsigned char *
522 nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
523 {
524 
525 	NVPAIR_ASSERT(nvp);
526 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
527 	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
528 
529 	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
530 	ptr += nvp->nvp_datasize;
531 	*leftp -= nvp->nvp_datasize;
532 
533 	return (ptr);
534 }
535 
536 unsigned char *
537 nvpair_pack_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
538 {
539 
540 	NVPAIR_ASSERT(nvp);
541 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
542 	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
543 
544 	memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
545 	ptr += nvp->nvp_datasize;
546 	*leftp -= nvp->nvp_datasize;
547 
548 	return (ptr);
549 }
550 
551 unsigned char *
552 nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
553 {
554 	unsigned int ii;
555 	size_t size, len;
556 	const char * const *array;
557 
558 	NVPAIR_ASSERT(nvp);
559 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
560 	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
561 
562 	size = 0;
563 	array = nvpair_get_string_array(nvp, NULL);
564 	PJDLOG_ASSERT(array != NULL);
565 
566 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
567 		len = strlen(array[ii]) + 1;
568 		PJDLOG_ASSERT(*leftp >= len);
569 
570 		memcpy(ptr, (const void *)array[ii], len);
571 		size += len;
572 		ptr += len;
573 		*leftp -= len;
574 	}
575 
576 	PJDLOG_ASSERT(size == nvp->nvp_datasize);
577 
578 	return (ptr);
579 }
580 
581 #ifndef _KERNEL
582 unsigned char *
583 nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr,
584     int64_t *fdidxp, size_t *leftp)
585 {
586 	int64_t value;
587 	const int *array;
588 	unsigned int ii;
589 
590 	NVPAIR_ASSERT(nvp);
591 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
592 	PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
593 
594 	array = nvpair_get_descriptor_array(nvp, NULL);
595 	PJDLOG_ASSERT(array != NULL);
596 
597 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
598 		PJDLOG_ASSERT(*leftp >= sizeof(value));
599 
600 		value = array[ii];
601 		if (value != -1) {
602 			/*
603 			 * If there is a real descriptor here, we change its
604 			 * number to position in the array of descriptors send
605 			 * via control message.
606 			 */
607 			PJDLOG_ASSERT(fdidxp != NULL);
608 
609 			value = *fdidxp;
610 			(*fdidxp)++;
611 		}
612 		memcpy(ptr, &value, sizeof(value));
613 		ptr += sizeof(value);
614 		*leftp -= sizeof(value);
615 	}
616 
617 	return (ptr);
618 }
619 #endif
620 
621 void
622 nvpair_init_datasize(nvpair_t *nvp)
623 {
624 
625 	NVPAIR_ASSERT(nvp);
626 
627 	if (nvp->nvp_type == NV_TYPE_NVLIST) {
628 		if (nvp->nvp_data == 0) {
629 			nvp->nvp_datasize = 0;
630 		} else {
631 			nvp->nvp_datasize =
632 			    nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
633 		}
634 	}
635 }
636 
637 const unsigned char *
638 nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
639     size_t *leftp)
640 {
641 	struct nvpair_header nvphdr;
642 
643 	if (*leftp < sizeof(nvphdr))
644 		goto fail;
645 
646 	memcpy(&nvphdr, ptr, sizeof(nvphdr));
647 	ptr += sizeof(nvphdr);
648 	*leftp -= sizeof(nvphdr);
649 
650 #if NV_TYPE_FIRST > 0
651 	if (nvphdr.nvph_type < NV_TYPE_FIRST)
652 		goto fail;
653 #endif
654 	if (nvphdr.nvph_type > NV_TYPE_LAST &&
655 	    nvphdr.nvph_type != NV_TYPE_NVLIST_UP &&
656 	    nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) {
657 		goto fail;
658 	}
659 
660 #if BYTE_ORDER == BIG_ENDIAN
661 	if (!isbe) {
662 		nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
663 		nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
664 	}
665 #else
666 	if (isbe) {
667 		nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
668 		nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
669 	}
670 #endif
671 
672 	if (nvphdr.nvph_namesize > NV_NAME_MAX)
673 		goto fail;
674 	if (*leftp < nvphdr.nvph_namesize)
675 		goto fail;
676 	if (nvphdr.nvph_namesize < 1)
677 		goto fail;
678 	if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
679 	    (size_t)(nvphdr.nvph_namesize - 1)) {
680 		goto fail;
681 	}
682 
683 	memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
684 	ptr += nvphdr.nvph_namesize;
685 	*leftp -= nvphdr.nvph_namesize;
686 
687 	if (*leftp < nvphdr.nvph_datasize)
688 		goto fail;
689 
690 	nvp->nvp_type = nvphdr.nvph_type;
691 	nvp->nvp_data = 0;
692 	nvp->nvp_datasize = nvphdr.nvph_datasize;
693 	nvp->nvp_nitems = nvphdr.nvph_nitems;
694 
695 	return (ptr);
696 fail:
697 	ERRNO_SET(EINVAL);
698 	return (NULL);
699 }
700 
701 const unsigned char *
702 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
703     size_t *leftp __unused)
704 {
705 
706 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
707 
708 	if (nvp->nvp_datasize != 0) {
709 		ERRNO_SET(EINVAL);
710 		return (NULL);
711 	}
712 
713 	return (ptr);
714 }
715 
716 const unsigned char *
717 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
718     size_t *leftp)
719 {
720 	uint8_t value;
721 
722 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
723 
724 	if (nvp->nvp_datasize != sizeof(value)) {
725 		ERRNO_SET(EINVAL);
726 		return (NULL);
727 	}
728 	if (*leftp < sizeof(value)) {
729 		ERRNO_SET(EINVAL);
730 		return (NULL);
731 	}
732 
733 	memcpy(&value, ptr, sizeof(value));
734 	ptr += sizeof(value);
735 	*leftp -= sizeof(value);
736 
737 	if (value != 0 && value != 1) {
738 		ERRNO_SET(EINVAL);
739 		return (NULL);
740 	}
741 
742 	nvp->nvp_data = (uint64_t)value;
743 
744 	return (ptr);
745 }
746 
747 const unsigned char *
748 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
749      size_t *leftp)
750 {
751 
752 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
753 
754 	if (nvp->nvp_datasize != sizeof(uint64_t)) {
755 		ERRNO_SET(EINVAL);
756 		return (NULL);
757 	}
758 	if (*leftp < sizeof(uint64_t)) {
759 		ERRNO_SET(EINVAL);
760 		return (NULL);
761 	}
762 
763 	if (isbe)
764 		nvp->nvp_data = be64dec(ptr);
765 	else
766 		nvp->nvp_data = le64dec(ptr);
767 
768 	ptr += sizeof(uint64_t);
769 	*leftp -= sizeof(uint64_t);
770 
771 	return (ptr);
772 }
773 
774 const unsigned char *
775 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
776     const unsigned char *ptr, size_t *leftp)
777 {
778 
779 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
780 
781 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
782 		ERRNO_SET(EINVAL);
783 		return (NULL);
784 	}
785 
786 	if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
787 	    nvp->nvp_datasize - 1) {
788 		ERRNO_SET(EINVAL);
789 		return (NULL);
790 	}
791 
792 	nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
793 	if (nvp->nvp_data == 0)
794 		return (NULL);
795 
796 	ptr += nvp->nvp_datasize;
797 	*leftp -= nvp->nvp_datasize;
798 
799 	return (ptr);
800 }
801 
802 const unsigned char *
803 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
804     const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
805 {
806 	nvlist_t *value;
807 
808 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
809 
810 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
811 		ERRNO_SET(EINVAL);
812 		return (NULL);
813 	}
814 
815 	value = nvlist_create(0);
816 	if (value == NULL)
817 		return (NULL);
818 
819 	ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
820 	if (ptr == NULL)
821 		return (NULL);
822 
823 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
824 	*child = value;
825 
826 	return (ptr);
827 }
828 
829 #ifndef _KERNEL
830 const unsigned char *
831 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
832     size_t *leftp, const int *fds, size_t nfds)
833 {
834 	int64_t idx;
835 
836 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
837 
838 	if (nvp->nvp_datasize != sizeof(idx)) {
839 		ERRNO_SET(EINVAL);
840 		return (NULL);
841 	}
842 	if (*leftp < sizeof(idx)) {
843 		ERRNO_SET(EINVAL);
844 		return (NULL);
845 	}
846 
847 	if (isbe)
848 		idx = be64dec(ptr);
849 	else
850 		idx = le64dec(ptr);
851 
852 	if (idx < 0) {
853 		ERRNO_SET(EINVAL);
854 		return (NULL);
855 	}
856 
857 	if ((size_t)idx >= nfds) {
858 		ERRNO_SET(EINVAL);
859 		return (NULL);
860 	}
861 
862 	nvp->nvp_data = (uint64_t)fds[idx];
863 
864 	ptr += sizeof(idx);
865 	*leftp -= sizeof(idx);
866 
867 	return (ptr);
868 }
869 #endif
870 
871 const unsigned char *
872 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
873     const unsigned char *ptr, size_t *leftp)
874 {
875 	void *value;
876 
877 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
878 
879 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
880 		ERRNO_SET(EINVAL);
881 		return (NULL);
882 	}
883 
884 	value = nv_malloc(nvp->nvp_datasize);
885 	if (value == NULL)
886 		return (NULL);
887 
888 	memcpy(value, ptr, nvp->nvp_datasize);
889 	ptr += nvp->nvp_datasize;
890 	*leftp -= nvp->nvp_datasize;
891 
892 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
893 
894 	return (ptr);
895 }
896 
897 const unsigned char *
898 nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp,
899     const unsigned char *ptr, size_t *leftp)
900 {
901 	uint8_t *value;
902 	size_t size;
903 	unsigned int i;
904 
905 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
906 
907 	size = sizeof(*value) * nvp->nvp_nitems;
908 	if (nvp->nvp_datasize != size || *leftp < size ||
909 	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
910 		ERRNO_SET(EINVAL);
911 		return (NULL);
912 	}
913 
914 	value = nv_malloc(size);
915 	if (value == NULL)
916 		return (NULL);
917 
918 	for (i = 0; i < nvp->nvp_nitems; i++) {
919 		value[i] = *(const uint8_t *)ptr;
920 
921 		ptr += sizeof(*value);
922 		*leftp -= sizeof(*value);
923 	}
924 
925 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
926 
927 	return (ptr);
928 }
929 
930 const unsigned char *
931 nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
932      size_t *leftp)
933 {
934 	uint64_t *value;
935 	size_t size;
936 	unsigned int i;
937 
938 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
939 
940 	size = sizeof(*value) * nvp->nvp_nitems;
941 	if (nvp->nvp_datasize != size || *leftp < size ||
942 	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
943 		ERRNO_SET(EINVAL);
944 		return (NULL);
945 	}
946 
947 	value = nv_malloc(size);
948 	if (value == NULL)
949 		return (NULL);
950 
951 	for (i = 0; i < nvp->nvp_nitems; i++) {
952 		if (isbe)
953 			value[i] = be64dec(ptr);
954 		else
955 			value[i] = le64dec(ptr);
956 
957 		ptr += sizeof(*value);
958 		*leftp -= sizeof(*value);
959 	}
960 
961 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
962 
963 	return (ptr);
964 }
965 
966 const unsigned char *
967 nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp,
968     const unsigned char *ptr, size_t *leftp)
969 {
970 	ssize_t size;
971 	size_t len;
972 	const char *tmp;
973 	char **value;
974 	unsigned int ii, j;
975 
976 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
977 
978 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 ||
979 	    nvp->nvp_nitems == 0) {
980 		ERRNO_SET(EINVAL);
981 		return (NULL);
982 	}
983 
984 	size = nvp->nvp_datasize;
985 	tmp = (const char *)ptr;
986 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
987 		len = strnlen(tmp, size - 1) + 1;
988 		size -= len;
989 		if (size < 0) {
990 			ERRNO_SET(EINVAL);
991 			return (NULL);
992 		}
993 		tmp += len;
994 	}
995 	if (size != 0) {
996 		ERRNO_SET(EINVAL);
997 		return (NULL);
998 	}
999 
1000 	value = nv_malloc(sizeof(*value) * nvp->nvp_nitems);
1001 	if (value == NULL)
1002 		return (NULL);
1003 
1004 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1005 		value[ii] = nv_strdup((const char *)ptr);
1006 		if (value[ii] == NULL)
1007 			goto out;
1008 		len = strlen(value[ii]) + 1;
1009 		ptr += len;
1010 		*leftp -= len;
1011 	}
1012 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
1013 
1014 	return (ptr);
1015 out:
1016 	for (j = 0; j < ii; j++)
1017 		nv_free(value[j]);
1018 	nv_free(value);
1019 	return (NULL);
1020 }
1021 
1022 #ifndef _KERNEL
1023 const unsigned char *
1024 nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
1025     const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
1026 {
1027 	int64_t idx;
1028 	size_t size;
1029 	unsigned int ii;
1030 	int *array;
1031 
1032 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1033 
1034 	size = sizeof(idx) * nvp->nvp_nitems;
1035 	if (nvp->nvp_datasize != size || *leftp < size ||
1036 	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
1037 		ERRNO_SET(EINVAL);
1038 		return (NULL);
1039 	}
1040 
1041 	array = (int *)nv_malloc(size);
1042 	if (array == NULL)
1043 		return (NULL);
1044 
1045 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1046 		if (isbe)
1047 			idx = be64dec(ptr);
1048 		else
1049 			idx = le64dec(ptr);
1050 
1051 		if (idx < 0) {
1052 			ERRNO_SET(EINVAL);
1053 			nv_free(array);
1054 			return (NULL);
1055 		}
1056 
1057 		if ((size_t)idx >= nfds) {
1058 			ERRNO_SET(EINVAL);
1059 			nv_free(array);
1060 			return (NULL);
1061 		}
1062 
1063 		array[ii] = (uint64_t)fds[idx];
1064 
1065 		ptr += sizeof(idx);
1066 		*leftp -= sizeof(idx);
1067 	}
1068 
1069 	nvp->nvp_data = (uint64_t)(uintptr_t)array;
1070 
1071 	return (ptr);
1072 }
1073 #endif
1074 
1075 const unsigned char *
1076 nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
1077     const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
1078 {
1079 	nvlist_t **value;
1080 	nvpair_t *tmpnvp;
1081 	unsigned int ii, j;
1082 	size_t sizeup;
1083 
1084 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1085 
1086 	sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
1087 	if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
1088 	    sizeup > *leftp) {
1089 		ERRNO_SET(EINVAL);
1090 		return (NULL);
1091 	}
1092 
1093 	value = nv_malloc(nvp->nvp_nitems * sizeof(*value));
1094 	if (value == NULL)
1095 		return (NULL);
1096 
1097 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1098 		value[ii] = nvlist_create(0);
1099 		if (value[ii] == NULL)
1100 			goto fail;
1101 		if (ii > 0) {
1102 			tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1103 			    (uint64_t)(uintptr_t)value[ii], 0, 0);
1104 			if (tmpnvp == NULL)
1105 				goto fail;
1106 			nvlist_set_array_next(value[ii - 1], tmpnvp);
1107 		}
1108 	}
1109 	nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
1110 
1111 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
1112 	*firstel = value[0];
1113 
1114 	return (ptr);
1115 fail:
1116 	ERRNO_SAVE();
1117 	for (j = 0; j <= ii; j++)
1118 		nvlist_destroy(value[j]);
1119 	nv_free(value);
1120 	ERRNO_RESTORE();
1121 
1122 	return (NULL);
1123 }
1124 
1125 const unsigned char *
1126 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
1127     nvpair_t **nvpp)
1128 {
1129 	nvpair_t *nvp, *tmp;
1130 
1131 	nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
1132 	if (nvp == NULL)
1133 		return (NULL);
1134 	nvp->nvp_name = (char *)(nvp + 1);
1135 
1136 	ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
1137 	if (ptr == NULL)
1138 		goto fail;
1139 	tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
1140 	if (tmp == NULL)
1141 		goto fail;
1142 	nvp = tmp;
1143 
1144 	/* Update nvp_name after realloc(). */
1145 	nvp->nvp_name = (char *)(nvp + 1);
1146 	nvp->nvp_data = 0x00;
1147 	nvp->nvp_magic = NVPAIR_MAGIC;
1148 	*nvpp = nvp;
1149 	return (ptr);
1150 fail:
1151 	nv_free(nvp);
1152 	return (NULL);
1153 }
1154 
1155 int
1156 nvpair_type(const nvpair_t *nvp)
1157 {
1158 
1159 	NVPAIR_ASSERT(nvp);
1160 
1161 	return (nvp->nvp_type);
1162 }
1163 
1164 const char *
1165 nvpair_name(const nvpair_t *nvp)
1166 {
1167 
1168 	NVPAIR_ASSERT(nvp);
1169 
1170 	return (nvp->nvp_name);
1171 }
1172 
1173 nvpair_t *
1174 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
1175 {
1176 	va_list valueap;
1177 	nvpair_t *nvp;
1178 
1179 	va_start(valueap, valuefmt);
1180 	nvp = nvpair_create_stringv(name, valuefmt, valueap);
1181 	va_end(valueap);
1182 
1183 	return (nvp);
1184 }
1185 
1186 nvpair_t *
1187 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
1188 {
1189 	nvpair_t *nvp;
1190 	char *str;
1191 	int len;
1192 
1193 	len = nv_vasprintf(&str, valuefmt, valueap);
1194 	if (len < 0)
1195 		return (NULL);
1196 	nvp = nvpair_create_string(name, str);
1197 	nv_free(str);
1198 	return (nvp);
1199 }
1200 
1201 nvpair_t *
1202 nvpair_create_null(const char *name)
1203 {
1204 
1205 	return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1206 }
1207 
1208 nvpair_t *
1209 nvpair_create_bool(const char *name, bool value)
1210 {
1211 
1212 	return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1213 	    sizeof(uint8_t), 0));
1214 }
1215 
1216 nvpair_t *
1217 nvpair_create_number(const char *name, uint64_t value)
1218 {
1219 
1220 	return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1221 }
1222 
1223 nvpair_t *
1224 nvpair_create_string(const char *name, const char *value)
1225 {
1226 	nvpair_t *nvp;
1227 	size_t size;
1228 	char *data;
1229 
1230 	if (value == NULL) {
1231 		ERRNO_SET(EINVAL);
1232 		return (NULL);
1233 	}
1234 
1235 	data = nv_strdup(value);
1236 	if (data == NULL)
1237 		return (NULL);
1238 	size = strlen(value) + 1;
1239 
1240 	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1241 	    size, 0);
1242 	if (nvp == NULL)
1243 		nv_free(data);
1244 
1245 	return (nvp);
1246 }
1247 
1248 nvpair_t *
1249 nvpair_create_nvlist(const char *name, const nvlist_t *value)
1250 {
1251 	nvlist_t *nvl;
1252 	nvpair_t *nvp;
1253 
1254 	if (value == NULL) {
1255 		ERRNO_SET(EINVAL);
1256 		return (NULL);
1257 	}
1258 
1259 	nvl = nvlist_clone(value);
1260 	if (nvl == NULL)
1261 		return (NULL);
1262 
1263 	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1264 	    0);
1265 	if (nvp == NULL)
1266 		nvlist_destroy(nvl);
1267 	else
1268 		nvlist_set_parent(nvl, nvp);
1269 
1270 	return (nvp);
1271 }
1272 
1273 #ifndef _KERNEL
1274 nvpair_t *
1275 nvpair_create_descriptor(const char *name, int value)
1276 {
1277 	nvpair_t *nvp;
1278 
1279 	value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1280 	if (value < 0)
1281 		return (NULL);
1282 
1283 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1284 	    sizeof(int64_t), 0);
1285 	if (nvp == NULL) {
1286 		ERRNO_SAVE();
1287 		close(value);
1288 		ERRNO_RESTORE();
1289 	}
1290 
1291 	return (nvp);
1292 }
1293 #endif
1294 
1295 nvpair_t *
1296 nvpair_create_binary(const char *name, const void *value, size_t size)
1297 {
1298 	nvpair_t *nvp;
1299 	void *data;
1300 
1301 	if (value == NULL || size == 0) {
1302 		ERRNO_SET(EINVAL);
1303 		return (NULL);
1304 	}
1305 
1306 	data = nv_malloc(size);
1307 	if (data == NULL)
1308 		return (NULL);
1309 	memcpy(data, value, size);
1310 
1311 	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1312 	    size, 0);
1313 	if (nvp == NULL)
1314 		nv_free(data);
1315 
1316 	return (nvp);
1317 }
1318 
1319 nvpair_t *
1320 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1321 {
1322 	nvpair_t *nvp;
1323 	size_t size;
1324 	void *data;
1325 
1326 	if (value == NULL || nitems == 0) {
1327 		ERRNO_SET(EINVAL);
1328 		return (NULL);
1329 	}
1330 
1331 	size = sizeof(value[0]) * nitems;
1332 	data = nv_malloc(size);
1333 	if (data == NULL)
1334 		return (NULL);
1335 
1336 	memcpy(data, value, size);
1337 	nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1338 	    size, nitems);
1339 	if (nvp == NULL) {
1340 		ERRNO_SAVE();
1341 		nv_free(data);
1342 		ERRNO_RESTORE();
1343 	}
1344 
1345 	return (nvp);
1346 }
1347 
1348 nvpair_t *
1349 nvpair_create_number_array(const char *name, const uint64_t *value,
1350     size_t nitems)
1351 {
1352 	nvpair_t *nvp;
1353 	size_t size;
1354 	void *data;
1355 
1356 	if (value == NULL || nitems == 0) {
1357 		ERRNO_SET(EINVAL);
1358 		return (NULL);
1359 	}
1360 
1361 	size = sizeof(value[0]) * nitems;
1362 	data = nv_malloc(size);
1363 	if (data == NULL)
1364 		return (NULL);
1365 
1366 	memcpy(data, value, size);
1367 	nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1368 	    (uint64_t)(uintptr_t)data, size, nitems);
1369 	if (nvp == NULL) {
1370 		ERRNO_SAVE();
1371 		nv_free(data);
1372 		ERRNO_RESTORE();
1373 	}
1374 
1375 	return (nvp);
1376 }
1377 
1378 nvpair_t *
1379 nvpair_create_string_array(const char *name, const char * const *value,
1380     size_t nitems)
1381 {
1382 	nvpair_t *nvp;
1383 	unsigned int ii;
1384 	size_t datasize, size;
1385 	char **data;
1386 
1387 	if (value == NULL || nitems == 0) {
1388 		ERRNO_SET(EINVAL);
1389 		return (NULL);
1390 	}
1391 
1392 	nvp = NULL;
1393 	datasize = 0;
1394 	data = nv_malloc(sizeof(value[0]) * nitems);
1395 	if (data == NULL)
1396 		return (NULL);
1397 
1398 	for (ii = 0; ii < nitems; ii++) {
1399 		if (value[ii] == NULL) {
1400 			ERRNO_SET(EINVAL);
1401 			goto fail;
1402 		}
1403 
1404 		size = strlen(value[ii]) + 1;
1405 		datasize += size;
1406 		data[ii] = nv_strdup(value[ii]);
1407 		if (data[ii] == NULL)
1408 			goto fail;
1409 	}
1410 	nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1411 	    (uint64_t)(uintptr_t)data, datasize, nitems);
1412 
1413 fail:
1414 	if (nvp == NULL) {
1415 		ERRNO_SAVE();
1416 		for (; ii > 0; ii--)
1417 			nv_free(data[ii - 1]);
1418 		nv_free(data);
1419 		ERRNO_RESTORE();
1420 	}
1421 
1422 	return (nvp);
1423 }
1424 
1425 nvpair_t *
1426 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1427     size_t nitems)
1428 {
1429 	unsigned int ii;
1430 	nvlist_t **nvls;
1431 	nvpair_t *parent;
1432 	int flags;
1433 
1434 	nvls = NULL;
1435 
1436 	if (value == NULL || nitems == 0) {
1437 		ERRNO_SET(EINVAL);
1438 		return (NULL);
1439 	}
1440 
1441 	nvls = nv_malloc(sizeof(value[0]) * nitems);
1442 	if (nvls == NULL)
1443 		return (NULL);
1444 
1445 	for (ii = 0; ii < nitems; ii++) {
1446 		if (value[ii] == NULL) {
1447 			ERRNO_SET(EINVAL);
1448 			goto fail;
1449 		}
1450 
1451 		nvls[ii] = nvlist_clone(value[ii]);
1452 		if (nvls[ii] == NULL)
1453 			goto fail;
1454 
1455 		if (ii > 0) {
1456 			nvpair_t *nvp;
1457 
1458 			nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1459 			    (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1460 			if (nvp == NULL) {
1461 				ERRNO_SAVE();
1462 				nvlist_destroy(nvls[ii]);
1463 				ERRNO_RESTORE();
1464 				goto fail;
1465 			}
1466 			nvlist_set_array_next(nvls[ii - 1], nvp);
1467 		}
1468 	}
1469 	flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1470 	nvlist_set_flags(nvls[nitems - 1], flags);
1471 
1472 	parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1473 	    (uint64_t)(uintptr_t)nvls, 0, nitems);
1474 	if (parent == NULL)
1475 		goto fail;
1476 
1477 	for (ii = 0; ii < nitems; ii++)
1478 		nvlist_set_parent(nvls[ii], parent);
1479 
1480 	return (parent);
1481 
1482 fail:
1483 	ERRNO_SAVE();
1484 	for (; ii > 0; ii--)
1485 		nvlist_destroy(nvls[ii - 1]);
1486 	nv_free(nvls);
1487 	ERRNO_RESTORE();
1488 
1489 	return (NULL);
1490 }
1491 
1492 #ifndef _KERNEL
1493 nvpair_t *
1494 nvpair_create_descriptor_array(const char *name, const int *value,
1495     size_t nitems)
1496 {
1497 	unsigned int ii;
1498 	nvpair_t *nvp;
1499 	int *fds;
1500 
1501 	if (value == NULL) {
1502 		ERRNO_SET(EINVAL);
1503 		return (NULL);
1504 	}
1505 
1506 	nvp = NULL;
1507 
1508 	fds = nv_malloc(sizeof(value[0]) * nitems);
1509 	if (fds == NULL)
1510 		return (NULL);
1511 	for (ii = 0; ii < nitems; ii++) {
1512 		if (value[ii] == -1) {
1513 			fds[ii] = -1;
1514 		} else {
1515 			fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1516 			if (fds[ii] == -1)
1517 				goto fail;
1518 		}
1519 	}
1520 
1521 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1522 	    (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1523 
1524 fail:
1525 	if (nvp == NULL) {
1526 		ERRNO_SAVE();
1527 		for (; ii > 0; ii--) {
1528 			if (fds[ii - 1] != -1)
1529 				close(fds[ii - 1]);
1530 		}
1531 		nv_free(fds);
1532 		ERRNO_RESTORE();
1533 	}
1534 
1535 	return (nvp);
1536 }
1537 #endif
1538 
1539 nvpair_t *
1540 nvpair_move_string(const char *name, char *value)
1541 {
1542 	nvpair_t *nvp;
1543 
1544 	if (value == NULL) {
1545 		ERRNO_SET(EINVAL);
1546 		return (NULL);
1547 	}
1548 
1549 	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1550 	    strlen(value) + 1, 0);
1551 	if (nvp == NULL) {
1552 		ERRNO_SAVE();
1553 		nv_free(value);
1554 		ERRNO_RESTORE();
1555 	}
1556 
1557 	return (nvp);
1558 }
1559 
1560 nvpair_t *
1561 nvpair_move_nvlist(const char *name, nvlist_t *value)
1562 {
1563 	nvpair_t *nvp;
1564 
1565 	if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1566 		ERRNO_SET(EINVAL);
1567 		return (NULL);
1568 	}
1569 
1570 	if (nvlist_error(value) != 0) {
1571 		ERRNO_SET(nvlist_error(value));
1572 		nvlist_destroy(value);
1573 		return (NULL);
1574 	}
1575 
1576 	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1577 	    0, 0);
1578 	if (nvp == NULL)
1579 		nvlist_destroy(value);
1580 	else
1581 		nvlist_set_parent(value, nvp);
1582 
1583 	return (nvp);
1584 }
1585 
1586 #ifndef _KERNEL
1587 nvpair_t *
1588 nvpair_move_descriptor(const char *name, int value)
1589 {
1590 	nvpair_t *nvp;
1591 
1592 	if (value < 0 || !fd_is_valid(value)) {
1593 		ERRNO_SET(EBADF);
1594 		return (NULL);
1595 	}
1596 
1597 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1598 	    sizeof(int64_t), 0);
1599 	if (nvp == NULL) {
1600 		ERRNO_SAVE();
1601 		close(value);
1602 		ERRNO_RESTORE();
1603 	}
1604 
1605 	return (nvp);
1606 }
1607 #endif
1608 
1609 nvpair_t *
1610 nvpair_move_binary(const char *name, void *value, size_t size)
1611 {
1612 	nvpair_t *nvp;
1613 
1614 	if (value == NULL || size == 0) {
1615 		ERRNO_SET(EINVAL);
1616 		return (NULL);
1617 	}
1618 
1619 	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1620 	    size, 0);
1621 	if (nvp == NULL) {
1622 		ERRNO_SAVE();
1623 		nv_free(value);
1624 		ERRNO_RESTORE();
1625 	}
1626 
1627 	return (nvp);
1628 }
1629 
1630 nvpair_t *
1631 nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1632 {
1633 	nvpair_t *nvp;
1634 
1635 	if (value == NULL || nitems == 0) {
1636 		ERRNO_SET(EINVAL);
1637 		return (NULL);
1638 	}
1639 
1640 	nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1641 	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1642 	if (nvp == NULL) {
1643 		ERRNO_SAVE();
1644 		nv_free(value);
1645 		ERRNO_RESTORE();
1646 	}
1647 
1648 	return (nvp);
1649 }
1650 
1651 nvpair_t *
1652 nvpair_move_string_array(const char *name, char **value, size_t nitems)
1653 {
1654 	nvpair_t *nvp;
1655 	size_t i, size;
1656 
1657 	if (value == NULL || nitems == 0) {
1658 		ERRNO_SET(EINVAL);
1659 		return (NULL);
1660 	}
1661 
1662 	size = 0;
1663 	for (i = 0; i < nitems; i++) {
1664 		if (value[i] == NULL) {
1665 			ERRNO_SET(EINVAL);
1666 			return (NULL);
1667 		}
1668 
1669 		size += strlen(value[i]) + 1;
1670 	}
1671 
1672 	nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1673 	    (uint64_t)(uintptr_t)value, size, nitems);
1674 	if (nvp == NULL) {
1675 		ERRNO_SAVE();
1676 		for (i = 0; i < nitems; i++)
1677 			nv_free(value[i]);
1678 		nv_free(value);
1679 		ERRNO_RESTORE();
1680 	}
1681 
1682 	return (nvp);
1683 }
1684 
1685 nvpair_t *
1686 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1687 {
1688 	nvpair_t *nvp;
1689 
1690 	if (value == NULL || nitems == 0) {
1691 		ERRNO_SET(EINVAL);
1692 		return (NULL);
1693 	}
1694 
1695 	nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1696 	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1697 	if (nvp == NULL) {
1698 		ERRNO_SAVE();
1699 		nv_free(value);
1700 		ERRNO_RESTORE();
1701 	}
1702 
1703 	return (nvp);
1704 }
1705 
1706 nvpair_t *
1707 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1708 {
1709 	nvpair_t *parent;
1710 	unsigned int ii;
1711 	int flags;
1712 
1713 	if (value == NULL || nitems == 0) {
1714 		ERRNO_SET(EINVAL);
1715 		return (NULL);
1716 	}
1717 
1718 	for (ii = 0; ii < nitems; ii++) {
1719 		if (value == NULL || nvlist_error(value[ii]) != 0 ||
1720 		    nvlist_get_pararr(value[ii], NULL) != NULL) {
1721 			ERRNO_SET(EINVAL);
1722 			goto fail;
1723 		}
1724 		if (ii > 0) {
1725 			nvpair_t *nvp;
1726 
1727 			nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1728 			    (uint64_t)(uintptr_t)value[ii], 0, 0);
1729 			if (nvp == NULL)
1730 				goto fail;
1731 			nvlist_set_array_next(value[ii - 1], nvp);
1732 		}
1733 	}
1734 	flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1735 	nvlist_set_flags(value[nitems - 1], flags);
1736 
1737 	parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1738 	    (uint64_t)(uintptr_t)value, 0, nitems);
1739 	if (parent == NULL)
1740 		goto fail;
1741 
1742 	for (ii = 0; ii < nitems; ii++)
1743 		nvlist_set_parent(value[ii], parent);
1744 
1745 	return (parent);
1746 fail:
1747 	ERRNO_SAVE();
1748 	for (ii = 0; ii < nitems; ii++) {
1749 		if (value[ii] != NULL &&
1750 		    nvlist_get_pararr(value[ii], NULL) != NULL) {
1751 			nvlist_destroy(value[ii]);
1752 		}
1753 	}
1754 	nv_free(value);
1755 	ERRNO_RESTORE();
1756 
1757 	return (NULL);
1758 }
1759 
1760 #ifndef _KERNEL
1761 nvpair_t *
1762 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1763 {
1764 	nvpair_t *nvp;
1765 	size_t i;
1766 
1767 	if (value == NULL || nitems == 0) {
1768 		ERRNO_SET(EINVAL);
1769 		return (NULL);
1770 	}
1771 
1772 	for (i = 0; i < nitems; i++) {
1773 		if (value[i] != -1 && !fd_is_valid(value[i])) {
1774 			ERRNO_SET(EBADF);
1775 			goto fail;
1776 		}
1777 	}
1778 
1779 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1780 	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1781 	if (nvp == NULL)
1782 		goto fail;
1783 
1784 	return (nvp);
1785 fail:
1786 	ERRNO_SAVE();
1787 	for (i = 0; i < nitems; i++) {
1788 		if (fd_is_valid(value[i]))
1789 			close(value[i]);
1790 	}
1791 	nv_free(value);
1792 	ERRNO_RESTORE();
1793 
1794 	return (NULL);
1795 }
1796 #endif
1797 
1798 bool
1799 nvpair_get_bool(const nvpair_t *nvp)
1800 {
1801 
1802 	NVPAIR_ASSERT(nvp);
1803 
1804 	return (nvp->nvp_data == 1);
1805 }
1806 
1807 uint64_t
1808 nvpair_get_number(const nvpair_t *nvp)
1809 {
1810 
1811 	NVPAIR_ASSERT(nvp);
1812 
1813 	return (nvp->nvp_data);
1814 }
1815 
1816 const char *
1817 nvpair_get_string(const nvpair_t *nvp)
1818 {
1819 
1820 	NVPAIR_ASSERT(nvp);
1821 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1822 
1823 	return ((const char *)(intptr_t)nvp->nvp_data);
1824 }
1825 
1826 const nvlist_t *
1827 nvpair_get_nvlist(const nvpair_t *nvp)
1828 {
1829 
1830 	NVPAIR_ASSERT(nvp);
1831 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1832 
1833 	return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1834 }
1835 
1836 #ifndef _KERNEL
1837 int
1838 nvpair_get_descriptor(const nvpair_t *nvp)
1839 {
1840 
1841 	NVPAIR_ASSERT(nvp);
1842 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1843 
1844 	return ((int)nvp->nvp_data);
1845 }
1846 #endif
1847 
1848 const void *
1849 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1850 {
1851 
1852 	NVPAIR_ASSERT(nvp);
1853 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1854 
1855 	if (sizep != NULL)
1856 		*sizep = nvp->nvp_datasize;
1857 
1858 	return ((const void *)(intptr_t)nvp->nvp_data);
1859 }
1860 
1861 const bool *
1862 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1863 {
1864 
1865 	NVPAIR_ASSERT(nvp);
1866 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1867 
1868 	if (nitems != NULL)
1869 		*nitems = nvp->nvp_nitems;
1870 
1871 	return ((const bool *)(intptr_t)nvp->nvp_data);
1872 }
1873 
1874 const uint64_t *
1875 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1876 {
1877 
1878 	NVPAIR_ASSERT(nvp);
1879 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1880 
1881 	if (nitems != NULL)
1882 		*nitems = nvp->nvp_nitems;
1883 
1884 	return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1885 }
1886 
1887 const char * const *
1888 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1889 {
1890 
1891 	NVPAIR_ASSERT(nvp);
1892 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1893 
1894 	if (nitems != NULL)
1895 		*nitems = nvp->nvp_nitems;
1896 
1897 	return ((const char * const *)(intptr_t)nvp->nvp_data);
1898 }
1899 
1900 const nvlist_t * const *
1901 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1902 {
1903 
1904 	NVPAIR_ASSERT(nvp);
1905 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1906 
1907 	if (nitems != NULL)
1908 		*nitems = nvp->nvp_nitems;
1909 
1910 	return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1911 }
1912 
1913 #ifndef _KERNEL
1914 const int *
1915 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1916 {
1917 
1918 	NVPAIR_ASSERT(nvp);
1919 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1920 
1921 	if (nitems != NULL)
1922 		*nitems = nvp->nvp_nitems;
1923 
1924 	return ((const int *)(intptr_t)nvp->nvp_data);
1925 }
1926 #endif
1927 
1928 int
1929 nvpair_append_bool_array(nvpair_t *nvp, const bool value)
1930 {
1931 
1932 	NVPAIR_ASSERT(nvp);
1933 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1934 	return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1935 }
1936 
1937 int
1938 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
1939 {
1940 
1941 	NVPAIR_ASSERT(nvp);
1942 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1943 	return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1944 }
1945 
1946 int
1947 nvpair_append_string_array(nvpair_t *nvp, const char *value)
1948 {
1949 	char *str;
1950 
1951 	NVPAIR_ASSERT(nvp);
1952 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1953 	if (value == NULL) {
1954 		ERRNO_SET(EINVAL);
1955 		return (-1);
1956 	}
1957 	str = nv_strdup(value);
1958 	if (str == NULL) {
1959 		return (-1);
1960 	}
1961 	if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
1962 		nv_free(str);
1963 		return (-1);
1964 	}
1965 	return (0);
1966 }
1967 
1968 int
1969 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
1970 {
1971 	nvpair_t *tmpnvp;
1972 	nvlist_t *nvl, *prev;
1973 	int flags;
1974 
1975 	NVPAIR_ASSERT(nvp);
1976 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1977 	if (value == NULL || nvlist_error(value) != 0 ||
1978 	    nvlist_get_pararr(value, NULL) != NULL) {
1979 		ERRNO_SET(EINVAL);
1980 		return (-1);
1981 	}
1982 	nvl = nvlist_clone(value);
1983 	if (nvl == NULL) {
1984 		return (-1);
1985 	}
1986 	flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
1987 	nvlist_set_flags(nvl, flags);
1988 
1989 	tmpnvp = NULL;
1990 	prev = NULL;
1991 	if (nvp->nvp_nitems > 0) {
1992 		nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
1993 
1994 		prev = nvls[nvp->nvp_nitems - 1];
1995 		PJDLOG_ASSERT(prev != NULL);
1996 
1997 		tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1998 		    (uint64_t)(uintptr_t)nvl, 0, 0);
1999 		if (tmpnvp == NULL) {
2000 			goto fail;
2001 		}
2002 	}
2003 	if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
2004 		goto fail;
2005 	}
2006 	if (tmpnvp) {
2007 		NVPAIR_ASSERT(tmpnvp);
2008 		nvlist_set_array_next(prev, tmpnvp);
2009 	}
2010 	nvlist_set_parent(nvl, nvp);
2011 	return (0);
2012 fail:
2013 	if (tmpnvp) {
2014 		nvpair_free(tmpnvp);
2015 	}
2016 	nvlist_destroy(nvl);
2017 	return (-1);
2018 }
2019 
2020 #ifndef _KERNEL
2021 int
2022 nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
2023 {
2024 	int fd;
2025 
2026 	NVPAIR_ASSERT(nvp);
2027 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
2028 	fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
2029 	if (fd == -1) {
2030 		return (-1);
2031 	}
2032 	if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
2033 		close(fd);
2034 		return (-1);
2035 	}
2036 	return (0);
2037 }
2038 #endif
2039 
2040 void
2041 nvpair_free(nvpair_t *nvp)
2042 {
2043 	size_t i;
2044 
2045 	NVPAIR_ASSERT(nvp);
2046 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
2047 
2048 	nvp->nvp_magic = 0;
2049 	switch (nvp->nvp_type) {
2050 #ifndef _KERNEL
2051 	case NV_TYPE_DESCRIPTOR:
2052 		close((int)nvp->nvp_data);
2053 		break;
2054 	case NV_TYPE_DESCRIPTOR_ARRAY:
2055 		for (i = 0; i < nvp->nvp_nitems; i++)
2056 			close(((int *)(intptr_t)nvp->nvp_data)[i]);
2057 		nv_free((int *)(intptr_t)nvp->nvp_data);
2058 		break;
2059 #endif
2060 	case NV_TYPE_NVLIST:
2061 		nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
2062 		break;
2063 	case NV_TYPE_STRING:
2064 		nv_free((char *)(intptr_t)nvp->nvp_data);
2065 		break;
2066 	case NV_TYPE_BINARY:
2067 		nv_free((void *)(intptr_t)nvp->nvp_data);
2068 		break;
2069 	case NV_TYPE_NVLIST_ARRAY:
2070 		for (i = 0; i < nvp->nvp_nitems; i++) {
2071 			nvlist_destroy(
2072 			    ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
2073 		}
2074 		nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
2075 		break;
2076 	case NV_TYPE_NUMBER_ARRAY:
2077 		nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
2078 		break;
2079 	case NV_TYPE_BOOL_ARRAY:
2080 		nv_free((bool *)(intptr_t)nvp->nvp_data);
2081 		break;
2082 	case NV_TYPE_STRING_ARRAY:
2083 		for (i = 0; i < nvp->nvp_nitems; i++)
2084 			nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
2085 		nv_free((char **)(intptr_t)nvp->nvp_data);
2086 		break;
2087 	}
2088 	nv_free(nvp);
2089 }
2090 
2091 void
2092 nvpair_free_structure(nvpair_t *nvp)
2093 {
2094 
2095 	NVPAIR_ASSERT(nvp);
2096 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
2097 
2098 	nvp->nvp_magic = 0;
2099 	nv_free(nvp);
2100 }
2101 
2102 const char *
2103 nvpair_type_string(int type)
2104 {
2105 
2106 	switch (type) {
2107 	case NV_TYPE_NULL:
2108 		return ("NULL");
2109 	case NV_TYPE_BOOL:
2110 		return ("BOOL");
2111 	case NV_TYPE_NUMBER:
2112 		return ("NUMBER");
2113 	case NV_TYPE_STRING:
2114 		return ("STRING");
2115 	case NV_TYPE_NVLIST:
2116 		return ("NVLIST");
2117 	case NV_TYPE_DESCRIPTOR:
2118 		return ("DESCRIPTOR");
2119 	case NV_TYPE_BINARY:
2120 		return ("BINARY");
2121 	case NV_TYPE_BOOL_ARRAY:
2122 		return ("BOOL ARRAY");
2123 	case NV_TYPE_NUMBER_ARRAY:
2124 		return ("NUMBER ARRAY");
2125 	case NV_TYPE_STRING_ARRAY:
2126 		return ("STRING ARRAY");
2127 	case NV_TYPE_NVLIST_ARRAY:
2128 		return ("NVLIST ARRAY");
2129 	case NV_TYPE_DESCRIPTOR_ARRAY:
2130 		return ("DESCRIPTOR ARRAY");
2131 	default:
2132 		return ("<UNKNOWN>");
2133 	}
2134 }
2135 
2136