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