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