xref: /freebsd/sys/contrib/libnv/bsd_nvpair.c (revision 716fd348)
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 __unused, 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 		nvphdr.nvph_nitems = le64toh(nvphdr.nvph_nitems);
665 	}
666 #else
667 	if (isbe) {
668 		nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
669 		nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
670 		nvphdr.nvph_nitems = be64toh(nvphdr.nvph_nitems);
671 	}
672 #endif
673 
674 	if (nvphdr.nvph_namesize > NV_NAME_MAX)
675 		goto fail;
676 	if (*leftp < nvphdr.nvph_namesize)
677 		goto fail;
678 	if (nvphdr.nvph_namesize < 1)
679 		goto fail;
680 	if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
681 	    (size_t)(nvphdr.nvph_namesize - 1)) {
682 		goto fail;
683 	}
684 
685 	memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
686 	ptr += nvphdr.nvph_namesize;
687 	*leftp -= nvphdr.nvph_namesize;
688 
689 	if (*leftp < nvphdr.nvph_datasize)
690 		goto fail;
691 
692 	nvp->nvp_type = nvphdr.nvph_type;
693 	nvp->nvp_data = 0;
694 	nvp->nvp_datasize = nvphdr.nvph_datasize;
695 	nvp->nvp_nitems = nvphdr.nvph_nitems;
696 
697 	return (ptr);
698 fail:
699 	ERRNO_SET(EINVAL);
700 	return (NULL);
701 }
702 
703 const unsigned char *
704 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
705     size_t *leftp __unused)
706 {
707 
708 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
709 
710 	if (nvp->nvp_datasize != 0) {
711 		ERRNO_SET(EINVAL);
712 		return (NULL);
713 	}
714 
715 	return (ptr);
716 }
717 
718 const unsigned char *
719 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
720     size_t *leftp)
721 {
722 	uint8_t value;
723 
724 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
725 
726 	if (nvp->nvp_datasize != sizeof(value)) {
727 		ERRNO_SET(EINVAL);
728 		return (NULL);
729 	}
730 	if (*leftp < sizeof(value)) {
731 		ERRNO_SET(EINVAL);
732 		return (NULL);
733 	}
734 
735 	memcpy(&value, ptr, sizeof(value));
736 	ptr += sizeof(value);
737 	*leftp -= sizeof(value);
738 
739 	if (value != 0 && value != 1) {
740 		ERRNO_SET(EINVAL);
741 		return (NULL);
742 	}
743 
744 	nvp->nvp_data = (uint64_t)value;
745 
746 	return (ptr);
747 }
748 
749 const unsigned char *
750 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
751      size_t *leftp)
752 {
753 
754 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
755 
756 	if (nvp->nvp_datasize != sizeof(uint64_t)) {
757 		ERRNO_SET(EINVAL);
758 		return (NULL);
759 	}
760 	if (*leftp < sizeof(uint64_t)) {
761 		ERRNO_SET(EINVAL);
762 		return (NULL);
763 	}
764 
765 	if (isbe)
766 		nvp->nvp_data = be64dec(ptr);
767 	else
768 		nvp->nvp_data = le64dec(ptr);
769 
770 	ptr += sizeof(uint64_t);
771 	*leftp -= sizeof(uint64_t);
772 
773 	return (ptr);
774 }
775 
776 const unsigned char *
777 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
778     const unsigned char *ptr, size_t *leftp)
779 {
780 
781 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
782 
783 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
784 		ERRNO_SET(EINVAL);
785 		return (NULL);
786 	}
787 
788 	if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
789 	    nvp->nvp_datasize - 1) {
790 		ERRNO_SET(EINVAL);
791 		return (NULL);
792 	}
793 
794 	nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
795 	if (nvp->nvp_data == 0)
796 		return (NULL);
797 
798 	ptr += nvp->nvp_datasize;
799 	*leftp -= nvp->nvp_datasize;
800 
801 	return (ptr);
802 }
803 
804 const unsigned char *
805 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
806     const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
807 {
808 	nvlist_t *value;
809 
810 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
811 
812 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
813 		ERRNO_SET(EINVAL);
814 		return (NULL);
815 	}
816 
817 	value = nvlist_create(0);
818 	if (value == NULL)
819 		return (NULL);
820 
821 	ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
822 	if (ptr == NULL)
823 		return (NULL);
824 
825 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
826 	*child = value;
827 
828 	return (ptr);
829 }
830 
831 #ifndef _KERNEL
832 const unsigned char *
833 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
834     size_t *leftp, const int *fds, size_t nfds)
835 {
836 	int64_t idx;
837 
838 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
839 
840 	if (nvp->nvp_datasize != sizeof(idx)) {
841 		ERRNO_SET(EINVAL);
842 		return (NULL);
843 	}
844 	if (*leftp < sizeof(idx)) {
845 		ERRNO_SET(EINVAL);
846 		return (NULL);
847 	}
848 
849 	if (isbe)
850 		idx = be64dec(ptr);
851 	else
852 		idx = le64dec(ptr);
853 
854 	if (idx < 0) {
855 		ERRNO_SET(EINVAL);
856 		return (NULL);
857 	}
858 
859 	if ((size_t)idx >= nfds) {
860 		ERRNO_SET(EINVAL);
861 		return (NULL);
862 	}
863 
864 	nvp->nvp_data = (uint64_t)fds[idx];
865 
866 	ptr += sizeof(idx);
867 	*leftp -= sizeof(idx);
868 
869 	return (ptr);
870 }
871 #endif
872 
873 const unsigned char *
874 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
875     const unsigned char *ptr, size_t *leftp)
876 {
877 	void *value;
878 
879 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
880 
881 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
882 		ERRNO_SET(EINVAL);
883 		return (NULL);
884 	}
885 
886 	value = nv_malloc(nvp->nvp_datasize);
887 	if (value == NULL)
888 		return (NULL);
889 
890 	memcpy(value, ptr, nvp->nvp_datasize);
891 	ptr += nvp->nvp_datasize;
892 	*leftp -= nvp->nvp_datasize;
893 
894 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
895 
896 	return (ptr);
897 }
898 
899 const unsigned char *
900 nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp,
901     const unsigned char *ptr, size_t *leftp)
902 {
903 	uint8_t *value;
904 	size_t size;
905 	unsigned int i;
906 
907 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
908 
909 	size = sizeof(*value) * nvp->nvp_nitems;
910 	if (nvp->nvp_datasize != size || *leftp < size ||
911 	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
912 		ERRNO_SET(EINVAL);
913 		return (NULL);
914 	}
915 
916 	value = nv_malloc(size);
917 	if (value == NULL)
918 		return (NULL);
919 
920 	for (i = 0; i < nvp->nvp_nitems; i++) {
921 		value[i] = *(const uint8_t *)ptr;
922 
923 		ptr += sizeof(*value);
924 		*leftp -= sizeof(*value);
925 	}
926 
927 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
928 
929 	return (ptr);
930 }
931 
932 const unsigned char *
933 nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
934      size_t *leftp)
935 {
936 	uint64_t *value;
937 	size_t size;
938 	unsigned int i;
939 
940 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
941 
942 	size = sizeof(*value) * nvp->nvp_nitems;
943 	if (nvp->nvp_datasize != size || *leftp < size ||
944 	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
945 		ERRNO_SET(EINVAL);
946 		return (NULL);
947 	}
948 
949 	value = nv_malloc(size);
950 	if (value == NULL)
951 		return (NULL);
952 
953 	for (i = 0; i < nvp->nvp_nitems; i++) {
954 		if (isbe)
955 			value[i] = be64dec(ptr);
956 		else
957 			value[i] = le64dec(ptr);
958 
959 		ptr += sizeof(*value);
960 		*leftp -= sizeof(*value);
961 	}
962 
963 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
964 
965 	return (ptr);
966 }
967 
968 const unsigned char *
969 nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp,
970     const unsigned char *ptr, size_t *leftp)
971 {
972 	ssize_t size;
973 	size_t len;
974 	const char *tmp;
975 	char **value;
976 	unsigned int ii, j;
977 
978 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
979 
980 	if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 ||
981 	    nvp->nvp_nitems == 0) {
982 		ERRNO_SET(EINVAL);
983 		return (NULL);
984 	}
985 
986 	size = nvp->nvp_datasize;
987 	tmp = (const char *)ptr;
988 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
989 		len = strnlen(tmp, size - 1) + 1;
990 		size -= len;
991 		if (size < 0) {
992 			ERRNO_SET(EINVAL);
993 			return (NULL);
994 		}
995 		tmp += len;
996 	}
997 	if (size != 0) {
998 		ERRNO_SET(EINVAL);
999 		return (NULL);
1000 	}
1001 
1002 	value = nv_malloc(sizeof(*value) * nvp->nvp_nitems);
1003 	if (value == NULL)
1004 		return (NULL);
1005 
1006 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1007 		value[ii] = nv_strdup((const char *)ptr);
1008 		if (value[ii] == NULL)
1009 			goto out;
1010 		len = strlen(value[ii]) + 1;
1011 		ptr += len;
1012 		*leftp -= len;
1013 	}
1014 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
1015 
1016 	return (ptr);
1017 out:
1018 	for (j = 0; j < ii; j++)
1019 		nv_free(value[j]);
1020 	nv_free(value);
1021 	return (NULL);
1022 }
1023 
1024 #ifndef _KERNEL
1025 const unsigned char *
1026 nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
1027     const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
1028 {
1029 	int64_t idx;
1030 	size_t size;
1031 	unsigned int ii;
1032 	int *array;
1033 
1034 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1035 
1036 	size = sizeof(idx) * nvp->nvp_nitems;
1037 	if (nvp->nvp_datasize != size || *leftp < size ||
1038 	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
1039 		ERRNO_SET(EINVAL);
1040 		return (NULL);
1041 	}
1042 
1043 	array = (int *)nv_malloc(size);
1044 	if (array == NULL)
1045 		return (NULL);
1046 
1047 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1048 		if (isbe)
1049 			idx = be64dec(ptr);
1050 		else
1051 			idx = le64dec(ptr);
1052 
1053 		if (idx < 0) {
1054 			ERRNO_SET(EINVAL);
1055 			nv_free(array);
1056 			return (NULL);
1057 		}
1058 
1059 		if ((size_t)idx >= nfds) {
1060 			ERRNO_SET(EINVAL);
1061 			nv_free(array);
1062 			return (NULL);
1063 		}
1064 
1065 		array[ii] = (uint64_t)fds[idx];
1066 
1067 		ptr += sizeof(idx);
1068 		*leftp -= sizeof(idx);
1069 	}
1070 
1071 	nvp->nvp_data = (uint64_t)(uintptr_t)array;
1072 
1073 	return (ptr);
1074 }
1075 #endif
1076 
1077 const unsigned char *
1078 nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
1079     const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
1080 {
1081 	nvlist_t **value;
1082 	nvpair_t *tmpnvp;
1083 	unsigned int ii, j;
1084 	size_t sizeup;
1085 
1086 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1087 
1088 	sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
1089 	if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
1090 	    sizeup > *leftp) {
1091 		ERRNO_SET(EINVAL);
1092 		return (NULL);
1093 	}
1094 
1095 	value = nv_malloc(nvp->nvp_nitems * sizeof(*value));
1096 	if (value == NULL)
1097 		return (NULL);
1098 
1099 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1100 		value[ii] = nvlist_create(0);
1101 		if (value[ii] == NULL)
1102 			goto fail;
1103 		if (ii > 0) {
1104 			tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1105 			    (uint64_t)(uintptr_t)value[ii], 0, 0);
1106 			if (tmpnvp == NULL)
1107 				goto fail;
1108 			nvlist_set_array_next(value[ii - 1], tmpnvp);
1109 		}
1110 	}
1111 	nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
1112 
1113 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
1114 	*firstel = value[0];
1115 
1116 	return (ptr);
1117 fail:
1118 	ERRNO_SAVE();
1119 	for (j = 0; j <= ii; j++)
1120 		nvlist_destroy(value[j]);
1121 	nv_free(value);
1122 	ERRNO_RESTORE();
1123 
1124 	return (NULL);
1125 }
1126 
1127 const unsigned char *
1128 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
1129     nvpair_t **nvpp)
1130 {
1131 	nvpair_t *nvp, *tmp;
1132 
1133 	nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
1134 	if (nvp == NULL)
1135 		return (NULL);
1136 	nvp->nvp_name = (char *)(nvp + 1);
1137 
1138 	ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
1139 	if (ptr == NULL)
1140 		goto fail;
1141 	tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
1142 	if (tmp == NULL)
1143 		goto fail;
1144 	nvp = tmp;
1145 
1146 	/* Update nvp_name after realloc(). */
1147 	nvp->nvp_name = (char *)(nvp + 1);
1148 	nvp->nvp_data = 0x00;
1149 	nvp->nvp_magic = NVPAIR_MAGIC;
1150 	*nvpp = nvp;
1151 	return (ptr);
1152 fail:
1153 	nv_free(nvp);
1154 	return (NULL);
1155 }
1156 
1157 int
1158 nvpair_type(const nvpair_t *nvp)
1159 {
1160 
1161 	NVPAIR_ASSERT(nvp);
1162 
1163 	return (nvp->nvp_type);
1164 }
1165 
1166 const char *
1167 nvpair_name(const nvpair_t *nvp)
1168 {
1169 
1170 	NVPAIR_ASSERT(nvp);
1171 
1172 	return (nvp->nvp_name);
1173 }
1174 
1175 nvpair_t *
1176 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
1177 {
1178 	va_list valueap;
1179 	nvpair_t *nvp;
1180 
1181 	va_start(valueap, valuefmt);
1182 	nvp = nvpair_create_stringv(name, valuefmt, valueap);
1183 	va_end(valueap);
1184 
1185 	return (nvp);
1186 }
1187 
1188 nvpair_t *
1189 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
1190 {
1191 	nvpair_t *nvp;
1192 	char *str;
1193 	int len;
1194 
1195 	len = nv_vasprintf(&str, valuefmt, valueap);
1196 	if (len < 0)
1197 		return (NULL);
1198 	nvp = nvpair_create_string(name, str);
1199 	nv_free(str);
1200 	return (nvp);
1201 }
1202 
1203 nvpair_t *
1204 nvpair_create_null(const char *name)
1205 {
1206 
1207 	return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1208 }
1209 
1210 nvpair_t *
1211 nvpair_create_bool(const char *name, bool value)
1212 {
1213 
1214 	return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1215 	    sizeof(uint8_t), 0));
1216 }
1217 
1218 nvpair_t *
1219 nvpair_create_number(const char *name, uint64_t value)
1220 {
1221 
1222 	return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1223 }
1224 
1225 nvpair_t *
1226 nvpair_create_string(const char *name, const char *value)
1227 {
1228 	nvpair_t *nvp;
1229 	size_t size;
1230 	char *data;
1231 
1232 	if (value == NULL) {
1233 		ERRNO_SET(EINVAL);
1234 		return (NULL);
1235 	}
1236 
1237 	data = nv_strdup(value);
1238 	if (data == NULL)
1239 		return (NULL);
1240 	size = strlen(value) + 1;
1241 
1242 	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1243 	    size, 0);
1244 	if (nvp == NULL)
1245 		nv_free(data);
1246 
1247 	return (nvp);
1248 }
1249 
1250 nvpair_t *
1251 nvpair_create_nvlist(const char *name, const nvlist_t *value)
1252 {
1253 	nvlist_t *nvl;
1254 	nvpair_t *nvp;
1255 
1256 	if (value == NULL) {
1257 		ERRNO_SET(EINVAL);
1258 		return (NULL);
1259 	}
1260 
1261 	nvl = nvlist_clone(value);
1262 	if (nvl == NULL)
1263 		return (NULL);
1264 
1265 	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1266 	    0);
1267 	if (nvp == NULL)
1268 		nvlist_destroy(nvl);
1269 	else
1270 		nvlist_set_parent(nvl, nvp);
1271 
1272 	return (nvp);
1273 }
1274 
1275 #ifndef _KERNEL
1276 nvpair_t *
1277 nvpair_create_descriptor(const char *name, int value)
1278 {
1279 	nvpair_t *nvp;
1280 
1281 	value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1282 	if (value < 0)
1283 		return (NULL);
1284 
1285 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1286 	    sizeof(int64_t), 0);
1287 	if (nvp == NULL) {
1288 		ERRNO_SAVE();
1289 		close(value);
1290 		ERRNO_RESTORE();
1291 	}
1292 
1293 	return (nvp);
1294 }
1295 #endif
1296 
1297 nvpair_t *
1298 nvpair_create_binary(const char *name, const void *value, size_t size)
1299 {
1300 	nvpair_t *nvp;
1301 	void *data;
1302 
1303 	if (value == NULL || size == 0) {
1304 		ERRNO_SET(EINVAL);
1305 		return (NULL);
1306 	}
1307 
1308 	data = nv_malloc(size);
1309 	if (data == NULL)
1310 		return (NULL);
1311 	memcpy(data, value, size);
1312 
1313 	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1314 	    size, 0);
1315 	if (nvp == NULL)
1316 		nv_free(data);
1317 
1318 	return (nvp);
1319 }
1320 
1321 nvpair_t *
1322 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1323 {
1324 	nvpair_t *nvp;
1325 	size_t size;
1326 	void *data;
1327 
1328 	if (value == NULL || nitems == 0) {
1329 		ERRNO_SET(EINVAL);
1330 		return (NULL);
1331 	}
1332 
1333 	size = sizeof(value[0]) * nitems;
1334 	data = nv_malloc(size);
1335 	if (data == NULL)
1336 		return (NULL);
1337 
1338 	memcpy(data, value, size);
1339 	nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1340 	    size, nitems);
1341 	if (nvp == NULL) {
1342 		ERRNO_SAVE();
1343 		nv_free(data);
1344 		ERRNO_RESTORE();
1345 	}
1346 
1347 	return (nvp);
1348 }
1349 
1350 nvpair_t *
1351 nvpair_create_number_array(const char *name, const uint64_t *value,
1352     size_t nitems)
1353 {
1354 	nvpair_t *nvp;
1355 	size_t size;
1356 	void *data;
1357 
1358 	if (value == NULL || nitems == 0) {
1359 		ERRNO_SET(EINVAL);
1360 		return (NULL);
1361 	}
1362 
1363 	size = sizeof(value[0]) * nitems;
1364 	data = nv_malloc(size);
1365 	if (data == NULL)
1366 		return (NULL);
1367 
1368 	memcpy(data, value, size);
1369 	nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1370 	    (uint64_t)(uintptr_t)data, size, nitems);
1371 	if (nvp == NULL) {
1372 		ERRNO_SAVE();
1373 		nv_free(data);
1374 		ERRNO_RESTORE();
1375 	}
1376 
1377 	return (nvp);
1378 }
1379 
1380 nvpair_t *
1381 nvpair_create_string_array(const char *name, const char * const *value,
1382     size_t nitems)
1383 {
1384 	nvpair_t *nvp;
1385 	unsigned int ii;
1386 	size_t datasize, size;
1387 	char **data;
1388 
1389 	if (value == NULL || nitems == 0) {
1390 		ERRNO_SET(EINVAL);
1391 		return (NULL);
1392 	}
1393 
1394 	nvp = NULL;
1395 	datasize = 0;
1396 	data = nv_malloc(sizeof(value[0]) * nitems);
1397 	if (data == NULL)
1398 		return (NULL);
1399 
1400 	for (ii = 0; ii < nitems; ii++) {
1401 		if (value[ii] == NULL) {
1402 			ERRNO_SET(EINVAL);
1403 			goto fail;
1404 		}
1405 
1406 		size = strlen(value[ii]) + 1;
1407 		datasize += size;
1408 		data[ii] = nv_strdup(value[ii]);
1409 		if (data[ii] == NULL)
1410 			goto fail;
1411 	}
1412 	nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1413 	    (uint64_t)(uintptr_t)data, datasize, nitems);
1414 
1415 fail:
1416 	if (nvp == NULL) {
1417 		ERRNO_SAVE();
1418 		for (; ii > 0; ii--)
1419 			nv_free(data[ii - 1]);
1420 		nv_free(data);
1421 		ERRNO_RESTORE();
1422 	}
1423 
1424 	return (nvp);
1425 }
1426 
1427 nvpair_t *
1428 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1429     size_t nitems)
1430 {
1431 	unsigned int ii;
1432 	nvlist_t **nvls;
1433 	nvpair_t *parent;
1434 	int flags;
1435 
1436 	nvls = NULL;
1437 
1438 	if (value == NULL || nitems == 0) {
1439 		ERRNO_SET(EINVAL);
1440 		return (NULL);
1441 	}
1442 
1443 	nvls = nv_malloc(sizeof(value[0]) * nitems);
1444 	if (nvls == NULL)
1445 		return (NULL);
1446 
1447 	for (ii = 0; ii < nitems; ii++) {
1448 		if (value[ii] == NULL) {
1449 			ERRNO_SET(EINVAL);
1450 			goto fail;
1451 		}
1452 
1453 		nvls[ii] = nvlist_clone(value[ii]);
1454 		if (nvls[ii] == NULL)
1455 			goto fail;
1456 
1457 		if (ii > 0) {
1458 			nvpair_t *nvp;
1459 
1460 			nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1461 			    (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1462 			if (nvp == NULL) {
1463 				ERRNO_SAVE();
1464 				nvlist_destroy(nvls[ii]);
1465 				ERRNO_RESTORE();
1466 				goto fail;
1467 			}
1468 			nvlist_set_array_next(nvls[ii - 1], nvp);
1469 		}
1470 	}
1471 	flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1472 	nvlist_set_flags(nvls[nitems - 1], flags);
1473 
1474 	parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1475 	    (uint64_t)(uintptr_t)nvls, 0, nitems);
1476 	if (parent == NULL)
1477 		goto fail;
1478 
1479 	for (ii = 0; ii < nitems; ii++)
1480 		nvlist_set_parent(nvls[ii], parent);
1481 
1482 	return (parent);
1483 
1484 fail:
1485 	ERRNO_SAVE();
1486 	for (; ii > 0; ii--)
1487 		nvlist_destroy(nvls[ii - 1]);
1488 	nv_free(nvls);
1489 	ERRNO_RESTORE();
1490 
1491 	return (NULL);
1492 }
1493 
1494 #ifndef _KERNEL
1495 nvpair_t *
1496 nvpair_create_descriptor_array(const char *name, const int *value,
1497     size_t nitems)
1498 {
1499 	unsigned int ii;
1500 	nvpair_t *nvp;
1501 	int *fds;
1502 
1503 	if (value == NULL) {
1504 		ERRNO_SET(EINVAL);
1505 		return (NULL);
1506 	}
1507 
1508 	nvp = NULL;
1509 
1510 	fds = nv_malloc(sizeof(value[0]) * nitems);
1511 	if (fds == NULL)
1512 		return (NULL);
1513 	for (ii = 0; ii < nitems; ii++) {
1514 		if (value[ii] == -1) {
1515 			fds[ii] = -1;
1516 		} else {
1517 			fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1518 			if (fds[ii] == -1)
1519 				goto fail;
1520 		}
1521 	}
1522 
1523 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1524 	    (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1525 
1526 fail:
1527 	if (nvp == NULL) {
1528 		ERRNO_SAVE();
1529 		for (; ii > 0; ii--) {
1530 			if (fds[ii - 1] != -1)
1531 				close(fds[ii - 1]);
1532 		}
1533 		nv_free(fds);
1534 		ERRNO_RESTORE();
1535 	}
1536 
1537 	return (nvp);
1538 }
1539 #endif
1540 
1541 nvpair_t *
1542 nvpair_move_string(const char *name, char *value)
1543 {
1544 	nvpair_t *nvp;
1545 
1546 	if (value == NULL) {
1547 		ERRNO_SET(EINVAL);
1548 		return (NULL);
1549 	}
1550 
1551 	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1552 	    strlen(value) + 1, 0);
1553 	if (nvp == NULL) {
1554 		ERRNO_SAVE();
1555 		nv_free(value);
1556 		ERRNO_RESTORE();
1557 	}
1558 
1559 	return (nvp);
1560 }
1561 
1562 nvpair_t *
1563 nvpair_move_nvlist(const char *name, nvlist_t *value)
1564 {
1565 	nvpair_t *nvp;
1566 
1567 	if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1568 		ERRNO_SET(EINVAL);
1569 		return (NULL);
1570 	}
1571 
1572 	if (nvlist_error(value) != 0) {
1573 		ERRNO_SET(nvlist_error(value));
1574 		nvlist_destroy(value);
1575 		return (NULL);
1576 	}
1577 
1578 	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1579 	    0, 0);
1580 	if (nvp == NULL)
1581 		nvlist_destroy(value);
1582 	else
1583 		nvlist_set_parent(value, nvp);
1584 
1585 	return (nvp);
1586 }
1587 
1588 #ifndef _KERNEL
1589 nvpair_t *
1590 nvpair_move_descriptor(const char *name, int value)
1591 {
1592 	nvpair_t *nvp;
1593 
1594 	if (value < 0 || !fd_is_valid(value)) {
1595 		ERRNO_SET(EBADF);
1596 		return (NULL);
1597 	}
1598 
1599 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1600 	    sizeof(int64_t), 0);
1601 	if (nvp == NULL) {
1602 		ERRNO_SAVE();
1603 		close(value);
1604 		ERRNO_RESTORE();
1605 	}
1606 
1607 	return (nvp);
1608 }
1609 #endif
1610 
1611 nvpair_t *
1612 nvpair_move_binary(const char *name, void *value, size_t size)
1613 {
1614 	nvpair_t *nvp;
1615 
1616 	if (value == NULL || size == 0) {
1617 		ERRNO_SET(EINVAL);
1618 		return (NULL);
1619 	}
1620 
1621 	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1622 	    size, 0);
1623 	if (nvp == NULL) {
1624 		ERRNO_SAVE();
1625 		nv_free(value);
1626 		ERRNO_RESTORE();
1627 	}
1628 
1629 	return (nvp);
1630 }
1631 
1632 nvpair_t *
1633 nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1634 {
1635 	nvpair_t *nvp;
1636 
1637 	if (value == NULL || nitems == 0) {
1638 		ERRNO_SET(EINVAL);
1639 		return (NULL);
1640 	}
1641 
1642 	nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1643 	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1644 	if (nvp == NULL) {
1645 		ERRNO_SAVE();
1646 		nv_free(value);
1647 		ERRNO_RESTORE();
1648 	}
1649 
1650 	return (nvp);
1651 }
1652 
1653 nvpair_t *
1654 nvpair_move_string_array(const char *name, char **value, size_t nitems)
1655 {
1656 	nvpair_t *nvp;
1657 	size_t i, size;
1658 
1659 	if (value == NULL || nitems == 0) {
1660 		ERRNO_SET(EINVAL);
1661 		return (NULL);
1662 	}
1663 
1664 	size = 0;
1665 	for (i = 0; i < nitems; i++) {
1666 		if (value[i] == NULL) {
1667 			ERRNO_SET(EINVAL);
1668 			return (NULL);
1669 		}
1670 
1671 		size += strlen(value[i]) + 1;
1672 	}
1673 
1674 	nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1675 	    (uint64_t)(uintptr_t)value, size, nitems);
1676 	if (nvp == NULL) {
1677 		ERRNO_SAVE();
1678 		for (i = 0; i < nitems; i++)
1679 			nv_free(value[i]);
1680 		nv_free(value);
1681 		ERRNO_RESTORE();
1682 	}
1683 
1684 	return (nvp);
1685 }
1686 
1687 nvpair_t *
1688 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1689 {
1690 	nvpair_t *nvp;
1691 
1692 	if (value == NULL || nitems == 0) {
1693 		ERRNO_SET(EINVAL);
1694 		return (NULL);
1695 	}
1696 
1697 	nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1698 	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1699 	if (nvp == NULL) {
1700 		ERRNO_SAVE();
1701 		nv_free(value);
1702 		ERRNO_RESTORE();
1703 	}
1704 
1705 	return (nvp);
1706 }
1707 
1708 nvpair_t *
1709 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1710 {
1711 	nvpair_t *parent;
1712 	unsigned int ii;
1713 	int flags;
1714 
1715 	if (value == NULL || nitems == 0) {
1716 		ERRNO_SET(EINVAL);
1717 		return (NULL);
1718 	}
1719 
1720 	for (ii = 0; ii < nitems; ii++) {
1721 		if (value == NULL || nvlist_error(value[ii]) != 0 ||
1722 		    nvlist_get_pararr(value[ii], NULL) != NULL) {
1723 			ERRNO_SET(EINVAL);
1724 			goto fail;
1725 		}
1726 		if (ii > 0) {
1727 			nvpair_t *nvp;
1728 
1729 			nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1730 			    (uint64_t)(uintptr_t)value[ii], 0, 0);
1731 			if (nvp == NULL)
1732 				goto fail;
1733 			nvlist_set_array_next(value[ii - 1], nvp);
1734 		}
1735 	}
1736 	flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1737 	nvlist_set_flags(value[nitems - 1], flags);
1738 
1739 	parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1740 	    (uint64_t)(uintptr_t)value, 0, nitems);
1741 	if (parent == NULL)
1742 		goto fail;
1743 
1744 	for (ii = 0; ii < nitems; ii++)
1745 		nvlist_set_parent(value[ii], parent);
1746 
1747 	return (parent);
1748 fail:
1749 	ERRNO_SAVE();
1750 	for (ii = 0; ii < nitems; ii++) {
1751 		if (value[ii] != NULL &&
1752 		    nvlist_get_pararr(value[ii], NULL) != NULL) {
1753 			nvlist_destroy(value[ii]);
1754 		}
1755 	}
1756 	nv_free(value);
1757 	ERRNO_RESTORE();
1758 
1759 	return (NULL);
1760 }
1761 
1762 #ifndef _KERNEL
1763 nvpair_t *
1764 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1765 {
1766 	nvpair_t *nvp;
1767 	size_t i;
1768 
1769 	if (value == NULL || nitems == 0) {
1770 		ERRNO_SET(EINVAL);
1771 		return (NULL);
1772 	}
1773 
1774 	for (i = 0; i < nitems; i++) {
1775 		if (value[i] != -1 && !fd_is_valid(value[i])) {
1776 			ERRNO_SET(EBADF);
1777 			goto fail;
1778 		}
1779 	}
1780 
1781 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1782 	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1783 	if (nvp == NULL)
1784 		goto fail;
1785 
1786 	return (nvp);
1787 fail:
1788 	ERRNO_SAVE();
1789 	for (i = 0; i < nitems; i++) {
1790 		if (fd_is_valid(value[i]))
1791 			close(value[i]);
1792 	}
1793 	nv_free(value);
1794 	ERRNO_RESTORE();
1795 
1796 	return (NULL);
1797 }
1798 #endif
1799 
1800 bool
1801 nvpair_get_bool(const nvpair_t *nvp)
1802 {
1803 
1804 	NVPAIR_ASSERT(nvp);
1805 
1806 	return (nvp->nvp_data == 1);
1807 }
1808 
1809 uint64_t
1810 nvpair_get_number(const nvpair_t *nvp)
1811 {
1812 
1813 	NVPAIR_ASSERT(nvp);
1814 
1815 	return (nvp->nvp_data);
1816 }
1817 
1818 const char *
1819 nvpair_get_string(const nvpair_t *nvp)
1820 {
1821 
1822 	NVPAIR_ASSERT(nvp);
1823 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1824 
1825 	return ((const char *)(intptr_t)nvp->nvp_data);
1826 }
1827 
1828 const nvlist_t *
1829 nvpair_get_nvlist(const nvpair_t *nvp)
1830 {
1831 
1832 	NVPAIR_ASSERT(nvp);
1833 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1834 
1835 	return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1836 }
1837 
1838 #ifndef _KERNEL
1839 int
1840 nvpair_get_descriptor(const nvpair_t *nvp)
1841 {
1842 
1843 	NVPAIR_ASSERT(nvp);
1844 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1845 
1846 	return ((int)nvp->nvp_data);
1847 }
1848 #endif
1849 
1850 const void *
1851 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1852 {
1853 
1854 	NVPAIR_ASSERT(nvp);
1855 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1856 
1857 	if (sizep != NULL)
1858 		*sizep = nvp->nvp_datasize;
1859 
1860 	return ((const void *)(intptr_t)nvp->nvp_data);
1861 }
1862 
1863 const bool *
1864 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1865 {
1866 
1867 	NVPAIR_ASSERT(nvp);
1868 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1869 
1870 	if (nitems != NULL)
1871 		*nitems = nvp->nvp_nitems;
1872 
1873 	return ((const bool *)(intptr_t)nvp->nvp_data);
1874 }
1875 
1876 const uint64_t *
1877 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1878 {
1879 
1880 	NVPAIR_ASSERT(nvp);
1881 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1882 
1883 	if (nitems != NULL)
1884 		*nitems = nvp->nvp_nitems;
1885 
1886 	return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1887 }
1888 
1889 const char * const *
1890 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1891 {
1892 
1893 	NVPAIR_ASSERT(nvp);
1894 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1895 
1896 	if (nitems != NULL)
1897 		*nitems = nvp->nvp_nitems;
1898 
1899 	return ((const char * const *)(intptr_t)nvp->nvp_data);
1900 }
1901 
1902 const nvlist_t * const *
1903 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1904 {
1905 
1906 	NVPAIR_ASSERT(nvp);
1907 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1908 
1909 	if (nitems != NULL)
1910 		*nitems = nvp->nvp_nitems;
1911 
1912 	return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1913 }
1914 
1915 #ifndef _KERNEL
1916 const int *
1917 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1918 {
1919 
1920 	NVPAIR_ASSERT(nvp);
1921 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1922 
1923 	if (nitems != NULL)
1924 		*nitems = nvp->nvp_nitems;
1925 
1926 	return ((const int *)(intptr_t)nvp->nvp_data);
1927 }
1928 #endif
1929 
1930 int
1931 nvpair_append_bool_array(nvpair_t *nvp, const bool value)
1932 {
1933 
1934 	NVPAIR_ASSERT(nvp);
1935 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1936 	return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1937 }
1938 
1939 int
1940 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
1941 {
1942 
1943 	NVPAIR_ASSERT(nvp);
1944 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1945 	return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1946 }
1947 
1948 int
1949 nvpair_append_string_array(nvpair_t *nvp, const char *value)
1950 {
1951 	char *str;
1952 
1953 	NVPAIR_ASSERT(nvp);
1954 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1955 	if (value == NULL) {
1956 		ERRNO_SET(EINVAL);
1957 		return (-1);
1958 	}
1959 	str = nv_strdup(value);
1960 	if (str == NULL) {
1961 		return (-1);
1962 	}
1963 	if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
1964 		nv_free(str);
1965 		return (-1);
1966 	}
1967 	return (0);
1968 }
1969 
1970 int
1971 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
1972 {
1973 	nvpair_t *tmpnvp;
1974 	nvlist_t *nvl, *prev;
1975 	int flags;
1976 
1977 	NVPAIR_ASSERT(nvp);
1978 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1979 	if (value == NULL || nvlist_error(value) != 0 ||
1980 	    nvlist_get_pararr(value, NULL) != NULL) {
1981 		ERRNO_SET(EINVAL);
1982 		return (-1);
1983 	}
1984 	nvl = nvlist_clone(value);
1985 	if (nvl == NULL) {
1986 		return (-1);
1987 	}
1988 	flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
1989 	nvlist_set_flags(nvl, flags);
1990 
1991 	tmpnvp = NULL;
1992 	prev = NULL;
1993 	if (nvp->nvp_nitems > 0) {
1994 		nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
1995 
1996 		prev = nvls[nvp->nvp_nitems - 1];
1997 		PJDLOG_ASSERT(prev != NULL);
1998 
1999 		tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
2000 		    (uint64_t)(uintptr_t)nvl, 0, 0);
2001 		if (tmpnvp == NULL) {
2002 			goto fail;
2003 		}
2004 	}
2005 	if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
2006 		goto fail;
2007 	}
2008 	if (tmpnvp) {
2009 		NVPAIR_ASSERT(tmpnvp);
2010 		nvlist_set_array_next(prev, tmpnvp);
2011 	}
2012 	nvlist_set_parent(nvl, nvp);
2013 	return (0);
2014 fail:
2015 	if (tmpnvp) {
2016 		nvpair_free(tmpnvp);
2017 	}
2018 	nvlist_destroy(nvl);
2019 	return (-1);
2020 }
2021 
2022 #ifndef _KERNEL
2023 int
2024 nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
2025 {
2026 	int fd;
2027 
2028 	NVPAIR_ASSERT(nvp);
2029 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
2030 	fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
2031 	if (fd == -1) {
2032 		return (-1);
2033 	}
2034 	if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
2035 		close(fd);
2036 		return (-1);
2037 	}
2038 	return (0);
2039 }
2040 #endif
2041 
2042 void
2043 nvpair_free(nvpair_t *nvp)
2044 {
2045 	size_t i;
2046 
2047 	NVPAIR_ASSERT(nvp);
2048 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
2049 
2050 	nvp->nvp_magic = 0;
2051 	switch (nvp->nvp_type) {
2052 #ifndef _KERNEL
2053 	case NV_TYPE_DESCRIPTOR:
2054 		close((int)nvp->nvp_data);
2055 		break;
2056 	case NV_TYPE_DESCRIPTOR_ARRAY:
2057 		for (i = 0; i < nvp->nvp_nitems; i++)
2058 			close(((int *)(intptr_t)nvp->nvp_data)[i]);
2059 		nv_free((int *)(intptr_t)nvp->nvp_data);
2060 		break;
2061 #endif
2062 	case NV_TYPE_NVLIST:
2063 		nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
2064 		break;
2065 	case NV_TYPE_STRING:
2066 		nv_free((char *)(intptr_t)nvp->nvp_data);
2067 		break;
2068 	case NV_TYPE_BINARY:
2069 		nv_free((void *)(intptr_t)nvp->nvp_data);
2070 		break;
2071 	case NV_TYPE_NVLIST_ARRAY:
2072 		for (i = 0; i < nvp->nvp_nitems; i++) {
2073 			nvlist_destroy(
2074 			    ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
2075 		}
2076 		nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
2077 		break;
2078 	case NV_TYPE_NUMBER_ARRAY:
2079 		nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
2080 		break;
2081 	case NV_TYPE_BOOL_ARRAY:
2082 		nv_free((bool *)(intptr_t)nvp->nvp_data);
2083 		break;
2084 	case NV_TYPE_STRING_ARRAY:
2085 		for (i = 0; i < nvp->nvp_nitems; i++)
2086 			nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
2087 		nv_free((char **)(intptr_t)nvp->nvp_data);
2088 		break;
2089 	}
2090 	nv_free(nvp);
2091 }
2092 
2093 void
2094 nvpair_free_structure(nvpair_t *nvp)
2095 {
2096 
2097 	NVPAIR_ASSERT(nvp);
2098 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
2099 
2100 	nvp->nvp_magic = 0;
2101 	nv_free(nvp);
2102 }
2103 
2104 const char *
2105 nvpair_type_string(int type)
2106 {
2107 
2108 	switch (type) {
2109 	case NV_TYPE_NULL:
2110 		return ("NULL");
2111 	case NV_TYPE_BOOL:
2112 		return ("BOOL");
2113 	case NV_TYPE_NUMBER:
2114 		return ("NUMBER");
2115 	case NV_TYPE_STRING:
2116 		return ("STRING");
2117 	case NV_TYPE_NVLIST:
2118 		return ("NVLIST");
2119 	case NV_TYPE_DESCRIPTOR:
2120 		return ("DESCRIPTOR");
2121 	case NV_TYPE_BINARY:
2122 		return ("BINARY");
2123 	case NV_TYPE_BOOL_ARRAY:
2124 		return ("BOOL ARRAY");
2125 	case NV_TYPE_NUMBER_ARRAY:
2126 		return ("NUMBER ARRAY");
2127 	case NV_TYPE_STRING_ARRAY:
2128 		return ("STRING ARRAY");
2129 	case NV_TYPE_NVLIST_ARRAY:
2130 		return ("NVLIST ARRAY");
2131 	case NV_TYPE_DESCRIPTOR_ARRAY:
2132 		return ("DESCRIPTOR ARRAY");
2133 	default:
2134 		return ("<UNKNOWN>");
2135 	}
2136 }
2137 
2138