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