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