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