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