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