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