]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libnv/nvlist.c
MFV r262639: ncurses 5.9 20140222 snapshot.
[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, *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                 goto out;
765
766         ret = nvl;
767 out:
768         serrno = errno;
769         free(buf);
770         free(fds);
771         errno = serrno;
772
773         return (ret);
774 }
775
776 nvlist_t *
777 nvlist_xfer(int sock, nvlist_t *nvl)
778 {
779
780         if (nvlist_send(sock, nvl) < 0) {
781                 nvlist_destroy(nvl);
782                 return (NULL);
783         }
784         nvlist_destroy(nvl);
785         return (nvlist_recv(sock));
786 }
787
788 nvpair_t *
789 nvlist_first_nvpair(const nvlist_t *nvl)
790 {
791
792         NVLIST_ASSERT(nvl);
793
794         return (TAILQ_FIRST(&nvl->nvl_head));
795 }
796
797 nvpair_t *
798 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
799 {
800         nvpair_t *retnvp;
801
802         NVLIST_ASSERT(nvl);
803         NVPAIR_ASSERT(nvp);
804         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
805
806         retnvp = nvpair_next(nvp);
807         PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
808
809         return (retnvp);
810
811 }
812
813 nvpair_t *
814 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
815 {
816         nvpair_t *retnvp;
817
818         NVLIST_ASSERT(nvl);
819         NVPAIR_ASSERT(nvp);
820         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
821
822         retnvp = nvpair_prev(nvp);
823         PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
824
825         return (retnvp);
826 }
827
828 const char *
829 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
830 {
831         nvpair_t *nvp;
832
833         NVLIST_ASSERT(nvl);
834         PJDLOG_ASSERT(cookiep != NULL);
835
836         if (*cookiep == NULL)
837                 nvp = nvlist_first_nvpair(nvl);
838         else
839                 nvp = nvlist_next_nvpair(nvl, *cookiep);
840         if (nvp == NULL)
841                 return (NULL);
842         if (typep != NULL)
843                 *typep = nvpair_type(nvp);
844         *cookiep = nvp;
845         return (nvpair_name(nvp));
846 }
847
848 bool
849 nvlist_exists(const nvlist_t *nvl, const char *name)
850 {
851
852         return (nvlist_existsf(nvl, "%s", name));
853 }
854
855 #define NVLIST_EXISTS(type)                                             \
856 bool                                                                    \
857 nvlist_exists_##type(const nvlist_t *nvl, const char *name)             \
858 {                                                                       \
859                                                                         \
860         return (nvlist_existsf_##type(nvl, "%s", name));                \
861 }
862
863 NVLIST_EXISTS(null)
864 NVLIST_EXISTS(bool)
865 NVLIST_EXISTS(number)
866 NVLIST_EXISTS(string)
867 NVLIST_EXISTS(nvlist)
868 NVLIST_EXISTS(descriptor)
869 NVLIST_EXISTS(binary)
870
871 #undef  NVLIST_EXISTS
872
873 bool
874 nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...)
875 {
876         va_list nameap;
877         bool ret;
878
879         va_start(nameap, namefmt);
880         ret = nvlist_existsv(nvl, namefmt, nameap);
881         va_end(nameap);
882         return (ret);
883 }
884
885 #define NVLIST_EXISTSF(type)                                            \
886 bool                                                                    \
887 nvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...)    \
888 {                                                                       \
889         va_list nameap;                                                 \
890         bool ret;                                                       \
891                                                                         \
892         va_start(nameap, namefmt);                                      \
893         ret = nvlist_existsv_##type(nvl, namefmt, nameap);              \
894         va_end(nameap);                                                 \
895         return (ret);                                                   \
896 }
897
898 NVLIST_EXISTSF(null)
899 NVLIST_EXISTSF(bool)
900 NVLIST_EXISTSF(number)
901 NVLIST_EXISTSF(string)
902 NVLIST_EXISTSF(nvlist)
903 NVLIST_EXISTSF(descriptor)
904 NVLIST_EXISTSF(binary)
905
906 #undef  NVLIST_EXISTSF
907
908 bool
909 nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap)
910 {
911
912         return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap) != NULL);
913 }
914
915 #define NVLIST_EXISTSV(type, TYPE)                                      \
916 bool                                                                    \
917 nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt,         \
918     va_list nameap)                                                     \
919 {                                                                       \
920                                                                         \
921         return (nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, nameap) !=   \
922             NULL);                                                      \
923 }
924
925 NVLIST_EXISTSV(null, NULL)
926 NVLIST_EXISTSV(bool, BOOL)
927 NVLIST_EXISTSV(number, NUMBER)
928 NVLIST_EXISTSV(string, STRING)
929 NVLIST_EXISTSV(nvlist, NVLIST)
930 NVLIST_EXISTSV(descriptor, DESCRIPTOR)
931 NVLIST_EXISTSV(binary, BINARY)
932
933 #undef  NVLIST_EXISTSV
934
935 void
936 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
937 {
938         nvpair_t *newnvp;
939
940         NVPAIR_ASSERT(nvp);
941
942         if (nvlist_error(nvl) != 0) {
943                 errno = nvlist_error(nvl);
944                 return;
945         }
946         if (nvlist_exists(nvl, nvpair_name(nvp))) {
947                 nvl->nvl_error = errno = EEXIST;
948                 return;
949         }
950
951         newnvp = nvpair_clone(nvp);
952         if (newnvp == NULL) {
953                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
954                 return;
955         }
956
957         nvpair_insert(&nvl->nvl_head, newnvp, nvl);
958 }
959
960 void
961 nvlist_add_null(nvlist_t *nvl, const char *name)
962 {
963
964         nvlist_addf_null(nvl, "%s", name);
965 }
966
967 void
968 nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
969 {
970
971         nvlist_addf_bool(nvl, value, "%s", name);
972 }
973
974 void
975 nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
976 {
977
978         nvlist_addf_number(nvl, value, "%s", name);
979 }
980
981 void
982 nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
983 {
984
985         nvlist_addf_string(nvl, value, "%s", name);
986 }
987
988 void
989 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
990 {
991         va_list valueap;
992
993         va_start(valueap, valuefmt);
994         nvlist_add_stringv(nvl, name, valuefmt, valueap);
995         va_end(valueap);
996 }
997
998 void
999 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1000     va_list valueap)
1001 {
1002         nvpair_t *nvp;
1003
1004         if (nvlist_error(nvl) != 0) {
1005                 errno = nvlist_error(nvl);
1006                 return;
1007         }
1008
1009         nvp = nvpair_create_stringv(name, valuefmt, valueap);
1010         if (nvp == NULL)
1011                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1012         else
1013                 nvlist_move_nvpair(nvl, nvp);
1014 }
1015
1016 void
1017 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1018 {
1019
1020         nvlist_addf_nvlist(nvl, value, "%s", name);
1021 }
1022
1023 void
1024 nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1025 {
1026
1027         nvlist_addf_descriptor(nvl, value, "%s", name);
1028 }
1029
1030 void
1031 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1032     size_t size)
1033 {
1034
1035         nvlist_addf_binary(nvl, value, size, "%s", name);
1036 }
1037
1038 void
1039 nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...)
1040 {
1041         va_list nameap;
1042
1043         va_start(nameap, namefmt);
1044         nvlist_addv_null(nvl, namefmt, nameap);
1045         va_end(nameap);
1046 }
1047
1048 void
1049 nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...)
1050 {
1051         va_list nameap;
1052
1053         va_start(nameap, namefmt);
1054         nvlist_addv_bool(nvl, value, namefmt, nameap);
1055         va_end(nameap);
1056 }
1057
1058 void
1059 nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1060 {
1061         va_list nameap;
1062
1063         va_start(nameap, namefmt);
1064         nvlist_addv_number(nvl, value, namefmt, nameap);
1065         va_end(nameap);
1066 }
1067
1068 void
1069 nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...)
1070 {
1071         va_list nameap;
1072
1073         va_start(nameap, namefmt);
1074         nvlist_addv_string(nvl, value, namefmt, nameap);
1075         va_end(nameap);
1076 }
1077
1078 void
1079 nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1080     ...)
1081 {
1082         va_list nameap;
1083
1084         va_start(nameap, namefmt);
1085         nvlist_addv_nvlist(nvl, value, namefmt, nameap);
1086         va_end(nameap);
1087 }
1088
1089 void
1090 nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...)
1091 {
1092         va_list nameap;
1093
1094         va_start(nameap, namefmt);
1095         nvlist_addv_descriptor(nvl, value, namefmt, nameap);
1096         va_end(nameap);
1097 }
1098
1099 void
1100 nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size,
1101     const char *namefmt, ...)
1102 {
1103         va_list nameap;
1104
1105         va_start(nameap, namefmt);
1106         nvlist_addv_binary(nvl, value, size, namefmt, nameap);
1107         va_end(nameap);
1108 }
1109
1110 void
1111 nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap)
1112 {
1113         nvpair_t *nvp;
1114
1115         if (nvlist_error(nvl) != 0) {
1116                 errno = nvlist_error(nvl);
1117                 return;
1118         }
1119
1120         nvp = nvpair_createv_null(namefmt, nameap);
1121         if (nvp == NULL)
1122                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1123         else
1124                 nvlist_move_nvpair(nvl, nvp);
1125 }
1126
1127 void
1128 nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap)
1129 {
1130         nvpair_t *nvp;
1131
1132         if (nvlist_error(nvl) != 0) {
1133                 errno = nvlist_error(nvl);
1134                 return;
1135         }
1136
1137         nvp = nvpair_createv_bool(value, namefmt, nameap);
1138         if (nvp == NULL)
1139                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1140         else
1141                 nvlist_move_nvpair(nvl, nvp);
1142 }
1143
1144 void
1145 nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt,
1146     va_list nameap)
1147 {
1148         nvpair_t *nvp;
1149
1150         if (nvlist_error(nvl) != 0) {
1151                 errno = nvlist_error(nvl);
1152                 return;
1153         }
1154
1155         nvp = nvpair_createv_number(value, namefmt, nameap);
1156         if (nvp == NULL)
1157                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1158         else
1159                 nvlist_move_nvpair(nvl, nvp);
1160 }
1161
1162 void
1163 nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt,
1164     va_list nameap)
1165 {
1166         nvpair_t *nvp;
1167
1168         if (nvlist_error(nvl) != 0) {
1169                 errno = nvlist_error(nvl);
1170                 return;
1171         }
1172
1173         nvp = nvpair_createv_string(value, namefmt, nameap);
1174         if (nvp == NULL)
1175                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1176         else
1177                 nvlist_move_nvpair(nvl, nvp);
1178 }
1179
1180 void
1181 nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1182     va_list nameap)
1183 {
1184         nvpair_t *nvp;
1185
1186         if (nvlist_error(nvl) != 0) {
1187                 errno = nvlist_error(nvl);
1188                 return;
1189         }
1190
1191         nvp = nvpair_createv_nvlist(value, namefmt, nameap);
1192         if (nvp == NULL)
1193                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1194         else
1195                 nvlist_move_nvpair(nvl, nvp);
1196 }
1197
1198 void
1199 nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1200     va_list nameap)
1201 {
1202         nvpair_t *nvp;
1203
1204         if (nvlist_error(nvl) != 0) {
1205                 errno = nvlist_error(nvl);
1206                 return;
1207         }
1208
1209         nvp = nvpair_createv_descriptor(value, namefmt, nameap);
1210         if (nvp == NULL)
1211                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1212         else
1213                 nvlist_move_nvpair(nvl, nvp);
1214 }
1215
1216 void
1217 nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size,
1218     const char *namefmt, va_list nameap)
1219 {
1220         nvpair_t *nvp;
1221
1222         if (nvlist_error(nvl) != 0) {
1223                 errno = nvlist_error(nvl);
1224                 return;
1225         }
1226
1227         nvp = nvpair_createv_binary(value, size, namefmt, nameap);
1228         if (nvp == NULL)
1229                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1230         else
1231                 nvlist_move_nvpair(nvl, nvp);
1232 }
1233
1234 void
1235 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1236 {
1237
1238         NVPAIR_ASSERT(nvp);
1239         PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1240
1241         if (nvlist_error(nvl) != 0) {
1242                 nvpair_free(nvp);
1243                 errno = nvlist_error(nvl);
1244                 return;
1245         }
1246         if (nvlist_exists(nvl, nvpair_name(nvp))) {
1247                 nvpair_free(nvp);
1248                 nvl->nvl_error = errno = EEXIST;
1249                 return;
1250         }
1251
1252         nvpair_insert(&nvl->nvl_head, nvp, nvl);
1253 }
1254
1255 #define NVLIST_MOVE(vtype, type)                                        \
1256 void                                                                    \
1257 nvlist_move_##type(nvlist_t *nvl, const char *name, vtype value)        \
1258 {                                                                       \
1259                                                                         \
1260         nvlist_movef_##type(nvl, value, "%s", name);                    \
1261 }
1262
1263 NVLIST_MOVE(char *, string)
1264 NVLIST_MOVE(nvlist_t *, nvlist)
1265 NVLIST_MOVE(int, descriptor)
1266
1267 #undef  NVLIST_MOVE
1268
1269 void
1270 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1271 {
1272
1273         nvlist_movef_binary(nvl, value, size, "%s", name);
1274 }
1275
1276 #define NVLIST_MOVEF(vtype, type)                                       \
1277 void                                                                    \
1278 nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt,    \
1279     ...)                                                                \
1280 {                                                                       \
1281         va_list nameap;                                                 \
1282                                                                         \
1283         va_start(nameap, namefmt);                                      \
1284         nvlist_movev_##type(nvl, value, namefmt, nameap);               \
1285         va_end(nameap);                                                 \
1286 }
1287
1288 NVLIST_MOVEF(char *, string)
1289 NVLIST_MOVEF(nvlist_t *, nvlist)
1290 NVLIST_MOVEF(int, descriptor)
1291
1292 #undef  NVLIST_MOVEF
1293
1294 void
1295 nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size,
1296     const char *namefmt, ...)
1297 {
1298         va_list nameap;
1299
1300         va_start(nameap, namefmt);
1301         nvlist_movev_binary(nvl, value, size, namefmt, nameap);
1302         va_end(nameap);
1303 }
1304
1305 void
1306 nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt,
1307     va_list nameap)
1308 {
1309         nvpair_t *nvp;
1310
1311         if (nvlist_error(nvl) != 0) {
1312                 free(value);
1313                 errno = nvlist_error(nvl);
1314                 return;
1315         }
1316
1317         nvp = nvpair_movev_string(value, namefmt, nameap);
1318         if (nvp == NULL)
1319                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1320         else
1321                 nvlist_move_nvpair(nvl, nvp);
1322 }
1323
1324 void
1325 nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
1326     va_list nameap)
1327 {
1328         nvpair_t *nvp;
1329
1330         if (nvlist_error(nvl) != 0) {
1331                 nvlist_destroy(value);
1332                 errno = nvlist_error(nvl);
1333                 return;
1334         }
1335
1336         nvp = nvpair_movev_nvlist(value, namefmt, nameap);
1337         if (nvp == NULL)
1338                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1339         else
1340                 nvlist_move_nvpair(nvl, nvp);
1341 }
1342
1343 void
1344 nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1345     va_list nameap)
1346 {
1347         nvpair_t *nvp;
1348
1349         if (nvlist_error(nvl) != 0) {
1350                 close(value);
1351                 errno = nvlist_error(nvl);
1352                 return;
1353         }
1354
1355         nvp = nvpair_movev_descriptor(value, namefmt, nameap);
1356         if (nvp == NULL)
1357                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1358         else
1359                 nvlist_move_nvpair(nvl, nvp);
1360 }
1361
1362 void
1363 nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size,
1364     const char *namefmt, va_list nameap)
1365 {
1366         nvpair_t *nvp;
1367
1368         if (nvlist_error(nvl) != 0) {
1369                 free(value);
1370                 errno = nvlist_error(nvl);
1371                 return;
1372         }
1373
1374         nvp = nvpair_movev_binary(value, size, namefmt, nameap);
1375         if (nvp == NULL)
1376                 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1377         else
1378                 nvlist_move_nvpair(nvl, nvp);
1379 }
1380
1381 #define NVLIST_GET(ftype, type)                                         \
1382 ftype                                                                   \
1383 nvlist_get_##type(const nvlist_t *nvl, const char *name)                \
1384 {                                                                       \
1385                                                                         \
1386         return (nvlist_getf_##type(nvl, "%s", name));                   \
1387 }
1388
1389 NVLIST_GET(const nvpair_t *, nvpair)
1390 NVLIST_GET(bool, bool)
1391 NVLIST_GET(uint64_t, number)
1392 NVLIST_GET(const char *, string)
1393 NVLIST_GET(const nvlist_t *, nvlist)
1394 NVLIST_GET(int, descriptor)
1395
1396 #undef  NVLIST_GET
1397
1398 const void *
1399 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1400 {
1401
1402         return (nvlist_getf_binary(nvl, sizep, "%s", name));
1403 }
1404
1405 #define NVLIST_GETF(ftype, type)                                        \
1406 ftype                                                                   \
1407 nvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...)       \
1408 {                                                                       \
1409         va_list nameap;                                                 \
1410         ftype value;                                                    \
1411                                                                         \
1412         va_start(nameap, namefmt);                                      \
1413         value = nvlist_getv_##type(nvl, namefmt, nameap);               \
1414         va_end(nameap);                                                 \
1415                                                                         \
1416         return (value);                                                 \
1417 }
1418
1419 NVLIST_GETF(const nvpair_t *, nvpair)
1420 NVLIST_GETF(bool, bool)
1421 NVLIST_GETF(uint64_t, number)
1422 NVLIST_GETF(const char *, string)
1423 NVLIST_GETF(const nvlist_t *, nvlist)
1424 NVLIST_GETF(int, descriptor)
1425
1426 #undef  NVLIST_GETF
1427
1428 const void *
1429 nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1430 {
1431         va_list nameap;
1432         const void *value;
1433
1434         va_start(nameap, namefmt);
1435         value = nvlist_getv_binary(nvl, sizep, namefmt, nameap);
1436         va_end(nameap);
1437
1438         return (value);
1439 }
1440
1441 const nvpair_t *
1442 nvlist_getv_nvpair(const nvlist_t *nvl, const char *namefmt, va_list nameap)
1443 {
1444
1445         return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap));
1446 }
1447
1448 #define NVLIST_GETV(ftype, type, TYPE)                                  \
1449 ftype                                                                   \
1450 nvlist_getv_##type(const nvlist_t *nvl, const char *namefmt,            \
1451     va_list nameap)                                                     \
1452 {                                                                       \
1453         va_list cnameap;                                                \
1454         const nvpair_t *nvp;                                            \
1455                                                                         \
1456         va_copy(cnameap, nameap);                                       \
1457         nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap);      \
1458         va_end(cnameap);                                                \
1459         if (nvp == NULL)                                                \
1460                 nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \
1461         return (nvpair_get_##type(nvp));                                \
1462 }
1463
1464 NVLIST_GETV(bool, bool, BOOL)
1465 NVLIST_GETV(uint64_t, number, NUMBER)
1466 NVLIST_GETV(const char *, string, STRING)
1467 NVLIST_GETV(const nvlist_t *, nvlist, NVLIST)
1468 NVLIST_GETV(int, descriptor, DESCRIPTOR)
1469
1470 #undef  NVLIST_GETV
1471
1472 const void *
1473 nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt,
1474     va_list nameap)
1475 {
1476         va_list cnameap;
1477         const nvpair_t *nvp;
1478
1479         va_copy(cnameap, nameap);
1480         nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap);
1481         va_end(cnameap);
1482         if (nvp == NULL)
1483                 nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap);
1484
1485         return (nvpair_get_binary(nvp, sizep));
1486 }
1487
1488 #define NVLIST_TAKE(ftype, type)                                        \
1489 ftype                                                                   \
1490 nvlist_take_##type(nvlist_t *nvl, const char *name)                     \
1491 {                                                                       \
1492                                                                         \
1493         return (nvlist_takef_##type(nvl, "%s", name));                  \
1494 }
1495
1496 NVLIST_TAKE(nvpair_t *, nvpair)
1497 NVLIST_TAKE(bool, bool)
1498 NVLIST_TAKE(uint64_t, number)
1499 NVLIST_TAKE(char *, string)
1500 NVLIST_TAKE(nvlist_t *, nvlist)
1501 NVLIST_TAKE(int, descriptor)
1502
1503 #undef  NVLIST_TAKE
1504
1505 void *
1506 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1507 {
1508
1509         return (nvlist_takef_binary(nvl, sizep, "%s", name));
1510 }
1511
1512 #define NVLIST_TAKEF(ftype, type)                                       \
1513 ftype                                                                   \
1514 nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...)            \
1515 {                                                                       \
1516         va_list nameap;                                                 \
1517         ftype value;                                                    \
1518                                                                         \
1519         va_start(nameap, namefmt);                                      \
1520         value = nvlist_takev_##type(nvl, namefmt, nameap);              \
1521         va_end(nameap);                                                 \
1522                                                                         \
1523         return (value);                                                 \
1524 }
1525
1526 NVLIST_TAKEF(nvpair_t *, nvpair)
1527 NVLIST_TAKEF(bool, bool)
1528 NVLIST_TAKEF(uint64_t, number)
1529 NVLIST_TAKEF(char *, string)
1530 NVLIST_TAKEF(nvlist_t *, nvlist)
1531 NVLIST_TAKEF(int, descriptor)
1532
1533 #undef  NVLIST_TAKEF
1534
1535 void *
1536 nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
1537 {
1538         va_list nameap;
1539         void *value;
1540
1541         va_start(nameap, namefmt);
1542         value = nvlist_takev_binary(nvl, sizep, namefmt, nameap);
1543         va_end(nameap);
1544
1545         return (value);
1546 }
1547
1548 nvpair_t *
1549 nvlist_takev_nvpair(nvlist_t *nvl, const char *namefmt, va_list nameap)
1550 {
1551         nvpair_t *nvp;
1552
1553         nvp = nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap);
1554         if (nvp != NULL)
1555                 nvlist_remove_nvpair(nvl, nvp);
1556         return (nvp);
1557 }
1558
1559 #define NVLIST_TAKEV(ftype, type, TYPE)                                 \
1560 ftype                                                                   \
1561 nvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
1562 {                                                                       \
1563         va_list cnameap;                                                \
1564         nvpair_t *nvp;                                                  \
1565         ftype value;                                                    \
1566                                                                         \
1567         va_copy(cnameap, nameap);                                       \
1568         nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap);      \
1569         va_end(cnameap);                                                \
1570         if (nvp == NULL)                                                \
1571                 nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \
1572         value = (ftype)(intptr_t)nvpair_get_##type(nvp);                \
1573         nvlist_remove_nvpair(nvl, nvp);                                 \
1574         nvpair_free_structure(nvp);                                     \
1575         return (value);                                                 \
1576 }
1577
1578 NVLIST_TAKEV(bool, bool, BOOL)
1579 NVLIST_TAKEV(uint64_t, number, NUMBER)
1580 NVLIST_TAKEV(char *, string, STRING)
1581 NVLIST_TAKEV(nvlist_t *, nvlist, NVLIST)
1582 NVLIST_TAKEV(int, descriptor, DESCRIPTOR)
1583
1584 #undef  NVLIST_TAKEV
1585
1586 void *
1587 nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt,
1588     va_list nameap)
1589 {
1590         va_list cnameap;
1591         nvpair_t *nvp;
1592         void *value;
1593
1594         va_copy(cnameap, nameap);
1595         nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap);
1596         va_end(cnameap);
1597         if (nvp == NULL)
1598                 nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap);
1599
1600         value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
1601         nvlist_remove_nvpair(nvl, nvp);
1602         nvpair_free_structure(nvp);
1603         return (value);
1604 }
1605
1606 void
1607 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1608 {
1609
1610         NVLIST_ASSERT(nvl);
1611         NVPAIR_ASSERT(nvp);
1612         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1613
1614         nvpair_remove(&nvl->nvl_head, nvp, nvl);
1615 }
1616
1617 void
1618 nvlist_free(nvlist_t *nvl, const char *name)
1619 {
1620
1621         nvlist_freef(nvl, "%s", name);
1622 }
1623
1624 #define NVLIST_FREE(type)                                               \
1625 void                                                                    \
1626 nvlist_free_##type(nvlist_t *nvl, const char *name)                     \
1627 {                                                                       \
1628                                                                         \
1629         nvlist_freef_##type(nvl, "%s", name);                           \
1630 }
1631
1632 NVLIST_FREE(null)
1633 NVLIST_FREE(bool)
1634 NVLIST_FREE(number)
1635 NVLIST_FREE(string)
1636 NVLIST_FREE(nvlist)
1637 NVLIST_FREE(descriptor)
1638 NVLIST_FREE(binary)
1639
1640 #undef  NVLIST_FREE
1641
1642 void
1643 nvlist_freef(nvlist_t *nvl, const char *namefmt, ...)
1644 {
1645         va_list nameap;
1646
1647         va_start(nameap, namefmt);
1648         nvlist_freev(nvl, namefmt, nameap);
1649         va_end(nameap);
1650 }
1651
1652 #define NVLIST_FREEF(type)                                              \
1653 void                                                                    \
1654 nvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...)            \
1655 {                                                                       \
1656         va_list nameap;                                                 \
1657                                                                         \
1658         va_start(nameap, namefmt);                                      \
1659         nvlist_freev_##type(nvl, namefmt, nameap);                      \
1660         va_end(nameap);                                                 \
1661 }
1662
1663 NVLIST_FREEF(null)
1664 NVLIST_FREEF(bool)
1665 NVLIST_FREEF(number)
1666 NVLIST_FREEF(string)
1667 NVLIST_FREEF(nvlist)
1668 NVLIST_FREEF(descriptor)
1669 NVLIST_FREEF(binary)
1670
1671 #undef  NVLIST_FREEF
1672
1673 void
1674 nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap)
1675 {
1676
1677         nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap);
1678 }
1679
1680 #define NVLIST_FREEV(type, TYPE)                                        \
1681 void                                                                    \
1682 nvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
1683 {                                                                       \
1684                                                                         \
1685         nvlist_freev_type(nvl, NV_TYPE_##TYPE, namefmt, nameap);        \
1686 }
1687
1688 NVLIST_FREEV(null, NULL)
1689 NVLIST_FREEV(bool, BOOL)
1690 NVLIST_FREEV(number, NUMBER)
1691 NVLIST_FREEV(string, STRING)
1692 NVLIST_FREEV(nvlist, NVLIST)
1693 NVLIST_FREEV(descriptor, DESCRIPTOR)
1694 NVLIST_FREEV(binary, BINARY)
1695 #undef  NVLIST_FREEV
1696
1697 void
1698 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1699 {
1700
1701         NVLIST_ASSERT(nvl);
1702         NVPAIR_ASSERT(nvp);
1703         PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1704
1705         nvlist_remove_nvpair(nvl, nvp);
1706         nvpair_free(nvp);
1707 }