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