]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/subr_nvlist.c
Merge ACPICA 20150515.
[FreeBSD/FreeBSD.git] / sys / kern / subr_nvlist.c
1 /*-
2  * Copyright (c) 2009-2013 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/endian.h>
35 #include <sys/queue.h>
36
37 #ifdef _KERNEL
38
39 #include <sys/errno.h>
40 #include <sys/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/systm.h>
44
45 #include <machine/stdarg.h>
46
47 #else
48 #include <sys/socket.h>
49
50 #include <errno.h>
51 #include <stdarg.h>
52 #include <stdbool.h>
53 #include <stdint.h>
54 #define _WITH_DPRINTF
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <unistd.h>
59
60 #include "msgio.h"
61 #endif
62
63 #ifdef HAVE_PJDLOG
64 #include <pjdlog.h>
65 #endif
66
67 #include <sys/nv.h>
68 #include <sys/nv_impl.h>
69 #include <sys/nvlist_impl.h>
70 #include <sys/nvpair_impl.h>
71
72 #ifndef HAVE_PJDLOG
73 #ifdef _KERNEL
74 #define PJDLOG_ASSERT(...)              MPASS(__VA_ARGS__)
75 #define PJDLOG_RASSERT(expr, ...)       KASSERT(expr, (__VA_ARGS__))
76 #define PJDLOG_ABORT(...)               panic(__VA_ARGS__)
77 #else
78 #include <assert.h>
79 #define PJDLOG_ASSERT(...)              assert(__VA_ARGS__)
80 #define PJDLOG_RASSERT(expr, ...)       assert(expr)
81 #define PJDLOG_ABORT(...)               do {                            \
82         fprintf(stderr, "%s:%u: ", __FILE__, __LINE__);                 \
83         fprintf(stderr, __VA_ARGS__);                                   \
84         fprintf(stderr, "\n");                                          \
85         abort();                                                        \
86 } while (0)
87 #endif
88 #endif
89
90 #define NV_FLAG_PRIVATE_MASK    (NV_FLAG_BIG_ENDIAN)
91 #define NV_FLAG_PUBLIC_MASK     (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE)
92 #define NV_FLAG_ALL_MASK        (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
93
94 #define NVLIST_MAGIC    0x6e766c        /* "nvl" */
95 struct nvlist {
96         int              nvl_magic;
97         int              nvl_error;
98         int              nvl_flags;
99         nvpair_t        *nvl_parent;
100         struct nvl_head  nvl_head;
101 };
102
103 #define NVLIST_ASSERT(nvl)      do {                                    \
104         PJDLOG_ASSERT((nvl) != NULL);                                   \
105         PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);                \
106 } while (0)
107
108 #ifdef _KERNEL
109 MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
110 #endif
111
112 #define NVPAIR_ASSERT(nvp)      nvpair_assert(nvp)
113
114 #define NVLIST_HEADER_MAGIC     0x6c
115 #define NVLIST_HEADER_VERSION   0x00
116 struct nvlist_header {
117         uint8_t         nvlh_magic;
118         uint8_t         nvlh_version;
119         uint8_t         nvlh_flags;
120         uint64_t        nvlh_descriptors;
121         uint64_t        nvlh_size;
122 } __packed;
123
124 nvlist_t *
125 nvlist_create(int flags)
126 {
127         nvlist_t *nvl;
128
129         PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
130
131         nvl = nv_malloc(sizeof(*nvl));
132         if (nvl == NULL)
133                 return (NULL);
134         nvl->nvl_error = 0;
135         nvl->nvl_flags = flags;
136         nvl->nvl_parent = NULL;
137         TAILQ_INIT(&nvl->nvl_head);
138         nvl->nvl_magic = NVLIST_MAGIC;
139
140         return (nvl);
141 }
142
143 void
144 nvlist_destroy(nvlist_t *nvl)
145 {
146         nvpair_t *nvp;
147
148         if (nvl == NULL)
149                 return;
150
151         ERRNO_SAVE();
152
153         NVLIST_ASSERT(nvl);
154
155         while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
156                 nvlist_remove_nvpair(nvl, nvp);
157                 nvpair_free(nvp);
158         }
159         nvl->nvl_magic = 0;
160         nv_free(nvl);
161
162         ERRNO_RESTORE();
163 }
164
165 void
166 nvlist_set_error(nvlist_t *nvl, int error)
167 {
168
169         PJDLOG_ASSERT(error != 0);
170
171         /*
172          * Check for error != 0 so that we don't do the wrong thing if somebody
173          * tries to abuse this API when asserts are disabled.
174          */
175         if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
176                 nvl->nvl_error = error;
177 }
178
179 int
180 nvlist_error(const nvlist_t *nvl)
181 {
182
183         if (nvl == NULL)
184                 return (ENOMEM);
185
186         NVLIST_ASSERT(nvl);
187
188         return (nvl->nvl_error);
189 }
190
191 nvpair_t *
192 nvlist_get_nvpair_parent(const nvlist_t *nvl)
193 {
194
195         NVLIST_ASSERT(nvl);
196
197         return (nvl->nvl_parent);
198 }
199
200 const nvlist_t *
201 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
202 {
203         nvpair_t *nvp;
204
205         NVLIST_ASSERT(nvl);
206
207         nvp = nvl->nvl_parent;
208         if (cookiep != NULL)
209                 *cookiep = nvp;
210         if (nvp == NULL)
211                 return (NULL);
212
213         return (nvpair_nvlist(nvp));
214 }
215
216 void
217 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
218 {
219
220         NVLIST_ASSERT(nvl);
221
222         nvl->nvl_parent = parent;
223 }
224
225 bool
226 nvlist_empty(const nvlist_t *nvl)
227 {
228
229         NVLIST_ASSERT(nvl);
230         PJDLOG_ASSERT(nvl->nvl_error == 0);
231
232         return (nvlist_first_nvpair(nvl) == NULL);
233 }
234
235 int
236 nvlist_flags(const nvlist_t *nvl)
237 {
238
239         NVLIST_ASSERT(nvl);
240         PJDLOG_ASSERT(nvl->nvl_error == 0);
241         PJDLOG_ASSERT((nvl->nvl_flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
242
243         return (nvl->nvl_flags);
244 }
245
246 static void
247 nvlist_report_missing(int type, const char *name)
248 {
249
250         PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
251             name, nvpair_type_string(type));
252 }
253
254 static nvpair_t *
255 nvlist_find(const nvlist_t *nvl, int type, const char *name)
256 {
257         nvpair_t *nvp;
258
259         NVLIST_ASSERT(nvl);
260         PJDLOG_ASSERT(nvl->nvl_error == 0);
261         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
262             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
263
264         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
265             nvp = nvlist_next_nvpair(nvl, nvp)) {
266                 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
267                         continue;
268                 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
269                         if (strcasecmp(nvpair_name(nvp), name) != 0)
270                                 continue;
271                 } else {
272                         if (strcmp(nvpair_name(nvp), name) != 0)
273                                 continue;
274                 }
275                 break;
276         }
277
278         if (nvp == NULL)
279                 ERRNO_SET(ENOENT);
280
281         return (nvp);
282 }
283
284 bool
285 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
286 {
287
288         NVLIST_ASSERT(nvl);
289         PJDLOG_ASSERT(nvl->nvl_error == 0);
290         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
291             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
292
293         return (nvlist_find(nvl, type, name) != NULL);
294 }
295
296 void
297 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
298 {
299         nvpair_t *nvp;
300
301         NVLIST_ASSERT(nvl);
302         PJDLOG_ASSERT(nvl->nvl_error == 0);
303         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
304             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
305
306         nvp = nvlist_find(nvl, type, name);
307         if (nvp != NULL)
308                 nvlist_free_nvpair(nvl, nvp);
309         else
310                 nvlist_report_missing(type, name);
311 }
312
313 nvlist_t *
314 nvlist_clone(const nvlist_t *nvl)
315 {
316         nvlist_t *newnvl;
317         nvpair_t *nvp, *newnvp;
318
319         NVLIST_ASSERT(nvl);
320
321         if (nvl->nvl_error != 0) {
322                 ERRNO_SET(nvl->nvl_error);
323                 return (NULL);
324         }
325
326         newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
327         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
328             nvp = nvlist_next_nvpair(nvl, nvp)) {
329                 newnvp = nvpair_clone(nvp);
330                 if (newnvp == NULL)
331                         break;
332                 nvlist_move_nvpair(newnvl, newnvp);
333         }
334         if (nvp != NULL) {
335                 nvlist_destroy(newnvl);
336                 return (NULL);
337         }
338         return (newnvl);
339 }
340
341 #ifndef _KERNEL
342 static bool
343 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
344 {
345
346         if (nvlist_error(nvl) != 0) {
347                 dprintf(fd, "%*serror: %d\n", level * 4, "",
348                     nvlist_error(nvl));
349                 return (true);
350         }
351
352         return (false);
353 }
354
355 /*
356  * Dump content of nvlist.
357  */
358 void
359 nvlist_dump(const nvlist_t *nvl, int fd)
360 {
361         const nvlist_t *tmpnvl;
362         nvpair_t *nvp, *tmpnvp;
363         void *cookie;
364         int level;
365
366         level = 0;
367         if (nvlist_dump_error_check(nvl, fd, level))
368                 return;
369
370         nvp = nvlist_first_nvpair(nvl);
371         while (nvp != NULL) {
372                 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
373                     nvpair_type_string(nvpair_type(nvp)));
374                 switch (nvpair_type(nvp)) {
375                 case NV_TYPE_NULL:
376                         dprintf(fd, " null\n");
377                         break;
378                 case NV_TYPE_BOOL:
379                         dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
380                             "TRUE" : "FALSE");
381                         break;
382                 case NV_TYPE_NUMBER:
383                         dprintf(fd, " %ju (%jd) (0x%jx)\n",
384                             (uintmax_t)nvpair_get_number(nvp),
385                             (intmax_t)nvpair_get_number(nvp),
386                             (uintmax_t)nvpair_get_number(nvp));
387                         break;
388                 case NV_TYPE_STRING:
389                         dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
390                         break;
391                 case NV_TYPE_NVLIST:
392                         dprintf(fd, "\n");
393                         tmpnvl = nvpair_get_nvlist(nvp);
394                         if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
395                                 break;
396                         tmpnvp = nvlist_first_nvpair(tmpnvl);
397                         if (tmpnvp != NULL) {
398                                 nvl = tmpnvl;
399                                 nvp = tmpnvp;
400                                 level++;
401                                 continue;
402                         }
403                         break;
404                 case NV_TYPE_DESCRIPTOR:
405                         dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
406                         break;
407                 case NV_TYPE_BINARY:
408                     {
409                         const unsigned char *binary;
410                         unsigned int ii;
411                         size_t size;
412
413                         binary = nvpair_get_binary(nvp, &size);
414                         dprintf(fd, " %zu ", size);
415                         for (ii = 0; ii < size; ii++)
416                                 dprintf(fd, "%02hhx", binary[ii]);
417                         dprintf(fd, "\n");
418                         break;
419                     }
420                 default:
421                         PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
422                 }
423
424                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
425                         cookie = NULL;
426                         nvl = nvlist_get_parent(nvl, &cookie);
427                         if (nvl == NULL)
428                                 return;
429                         nvp = cookie;
430                         level--;
431                 }
432         }
433 }
434
435 void
436 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
437 {
438
439         fflush(fp);
440         nvlist_dump(nvl, fileno(fp));
441 }
442 #endif
443
444 /*
445  * The function obtains size of the nvlist after nvlist_pack().
446  */
447 size_t
448 nvlist_size(const nvlist_t *nvl)
449 {
450         const nvlist_t *tmpnvl;
451         const nvpair_t *nvp, *tmpnvp;
452         void *cookie;
453         size_t size;
454
455         NVLIST_ASSERT(nvl);
456         PJDLOG_ASSERT(nvl->nvl_error == 0);
457
458         size = sizeof(struct nvlist_header);
459         nvp = nvlist_first_nvpair(nvl);
460         while (nvp != NULL) {
461                 size += nvpair_header_size();
462                 size += strlen(nvpair_name(nvp)) + 1;
463                 if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
464                         size += sizeof(struct nvlist_header);
465                         size += nvpair_header_size() + 1;
466                         tmpnvl = nvpair_get_nvlist(nvp);
467                         PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
468                         tmpnvp = nvlist_first_nvpair(tmpnvl);
469                         if (tmpnvp != NULL) {
470                                 nvl = tmpnvl;
471                                 nvp = tmpnvp;
472                                 continue;
473                         }
474                 } else {
475                         size += nvpair_size(nvp);
476                 }
477
478                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
479                         cookie = NULL;
480                         nvl = nvlist_get_parent(nvl, &cookie);
481                         if (nvl == NULL)
482                                 goto out;
483                         nvp = cookie;
484                 }
485         }
486
487 out:
488         return (size);
489 }
490
491 #ifndef _KERNEL
492 static int *
493 nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
494 {
495         nvpair_t *nvp;
496         const char *name;
497         int type;
498
499         NVLIST_ASSERT(nvl);
500         PJDLOG_ASSERT(nvl->nvl_error == 0);
501
502         nvp = NULL;
503         do {
504                 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
505                         switch (type) {
506                         case NV_TYPE_DESCRIPTOR:
507                                 *descs = nvpair_get_descriptor(nvp);
508                                 descs++;
509                                 break;
510                         case NV_TYPE_NVLIST:
511                                 nvl = nvpair_get_nvlist(nvp);
512                                 nvp = NULL;
513                                 break;
514                         }
515                 }
516         } while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
517
518         return (descs);
519 }
520 #endif
521
522 #ifndef _KERNEL
523 int *
524 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
525 {
526         size_t nitems;
527         int *fds;
528
529         nitems = nvlist_ndescriptors(nvl);
530         fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
531         if (fds == NULL)
532                 return (NULL);
533         if (nitems > 0)
534                 nvlist_xdescriptors(nvl, fds);
535         fds[nitems] = -1;
536         if (nitemsp != NULL)
537                 *nitemsp = nitems;
538         return (fds);
539 }
540 #endif
541
542 size_t
543 nvlist_ndescriptors(const nvlist_t *nvl)
544 {
545 #ifndef _KERNEL
546         nvpair_t *nvp;
547         const char *name;
548         size_t ndescs;
549         int type;
550
551         NVLIST_ASSERT(nvl);
552         PJDLOG_ASSERT(nvl->nvl_error == 0);
553
554         ndescs = 0;
555         nvp = NULL;
556         do {
557                 while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) {
558                         switch (type) {
559                         case NV_TYPE_DESCRIPTOR:
560                                 ndescs++;
561                                 break;
562                         case NV_TYPE_NVLIST:
563                                 nvl = nvpair_get_nvlist(nvp);
564                                 nvp = NULL;
565                                 break;
566                         }
567                 }
568         } while ((nvl = nvlist_get_parent(nvl, (void**)&nvp)) != NULL);
569
570         return (ndescs);
571 #else
572         return (0);
573 #endif
574 }
575
576 static unsigned char *
577 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
578 {
579         struct nvlist_header nvlhdr;
580
581         NVLIST_ASSERT(nvl);
582
583         nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
584         nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
585         nvlhdr.nvlh_flags = nvl->nvl_flags;
586 #if BYTE_ORDER == BIG_ENDIAN
587         nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
588 #endif
589         nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
590         nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
591         PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
592         memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
593         ptr += sizeof(nvlhdr);
594         *leftp -= sizeof(nvlhdr);
595
596         return (ptr);
597 }
598
599 static void *
600 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
601 {
602         unsigned char *buf, *ptr;
603         size_t left, size;
604         const nvlist_t *tmpnvl;
605         nvpair_t *nvp, *tmpnvp;
606         void *cookie;
607
608         NVLIST_ASSERT(nvl);
609
610         if (nvl->nvl_error != 0) {
611                 ERRNO_SET(nvl->nvl_error);
612                 return (NULL);
613         }
614
615         size = nvlist_size(nvl);
616         buf = nv_malloc(size);
617         if (buf == NULL)
618                 return (NULL);
619
620         ptr = buf;
621         left = size;
622
623         ptr = nvlist_pack_header(nvl, ptr, &left);
624
625         nvp = nvlist_first_nvpair(nvl);
626         while (nvp != NULL) {
627                 NVPAIR_ASSERT(nvp);
628
629                 nvpair_init_datasize(nvp);
630                 ptr = nvpair_pack_header(nvp, ptr, &left);
631                 if (ptr == NULL) {
632                         nv_free(buf);
633                         return (NULL);
634                 }
635                 switch (nvpair_type(nvp)) {
636                 case NV_TYPE_NULL:
637                         ptr = nvpair_pack_null(nvp, ptr, &left);
638                         break;
639                 case NV_TYPE_BOOL:
640                         ptr = nvpair_pack_bool(nvp, ptr, &left);
641                         break;
642                 case NV_TYPE_NUMBER:
643                         ptr = nvpair_pack_number(nvp, ptr, &left);
644                         break;
645                 case NV_TYPE_STRING:
646                         ptr = nvpair_pack_string(nvp, ptr, &left);
647                         break;
648                 case NV_TYPE_NVLIST:
649                         tmpnvl = nvpair_get_nvlist(nvp);
650                         ptr = nvlist_pack_header(tmpnvl, ptr, &left);
651                         if (ptr == NULL)
652                                 goto out;
653                         tmpnvp = nvlist_first_nvpair(tmpnvl);
654                         if (tmpnvp != NULL) {
655                                 nvl = tmpnvl;
656                                 nvp = tmpnvp;
657                                 continue;
658                         }
659                         ptr = nvpair_pack_nvlist_up(ptr, &left);
660                         break;
661 #ifndef _KERNEL
662                 case NV_TYPE_DESCRIPTOR:
663                         ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
664                         break;
665 #endif
666                 case NV_TYPE_BINARY:
667                         ptr = nvpair_pack_binary(nvp, ptr, &left);
668                         break;
669                 default:
670                         PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
671                 }
672                 if (ptr == NULL) {
673                         nv_free(buf);
674                         return (NULL);
675                 }
676                 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
677                         cookie = NULL;
678                         nvl = nvlist_get_parent(nvl, &cookie);
679                         if (nvl == NULL)
680                                 goto out;
681                         nvp = cookie;
682                         ptr = nvpair_pack_nvlist_up(ptr, &left);
683                         if (ptr == NULL)
684                                 goto out;
685                 }
686         }
687
688 out:
689         if (sizep != NULL)
690                 *sizep = size;
691         return (buf);
692 }
693
694 void *
695 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
696 {
697
698         NVLIST_ASSERT(nvl);
699
700         if (nvl->nvl_error != 0) {
701                 ERRNO_SET(nvl->nvl_error);
702                 return (NULL);
703         }
704
705         if (nvlist_ndescriptors(nvl) > 0) {
706                 ERRNO_SET(EOPNOTSUPP);
707                 return (NULL);
708         }
709
710         return (nvlist_xpack(nvl, NULL, sizep));
711 }
712
713 static bool
714 nvlist_check_header(struct nvlist_header *nvlhdrp)
715 {
716
717         if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
718                 ERRNO_SET(EINVAL);
719                 return (false);
720         }
721         if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
722                 ERRNO_SET(EINVAL);
723                 return (false);
724         }
725 #if BYTE_ORDER == BIG_ENDIAN
726         if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
727                 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
728                 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
729         }
730 #else
731         if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
732                 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
733                 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
734         }
735 #endif
736         return (true);
737 }
738
739 const unsigned char *
740 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
741     bool *isbep, size_t *leftp)
742 {
743         struct nvlist_header nvlhdr;
744
745         if (*leftp < sizeof(nvlhdr))
746                 goto failed;
747
748         memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
749
750         if (!nvlist_check_header(&nvlhdr))
751                 goto failed;
752
753         if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
754                 goto failed;
755
756         /*
757          * nvlh_descriptors might be smaller than nfds in embedded nvlists.
758          */
759         if (nvlhdr.nvlh_descriptors > nfds)
760                 goto failed;
761
762         if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
763                 goto failed;
764
765         nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
766
767         ptr += sizeof(nvlhdr);
768         if (isbep != NULL)
769                 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
770         *leftp -= sizeof(nvlhdr);
771
772         return (ptr);
773 failed:
774         ERRNO_SET(EINVAL);
775         return (NULL);
776 }
777
778 static nvlist_t *
779 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
780     int flags)
781 {
782         const unsigned char *ptr;
783         nvlist_t *nvl, *retnvl, *tmpnvl;
784         nvpair_t *nvp;
785         size_t left;
786         bool isbe;
787
788         PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
789
790         left = size;
791         ptr = buf;
792
793         tmpnvl = NULL;
794         nvl = retnvl = nvlist_create(0);
795         if (nvl == NULL)
796                 goto failed;
797
798         ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
799         if (ptr == NULL)
800                 goto failed;
801         if (nvl->nvl_flags != flags) {
802                 ERRNO_SET(EILSEQ);
803                 goto failed;
804         }
805
806         while (left > 0) {
807                 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
808                 if (ptr == NULL)
809                         goto failed;
810                 switch (nvpair_type(nvp)) {
811                 case NV_TYPE_NULL:
812                         ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
813                         break;
814                 case NV_TYPE_BOOL:
815                         ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
816                         break;
817                 case NV_TYPE_NUMBER:
818                         ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
819                         break;
820                 case NV_TYPE_STRING:
821                         ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
822                         break;
823                 case NV_TYPE_NVLIST:
824                         ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
825                             &tmpnvl);
826                         nvlist_set_parent(tmpnvl, nvp);
827                         break;
828 #ifndef _KERNEL
829                 case NV_TYPE_DESCRIPTOR:
830                         ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
831                             fds, nfds);
832                         break;
833 #endif
834                 case NV_TYPE_BINARY:
835                         ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
836                         break;
837                 case NV_TYPE_NVLIST_UP:
838                         if (nvl->nvl_parent == NULL)
839                                 goto failed;
840                         nvl = nvpair_nvlist(nvl->nvl_parent);
841                         continue;
842                 default:
843                         PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
844                 }
845                 if (ptr == NULL)
846                         goto failed;
847                 nvlist_move_nvpair(nvl, nvp);
848                 if (tmpnvl != NULL) {
849                         nvl = tmpnvl;
850                         tmpnvl = NULL;
851                 }
852         }
853
854         return (retnvl);
855 failed:
856         nvlist_destroy(retnvl);
857         return (NULL);
858 }
859
860 nvlist_t *
861 nvlist_unpack(const void *buf, size_t size, int flags)
862 {
863
864         return (nvlist_xunpack(buf, size, NULL, 0, flags));
865 }
866
867 #ifndef _KERNEL
868 int
869 nvlist_send(int sock, const nvlist_t *nvl)
870 {
871         size_t datasize, nfds;
872         int *fds;
873         void *data;
874         int64_t fdidx;
875         int ret;
876
877         if (nvlist_error(nvl) != 0) {
878                 ERRNO_SET(nvlist_error(nvl));
879                 return (-1);
880         }
881
882         fds = nvlist_descriptors(nvl, &nfds);
883         if (fds == NULL)
884                 return (-1);
885
886         ret = -1;
887         data = NULL;
888         fdidx = 0;
889
890         data = nvlist_xpack(nvl, &fdidx, &datasize);
891         if (data == NULL)
892                 goto out;
893
894         if (buf_send(sock, data, datasize) == -1)
895                 goto out;
896
897         if (nfds > 0) {
898                 if (fd_send(sock, fds, nfds) == -1)
899                         goto out;
900         }
901
902         ret = 0;
903 out:
904         ERRNO_SAVE();
905         free(fds);
906         free(data);
907         ERRNO_RESTORE();
908         return (ret);
909 }
910
911 nvlist_t *
912 nvlist_recv(int sock, int flags)
913 {
914         struct nvlist_header nvlhdr;
915         nvlist_t *nvl, *ret;
916         unsigned char *buf;
917         size_t nfds, size, i;
918         int *fds;
919
920         if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
921                 return (NULL);
922
923         if (!nvlist_check_header(&nvlhdr))
924                 return (NULL);
925
926         nfds = (size_t)nvlhdr.nvlh_descriptors;
927         size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
928
929         buf = nv_malloc(size);
930         if (buf == NULL)
931                 return (NULL);
932
933         memcpy(buf, &nvlhdr, sizeof(nvlhdr));
934
935         ret = NULL;
936         fds = NULL;
937
938         if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
939                 goto out;
940
941         if (nfds > 0) {
942                 fds = nv_malloc(nfds * sizeof(fds[0]));
943                 if (fds == NULL)
944                         goto out;
945                 if (fd_recv(sock, fds, nfds) == -1)
946                         goto out;
947         }
948
949         nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
950         if (nvl == NULL) {
951                 ERRNO_SAVE();
952                 for (i = 0; i < nfds; i++)
953                         close(fds[i]);
954                 ERRNO_RESTORE();
955                 goto out;
956         }
957
958         ret = nvl;
959 out:
960         ERRNO_SAVE();
961         free(buf);
962         free(fds);
963         ERRNO_RESTORE();
964
965         return (ret);
966 }
967
968 nvlist_t *
969 nvlist_xfer(int sock, nvlist_t *nvl, int flags)
970 {
971
972         if (nvlist_send(sock, nvl) < 0) {
973                 nvlist_destroy(nvl);
974                 return (NULL);
975         }
976         nvlist_destroy(nvl);
977         return (nvlist_recv(sock, flags));
978 }
979 #endif
980
981 nvpair_t *
982 nvlist_first_nvpair(const nvlist_t *nvl)
983 {
984
985         NVLIST_ASSERT(nvl);
986
987         return (TAILQ_FIRST(&nvl->nvl_head));
988 }
989
990 nvpair_t *
991 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
992 {
993         nvpair_t *retnvp;
994
995         NVLIST_ASSERT(nvl);
996         NVPAIR_ASSERT(nvp);
997         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
998
999         retnvp = nvpair_next(nvp);
1000         PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1001
1002         return (retnvp);
1003
1004 }
1005
1006 nvpair_t *
1007 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1008 {
1009         nvpair_t *retnvp;
1010
1011         NVLIST_ASSERT(nvl);
1012         NVPAIR_ASSERT(nvp);
1013         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1014
1015         retnvp = nvpair_prev(nvp);
1016         PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1017
1018         return (retnvp);
1019 }
1020
1021 const char *
1022 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1023 {
1024         nvpair_t *nvp;
1025
1026         NVLIST_ASSERT(nvl);
1027         PJDLOG_ASSERT(cookiep != NULL);
1028
1029         if (*cookiep == NULL)
1030                 nvp = nvlist_first_nvpair(nvl);
1031         else
1032                 nvp = nvlist_next_nvpair(nvl, *cookiep);
1033         if (nvp == NULL)
1034                 return (NULL);
1035         if (typep != NULL)
1036                 *typep = nvpair_type(nvp);
1037         *cookiep = nvp;
1038         return (nvpair_name(nvp));
1039 }
1040
1041 bool
1042 nvlist_exists(const nvlist_t *nvl, const char *name)
1043 {
1044
1045         return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1046 }
1047
1048 #define NVLIST_EXISTS(type, TYPE)                                       \
1049 bool                                                                    \
1050 nvlist_exists_##type(const nvlist_t *nvl, const char *name)             \
1051 {                                                                       \
1052                                                                         \
1053         return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL);        \
1054 }
1055
1056 NVLIST_EXISTS(null, NULL)
1057 NVLIST_EXISTS(bool, BOOL)
1058 NVLIST_EXISTS(number, NUMBER)
1059 NVLIST_EXISTS(string, STRING)
1060 NVLIST_EXISTS(nvlist, NVLIST)
1061 #ifndef _KERNEL
1062 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1063 #endif
1064 NVLIST_EXISTS(binary, BINARY)
1065
1066 #undef  NVLIST_EXISTS
1067
1068 void
1069 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1070 {
1071         nvpair_t *newnvp;
1072
1073         NVPAIR_ASSERT(nvp);
1074
1075         if (nvlist_error(nvl) != 0) {
1076                 ERRNO_SET(nvlist_error(nvl));
1077                 return;
1078         }
1079         if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1080                 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1081                         nvl->nvl_error = EEXIST;
1082                         ERRNO_SET(nvlist_error(nvl));
1083                         return;
1084                 }
1085         }
1086
1087         newnvp = nvpair_clone(nvp);
1088         if (newnvp == NULL) {
1089                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1090                 ERRNO_SET(nvlist_error(nvl));
1091                 return;
1092         }
1093
1094         nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1095 }
1096
1097 void
1098 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1099 {
1100         va_list valueap;
1101
1102         va_start(valueap, valuefmt);
1103         nvlist_add_stringv(nvl, name, valuefmt, valueap);
1104         va_end(valueap);
1105 }
1106
1107 void
1108 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1109     va_list valueap)
1110 {
1111         nvpair_t *nvp;
1112
1113         if (nvlist_error(nvl) != 0) {
1114                 ERRNO_SET(nvlist_error(nvl));
1115                 return;
1116         }
1117
1118         nvp = nvpair_create_stringv(name, valuefmt, valueap);
1119         if (nvp == NULL) {
1120                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1121                 ERRNO_SET(nvl->nvl_error);
1122         } else {
1123                 nvlist_move_nvpair(nvl, nvp);
1124         }
1125 }
1126
1127 void
1128 nvlist_add_null(nvlist_t *nvl, const char *name)
1129 {
1130         nvpair_t *nvp;
1131
1132         if (nvlist_error(nvl) != 0) {
1133                 ERRNO_SET(nvlist_error(nvl));
1134                 return;
1135         }
1136
1137         nvp = nvpair_create_null(name);
1138         if (nvp == NULL) {
1139                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1140                 ERRNO_SET(nvl->nvl_error);
1141         } else {
1142                 nvlist_move_nvpair(nvl, nvp);
1143         }
1144 }
1145
1146 void
1147 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1148     size_t size)
1149 {
1150         nvpair_t *nvp;
1151
1152         if (nvlist_error(nvl) != 0) {
1153                 ERRNO_SET(nvlist_error(nvl));
1154                 return;
1155         }
1156
1157         nvp = nvpair_create_binary(name, value, size);
1158         if (nvp == NULL) {
1159                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1160                 ERRNO_SET(nvl->nvl_error);
1161         } else {
1162                 nvlist_move_nvpair(nvl, nvp);
1163         }
1164 }
1165
1166
1167 #define NVLIST_ADD(vtype, type)                                         \
1168 void                                                                    \
1169 nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value)         \
1170 {                                                                       \
1171         nvpair_t *nvp;                                                  \
1172                                                                         \
1173         if (nvlist_error(nvl) != 0) {                                   \
1174                 ERRNO_SET(nvlist_error(nvl));                           \
1175                 return;                                                 \
1176         }                                                               \
1177                                                                         \
1178         nvp = nvpair_create_##type(name, value);                        \
1179         if (nvp == NULL) {                                              \
1180                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);              \
1181                 ERRNO_SET(nvl->nvl_error);                              \
1182         } else {                                                        \
1183                 nvlist_move_nvpair(nvl, nvp);                           \
1184         }                                                               \
1185 }
1186
1187 NVLIST_ADD(bool, bool)
1188 NVLIST_ADD(uint64_t, number)
1189 NVLIST_ADD(const char *, string)
1190 NVLIST_ADD(const nvlist_t *, nvlist)
1191 #ifndef _KERNEL
1192 NVLIST_ADD(int, descriptor);
1193 #endif
1194
1195 #undef  NVLIST_ADD
1196
1197 void
1198 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1199 {
1200
1201         NVPAIR_ASSERT(nvp);
1202         PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1203
1204         if (nvlist_error(nvl) != 0) {
1205                 nvpair_free(nvp);
1206                 ERRNO_SET(nvlist_error(nvl));
1207                 return;
1208         }
1209         if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1210                 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1211                         nvpair_free(nvp);
1212                         nvl->nvl_error = EEXIST;
1213                         ERRNO_SET(nvl->nvl_error);
1214                         return;
1215                 }
1216         }
1217
1218         nvpair_insert(&nvl->nvl_head, nvp, nvl);
1219 }
1220
1221 void
1222 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1223 {
1224         nvpair_t *nvp;
1225
1226         if (nvlist_error(nvl) != 0) {
1227                 nv_free(value);
1228                 ERRNO_SET(nvlist_error(nvl));
1229                 return;
1230         }
1231
1232         nvp = nvpair_move_string(name, value);
1233         if (nvp == NULL) {
1234                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1235                 ERRNO_SET(nvl->nvl_error);
1236         } else {
1237                 nvlist_move_nvpair(nvl, nvp);
1238         }
1239 }
1240
1241 void
1242 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1243 {
1244         nvpair_t *nvp;
1245
1246         if (nvlist_error(nvl) != 0) {
1247                 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1248                         nvlist_destroy(value);
1249                 ERRNO_SET(nvlist_error(nvl));
1250                 return;
1251         }
1252
1253         nvp = nvpair_move_nvlist(name, value);
1254         if (nvp == NULL) {
1255                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1256                 ERRNO_SET(nvl->nvl_error);
1257         } else {
1258                 nvlist_move_nvpair(nvl, nvp);
1259         }
1260 }
1261
1262 #ifndef _KERNEL
1263 void
1264 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1265 {
1266         nvpair_t *nvp;
1267
1268         if (nvlist_error(nvl) != 0) {
1269                 close(value);
1270                 ERRNO_SET(nvlist_error(nvl));
1271                 return;
1272         }
1273
1274         nvp = nvpair_move_descriptor(name, value);
1275         if (nvp == NULL) {
1276                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1277                 ERRNO_SET(nvl->nvl_error);
1278         } else {
1279                 nvlist_move_nvpair(nvl, nvp);
1280         }
1281 }
1282 #endif
1283
1284 void
1285 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1286 {
1287         nvpair_t *nvp;
1288
1289         if (nvlist_error(nvl) != 0) {
1290                 nv_free(value);
1291                 ERRNO_SET(nvlist_error(nvl));
1292                 return;
1293         }
1294
1295         nvp = nvpair_move_binary(name, value, size);
1296         if (nvp == NULL) {
1297                 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1298                 ERRNO_SET(nvl->nvl_error);
1299         } else {
1300                 nvlist_move_nvpair(nvl, nvp);
1301         }
1302 }
1303
1304 const nvpair_t *
1305 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1306 {
1307
1308         return (nvlist_find(nvl, NV_TYPE_NONE, name));
1309 }
1310
1311 #define NVLIST_GET(ftype, type, TYPE)                                   \
1312 ftype                                                                   \
1313 nvlist_get_##type(const nvlist_t *nvl, const char *name)                \
1314 {                                                                       \
1315         const nvpair_t *nvp;                                            \
1316                                                                         \
1317         nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);                   \
1318         if (nvp == NULL)                                                \
1319                 nvlist_report_missing(NV_TYPE_##TYPE, name);            \
1320         return (nvpair_get_##type(nvp));                                \
1321 }
1322
1323 NVLIST_GET(bool, bool, BOOL)
1324 NVLIST_GET(uint64_t, number, NUMBER)
1325 NVLIST_GET(const char *, string, STRING)
1326 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1327 #ifndef _KERNEL
1328 NVLIST_GET(int, descriptor, DESCRIPTOR)
1329 #endif
1330
1331 #undef  NVLIST_GET
1332
1333 const void *
1334 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1335 {
1336         nvpair_t *nvp;
1337
1338         nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1339         if (nvp == NULL)
1340                 nvlist_report_missing(NV_TYPE_BINARY, name);
1341
1342         return (nvpair_get_binary(nvp, sizep));
1343 }
1344
1345 #define NVLIST_TAKE(ftype, type, TYPE)                                  \
1346 ftype                                                                   \
1347 nvlist_take_##type(nvlist_t *nvl, const char *name)                     \
1348 {                                                                       \
1349         nvpair_t *nvp;                                                  \
1350         ftype value;                                                    \
1351                                                                         \
1352         nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);                   \
1353         if (nvp == NULL)                                                \
1354                 nvlist_report_missing(NV_TYPE_##TYPE, name);            \
1355         value = (ftype)(intptr_t)nvpair_get_##type(nvp);                \
1356         nvlist_remove_nvpair(nvl, nvp);                                 \
1357         nvpair_free_structure(nvp);                                     \
1358         return (value);                                                 \
1359 }
1360
1361 NVLIST_TAKE(bool, bool, BOOL)
1362 NVLIST_TAKE(uint64_t, number, NUMBER)
1363 NVLIST_TAKE(char *, string, STRING)
1364 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1365 #ifndef _KERNEL
1366 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1367 #endif
1368
1369 #undef  NVLIST_TAKE
1370
1371 void *
1372 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1373 {
1374         nvpair_t *nvp;
1375         void *value;
1376
1377         nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1378         if (nvp == NULL)
1379                 nvlist_report_missing(NV_TYPE_BINARY, name);
1380
1381         value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1382         nvlist_remove_nvpair(nvl, nvp);
1383         nvpair_free_structure(nvp);
1384         return (value);
1385 }
1386
1387 void
1388 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1389 {
1390
1391         NVLIST_ASSERT(nvl);
1392         NVPAIR_ASSERT(nvp);
1393         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1394
1395         nvpair_remove(&nvl->nvl_head, nvp, nvl);
1396 }
1397
1398 void
1399 nvlist_free(nvlist_t *nvl, const char *name)
1400 {
1401
1402         nvlist_free_type(nvl, name, NV_TYPE_NONE);
1403 }
1404
1405 #define NVLIST_FREE(type, TYPE)                                         \
1406 void                                                                    \
1407 nvlist_free_##type(nvlist_t *nvl, const char *name)                     \
1408 {                                                                       \
1409                                                                         \
1410         nvlist_free_type(nvl, name, NV_TYPE_##TYPE);                    \
1411 }
1412
1413 NVLIST_FREE(null, NULL)
1414 NVLIST_FREE(bool, BOOL)
1415 NVLIST_FREE(number, NUMBER)
1416 NVLIST_FREE(string, STRING)
1417 NVLIST_FREE(nvlist, NVLIST)
1418 #ifndef _KERNEL
1419 NVLIST_FREE(descriptor, DESCRIPTOR)
1420 #endif
1421 NVLIST_FREE(binary, BINARY)
1422
1423 #undef  NVLIST_FREE
1424
1425 void
1426 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1427 {
1428
1429         NVLIST_ASSERT(nvl);
1430         NVPAIR_ASSERT(nvp);
1431         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1432
1433         nvlist_remove_nvpair(nvl, nvp);
1434         nvpair_free(nvp);
1435 }
1436