xref: /freebsd/sys/contrib/libnv/bsd_nvpair.c (revision e47161e5f1f01ef300c6e7efdb9c92e3a6c497ff)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
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 (tmp[len - 1] != '\0') {
992 			ERRNO_SET(EINVAL);
993 			return (NULL);
994 		}
995 		if (size < 0) {
996 			ERRNO_SET(EINVAL);
997 			return (NULL);
998 		}
999 		tmp += len;
1000 	}
1001 	if (size != 0) {
1002 		ERRNO_SET(EINVAL);
1003 		return (NULL);
1004 	}
1005 
1006 	value = nv_calloc(nvp->nvp_nitems, sizeof(*value));
1007 	if (value == NULL)
1008 		return (NULL);
1009 
1010 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1011 		value[ii] = nv_strdup((const char *)ptr);
1012 		if (value[ii] == NULL)
1013 			goto out;
1014 		len = strlen(value[ii]) + 1;
1015 		ptr += len;
1016 		*leftp -= len;
1017 	}
1018 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
1019 
1020 	return (ptr);
1021 out:
1022 	for (j = 0; j < ii; j++)
1023 		nv_free(value[j]);
1024 	nv_free(value);
1025 	return (NULL);
1026 }
1027 
1028 #ifndef _KERNEL
1029 const unsigned char *
1030 nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
1031     const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
1032 {
1033 	int64_t idx;
1034 	size_t size;
1035 	unsigned int ii;
1036 	int *array;
1037 
1038 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1039 
1040 	size = sizeof(idx) * nvp->nvp_nitems;
1041 	if (nvp->nvp_datasize != size || *leftp < size ||
1042 	    nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
1043 		ERRNO_SET(EINVAL);
1044 		return (NULL);
1045 	}
1046 
1047 	array = (int *)nv_malloc(size);
1048 	if (array == NULL)
1049 		return (NULL);
1050 
1051 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1052 		if (isbe)
1053 			idx = be64dec(ptr);
1054 		else
1055 			idx = le64dec(ptr);
1056 
1057 		if (idx < 0) {
1058 			ERRNO_SET(EINVAL);
1059 			nv_free(array);
1060 			return (NULL);
1061 		}
1062 
1063 		if ((size_t)idx >= nfds) {
1064 			ERRNO_SET(EINVAL);
1065 			nv_free(array);
1066 			return (NULL);
1067 		}
1068 
1069 		array[ii] = (uint64_t)fds[idx];
1070 
1071 		ptr += sizeof(idx);
1072 		*leftp -= sizeof(idx);
1073 	}
1074 
1075 	nvp->nvp_data = (uint64_t)(uintptr_t)array;
1076 
1077 	return (ptr);
1078 }
1079 #endif
1080 
1081 const unsigned char *
1082 nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
1083     const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
1084 {
1085 	nvlist_t **value;
1086 	nvpair_t *tmpnvp;
1087 	unsigned int ii, j;
1088 	size_t sizeup;
1089 
1090 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1091 
1092 	sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
1093 	if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
1094 	    sizeup > *leftp) {
1095 		ERRNO_SET(EINVAL);
1096 		return (NULL);
1097 	}
1098 
1099 	value = nv_calloc(nvp->nvp_nitems, sizeof(*value));
1100 	if (value == NULL)
1101 		return (NULL);
1102 
1103 	for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1104 		value[ii] = nvlist_create(0);
1105 		if (value[ii] == NULL)
1106 			goto fail;
1107 		if (ii > 0) {
1108 			tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1109 			    (uint64_t)(uintptr_t)value[ii], 0, 0);
1110 			if (tmpnvp == NULL)
1111 				goto fail;
1112 			nvlist_set_array_next(value[ii - 1], tmpnvp);
1113 		}
1114 	}
1115 	nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
1116 
1117 	nvp->nvp_data = (uint64_t)(uintptr_t)value;
1118 	*firstel = value[0];
1119 
1120 	return (ptr);
1121 fail:
1122 	ERRNO_SAVE();
1123 	for (j = 0; j <= ii; j++)
1124 		nvlist_destroy(value[j]);
1125 	nv_free(value);
1126 	ERRNO_RESTORE();
1127 
1128 	return (NULL);
1129 }
1130 
1131 const unsigned char *
1132 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
1133     nvpair_t **nvpp)
1134 {
1135 	nvpair_t *nvp, *tmp;
1136 
1137 	nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
1138 	if (nvp == NULL)
1139 		return (NULL);
1140 	nvp->nvp_name = (char *)(nvp + 1);
1141 
1142 	ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
1143 	if (ptr == NULL)
1144 		goto fail;
1145 	tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
1146 	if (tmp == NULL)
1147 		goto fail;
1148 	nvp = tmp;
1149 
1150 	/* Update nvp_name after realloc(). */
1151 	nvp->nvp_name = (char *)(nvp + 1);
1152 	nvp->nvp_data = 0x00;
1153 	nvp->nvp_magic = NVPAIR_MAGIC;
1154 	*nvpp = nvp;
1155 	return (ptr);
1156 fail:
1157 	nv_free(nvp);
1158 	return (NULL);
1159 }
1160 
1161 int
1162 nvpair_type(const nvpair_t *nvp)
1163 {
1164 
1165 	NVPAIR_ASSERT(nvp);
1166 
1167 	return (nvp->nvp_type);
1168 }
1169 
1170 const char *
1171 nvpair_name(const nvpair_t *nvp)
1172 {
1173 
1174 	NVPAIR_ASSERT(nvp);
1175 
1176 	return (nvp->nvp_name);
1177 }
1178 
1179 nvpair_t *
1180 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
1181 {
1182 	va_list valueap;
1183 	nvpair_t *nvp;
1184 
1185 	va_start(valueap, valuefmt);
1186 	nvp = nvpair_create_stringv(name, valuefmt, valueap);
1187 	va_end(valueap);
1188 
1189 	return (nvp);
1190 }
1191 
1192 nvpair_t *
1193 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
1194 {
1195 	nvpair_t *nvp;
1196 	char *str;
1197 	int len;
1198 
1199 	len = nv_vasprintf(&str, valuefmt, valueap);
1200 	if (len < 0)
1201 		return (NULL);
1202 	nvp = nvpair_create_string(name, str);
1203 	nv_free(str);
1204 	return (nvp);
1205 }
1206 
1207 nvpair_t *
1208 nvpair_create_null(const char *name)
1209 {
1210 
1211 	return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1212 }
1213 
1214 nvpair_t *
1215 nvpair_create_bool(const char *name, bool value)
1216 {
1217 
1218 	return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1219 	    sizeof(uint8_t), 0));
1220 }
1221 
1222 nvpair_t *
1223 nvpair_create_number(const char *name, uint64_t value)
1224 {
1225 
1226 	return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1227 }
1228 
1229 nvpair_t *
1230 nvpair_create_string(const char *name, const char *value)
1231 {
1232 	nvpair_t *nvp;
1233 	size_t size;
1234 	char *data;
1235 
1236 	if (value == NULL) {
1237 		ERRNO_SET(EINVAL);
1238 		return (NULL);
1239 	}
1240 
1241 	data = nv_strdup(value);
1242 	if (data == NULL)
1243 		return (NULL);
1244 	size = strlen(value) + 1;
1245 
1246 	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1247 	    size, 0);
1248 	if (nvp == NULL)
1249 		nv_free(data);
1250 
1251 	return (nvp);
1252 }
1253 
1254 nvpair_t *
1255 nvpair_create_nvlist(const char *name, const nvlist_t *value)
1256 {
1257 	nvlist_t *nvl;
1258 	nvpair_t *nvp;
1259 
1260 	if (value == NULL) {
1261 		ERRNO_SET(EINVAL);
1262 		return (NULL);
1263 	}
1264 
1265 	nvl = nvlist_clone(value);
1266 	if (nvl == NULL)
1267 		return (NULL);
1268 
1269 	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1270 	    0);
1271 	if (nvp == NULL)
1272 		nvlist_destroy(nvl);
1273 	else
1274 		nvlist_set_parent(nvl, nvp);
1275 
1276 	return (nvp);
1277 }
1278 
1279 #ifndef _KERNEL
1280 nvpair_t *
1281 nvpair_create_descriptor(const char *name, int value)
1282 {
1283 	nvpair_t *nvp;
1284 
1285 	value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1286 	if (value < 0)
1287 		return (NULL);
1288 
1289 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1290 	    sizeof(int64_t), 0);
1291 	if (nvp == NULL) {
1292 		ERRNO_SAVE();
1293 		close(value);
1294 		ERRNO_RESTORE();
1295 	}
1296 
1297 	return (nvp);
1298 }
1299 #endif
1300 
1301 nvpair_t *
1302 nvpair_create_binary(const char *name, const void *value, size_t size)
1303 {
1304 	nvpair_t *nvp;
1305 	void *data;
1306 
1307 	if (value == NULL || size == 0) {
1308 		ERRNO_SET(EINVAL);
1309 		return (NULL);
1310 	}
1311 
1312 	data = nv_malloc(size);
1313 	if (data == NULL)
1314 		return (NULL);
1315 	memcpy(data, value, size);
1316 
1317 	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1318 	    size, 0);
1319 	if (nvp == NULL)
1320 		nv_free(data);
1321 
1322 	return (nvp);
1323 }
1324 
1325 nvpair_t *
1326 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1327 {
1328 	nvpair_t *nvp;
1329 	size_t size;
1330 	void *data;
1331 
1332 	if (value == NULL || nitems == 0) {
1333 		ERRNO_SET(EINVAL);
1334 		return (NULL);
1335 	}
1336 
1337 	data = nv_calloc(nitems, sizeof(value[0]));
1338 	if (data == NULL)
1339 		return (NULL);
1340 	size = sizeof(value[0]) * nitems;
1341 
1342 	memcpy(data, value, size);
1343 	nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1344 	    size, nitems);
1345 	if (nvp == NULL) {
1346 		ERRNO_SAVE();
1347 		nv_free(data);
1348 		ERRNO_RESTORE();
1349 	}
1350 
1351 	return (nvp);
1352 }
1353 
1354 nvpair_t *
1355 nvpair_create_number_array(const char *name, const uint64_t *value,
1356     size_t nitems)
1357 {
1358 	nvpair_t *nvp;
1359 	size_t size;
1360 	void *data;
1361 
1362 	if (value == NULL || nitems == 0) {
1363 		ERRNO_SET(EINVAL);
1364 		return (NULL);
1365 	}
1366 
1367 	data = nv_calloc(nitems, sizeof(value[0]));
1368 	if (data == NULL)
1369 		return (NULL);
1370 	size = sizeof(value[0]) * nitems;
1371 
1372 	memcpy(data, value, size);
1373 	nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1374 	    (uint64_t)(uintptr_t)data, size, nitems);
1375 	if (nvp == NULL) {
1376 		ERRNO_SAVE();
1377 		nv_free(data);
1378 		ERRNO_RESTORE();
1379 	}
1380 
1381 	return (nvp);
1382 }
1383 
1384 nvpair_t *
1385 nvpair_create_string_array(const char *name, const char * const *value,
1386     size_t nitems)
1387 {
1388 	nvpair_t *nvp;
1389 	unsigned int ii;
1390 	size_t datasize, size;
1391 	char **data;
1392 
1393 	if (value == NULL || nitems == 0) {
1394 		ERRNO_SET(EINVAL);
1395 		return (NULL);
1396 	}
1397 
1398 	nvp = NULL;
1399 	datasize = 0;
1400 	data = nv_calloc(nitems, sizeof(value[0]));
1401 	if (data == NULL)
1402 		return (NULL);
1403 
1404 	for (ii = 0; ii < nitems; ii++) {
1405 		if (value[ii] == NULL) {
1406 			ERRNO_SET(EINVAL);
1407 			goto fail;
1408 		}
1409 
1410 		size = strlen(value[ii]) + 1;
1411 		datasize += size;
1412 		data[ii] = nv_strdup(value[ii]);
1413 		if (data[ii] == NULL)
1414 			goto fail;
1415 	}
1416 	nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1417 	    (uint64_t)(uintptr_t)data, datasize, nitems);
1418 
1419 fail:
1420 	if (nvp == NULL) {
1421 		ERRNO_SAVE();
1422 		for (; ii > 0; ii--)
1423 			nv_free(data[ii - 1]);
1424 		nv_free(data);
1425 		ERRNO_RESTORE();
1426 	}
1427 
1428 	return (nvp);
1429 }
1430 
1431 nvpair_t *
1432 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1433     size_t nitems)
1434 {
1435 	unsigned int ii;
1436 	nvlist_t **nvls;
1437 	nvpair_t *parent;
1438 	int flags;
1439 
1440 	nvls = NULL;
1441 
1442 	if (value == NULL || nitems == 0) {
1443 		ERRNO_SET(EINVAL);
1444 		return (NULL);
1445 	}
1446 
1447 	nvls = nv_calloc(nitems, sizeof(value[0]));
1448 	if (nvls == NULL)
1449 		return (NULL);
1450 
1451 	for (ii = 0; ii < nitems; ii++) {
1452 		if (value[ii] == NULL) {
1453 			ERRNO_SET(EINVAL);
1454 			goto fail;
1455 		}
1456 
1457 		nvls[ii] = nvlist_clone(value[ii]);
1458 		if (nvls[ii] == NULL)
1459 			goto fail;
1460 
1461 		if (ii > 0) {
1462 			nvpair_t *nvp;
1463 
1464 			nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1465 			    (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1466 			if (nvp == NULL) {
1467 				ERRNO_SAVE();
1468 				nvlist_destroy(nvls[ii]);
1469 				ERRNO_RESTORE();
1470 				goto fail;
1471 			}
1472 			nvlist_set_array_next(nvls[ii - 1], nvp);
1473 		}
1474 	}
1475 	flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1476 	nvlist_set_flags(nvls[nitems - 1], flags);
1477 
1478 	parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1479 	    (uint64_t)(uintptr_t)nvls, 0, nitems);
1480 	if (parent == NULL)
1481 		goto fail;
1482 
1483 	for (ii = 0; ii < nitems; ii++)
1484 		nvlist_set_parent(nvls[ii], parent);
1485 
1486 	return (parent);
1487 
1488 fail:
1489 	ERRNO_SAVE();
1490 	for (; ii > 0; ii--)
1491 		nvlist_destroy(nvls[ii - 1]);
1492 	nv_free(nvls);
1493 	ERRNO_RESTORE();
1494 
1495 	return (NULL);
1496 }
1497 
1498 #ifndef _KERNEL
1499 nvpair_t *
1500 nvpair_create_descriptor_array(const char *name, const int *value,
1501     size_t nitems)
1502 {
1503 	unsigned int ii;
1504 	nvpair_t *nvp;
1505 	int *fds;
1506 
1507 	if (value == NULL) {
1508 		ERRNO_SET(EINVAL);
1509 		return (NULL);
1510 	}
1511 
1512 	nvp = NULL;
1513 
1514 	fds = nv_calloc(nitems, sizeof(value[0]));
1515 	if (fds == NULL)
1516 		return (NULL);
1517 	for (ii = 0; ii < nitems; ii++) {
1518 		if (value[ii] == -1) {
1519 			fds[ii] = -1;
1520 		} else {
1521 			fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1522 			if (fds[ii] == -1)
1523 				goto fail;
1524 		}
1525 	}
1526 
1527 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1528 	    (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1529 
1530 fail:
1531 	if (nvp == NULL) {
1532 		ERRNO_SAVE();
1533 		for (; ii > 0; ii--) {
1534 			if (fds[ii - 1] != -1)
1535 				close(fds[ii - 1]);
1536 		}
1537 		nv_free(fds);
1538 		ERRNO_RESTORE();
1539 	}
1540 
1541 	return (nvp);
1542 }
1543 #endif
1544 
1545 nvpair_t *
1546 nvpair_move_string(const char *name, char *value)
1547 {
1548 	nvpair_t *nvp;
1549 
1550 	if (value == NULL) {
1551 		ERRNO_SET(EINVAL);
1552 		return (NULL);
1553 	}
1554 
1555 	nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1556 	    strlen(value) + 1, 0);
1557 	if (nvp == NULL) {
1558 		ERRNO_SAVE();
1559 		nv_free(value);
1560 		ERRNO_RESTORE();
1561 	}
1562 
1563 	return (nvp);
1564 }
1565 
1566 nvpair_t *
1567 nvpair_move_nvlist(const char *name, nvlist_t *value)
1568 {
1569 	nvpair_t *nvp;
1570 
1571 	if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1572 		ERRNO_SET(EINVAL);
1573 		return (NULL);
1574 	}
1575 
1576 	if (nvlist_error(value) != 0) {
1577 		ERRNO_SET(nvlist_error(value));
1578 		nvlist_destroy(value);
1579 		return (NULL);
1580 	}
1581 
1582 	nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1583 	    0, 0);
1584 	if (nvp == NULL)
1585 		nvlist_destroy(value);
1586 	else
1587 		nvlist_set_parent(value, nvp);
1588 
1589 	return (nvp);
1590 }
1591 
1592 #ifndef _KERNEL
1593 nvpair_t *
1594 nvpair_move_descriptor(const char *name, int value)
1595 {
1596 	nvpair_t *nvp;
1597 
1598 	if (value < 0 || !fd_is_valid(value)) {
1599 		ERRNO_SET(EBADF);
1600 		return (NULL);
1601 	}
1602 
1603 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1604 	    sizeof(int64_t), 0);
1605 	if (nvp == NULL) {
1606 		ERRNO_SAVE();
1607 		close(value);
1608 		ERRNO_RESTORE();
1609 	}
1610 
1611 	return (nvp);
1612 }
1613 #endif
1614 
1615 nvpair_t *
1616 nvpair_move_binary(const char *name, void *value, size_t size)
1617 {
1618 	nvpair_t *nvp;
1619 
1620 	if (value == NULL || size == 0) {
1621 		ERRNO_SET(EINVAL);
1622 		return (NULL);
1623 	}
1624 
1625 	nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1626 	    size, 0);
1627 	if (nvp == NULL) {
1628 		ERRNO_SAVE();
1629 		nv_free(value);
1630 		ERRNO_RESTORE();
1631 	}
1632 
1633 	return (nvp);
1634 }
1635 
1636 nvpair_t *
1637 nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1638 {
1639 	nvpair_t *nvp;
1640 
1641 	if (value == NULL || nitems == 0) {
1642 		ERRNO_SET(EINVAL);
1643 		return (NULL);
1644 	}
1645 
1646 	nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1647 	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1648 	if (nvp == NULL) {
1649 		ERRNO_SAVE();
1650 		nv_free(value);
1651 		ERRNO_RESTORE();
1652 	}
1653 
1654 	return (nvp);
1655 }
1656 
1657 nvpair_t *
1658 nvpair_move_string_array(const char *name, char **value, size_t nitems)
1659 {
1660 	nvpair_t *nvp;
1661 	size_t i, size;
1662 
1663 	if (value == NULL || nitems == 0) {
1664 		ERRNO_SET(EINVAL);
1665 		return (NULL);
1666 	}
1667 
1668 	size = 0;
1669 	for (i = 0; i < nitems; i++) {
1670 		if (value[i] == NULL) {
1671 			ERRNO_SET(EINVAL);
1672 			return (NULL);
1673 		}
1674 
1675 		size += strlen(value[i]) + 1;
1676 	}
1677 
1678 	nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1679 	    (uint64_t)(uintptr_t)value, size, nitems);
1680 	if (nvp == NULL) {
1681 		ERRNO_SAVE();
1682 		for (i = 0; i < nitems; i++)
1683 			nv_free(value[i]);
1684 		nv_free(value);
1685 		ERRNO_RESTORE();
1686 	}
1687 
1688 	return (nvp);
1689 }
1690 
1691 nvpair_t *
1692 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1693 {
1694 	nvpair_t *nvp;
1695 
1696 	if (value == NULL || nitems == 0) {
1697 		ERRNO_SET(EINVAL);
1698 		return (NULL);
1699 	}
1700 
1701 	nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1702 	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1703 	if (nvp == NULL) {
1704 		ERRNO_SAVE();
1705 		nv_free(value);
1706 		ERRNO_RESTORE();
1707 	}
1708 
1709 	return (nvp);
1710 }
1711 
1712 nvpair_t *
1713 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1714 {
1715 	nvpair_t *parent;
1716 	unsigned int ii;
1717 	int flags;
1718 
1719 	if (value == NULL || nitems == 0) {
1720 		ERRNO_SET(EINVAL);
1721 		return (NULL);
1722 	}
1723 
1724 	for (ii = 0; ii < nitems; ii++) {
1725 		if (value == NULL || nvlist_error(value[ii]) != 0 ||
1726 		    nvlist_get_pararr(value[ii], NULL) != NULL) {
1727 			ERRNO_SET(EINVAL);
1728 			goto fail;
1729 		}
1730 		if (ii > 0) {
1731 			nvpair_t *nvp;
1732 
1733 			nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1734 			    (uint64_t)(uintptr_t)value[ii], 0, 0);
1735 			if (nvp == NULL)
1736 				goto fail;
1737 			nvlist_set_array_next(value[ii - 1], nvp);
1738 		}
1739 	}
1740 	flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1741 	nvlist_set_flags(value[nitems - 1], flags);
1742 
1743 	parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1744 	    (uint64_t)(uintptr_t)value, 0, nitems);
1745 	if (parent == NULL)
1746 		goto fail;
1747 
1748 	for (ii = 0; ii < nitems; ii++)
1749 		nvlist_set_parent(value[ii], parent);
1750 
1751 	return (parent);
1752 fail:
1753 	ERRNO_SAVE();
1754 	for (ii = 0; ii < nitems; ii++) {
1755 		if (value[ii] != NULL &&
1756 		    nvlist_get_pararr(value[ii], NULL) != NULL) {
1757 			nvlist_destroy(value[ii]);
1758 		}
1759 	}
1760 	nv_free(value);
1761 	ERRNO_RESTORE();
1762 
1763 	return (NULL);
1764 }
1765 
1766 #ifndef _KERNEL
1767 nvpair_t *
1768 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1769 {
1770 	nvpair_t *nvp;
1771 	size_t i;
1772 
1773 	if (value == NULL || nitems == 0) {
1774 		ERRNO_SET(EINVAL);
1775 		return (NULL);
1776 	}
1777 
1778 	for (i = 0; i < nitems; i++) {
1779 		if (value[i] != -1 && !fd_is_valid(value[i])) {
1780 			ERRNO_SET(EBADF);
1781 			goto fail;
1782 		}
1783 	}
1784 
1785 	nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1786 	    (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1787 	if (nvp == NULL)
1788 		goto fail;
1789 
1790 	return (nvp);
1791 fail:
1792 	ERRNO_SAVE();
1793 	for (i = 0; i < nitems; i++) {
1794 		if (fd_is_valid(value[i]))
1795 			close(value[i]);
1796 	}
1797 	nv_free(value);
1798 	ERRNO_RESTORE();
1799 
1800 	return (NULL);
1801 }
1802 #endif
1803 
1804 bool
1805 nvpair_get_bool(const nvpair_t *nvp)
1806 {
1807 
1808 	NVPAIR_ASSERT(nvp);
1809 
1810 	return (nvp->nvp_data == 1);
1811 }
1812 
1813 uint64_t
1814 nvpair_get_number(const nvpair_t *nvp)
1815 {
1816 
1817 	NVPAIR_ASSERT(nvp);
1818 
1819 	return (nvp->nvp_data);
1820 }
1821 
1822 const char *
1823 nvpair_get_string(const nvpair_t *nvp)
1824 {
1825 
1826 	NVPAIR_ASSERT(nvp);
1827 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1828 
1829 	return ((const char *)(intptr_t)nvp->nvp_data);
1830 }
1831 
1832 const nvlist_t *
1833 nvpair_get_nvlist(const nvpair_t *nvp)
1834 {
1835 
1836 	NVPAIR_ASSERT(nvp);
1837 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1838 
1839 	return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1840 }
1841 
1842 #ifndef _KERNEL
1843 int
1844 nvpair_get_descriptor(const nvpair_t *nvp)
1845 {
1846 
1847 	NVPAIR_ASSERT(nvp);
1848 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1849 
1850 	return ((int)nvp->nvp_data);
1851 }
1852 #endif
1853 
1854 const void *
1855 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1856 {
1857 
1858 	NVPAIR_ASSERT(nvp);
1859 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1860 
1861 	if (sizep != NULL)
1862 		*sizep = nvp->nvp_datasize;
1863 
1864 	return ((const void *)(intptr_t)nvp->nvp_data);
1865 }
1866 
1867 const bool *
1868 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1869 {
1870 
1871 	NVPAIR_ASSERT(nvp);
1872 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1873 
1874 	if (nitems != NULL)
1875 		*nitems = nvp->nvp_nitems;
1876 
1877 	return ((const bool *)(intptr_t)nvp->nvp_data);
1878 }
1879 
1880 const uint64_t *
1881 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1882 {
1883 
1884 	NVPAIR_ASSERT(nvp);
1885 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1886 
1887 	if (nitems != NULL)
1888 		*nitems = nvp->nvp_nitems;
1889 
1890 	return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1891 }
1892 
1893 const char * const *
1894 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1895 {
1896 
1897 	NVPAIR_ASSERT(nvp);
1898 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1899 
1900 	if (nitems != NULL)
1901 		*nitems = nvp->nvp_nitems;
1902 
1903 	return ((const char * const *)(intptr_t)nvp->nvp_data);
1904 }
1905 
1906 const nvlist_t * const *
1907 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1908 {
1909 
1910 	NVPAIR_ASSERT(nvp);
1911 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1912 
1913 	if (nitems != NULL)
1914 		*nitems = nvp->nvp_nitems;
1915 
1916 	return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1917 }
1918 
1919 #ifndef _KERNEL
1920 const int *
1921 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1922 {
1923 
1924 	NVPAIR_ASSERT(nvp);
1925 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1926 
1927 	if (nitems != NULL)
1928 		*nitems = nvp->nvp_nitems;
1929 
1930 	return ((const int *)(intptr_t)nvp->nvp_data);
1931 }
1932 #endif
1933 
1934 int
1935 nvpair_append_bool_array(nvpair_t *nvp, const bool value)
1936 {
1937 
1938 	NVPAIR_ASSERT(nvp);
1939 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1940 	return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1941 }
1942 
1943 int
1944 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
1945 {
1946 
1947 	NVPAIR_ASSERT(nvp);
1948 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1949 	return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1950 }
1951 
1952 int
1953 nvpair_append_string_array(nvpair_t *nvp, const char *value)
1954 {
1955 	char *str;
1956 
1957 	NVPAIR_ASSERT(nvp);
1958 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1959 	if (value == NULL) {
1960 		ERRNO_SET(EINVAL);
1961 		return (-1);
1962 	}
1963 	str = nv_strdup(value);
1964 	if (str == NULL) {
1965 		return (-1);
1966 	}
1967 	if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
1968 		nv_free(str);
1969 		return (-1);
1970 	}
1971 	return (0);
1972 }
1973 
1974 int
1975 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
1976 {
1977 	nvpair_t *tmpnvp;
1978 	nvlist_t *nvl, *prev;
1979 	int flags;
1980 
1981 	NVPAIR_ASSERT(nvp);
1982 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1983 	if (value == NULL || nvlist_error(value) != 0 ||
1984 	    nvlist_get_pararr(value, NULL) != NULL) {
1985 		ERRNO_SET(EINVAL);
1986 		return (-1);
1987 	}
1988 	nvl = nvlist_clone(value);
1989 	if (nvl == NULL) {
1990 		return (-1);
1991 	}
1992 	flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
1993 	nvlist_set_flags(nvl, flags);
1994 
1995 	tmpnvp = NULL;
1996 	prev = NULL;
1997 	if (nvp->nvp_nitems > 0) {
1998 		nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
1999 
2000 		prev = nvls[nvp->nvp_nitems - 1];
2001 		PJDLOG_ASSERT(prev != NULL);
2002 
2003 		tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
2004 		    (uint64_t)(uintptr_t)nvl, 0, 0);
2005 		if (tmpnvp == NULL) {
2006 			goto fail;
2007 		}
2008 	}
2009 	if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
2010 		goto fail;
2011 	}
2012 	if (tmpnvp) {
2013 		NVPAIR_ASSERT(tmpnvp);
2014 		nvlist_set_array_next(prev, tmpnvp);
2015 	}
2016 	nvlist_set_parent(nvl, nvp);
2017 	return (0);
2018 fail:
2019 	if (tmpnvp) {
2020 		nvpair_free(tmpnvp);
2021 	}
2022 	nvlist_destroy(nvl);
2023 	return (-1);
2024 }
2025 
2026 #ifndef _KERNEL
2027 int
2028 nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
2029 {
2030 	int fd;
2031 
2032 	NVPAIR_ASSERT(nvp);
2033 	PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
2034 	fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
2035 	if (fd == -1) {
2036 		return (-1);
2037 	}
2038 	if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
2039 		close(fd);
2040 		return (-1);
2041 	}
2042 	return (0);
2043 }
2044 #endif
2045 
2046 void
2047 nvpair_free(nvpair_t *nvp)
2048 {
2049 	size_t i;
2050 
2051 	NVPAIR_ASSERT(nvp);
2052 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
2053 
2054 	nvp->nvp_magic = 0;
2055 	switch (nvp->nvp_type) {
2056 #ifndef _KERNEL
2057 	case NV_TYPE_DESCRIPTOR:
2058 		close((int)nvp->nvp_data);
2059 		break;
2060 	case NV_TYPE_DESCRIPTOR_ARRAY:
2061 		for (i = 0; i < nvp->nvp_nitems; i++)
2062 			close(((int *)(intptr_t)nvp->nvp_data)[i]);
2063 		nv_free((int *)(intptr_t)nvp->nvp_data);
2064 		break;
2065 #endif
2066 	case NV_TYPE_NVLIST:
2067 		nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
2068 		break;
2069 	case NV_TYPE_STRING:
2070 		nv_free((char *)(intptr_t)nvp->nvp_data);
2071 		break;
2072 	case NV_TYPE_BINARY:
2073 		nv_free((void *)(intptr_t)nvp->nvp_data);
2074 		break;
2075 	case NV_TYPE_NVLIST_ARRAY:
2076 		for (i = 0; i < nvp->nvp_nitems; i++) {
2077 			nvlist_destroy(
2078 			    ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
2079 		}
2080 		nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
2081 		break;
2082 	case NV_TYPE_NUMBER_ARRAY:
2083 		nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
2084 		break;
2085 	case NV_TYPE_BOOL_ARRAY:
2086 		nv_free((bool *)(intptr_t)nvp->nvp_data);
2087 		break;
2088 	case NV_TYPE_STRING_ARRAY:
2089 		for (i = 0; i < nvp->nvp_nitems; i++)
2090 			nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
2091 		nv_free((char **)(intptr_t)nvp->nvp_data);
2092 		break;
2093 	}
2094 	nv_free(nvp);
2095 }
2096 
2097 void
2098 nvpair_free_structure(nvpair_t *nvp)
2099 {
2100 
2101 	NVPAIR_ASSERT(nvp);
2102 	PJDLOG_ASSERT(nvp->nvp_list == NULL);
2103 
2104 	nvp->nvp_magic = 0;
2105 	nv_free(nvp);
2106 }
2107 
2108 const char *
2109 nvpair_type_string(int type)
2110 {
2111 
2112 	switch (type) {
2113 	case NV_TYPE_NULL:
2114 		return ("NULL");
2115 	case NV_TYPE_BOOL:
2116 		return ("BOOL");
2117 	case NV_TYPE_NUMBER:
2118 		return ("NUMBER");
2119 	case NV_TYPE_STRING:
2120 		return ("STRING");
2121 	case NV_TYPE_NVLIST:
2122 		return ("NVLIST");
2123 	case NV_TYPE_DESCRIPTOR:
2124 		return ("DESCRIPTOR");
2125 	case NV_TYPE_BINARY:
2126 		return ("BINARY");
2127 	case NV_TYPE_BOOL_ARRAY:
2128 		return ("BOOL ARRAY");
2129 	case NV_TYPE_NUMBER_ARRAY:
2130 		return ("NUMBER ARRAY");
2131 	case NV_TYPE_STRING_ARRAY:
2132 		return ("STRING ARRAY");
2133 	case NV_TYPE_NVLIST_ARRAY:
2134 		return ("NVLIST ARRAY");
2135 	case NV_TYPE_DESCRIPTOR_ARRAY:
2136 		return ("DESCRIPTOR ARRAY");
2137 	default:
2138 		return ("<UNKNOWN>");
2139 	}
2140 }
2141 
2142