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