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