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