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