]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libnv/nvlist.c
MFp4 @1189139:
[FreeBSD/FreeBSD.git] / lib / libnv / 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 #include <sys/socket.h>
37
38 #include <errno.h>
39 #include <stdarg.h>
40 #include <stdbool.h>
41 #include <stdint.h>
42 #define _WITH_DPRINTF
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47
48 #ifdef HAVE_PJDLOG
49 #include <pjdlog.h>
50 #endif
51
52 #include "msgio.h"
53 #include "nv.h"
54 #include "nv_impl.h"
55 #include "nvlist_impl.h"
56 #include "nvpair_impl.h"
57
58 #ifndef HAVE_PJDLOG
59 #include <assert.h>
60 #define PJDLOG_ASSERT(...)              assert(__VA_ARGS__)
61 #define PJDLOG_RASSERT(expr, ...)       assert(expr)
62 #define PJDLOG_ABORT(...)               do {                            \
63         fprintf(stderr, "%s:%u: ", __FILE__, __LINE__);                 \
64         fprintf(stderr, __VA_ARGS__);                                   \
65         fprintf(stderr, "\n");                                          \
66         abort();                                                        \
67 } while (0)
68 #endif
69
70 #define NV_FLAG_PRIVATE_MASK    (NV_FLAG_BIG_ENDIAN)
71 #define NV_FLAG_PUBLIC_MASK     (NV_FLAG_IGNORE_CASE)
72 #define NV_FLAG_ALL_MASK        (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
73
74 #define NVLIST_MAGIC    0x6e766c        /* "nvl" */
75 struct nvlist {
76         int             nvl_magic;
77         int             nvl_error;
78         int             nvl_flags;
79         struct nvl_head nvl_head;
80 };
81
82 #define NVLIST_ASSERT(nvl)      do {                                    \
83         PJDLOG_ASSERT((nvl) != NULL);                                   \
84         PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);                \
85 } while (0)
86
87 #define NVPAIR_ASSERT(nvp)      nvpair_assert(nvp)
88
89 #define NVLIST_HEADER_MAGIC     0x6c
90 #define NVLIST_HEADER_VERSION   0x00
91 struct nvlist_header {
92         uint8_t         nvlh_magic;
93         uint8_t         nvlh_version;
94         uint8_t         nvlh_flags;
95         uint64_t        nvlh_descriptors;
96         uint64_t        nvlh_size;
97 } __packed;
98
99 nvlist_t *
100 nvlist_create(int flags)
101 {
102         nvlist_t *nvl;
103
104         PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
105
106         nvl = malloc(sizeof(*nvl));
107         nvl->nvl_error = 0;
108         nvl->nvl_flags = flags;
109         TAILQ_INIT(&nvl->nvl_head);
110         nvl->nvl_magic = NVLIST_MAGIC;
111
112         return (nvl);
113 }
114
115 void
116 nvlist_destroy(nvlist_t *nvl)
117 {
118         nvpair_t *nvp;
119         int serrno;
120
121         if (nvl == NULL)
122                 return;
123
124         serrno = errno;
125
126         NVLIST_ASSERT(nvl);
127
128         while ((nvp = nvlist_first_nvpair(nvl)) != NULL)
129                 nvlist_remove_nvpair(nvl, nvp);
130         nvl->nvl_magic = 0;
131         free(nvl);
132
133         errno = serrno;
134 }
135
136 int
137 nvlist_error(const nvlist_t *nvl)
138 {
139
140         if (nvl == NULL)
141                 return (ENOMEM);
142
143         NVLIST_ASSERT(nvl);
144
145         return (nvl->nvl_error);
146 }
147
148 bool
149 nvlist_empty(const nvlist_t *nvl)
150 {
151
152         NVLIST_ASSERT(nvl);
153         PJDLOG_ASSERT(nvl->nvl_error == 0);
154
155         return (nvlist_first_nvpair(nvl) == NULL);
156 }
157
158 static void
159 nvlist_report_missing(int type, const char *namefmt, va_list nameap)
160 {
161         char *name;
162
163         vasprintf(&name, namefmt, nameap);
164         PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
165             name != NULL ? name : "N/A", nvpair_type_string(type));
166 }
167
168 static nvpair_t *
169 nvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
170 {
171         nvpair_t *nvp;
172         char *name;
173
174         NVLIST_ASSERT(nvl);
175         PJDLOG_ASSERT(nvl->nvl_error == 0);
176         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
177             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
178
179         if (vasprintf(&name, namefmt, nameap) < 0)
180                 return (NULL);
181
182         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
183             nvp = nvlist_next_nvpair(nvl, nvp)) {
184                 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
185                         continue;
186                 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
187                         if (strcasecmp(nvpair_name(nvp), name) != 0)
188                                 continue;
189                 } else {
190                         if (strcmp(nvpair_name(nvp), name) != 0)
191                                 continue;
192                 }
193                 break;
194         }
195
196         free(name);
197
198         if (nvp == NULL)
199                 errno = ENOENT;
200
201         return (nvp);
202 }
203
204 bool
205 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
206 {
207
208         return (nvlist_existsf_type(nvl, type, "%s", name));
209 }
210
211 bool
212 nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...)
213 {
214         va_list nameap;
215         bool ret;
216
217         va_start(nameap, namefmt);
218         ret = nvlist_existsv_type(nvl, type, namefmt, nameap);
219         va_end(nameap);
220
221         return (ret);
222 }
223
224 bool
225 nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt,
226     va_list nameap)
227 {
228
229         NVLIST_ASSERT(nvl);
230         PJDLOG_ASSERT(nvl->nvl_error == 0);
231         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
232             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
233
234         return (nvlist_findv(nvl, type, namefmt, nameap) != NULL);
235 }
236
237 void
238 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
239 {
240
241         nvlist_freef_type(nvl, type, "%s", name);
242 }
243
244 void
245 nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...)
246 {
247         va_list nameap;
248
249         va_start(nameap, namefmt);
250         nvlist_freev_type(nvl, type, namefmt, nameap);
251         va_end(nameap);
252 }
253
254 void
255 nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
256 {
257         va_list cnameap;
258         nvpair_t *nvp;
259
260         NVLIST_ASSERT(nvl);
261         PJDLOG_ASSERT(nvl->nvl_error == 0);
262         PJDLOG_ASSERT(type == NV_TYPE_NONE ||
263             (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
264
265         va_copy(cnameap, nameap);
266         nvp = nvlist_findv(nvl, type, namefmt, cnameap);
267         va_end(cnameap);
268         if (nvp != NULL)
269                 nvlist_free_nvpair(nvl, nvp);
270         else
271                 nvlist_report_missing(type, namefmt, nameap);
272 }
273
274 nvlist_t *
275 nvlist_clone(const nvlist_t *nvl)
276 {
277         nvlist_t *newnvl;
278         nvpair_t *nvp, *newnvp;
279
280         NVLIST_ASSERT(nvl);
281
282         if (nvl->nvl_error != 0) {
283                 errno = nvl->nvl_error;
284                 return (NULL);
285         }
286
287         newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
288         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
289             nvp = nvlist_next_nvpair(nvl, nvp)) {
290                 newnvp = nvpair_clone(nvp);
291                 if (newnvp == NULL)
292                         break;
293                 nvlist_move_nvpair(newnvl, newnvp);
294         }
295         if (nvp != NULL) {
296                 nvlist_destroy(newnvl);
297                 return (NULL);
298         }
299         return (newnvl);
300 }
301
302 /*
303  * Dump content of nvlist.
304  */
305 static void
306 nvlist_xdump(const nvlist_t *nvl, int fd, int level)
307 {
308         nvpair_t *nvp;
309
310         PJDLOG_ASSERT(level < 3);
311
312         if (nvlist_error(nvl) != 0) {
313                 dprintf(fd, "%*serror: %d\n", level * 4, "",
314                     nvlist_error(nvl));
315                 return;
316         }
317
318         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
319             nvp = nvlist_next_nvpair(nvl, nvp)) {
320                 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
321                     nvpair_type_string(nvpair_type(nvp)));
322                 switch (nvpair_type(nvp)) {
323                 case NV_TYPE_NULL:
324                         dprintf(fd, " null\n");
325                         break;
326                 case NV_TYPE_BOOL:
327                         dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
328                             "TRUE" : "FALSE");
329                         break;
330                 case NV_TYPE_NUMBER:
331                         dprintf(fd, " %ju (%jd) (0x%jx)\n",
332                             (uintmax_t)nvpair_get_number(nvp),
333                             (intmax_t)nvpair_get_number(nvp),
334                             (uintmax_t)nvpair_get_number(nvp));
335                         break;
336                 case NV_TYPE_STRING:
337                         dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
338                         break;
339                 case NV_TYPE_NVLIST:
340                         dprintf(fd, "\n");
341                         nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1);
342                         break;
343                 case NV_TYPE_DESCRIPTOR:
344                         dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
345                         break;
346                 case NV_TYPE_BINARY:
347                     {
348                         const unsigned char *binary;
349                         unsigned int ii;
350                         size_t size;
351
352                         binary = nvpair_get_binary(nvp, &size);
353                         dprintf(fd, " %zu ", size);
354                         for (ii = 0; ii < size; ii++)
355                                 dprintf(fd, "%02hhx", binary[ii]);
356                         dprintf(fd, "\n");
357                         break;
358                     }
359                 default:
360                         PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
361                 }
362         }
363 }
364
365 void
366 nvlist_dump(const nvlist_t *nvl, int fd)
367 {
368
369         nvlist_xdump(nvl, fd, 0);
370 }
371
372 void
373 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
374 {
375
376         fflush(fp);
377         nvlist_dump(nvl, fileno(fp));
378 }
379
380 /*
381  * The function obtains size of the nvlist after nvlist_pack().
382  * Additional argument 'level' allows to track how deep are we as we obtain
383  * size of the NV_TYPE_NVLIST elements using recursion. We allow at most
384  * three levels of recursion.
385  */
386 static size_t
387 nvlist_xsize(const nvlist_t *nvl, int level)
388 {
389         const nvpair_t *nvp;
390         size_t size;
391
392         NVLIST_ASSERT(nvl);
393         PJDLOG_ASSERT(nvl->nvl_error == 0);
394         PJDLOG_ASSERT(level < 3);
395
396         size = sizeof(struct nvlist_header);
397         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
398             nvp = nvlist_next_nvpair(nvl, nvp)) {
399                 size += nvpair_header_size();
400                 size += strlen(nvpair_name(nvp)) + 1;
401                 if (nvpair_type(nvp) == NV_TYPE_NVLIST)
402                         size += nvlist_xsize(nvpair_get_nvlist(nvp), level + 1);
403                 else
404                         size += nvpair_size(nvp);
405         }
406
407         return (size);
408 }
409
410 size_t
411 nvlist_size(const nvlist_t *nvl)
412 {
413
414         return (nvlist_xsize(nvl, 0));
415 }
416
417 static int *
418 nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
419 {
420         const nvpair_t *nvp;
421
422         NVLIST_ASSERT(nvl);
423         PJDLOG_ASSERT(nvl->nvl_error == 0);
424         PJDLOG_ASSERT(level < 3);
425
426         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
427             nvp = nvlist_next_nvpair(nvl, nvp)) {
428                 switch (nvpair_type(nvp)) {
429                 case NV_TYPE_DESCRIPTOR:
430                         *descs = nvpair_get_descriptor(nvp);
431                         descs++;
432                         break;
433                 case NV_TYPE_NVLIST:
434                         descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
435                             descs, level + 1);
436                         break;
437                 }
438         }
439
440         return (descs);
441 }
442
443 int *
444 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
445 {
446         size_t nitems;
447         int *fds;
448
449         nitems = nvlist_ndescriptors(nvl);
450         fds = malloc(sizeof(fds[0]) * (nitems + 1));
451         if (fds == NULL)
452                 return (NULL);
453         if (nitems > 0)
454                 nvlist_xdescriptors(nvl, fds, 0);
455         fds[nitems] = -1;
456         if (nitemsp != NULL)
457                 *nitemsp = nitems;
458         return (fds);
459 }
460
461 static size_t
462 nvlist_xndescriptors(const nvlist_t *nvl, int level)
463 {
464         const nvpair_t *nvp;
465         size_t ndescs;
466
467         NVLIST_ASSERT(nvl);
468         PJDLOG_ASSERT(nvl->nvl_error == 0);
469         PJDLOG_ASSERT(level < 3);
470
471         ndescs = 0;
472         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
473             nvp = nvlist_next_nvpair(nvl, nvp)) {
474                 switch (nvpair_type(nvp)) {
475                 case NV_TYPE_DESCRIPTOR:
476                         ndescs++;
477                         break;
478                 case NV_TYPE_NVLIST:
479                         ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
480                             level + 1);
481                         break;
482                 }
483         }
484
485         return (ndescs);
486 }
487
488 size_t
489 nvlist_ndescriptors(const nvlist_t *nvl)
490 {
491
492         return (nvlist_xndescriptors(nvl, 0));
493 }
494
495 static unsigned char *
496 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
497 {
498         struct nvlist_header nvlhdr;
499
500         NVLIST_ASSERT(nvl);
501
502         nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
503         nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
504         nvlhdr.nvlh_flags = nvl->nvl_flags;
505 #if BYTE_ORDER == BIG_ENDIAN
506         nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
507 #endif
508         nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
509         nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
510         PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
511         memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
512         ptr += sizeof(nvlhdr);
513         *leftp -= sizeof(nvlhdr);
514
515         return (ptr);
516 }
517
518 void *
519 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
520 {
521         unsigned char *buf, *ptr;
522         size_t left, size;
523         nvpair_t *nvp;
524
525         NVLIST_ASSERT(nvl);
526
527         if (nvl->nvl_error != 0) {
528                 errno = nvl->nvl_error;
529                 return (NULL);
530         }
531
532         size = nvlist_size(nvl);
533         buf = malloc(size);
534         if (buf == NULL)
535                 return (NULL);
536
537         ptr = buf;
538         left = size;
539
540         ptr = nvlist_pack_header(nvl, ptr, &left);
541
542         for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
543             nvp = nvlist_next_nvpair(nvl, nvp)) {
544                 ptr = nvpair_pack(nvp, ptr, fdidxp, &left);
545                 if (ptr == NULL) {
546                         free(buf);
547                         return (NULL);
548                 }
549         }
550
551         if (sizep != NULL)
552                 *sizep = size;
553         return (buf);
554 }
555
556 void *
557 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
558 {
559
560         NVLIST_ASSERT(nvl);
561
562         if (nvl->nvl_error != 0) {
563                 errno = nvl->nvl_error;
564                 return (NULL);
565         }
566
567         if (nvlist_ndescriptors(nvl) > 0) {
568                 errno = EOPNOTSUPP;
569                 return (NULL);
570         }
571
572         return (nvlist_xpack(nvl, NULL, sizep));
573 }
574
575 static bool
576 nvlist_check_header(struct nvlist_header *nvlhdrp)
577 {
578
579         if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
580                 errno = EINVAL;
581                 return (false);
582         }
583         if ((nvlhdrp->nvlh_flags &= ~NV_FLAG_ALL_MASK) != 0) {
584                 errno = EINVAL;
585                 return (false);
586         }
587 #if BYTE_ORDER == BIG_ENDIAN
588         if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
589                 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
590                 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
591         }
592 #else
593         if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
594                 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
595                 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
596         }
597 #endif
598         return (true);
599 }
600
601 static const unsigned char *
602 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
603     int *flagsp, size_t *leftp)
604 {
605         struct nvlist_header nvlhdr;
606
607         if (*leftp < sizeof(nvlhdr))
608                 goto failed;
609
610         memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
611
612         if (!nvlist_check_header(&nvlhdr))
613                 goto failed;
614
615         if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
616                 goto failed;
617
618         /*
619          * nvlh_descriptors might be smaller than nfds in embedded nvlists.
620          */
621         if (nvlhdr.nvlh_descriptors > nfds)
622                 goto failed;
623
624         if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
625                 goto failed;
626
627         nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
628
629         ptr += sizeof(nvlhdr);
630         *flagsp = (int)nvlhdr.nvlh_flags;
631         *leftp -= sizeof(nvlhdr);
632
633         return (ptr);
634 failed:
635         errno = EINVAL;
636         return (NULL);
637 }
638
639 nvlist_t *
640 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
641 {
642         const unsigned char *ptr;
643         nvlist_t *nvl;
644         nvpair_t *nvp;
645         size_t left;
646         int flags;
647
648         left = size;
649         ptr = buf;
650
651         nvl = nvlist_create(0);
652         if (nvl == NULL)
653                 goto failed;
654
655         ptr = nvlist_unpack_header(nvl, ptr, nfds, &flags, &left);
656         if (ptr == NULL)
657                 goto failed;
658
659         while (left > 0) {
660                 ptr = nvpair_unpack(flags, ptr, &left, fds, nfds, &nvp);
661                 if (ptr == NULL)
662                         goto failed;
663                 nvlist_move_nvpair(nvl, nvp);
664         }
665
666         return (nvl);
667 failed:
668         nvlist_destroy(nvl);
669         return (NULL);
670 }
671
672 nvlist_t *
673 nvlist_unpack(const void *buf, size_t size)
674 {
675
676         return (nvlist_xunpack(buf, size, NULL, 0));
677 }
678
679 int
680 nvlist_send(int sock, const nvlist_t *nvl)
681 {
682         size_t datasize, nfds;
683         int *fds;
684         void *data;
685         int64_t fdidx;
686         int serrno, ret;
687
688         if (nvlist_error(nvl) != 0) {
689                 errno = nvlist_error(nvl);
690                 return (-1);
691         }
692
693         fds = nvlist_descriptors(nvl, &nfds);
694         if (fds == NULL)
695                 return (-1);
696
697         ret = -1;
698         data = NULL;
699         fdidx = 0;
700
701         data = nvlist_xpack(nvl, &fdidx, &datasize);
702         if (data == NULL)
703                 goto out;
704
705         if (buf_send(sock, data, datasize) == -1)
706                 goto out;
707
708         if (nfds > 0) {
709                 if (fd_send(sock, fds, nfds) == -1)
710                         goto out;
711         }
712
713         ret = 0;
714 out:
715         serrno = errno;
716         free(fds);
717         free(data);
718         errno = serrno;
719         return (ret);
720 }
721
722 nvlist_t *
723 nvlist_recv(int sock)
724 {
725         struct nvlist_header nvlhdr;
726         nvlist_t *nvl, *ret;
727         unsigned char *buf;
728         size_t nfds, size;
729         int serrno, *fds;
730
731         if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
732                 return (NULL);
733
734         if (!nvlist_check_header(&nvlhdr))
735                 return (NULL);
736
737         nfds = (size_t)nvlhdr.nvlh_descriptors;
738         size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
739
740         buf = malloc(size);
741         if (buf == NULL)
742                 return (NULL);
743
744         memcpy(buf, &nvlhdr, sizeof(nvlhdr));
745
746         ret = NULL;
747         fds = NULL;
748
749         if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
750                 goto out;
751
752         if (nfds > 0) {
753                 fds = malloc(nfds * sizeof(fds[0]));
754                 if (fds == NULL)
755                         goto out;
756                 if (fd_recv(sock, fds, nfds) == -1)
757                         goto out;
758         }
759
760         nvl = nvlist_xunpack(buf, size, fds, nfds);
761         if (nvl == NULL)
762                 goto out;
763
764         ret = nvl;
765 out:
766         serrno = errno;
767         free(buf);
768         free(fds);
769         errno = serrno;
770
771         return (ret);
772 }
773
774 nvlist_t *
775 nvlist_xfer(int sock, nvlist_t *nvl)
776 {
777
778         if (nvlist_send(sock, nvl) < 0) {
779                 nvlist_destroy(nvl);
780                 return (NULL);
781         }
782         nvlist_destroy(nvl);
783         return (nvlist_recv(sock));
784 }
785
786 nvpair_t *
787 nvlist_first_nvpair(const nvlist_t *nvl)
788 {
789
790         NVLIST_ASSERT(nvl);
791
792         return (TAILQ_FIRST(&nvl->nvl_head));
793 }
794
795 nvpair_t *
796 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
797 {
798         nvpair_t *retnvp;
799
800         NVLIST_ASSERT(nvl);
801         NVPAIR_ASSERT(nvp);
802         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
803
804         retnvp = nvpair_next(nvp);
805         PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
806
807         return (retnvp);
808
809 }
810
811 nvpair_t *
812 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
813 {
814         nvpair_t *retnvp;
815
816         NVLIST_ASSERT(nvl);
817         NVPAIR_ASSERT(nvp);
818         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
819
820         retnvp = nvpair_prev(nvp);
821         PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
822
823         return (retnvp);
824 }
825
826 const char *
827 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
828 {
829         nvpair_t *nvp;
830
831         NVLIST_ASSERT(nvl);
832         PJDLOG_ASSERT(cookiep != NULL);
833
834         if (*cookiep == NULL)
835                 nvp = nvlist_first_nvpair(nvl);
836         else
837                 nvp = nvlist_next_nvpair(nvl, *cookiep);
838         if (nvp == NULL)
839                 return (NULL);
840         if (typep != NULL)
841                 *typep = nvpair_type(nvp);
842         *cookiep = nvp;
843         return (nvpair_name(nvp));
844 }
845
846 bool
847 nvlist_exists(const nvlist_t *nvl, const char *name)
848 {
849
850         return (nvlist_existsf(nvl, "%s", name));
851 }
852
853 #define NVLIST_EXISTS(type)                                             \
854 bool                                                                    \
855 nvlist_exists_##type(const nvlist_t *nvl, const char *name)             \
856 {                                                                       \
857                                                                         \
858         return (nvlist_existsf_##type(nvl, "%s", name));                \
859 }
860
861 NVLIST_EXISTS(null)
862 NVLIST_EXISTS(bool)
863 NVLIST_EXISTS(number)
864 NVLIST_EXISTS(string)
865 NVLIST_EXISTS(nvlist)
866 NVLIST_EXISTS(descriptor)
867 NVLIST_EXISTS(binary)
868
869 #undef  NVLIST_EXISTS
870
871 bool
872 nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...)
873 {
874         va_list nameap;
875         bool ret;
876
877         va_start(nameap, namefmt);
878         ret = nvlist_existsv(nvl, namefmt, nameap);
879         va_end(nameap);
880         return (ret);
881 }
882
883 #define NVLIST_EXISTSF(type)                                            \
884 bool                                                                    \
885 nvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...)    \
886 {                                                                       \
887         va_list nameap;                                                 \
888         bool ret;                                                       \
889                                                                         \
890         va_start(nameap, namefmt);                                      \
891         ret = nvlist_existsv_##type(nvl, namefmt, nameap);              \
892         va_end(nameap);                                                 \
893         return (ret);                                                   \
894 }
895
896 NVLIST_EXISTSF(null)
897 NVLIST_EXISTSF(bool)
898 NVLIST_EXISTSF(number)
899 NVLIST_EXISTSF(string)
900 NVLIST_EXISTSF(nvlist)
901 NVLIST_EXISTSF(descriptor)
902 NVLIST_EXISTSF(binary)
903
904 #undef  NVLIST_EXISTSF
905
906 bool
907 nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap)
908 {
909
910         return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap) != NULL);
911 }
912
913 #define NVLIST_EXISTSV(type, TYPE)                                      \
914 bool                                                                    \
915 nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt,         \
916     va_list nameap)                                                     \
917 {                                                                       \
918                                                                         \
919         return (nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, nameap) !=   \
920             NULL);                                                      \
921 }
922
923 NVLIST_EXISTSV(null, NULL)
924 NVLIST_EXISTSV(bool, BOOL)
925 NVLIST_EXISTSV(number, NUMBER)
926 NVLIST_EXISTSV(string, STRING)
927 NVLIST_EXISTSV(nvlist, NVLIST)
928 NVLIST_EXISTSV(descriptor, DESCRIPTOR)
929 NVLIST_EXISTSV(binary, BINARY)
930
931 #undef  NVLIST_EXISTSV
932
933 void
934 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
935 {
936         nvpair_t *newnvp;
937
938         NVPAIR_ASSERT(nvp);
939
940         if (nvlist_error(nvl) != 0) {
941                 errno = nvlist_error(nvl);
942                 return;
943         }
944         if (nvlist_exists(nvl, nvpair_name(nvp))) {
945                 nvl->nvl_error = errno = EEXIST;
946                 return;
947         }
948
949         newnvp = nvpair_clone(nvp);
950         if (newnvp == NULL) {
951                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
952                 return;
953         }
954
955         nvpair_insert(&nvl->nvl_head, newnvp, nvl);
956 }
957
958 void
959 nvlist_add_null(nvlist_t *nvl, const char *name)
960 {
961
962         nvlist_addf_null(nvl, "%s", name);
963 }
964
965 void
966 nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
967 {
968
969         nvlist_addf_bool(nvl, value, "%s", name);
970 }
971
972 void
973 nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
974 {
975
976         nvlist_addf_number(nvl, value, "%s", name);
977 }
978
979 void
980 nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
981 {
982
983         nvlist_addf_string(nvl, value, "%s", name);
984 }
985
986 void
987 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
988 {
989         va_list valueap;
990
991         va_start(valueap, valuefmt);
992         nvlist_add_stringv(nvl, name, valuefmt, valueap);
993         va_end(valueap);
994 }
995
996 void
997 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
998     va_list valueap)
999 {
1000         nvpair_t *nvp;
1001
1002         if (nvlist_error(nvl) != 0) {
1003                 errno = nvlist_error(nvl);
1004                 return;
1005         }
1006
1007         nvp = nvpair_create_stringv(name, valuefmt, valueap);
1008         if (nvp == NULL)
1009                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1010         else
1011                 nvlist_move_nvpair(nvl, nvp);
1012 }
1013
1014 void
1015 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1016 {
1017
1018         nvlist_addf_nvlist(nvl, value, "%s", name);
1019 }
1020
1021 void
1022 nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1023 {
1024
1025         nvlist_addf_descriptor(nvl, value, "%s", name);
1026 }
1027
1028 void
1029 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1030     size_t size)
1031 {
1032
1033         nvlist_addf_binary(nvl, value, size, "%s", name);
1034 }
1035
1036 void
1037 nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...)
1038 {
1039         va_list nameap;
1040
1041         va_start(nameap, namefmt);
1042         nvlist_addv_null(nvl, namefmt, nameap);
1043         va_end(nameap);
1044 }
1045
1046 void
1047 nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...)
1048 {
1049         va_list nameap;
1050
1051         va_start(nameap, namefmt);
1052         nvlist_addv_bool(nvl, value, namefmt, nameap);
1053         va_end(nameap);
1054 }
1055
1056 void
1057 nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1058 {
1059         va_list nameap;
1060
1061         va_start(nameap, namefmt);
1062         nvlist_addv_number(nvl, value, namefmt, nameap);
1063         va_end(nameap);
1064 }
1065
1066 void
1067 nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...)
1068 {
1069         va_list nameap;
1070
1071         va_start(nameap, namefmt);
1072         nvlist_addv_string(nvl, value, namefmt, nameap);
1073         va_end(nameap);
1074 }
1075
1076 void
1077 nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1078     ...)
1079 {
1080         va_list nameap;
1081
1082         va_start(nameap, namefmt);
1083         nvlist_addv_nvlist(nvl, value, namefmt, nameap);
1084         va_end(nameap);
1085 }
1086
1087 void
1088 nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...)
1089 {
1090         va_list nameap;
1091
1092         va_start(nameap, namefmt);
1093         nvlist_addv_descriptor(nvl, value, namefmt, nameap);
1094         va_end(nameap);
1095 }
1096
1097 void
1098 nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size,
1099     const char *namefmt, ...)
1100 {
1101         va_list nameap;
1102
1103         va_start(nameap, namefmt);
1104         nvlist_addv_binary(nvl, value, size, namefmt, nameap);
1105         va_end(nameap);
1106 }
1107
1108 void
1109 nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap)
1110 {
1111         nvpair_t *nvp;
1112
1113         if (nvlist_error(nvl) != 0) {
1114                 errno = nvlist_error(nvl);
1115                 return;
1116         }
1117
1118         nvp = nvpair_createv_null(namefmt, nameap);
1119         if (nvp == NULL)
1120                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1121         else
1122                 nvlist_move_nvpair(nvl, nvp);
1123 }
1124
1125 void
1126 nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap)
1127 {
1128         nvpair_t *nvp;
1129
1130         if (nvlist_error(nvl) != 0) {
1131                 errno = nvlist_error(nvl);
1132                 return;
1133         }
1134
1135         nvp = nvpair_createv_bool(value, namefmt, nameap);
1136         if (nvp == NULL)
1137                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1138         else
1139                 nvlist_move_nvpair(nvl, nvp);
1140 }
1141
1142 void
1143 nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt,
1144     va_list nameap)
1145 {
1146         nvpair_t *nvp;
1147
1148         if (nvlist_error(nvl) != 0) {
1149                 errno = nvlist_error(nvl);
1150                 return;
1151         }
1152
1153         nvp = nvpair_createv_number(value, namefmt, nameap);
1154         if (nvp == NULL)
1155                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1156         else
1157                 nvlist_move_nvpair(nvl, nvp);
1158 }
1159
1160 void
1161 nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt,
1162     va_list nameap)
1163 {
1164         nvpair_t *nvp;
1165
1166         if (nvlist_error(nvl) != 0) {
1167                 errno = nvlist_error(nvl);
1168                 return;
1169         }
1170
1171         nvp = nvpair_createv_string(value, namefmt, nameap);
1172         if (nvp == NULL)
1173                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1174         else
1175                 nvlist_move_nvpair(nvl, nvp);
1176 }
1177
1178 void
1179 nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1180     va_list nameap)
1181 {
1182         nvpair_t *nvp;
1183
1184         if (nvlist_error(nvl) != 0) {
1185                 errno = nvlist_error(nvl);
1186                 return;
1187         }
1188
1189         nvp = nvpair_createv_nvlist(value, namefmt, nameap);
1190         if (nvp == NULL)
1191                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1192         else
1193                 nvlist_move_nvpair(nvl, nvp);
1194 }
1195
1196 void
1197 nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1198     va_list nameap)
1199 {
1200         nvpair_t *nvp;
1201
1202         if (nvlist_error(nvl) != 0) {
1203                 errno = nvlist_error(nvl);
1204                 return;
1205         }
1206
1207         nvp = nvpair_createv_descriptor(value, namefmt, nameap);
1208         if (nvp == NULL)
1209                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1210         else
1211                 nvlist_move_nvpair(nvl, nvp);
1212 }
1213
1214 void
1215 nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size,
1216     const char *namefmt, va_list nameap)
1217 {
1218         nvpair_t *nvp;
1219
1220         if (nvlist_error(nvl) != 0) {
1221                 errno = nvlist_error(nvl);
1222                 return;
1223         }
1224
1225         nvp = nvpair_createv_binary(value, size, namefmt, nameap);
1226         if (nvp == NULL)
1227                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1228         else
1229                 nvlist_move_nvpair(nvl, nvp);
1230 }
1231
1232 void
1233 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1234 {
1235
1236         NVPAIR_ASSERT(nvp);
1237         PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1238
1239         if (nvlist_error(nvl) != 0) {
1240                 nvpair_free(nvp);
1241                 errno = nvlist_error(nvl);
1242                 return;
1243         }
1244         if (nvlist_exists(nvl, nvpair_name(nvp))) {
1245                 nvpair_free(nvp);
1246                 nvl->nvl_error = errno = EEXIST;
1247                 return;
1248         }
1249
1250         nvpair_insert(&nvl->nvl_head, nvp, nvl);
1251 }
1252
1253 #define NVLIST_MOVE(vtype, type)                                        \
1254 void                                                                    \
1255 nvlist_move_##type(nvlist_t *nvl, const char *name, vtype value)        \
1256 {                                                                       \
1257                                                                         \
1258         nvlist_movef_##type(nvl, value, "%s", name);                    \
1259 }
1260
1261 NVLIST_MOVE(char *, string)
1262 NVLIST_MOVE(nvlist_t *, nvlist)
1263 NVLIST_MOVE(int, descriptor)
1264
1265 #undef  NVLIST_MOVE
1266
1267 void
1268 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1269 {
1270
1271         nvlist_movef_binary(nvl, value, size, "%s", name);
1272 }
1273
1274 #define NVLIST_MOVEF(vtype, type)                                       \
1275 void                                                                    \
1276 nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt,    \
1277     ...)                                                                \
1278 {                                                                       \
1279         va_list nameap;                                                 \
1280                                                                         \
1281         va_start(nameap, namefmt);                                      \
1282         nvlist_movev_##type(nvl, value, namefmt, nameap);               \
1283         va_end(nameap);                                                 \
1284 }
1285
1286 NVLIST_MOVEF(char *, string)
1287 NVLIST_MOVEF(nvlist_t *, nvlist)
1288 NVLIST_MOVEF(int, descriptor)
1289
1290 #undef  NVLIST_MOVEF
1291
1292 void
1293 nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size,
1294     const char *namefmt, ...)
1295 {
1296         va_list nameap;
1297
1298         va_start(nameap, namefmt);
1299         nvlist_movev_binary(nvl, value, size, namefmt, nameap);
1300         va_end(nameap);
1301 }
1302
1303 void
1304 nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt,
1305     va_list nameap)
1306 {
1307         nvpair_t *nvp;
1308
1309         if (nvlist_error(nvl) != 0) {
1310                 free(value);
1311                 errno = nvlist_error(nvl);
1312                 return;
1313         }
1314
1315         nvp = nvpair_movev_string(value, namefmt, nameap);
1316         if (nvp == NULL)
1317                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1318         else
1319                 nvlist_move_nvpair(nvl, nvp);
1320 }
1321
1322 void
1323 nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
1324     va_list nameap)
1325 {
1326         nvpair_t *nvp;
1327
1328         if (nvlist_error(nvl) != 0) {
1329                 nvlist_destroy(value);
1330                 errno = nvlist_error(nvl);
1331                 return;
1332         }
1333
1334         nvp = nvpair_movev_nvlist(value, namefmt, nameap);
1335         if (nvp == NULL)
1336                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1337         else
1338                 nvlist_move_nvpair(nvl, nvp);
1339 }
1340
1341 void
1342 nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1343     va_list nameap)
1344 {
1345         nvpair_t *nvp;
1346
1347         if (nvlist_error(nvl) != 0) {
1348                 close(value);
1349                 errno = nvlist_error(nvl);
1350                 return;
1351         }
1352
1353         nvp = nvpair_movev_descriptor(value, namefmt, nameap);
1354         if (nvp == NULL)
1355                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1356         else
1357                 nvlist_move_nvpair(nvl, nvp);
1358 }
1359
1360 void
1361 nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size,
1362     const char *namefmt, va_list nameap)
1363 {
1364         nvpair_t *nvp;
1365
1366         if (nvlist_error(nvl) != 0) {
1367                 free(value);
1368                 errno = nvlist_error(nvl);
1369                 return;
1370         }
1371
1372         nvp = nvpair_movev_binary(value, size, namefmt, nameap);
1373         if (nvp == NULL)
1374                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1375         else
1376                 nvlist_move_nvpair(nvl, nvp);
1377 }
1378
1379 #define NVLIST_GET(ftype, type)                                         \
1380 ftype                                                                   \
1381 nvlist_get_##type(const nvlist_t *nvl, const char *name)                \
1382 {                                                                       \
1383                                                                         \
1384         return (nvlist_getf_##type(nvl, "%s", name));                   \
1385 }
1386
1387 NVLIST_GET(const nvpair_t *, nvpair)
1388 NVLIST_GET(bool, bool)
1389 NVLIST_GET(uint64_t, number)
1390 NVLIST_GET(const char *, string)
1391 NVLIST_GET(const nvlist_t *, nvlist)
1392 NVLIST_GET(int, descriptor)
1393
1394 #undef  NVLIST_GET
1395
1396 const void *
1397 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1398 {
1399
1400         return (nvlist_getf_binary(nvl, sizep, "%s", name));
1401 }
1402
1403 #define NVLIST_GETF(ftype, type)                                        \
1404 ftype                                                                   \
1405 nvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...)       \
1406 {                                                                       \
1407         va_list nameap;                                                 \
1408         ftype value;                                                    \
1409                                                                         \
1410         va_start(nameap, namefmt);                                      \
1411         value = nvlist_getv_##type(nvl, namefmt, nameap);               \
1412         va_end(nameap);                                                 \
1413                                                                         \
1414         return (value);                                                 \
1415 }
1416
1417 NVLIST_GETF(const nvpair_t *, nvpair)
1418 NVLIST_GETF(bool, bool)
1419 NVLIST_GETF(uint64_t, number)
1420 NVLIST_GETF(const char *, string)
1421 NVLIST_GETF(const nvlist_t *, nvlist)
1422 NVLIST_GETF(int, descriptor)
1423
1424 #undef  NVLIST_GETF
1425
1426 const void *
1427 nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1428 {
1429         va_list nameap;
1430         const void *value;
1431
1432         va_start(nameap, namefmt);
1433         value = nvlist_getv_binary(nvl, sizep, namefmt, nameap);
1434         va_end(nameap);
1435
1436         return (value);
1437 }
1438
1439 const nvpair_t *
1440 nvlist_getv_nvpair(const nvlist_t *nvl, const char *namefmt, va_list nameap)
1441 {
1442
1443         return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap));
1444 }
1445
1446 #define NVLIST_GETV(ftype, type, TYPE)                                  \
1447 ftype                                                                   \
1448 nvlist_getv_##type(const nvlist_t *nvl, const char *namefmt,            \
1449     va_list nameap)                                                     \
1450 {                                                                       \
1451         va_list cnameap;                                                \
1452         const nvpair_t *nvp;                                            \
1453                                                                         \
1454         va_copy(cnameap, nameap);                                       \
1455         nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap);      \
1456         va_end(cnameap);                                                \
1457         if (nvp == NULL)                                                \
1458                 nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \
1459         return (nvpair_get_##type(nvp));                                \
1460 }
1461
1462 NVLIST_GETV(bool, bool, BOOL)
1463 NVLIST_GETV(uint64_t, number, NUMBER)
1464 NVLIST_GETV(const char *, string, STRING)
1465 NVLIST_GETV(const nvlist_t *, nvlist, NVLIST)
1466 NVLIST_GETV(int, descriptor, DESCRIPTOR)
1467
1468 #undef  NVLIST_GETV
1469
1470 const void *
1471 nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt,
1472     va_list nameap)
1473 {
1474         va_list cnameap;
1475         const nvpair_t *nvp;
1476
1477         va_copy(cnameap, nameap);
1478         nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap);
1479         va_end(cnameap);
1480         if (nvp == NULL)
1481                 nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap);
1482
1483         return (nvpair_get_binary(nvp, sizep));
1484 }
1485
1486 #define NVLIST_TAKE(ftype, type)                                        \
1487 ftype                                                                   \
1488 nvlist_take_##type(nvlist_t *nvl, const char *name)                     \
1489 {                                                                       \
1490                                                                         \
1491         return (nvlist_takef_##type(nvl, "%s", name));                  \
1492 }
1493
1494 NVLIST_TAKE(nvpair_t *, nvpair)
1495 NVLIST_TAKE(bool, bool)
1496 NVLIST_TAKE(uint64_t, number)
1497 NVLIST_TAKE(char *, string)
1498 NVLIST_TAKE(nvlist_t *, nvlist)
1499 NVLIST_TAKE(int, descriptor)
1500
1501 #undef  NVLIST_TAKE
1502
1503 void *
1504 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1505 {
1506
1507         return (nvlist_takef_binary(nvl, sizep, "%s", name));
1508 }
1509
1510 #define NVLIST_TAKEF(ftype, type)                                       \
1511 ftype                                                                   \
1512 nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...)            \
1513 {                                                                       \
1514         va_list nameap;                                                 \
1515         ftype value;                                                    \
1516                                                                         \
1517         va_start(nameap, namefmt);                                      \
1518         value = nvlist_takev_##type(nvl, namefmt, nameap);              \
1519         va_end(nameap);                                                 \
1520                                                                         \
1521         return (value);                                                 \
1522 }
1523
1524 NVLIST_TAKEF(nvpair_t *, nvpair)
1525 NVLIST_TAKEF(bool, bool)
1526 NVLIST_TAKEF(uint64_t, number)
1527 NVLIST_TAKEF(char *, string)
1528 NVLIST_TAKEF(nvlist_t *, nvlist)
1529 NVLIST_TAKEF(int, descriptor)
1530
1531 #undef  NVLIST_TAKEF
1532
1533 void *
1534 nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1535 {
1536         va_list nameap;
1537         void *value;
1538
1539         va_start(nameap, namefmt);
1540         value = nvlist_takev_binary(nvl, sizep, namefmt, nameap);
1541         va_end(nameap);
1542
1543         return (value);
1544 }
1545
1546 nvpair_t *
1547 nvlist_takev_nvpair(nvlist_t *nvl, const char *namefmt, va_list nameap)
1548 {
1549         nvpair_t *nvp;
1550
1551         nvp = nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap);
1552         if (nvp != NULL)
1553                 nvlist_remove_nvpair(nvl, nvp);
1554         return (nvp);
1555 }
1556
1557 #define NVLIST_TAKEV(ftype, type, TYPE)                                 \
1558 ftype                                                                   \
1559 nvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
1560 {                                                                       \
1561         va_list cnameap;                                                \
1562         nvpair_t *nvp;                                                  \
1563         ftype value;                                                    \
1564                                                                         \
1565         va_copy(cnameap, nameap);                                       \
1566         nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap);      \
1567         va_end(cnameap);                                                \
1568         if (nvp == NULL)                                                \
1569                 nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \
1570         value = (ftype)(intptr_t)nvpair_get_##type(nvp);                \
1571         nvlist_remove_nvpair(nvl, nvp);                                 \
1572         nvpair_free_structure(nvp);                                     \
1573         return (value);                                                 \
1574 }
1575
1576 NVLIST_TAKEV(bool, bool, BOOL)
1577 NVLIST_TAKEV(uint64_t, number, NUMBER)
1578 NVLIST_TAKEV(char *, string, STRING)
1579 NVLIST_TAKEV(nvlist_t *, nvlist, NVLIST)
1580 NVLIST_TAKEV(int, descriptor, DESCRIPTOR)
1581
1582 #undef  NVLIST_TAKEV
1583
1584 void *
1585 nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt,
1586     va_list nameap)
1587 {
1588         va_list cnameap;
1589         nvpair_t *nvp;
1590         void *value;
1591
1592         va_copy(cnameap, nameap);
1593         nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap);
1594         va_end(cnameap);
1595         if (nvp == NULL)
1596                 nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap);
1597
1598         value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1599         nvlist_remove_nvpair(nvl, nvp);
1600         nvpair_free_structure(nvp);
1601         return (value);
1602 }
1603
1604 void
1605 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1606 {
1607
1608         NVLIST_ASSERT(nvl);
1609         NVPAIR_ASSERT(nvp);
1610         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1611
1612         nvpair_remove(&nvl->nvl_head, nvp, nvl);
1613 }
1614
1615 void
1616 nvlist_free(nvlist_t *nvl, const char *name)
1617 {
1618
1619         nvlist_freef(nvl, "%s", name);
1620 }
1621
1622 #define NVLIST_FREE(type)                                               \
1623 void                                                                    \
1624 nvlist_free_##type(nvlist_t *nvl, const char *name)                     \
1625 {                                                                       \
1626                                                                         \
1627         nvlist_freef_##type(nvl, "%s", name);                           \
1628 }
1629
1630 NVLIST_FREE(null)
1631 NVLIST_FREE(bool)
1632 NVLIST_FREE(number)
1633 NVLIST_FREE(string)
1634 NVLIST_FREE(nvlist)
1635 NVLIST_FREE(descriptor)
1636 NVLIST_FREE(binary)
1637
1638 #undef  NVLIST_FREE
1639
1640 void
1641 nvlist_freef(nvlist_t *nvl, const char *namefmt, ...)
1642 {
1643         va_list nameap;
1644
1645         va_start(nameap, namefmt);
1646         nvlist_freev(nvl, namefmt, nameap);
1647         va_end(nameap);
1648 }
1649
1650 #define NVLIST_FREEF(type)                                              \
1651 void                                                                    \
1652 nvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...)            \
1653 {                                                                       \
1654         va_list nameap;                                                 \
1655                                                                         \
1656         va_start(nameap, namefmt);                                      \
1657         nvlist_freev_##type(nvl, namefmt, nameap);                      \
1658         va_end(nameap);                                                 \
1659 }
1660
1661 NVLIST_FREEF(null)
1662 NVLIST_FREEF(bool)
1663 NVLIST_FREEF(number)
1664 NVLIST_FREEF(string)
1665 NVLIST_FREEF(nvlist)
1666 NVLIST_FREEF(descriptor)
1667 NVLIST_FREEF(binary)
1668
1669 #undef  NVLIST_FREEF
1670
1671 void
1672 nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap)
1673 {
1674
1675         nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap);
1676 }
1677
1678 #define NVLIST_FREEV(type, TYPE)                                        \
1679 void                                                                    \
1680 nvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
1681 {                                                                       \
1682                                                                         \
1683         nvlist_freev_type(nvl, NV_TYPE_##TYPE, namefmt, nameap);        \
1684 }
1685
1686 NVLIST_FREEV(null, NULL)
1687 NVLIST_FREEV(bool, BOOL)
1688 NVLIST_FREEV(number, NUMBER)
1689 NVLIST_FREEV(string, STRING)
1690 NVLIST_FREEV(nvlist, NVLIST)
1691 NVLIST_FREEV(descriptor, DESCRIPTOR)
1692 NVLIST_FREEV(binary, BINARY)
1693 #undef  NVLIST_FREEV
1694
1695 void
1696 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1697 {
1698
1699         NVLIST_ASSERT(nvl);
1700         NVPAIR_ASSERT(nvp);
1701         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1702
1703         nvlist_remove_nvpair(nvl, nvp);
1704         nvpair_free(nvp);
1705 }