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