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