1 /*-
2 * Copyright (c) 2009-2013 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/endian.h>
35 #include <sys/queue.h>
36
37 #ifdef _KERNEL
38
39 #include <sys/errno.h>
40 #include <sys/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/systm.h>
44
45 #include <machine/stdarg.h>
46
47 #else
48 #include <sys/socket.h>
49
50 #include <errno.h>
51 #include <stdarg.h>
52 #include <stdbool.h>
53 #include <stdint.h>
54 #define _WITH_DPRINTF
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <unistd.h>
59
60 #include "msgio.h"
61 #endif
62
63 #ifdef HAVE_PJDLOG
64 #include <pjdlog.h>
65 #endif
66
67 #include "nv.h"
68 #include "nv_impl.h"
69 #include "nvlist_impl.h"
70 #include "nvpair_impl.h"
71
72 #ifndef HAVE_PJDLOG
73 #ifdef _KERNEL
74 #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
75 #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
76 #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
77 #else
78 #include <assert.h>
79 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
80 #define PJDLOG_RASSERT(expr, ...) assert(expr)
81 #define PJDLOG_ABORT(...) do { \
82 fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \
83 fprintf(stderr, __VA_ARGS__); \
84 fprintf(stderr, "\n"); \
85 abort(); \
86 } while (0)
87 #endif
88 #endif
89
90 #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN)
91 #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE)
92 #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
93
94 #define NVLIST_MAGIC 0x6e766c /* "nvl" */
95 struct nvlist {
96 int nvl_magic;
97 int nvl_error;
98 int nvl_flags;
99 int nvl_type;
100 nvpair_t *nvl_parent;
101 struct nvl_head nvl_head;
102 };
103
104 #define NVLIST_ASSERT(nvl) do { \
105 PJDLOG_ASSERT((nvl) != NULL); \
106 PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \
107 } while (0)
108
109 #ifdef _KERNEL
110 MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
111 #endif
112
113 #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp)
114
115 #define NVLIST_HEADER_MAGIC 0x6c
116 #define NVLIST_HEADER_VERSION 0x00
117 struct nvlist_header {
118 uint8_t nvlh_magic;
119 uint8_t nvlh_version;
120 uint8_t nvlh_flags;
121 uint8_t nvlh_type;
122 uint64_t nvlh_descriptors;
123 uint64_t nvlh_size;
124 } __packed;
125
126 nvlist_t *
nvlist_create(int flags)127 nvlist_create(int flags)
128 {
129 nvlist_t *nvl;
130
131 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
132
133 nvl = nv_malloc(sizeof(*nvl));
134 nvl->nvl_error = 0;
135 nvl->nvl_flags = flags;
136 nvl->nvl_parent = NULL;
137 nvl->nvl_type = NV_TYPE_NVLIST;
138 TAILQ_INIT(&nvl->nvl_head);
139 nvl->nvl_magic = NVLIST_MAGIC;
140
141 return (nvl);
142 }
143
144 nvlist_t *
nvlist_create_array(int flags)145 nvlist_create_array(int flags)
146 {
147 nvlist_t *nvl;
148
149 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
150
151 nvl = nv_malloc(sizeof(*nvl));
152 nvl->nvl_error = 0;
153 nvl->nvl_flags = flags;
154 nvl->nvl_parent = NULL;
155 nvl->nvl_type = NV_TYPE_NVLIST_ARRAY;
156 TAILQ_INIT(&nvl->nvl_head);
157 nvl->nvl_magic = NVLIST_MAGIC;
158
159 return (nvl);
160 }
161
162 nvlist_t *
nvlist_create_dictionary(int flags)163 nvlist_create_dictionary(int flags)
164 {
165 nvlist_t *nvl;
166
167 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
168
169 nvl = nv_malloc(sizeof(*nvl));
170 nvl->nvl_error = 0;
171 nvl->nvl_flags = flags;
172 nvl->nvl_parent = NULL;
173 nvl->nvl_type = NV_TYPE_NVLIST_DICTIONARY;
174 TAILQ_INIT(&nvl->nvl_head);
175 nvl->nvl_magic = NVLIST_MAGIC;
176
177 printf("1 nvl = %p\n", nvl);
178 return (nvl);
179 }
180
181 void
nvlist_destroy(nvlist_t * nvl)182 nvlist_destroy(nvlist_t *nvl)
183 {
184 nvpair_t *nvp;
185 int serrno;
186
187 if (nvl == NULL)
188 return;
189
190 SAVE_ERRNO(serrno);
191
192 NVLIST_ASSERT(nvl);
193
194 while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
195 nvlist_remove_nvpair(nvl, nvp);
196 nvpair_free(nvp);
197 }
198 nvl->nvl_magic = 0;
199 nv_free(nvl);
200
201 RESTORE_ERRNO(serrno);
202 }
203
204 void
nvlist_set_error(nvlist_t * nvl,int error)205 nvlist_set_error(nvlist_t *nvl, int error)
206 {
207
208 PJDLOG_ASSERT(error != 0);
209
210 /*
211 * Check for error != 0 so that we don't do the wrong thing if somebody
212 * tries to abuse this API when asserts are disabled.
213 */
214 if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
215 nvl->nvl_error = error;
216 }
217
218 int
nvlist_error(const nvlist_t * nvl)219 nvlist_error(const nvlist_t *nvl)
220 {
221
222 if (nvl == NULL)
223 return (ENOMEM);
224
225 NVLIST_ASSERT(nvl);
226
227 return (nvl->nvl_error);
228 }
229
230 nvpair_t *
nvlist_get_nvpair_parent(const nvlist_t * nvl)231 nvlist_get_nvpair_parent(const nvlist_t *nvl)
232 {
233
234 NVLIST_ASSERT(nvl);
235
236 return (nvl->nvl_parent);
237 }
238
239 const nvlist_t *
nvlist_get_parent(const nvlist_t * nvl,void ** cookiep)240 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
241 {
242 nvpair_t *nvp;
243
244 NVLIST_ASSERT(nvl);
245
246 nvp = nvl->nvl_parent;
247 if (cookiep != NULL)
248 *cookiep = nvp;
249 if (nvp == NULL)
250 return (NULL);
251
252 return (nvpair_nvlist(nvp));
253 }
254
255 void
nvlist_set_parent(nvlist_t * nvl,nvpair_t * parent)256 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
257 {
258
259 NVLIST_ASSERT(nvl);
260
261 nvl->nvl_parent = parent;
262 }
263
264 bool
nvlist_empty(const nvlist_t * nvl)265 nvlist_empty(const nvlist_t *nvl)
266 {
267
268 NVLIST_ASSERT(nvl);
269 PJDLOG_ASSERT(nvl->nvl_error == 0);
270
271 return (nvlist_first_nvpair(nvl) == NULL);
272 }
273
274 int
nvlist_type(const nvlist_t * nvl)275 nvlist_type(const nvlist_t *nvl)
276 {
277
278 NVLIST_ASSERT(nvl);
279 PJDLOG_ASSERT(nvl->nvl_error == 0);
280
281 return (nvl->nvl_type);
282 }
283
284 static void
nvlist_report_missing(int type,const char * name)285 nvlist_report_missing(int type, const char *name)
286 {
287
288 PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
289 name, nvpair_type_string(type));
290 }
291
292 static nvpair_t *
nvlist_find(const nvlist_t * nvl,int type,const char * name)293 nvlist_find(const nvlist_t *nvl, int type, const char *name)
294 {
295 nvpair_t *nvp;
296
297 NVLIST_ASSERT(nvl);
298 PJDLOG_ASSERT(nvl->nvl_error == 0);
299 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
300 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
301
302 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
303 nvp = nvlist_next_nvpair(nvl, nvp)) {
304 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
305 continue;
306 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
307 if (strcasecmp(nvpair_name(nvp), name) != 0)
308 continue;
309 } else {
310 if (strcmp(nvpair_name(nvp), name) != 0)
311 continue;
312 }
313 break;
314 }
315
316 if (nvp == NULL)
317 RESTORE_ERRNO(ENOENT);
318
319 return (nvp);
320 }
321
322 bool
nvlist_exists_type(const nvlist_t * nvl,const char * name,int type)323 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
324 {
325
326 NVLIST_ASSERT(nvl);
327 PJDLOG_ASSERT(nvl->nvl_error == 0);
328 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
329 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
330
331 return (nvlist_find(nvl, type, name) != NULL);
332 }
333
334 #ifndef _KERNEL
335 bool
nvlist_existsf_type(const nvlist_t * nvl,int type,const char * namefmt,...)336 nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...)
337 {
338 va_list nameap;
339 bool ret;
340
341 va_start(nameap, namefmt);
342 ret = nvlist_existsv_type(nvl, type, namefmt, nameap);
343 va_end(nameap);
344
345 return (ret);
346 }
347
348 bool
nvlist_existsv_type(const nvlist_t * nvl,int type,const char * namefmt,va_list nameap)349 nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt,
350 va_list nameap)
351 {
352 char *name;
353 bool exists;
354
355 nv_vasprintf(&name, namefmt, nameap);
356 if (name == NULL)
357 return (false);
358
359 exists = nvlist_exists_type(nvl, name, type);
360 nv_free(name);
361 return (exists);
362 }
363 #endif
364
365 void
nvlist_free_type(nvlist_t * nvl,const char * name,int type)366 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
367 {
368 nvpair_t *nvp;
369
370 NVLIST_ASSERT(nvl);
371 PJDLOG_ASSERT(nvl->nvl_error == 0);
372 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
373 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
374
375 nvp = nvlist_find(nvl, type, name);
376 if (nvp != NULL)
377 nvlist_free_nvpair(nvl, nvp);
378 else
379 nvlist_report_missing(type, name);
380 }
381
382 #ifndef _KERNEL
383 void
nvlist_freef_type(nvlist_t * nvl,int type,const char * namefmt,...)384 nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...)
385 {
386 va_list nameap;
387
388 va_start(nameap, namefmt);
389 nvlist_freev_type(nvl, type, namefmt, nameap);
390 va_end(nameap);
391 }
392
393 void
nvlist_freev_type(nvlist_t * nvl,int type,const char * namefmt,va_list nameap)394 nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap)
395 {
396 char *name;
397
398 nv_vasprintf(&name, namefmt, nameap);
399 if (name == NULL)
400 nvlist_report_missing(type, "<unknown>");
401 nvlist_free_type(nvl, name, type);
402 nv_free(name);
403 }
404 #endif
405
406 nvlist_t *
nvlist_clone(const nvlist_t * nvl)407 nvlist_clone(const nvlist_t *nvl)
408 {
409 nvlist_t *newnvl;
410 nvpair_t *nvp, *newnvp;
411
412 NVLIST_ASSERT(nvl);
413
414 if (nvl->nvl_error != 0) {
415 RESTORE_ERRNO(nvl->nvl_error);
416 return (NULL);
417 }
418
419 newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
420 newnvl->nvl_type = nvl->nvl_type;
421 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
422 nvp = nvlist_next_nvpair(nvl, nvp)) {
423 newnvp = nvpair_clone(nvp);
424 if (newnvp == NULL)
425 break;
426 nvlist_move_nvpair(newnvl, newnvp);
427 }
428 if (nvp != NULL) {
429 nvlist_destroy(newnvl);
430 return (NULL);
431 }
432 return (newnvl);
433 }
434
435 #ifndef _KERNEL
436 static bool
nvlist_dump_error_check(const nvlist_t * nvl,int fd,int level)437 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
438 {
439
440 if (nvlist_error(nvl) != 0) {
441 dprintf(fd, "%*serror: %d\n", level * 4, "",
442 nvlist_error(nvl));
443 return (true);
444 }
445
446 return (false);
447 }
448
449 /*
450 * Dump content of nvlist.
451 */
452 void
nvlist_dump(const nvlist_t * nvl,int fd)453 nvlist_dump(const nvlist_t *nvl, int fd)
454 {
455 const nvlist_t *tmpnvl;
456 nvpair_t *nvp, *tmpnvp;
457 void *cookie;
458 int level;
459
460 level = 0;
461 if (nvlist_dump_error_check(nvl, fd, level))
462 return;
463
464 nvp = nvlist_first_nvpair(nvl);
465 while (nvp != NULL) {
466 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
467 nvpair_type_string(nvpair_type(nvp)));
468 switch (nvpair_type(nvp)) {
469 case NV_TYPE_NULL:
470 dprintf(fd, " null\n");
471 break;
472 case NV_TYPE_BOOL:
473 dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
474 "TRUE" : "FALSE");
475 break;
476 case NV_TYPE_NUMBER:
477 case NV_TYPE_PTR:
478 case NV_TYPE_UINT64:
479 case NV_TYPE_INT64:
480 case NV_TYPE_ENDPOINT:
481 case NV_TYPE_DATE:
482 dprintf(fd, " %ju (%jd) (0x%jx)\n",
483 (uintmax_t)nvpair_get_number(nvp),
484 (intmax_t)nvpair_get_number(nvp),
485 (uintmax_t)nvpair_get_number(nvp));
486 break;
487 case NV_TYPE_STRING:
488 dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
489 break;
490 case NV_TYPE_NVLIST:
491 case NV_TYPE_NVLIST_ARRAY:
492 case NV_TYPE_NVLIST_DICTIONARY:
493 dprintf(fd, "\n");
494 tmpnvl = nvpair_get_nvlist(nvp);
495 if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
496 break;
497 tmpnvp = nvlist_first_nvpair(tmpnvl);
498 if (tmpnvp != NULL) {
499 nvl = tmpnvl;
500 nvp = tmpnvp;
501 level++;
502 continue;
503 }
504 break;
505 case NV_TYPE_DESCRIPTOR:
506 dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
507 break;
508 case NV_TYPE_BINARY:
509 {
510 const unsigned char *binary;
511 unsigned int ii;
512 size_t size;
513
514 binary = nvpair_get_binary(nvp, &size);
515 dprintf(fd, " %zu ", size);
516 for (ii = 0; ii < size; ii++)
517 dprintf(fd, "%02hhx", binary[ii]);
518 dprintf(fd, "\n");
519 break;
520 }
521 case NV_TYPE_UUID:
522 {
523 char *str;
524 int status;
525 const uuid_t *uuid;
526
527 uuid = nvpair_get_uuid(nvp);
528 uuid_to_string(uuid, &str, &status);
529 if (status == uuid_s_ok)
530 dprintf(fd, " [%s]\n", str);
531
532 free(str);
533 break;
534 }
535 default:
536 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
537 }
538
539 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
540 cookie = NULL;
541 nvl = nvlist_get_parent(nvl, &cookie);
542 if (nvl == NULL)
543 return;
544 nvp = cookie;
545 level--;
546 }
547 }
548 }
549
550 void
nvlist_fdump(const nvlist_t * nvl,FILE * fp)551 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
552 {
553
554 fflush(fp);
555 nvlist_dump(nvl, fileno(fp));
556 }
557 #endif
558
559 /*
560 * The function obtains size of the nvlist after nvlist_pack().
561 */
562 size_t
nvlist_size(const nvlist_t * nvl)563 nvlist_size(const nvlist_t *nvl)
564 {
565 const nvlist_t *tmpnvl;
566 const nvpair_t *nvp, *tmpnvp;
567 void *cookie;
568 size_t size;
569
570 NVLIST_ASSERT(nvl);
571 PJDLOG_ASSERT(nvl->nvl_error == 0);
572
573 size = sizeof(struct nvlist_header);
574 nvp = nvlist_first_nvpair(nvl);
575 while (nvp != NULL) {
576 size += nvpair_header_size();
577 size += strlen(nvpair_name(nvp)) + 1;
578 if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY ||
579 nvpair_type(nvp) == NV_TYPE_NVLIST_DICTIONARY ||
580 nvpair_type(nvp) == NV_TYPE_NVLIST) {
581 size += sizeof(struct nvlist_header);
582 size += nvpair_header_size() + 1;
583 tmpnvl = nvpair_get_nvlist(nvp);
584 PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
585 tmpnvp = nvlist_first_nvpair(tmpnvl);
586 if (tmpnvp != NULL) {
587 nvl = tmpnvl;
588 nvp = tmpnvp;
589 continue;
590 }
591 } else {
592 size += nvpair_size(nvp);
593 }
594
595 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
596 cookie = NULL;
597 nvl = nvlist_get_parent(nvl, &cookie);
598 if (nvl == NULL)
599 goto out;
600 nvp = cookie;
601 }
602 }
603
604 out:
605 return (size);
606 }
607
608 #ifndef _KERNEL
609 static int *
nvlist_xdescriptors(const nvlist_t * nvl,int * descs,int level)610 nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
611 {
612 const nvpair_t *nvp;
613
614 NVLIST_ASSERT(nvl);
615 PJDLOG_ASSERT(nvl->nvl_error == 0);
616 PJDLOG_ASSERT(level < 3);
617
618 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
619 nvp = nvlist_next_nvpair(nvl, nvp)) {
620 switch (nvpair_type(nvp)) {
621 case NV_TYPE_DESCRIPTOR:
622 *descs = nvpair_get_descriptor(nvp);
623 descs++;
624 break;
625 case NV_TYPE_NVLIST:
626 case NV_TYPE_NVLIST_ARRAY:
627 case NV_TYPE_NVLIST_DICTIONARY:
628 descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp),
629 descs, level + 1);
630 break;
631 }
632 }
633
634 return (descs);
635 }
636 #endif
637
638 #ifndef _KERNEL
639 int *
nvlist_descriptors(const nvlist_t * nvl,size_t * nitemsp)640 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
641 {
642 size_t nitems;
643 int *fds;
644
645 nitems = nvlist_ndescriptors(nvl);
646 fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
647 if (fds == NULL)
648 return (NULL);
649 if (nitems > 0)
650 nvlist_xdescriptors(nvl, fds, 0);
651 fds[nitems] = -1;
652 if (nitemsp != NULL)
653 *nitemsp = nitems;
654 return (fds);
655 }
656 #endif
657
658 static size_t
nvlist_xndescriptors(const nvlist_t * nvl,int level)659 nvlist_xndescriptors(const nvlist_t *nvl, int level)
660 {
661 #ifndef _KERNEL
662 const nvpair_t *nvp;
663 size_t ndescs;
664
665 NVLIST_ASSERT(nvl);
666 PJDLOG_ASSERT(nvl->nvl_error == 0);
667 PJDLOG_ASSERT(level < 3);
668
669 ndescs = 0;
670 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
671 nvp = nvlist_next_nvpair(nvl, nvp)) {
672 switch (nvpair_type(nvp)) {
673 case NV_TYPE_DESCRIPTOR:
674 ndescs++;
675 break;
676 case NV_TYPE_NVLIST:
677 case NV_TYPE_NVLIST_ARRAY:
678 case NV_TYPE_NVLIST_DICTIONARY:
679 ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp),
680 level + 1);
681 break;
682 }
683 }
684
685 return (ndescs);
686 #else
687 return (0);
688 #endif
689 }
690
691 size_t
nvlist_ndescriptors(const nvlist_t * nvl)692 nvlist_ndescriptors(const nvlist_t *nvl)
693 {
694
695 return (nvlist_xndescriptors(nvl, 0));
696 }
697
698 static unsigned char *
nvlist_pack_header(const nvlist_t * nvl,unsigned char * ptr,size_t * leftp)699 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
700 {
701 struct nvlist_header nvlhdr;
702
703 NVLIST_ASSERT(nvl);
704
705 nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
706 nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
707 nvlhdr.nvlh_flags = nvl->nvl_flags;
708 nvlhdr.nvlh_type = (uint8_t)nvl->nvl_type;
709 #if BYTE_ORDER == BIG_ENDIAN
710 nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
711 #endif
712 nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
713 nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
714 PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
715 memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
716 ptr += sizeof(nvlhdr);
717 *leftp -= sizeof(nvlhdr);
718
719 return (ptr);
720 }
721
722 void *
nvlist_xpack(const nvlist_t * nvl,void * ubuf,int64_t * fdidxp,size_t * sizep)723 nvlist_xpack(const nvlist_t *nvl, void *ubuf, int64_t *fdidxp, size_t *sizep)
724 {
725 unsigned char *buf, *ptr;
726 size_t left, size;
727 const nvlist_t *tmpnvl;
728 nvpair_t *nvp, *tmpnvp;
729 void *cookie;
730
731 NVLIST_ASSERT(nvl);
732
733 if (nvl->nvl_error != 0) {
734 RESTORE_ERRNO(nvl->nvl_error);
735 return (NULL);
736 }
737
738 size = nvlist_size(nvl);
739 if (ubuf) {
740 if (sizep == NULL || *sizep != size)
741 return (NULL);
742 else
743 buf = ubuf;
744 } else
745 buf = nv_malloc(size);
746 if (buf == NULL)
747 return (NULL);
748
749 ptr = buf;
750 left = size;
751
752 ptr = nvlist_pack_header(nvl, ptr, &left);
753
754 nvp = nvlist_first_nvpair(nvl);
755 while (nvp != NULL) {
756 NVPAIR_ASSERT(nvp);
757
758 nvpair_init_datasize(nvp);
759 ptr = nvpair_pack_header(nvp, ptr, &left);
760 if (ptr == NULL) {
761 nv_free(buf);
762 return (NULL);
763 }
764 switch (nvpair_type(nvp)) {
765 case NV_TYPE_NULL:
766 ptr = nvpair_pack_null(nvp, ptr, &left);
767 break;
768 case NV_TYPE_BOOL:
769 ptr = nvpair_pack_bool(nvp, ptr, &left);
770 break;
771 case NV_TYPE_NUMBER:
772 case NV_TYPE_PTR:
773 case NV_TYPE_UINT64:
774 case NV_TYPE_INT64:
775 case NV_TYPE_ENDPOINT:
776 ptr = nvpair_pack_number(nvp, ptr, &left);
777 break;
778 case NV_TYPE_STRING:
779 ptr = nvpair_pack_string(nvp, ptr, &left);
780 break;
781 case NV_TYPE_NVLIST:
782 case NV_TYPE_NVLIST_ARRAY:
783 case NV_TYPE_NVLIST_DICTIONARY:
784 tmpnvl = nvpair_get_nvlist(nvp);
785 ptr = nvlist_pack_header(tmpnvl, ptr, &left);
786 if (ptr == NULL)
787 goto out;
788 tmpnvp = nvlist_first_nvpair(tmpnvl);
789 if (tmpnvp != NULL) {
790 nvl = tmpnvl;
791 nvp = tmpnvp;
792 continue;
793 }
794 ptr = nvpair_pack_nvlist_up(ptr, &left);
795 break;
796 #ifndef _KERNEL
797 case NV_TYPE_DESCRIPTOR:
798 ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
799 break;
800 #endif
801 case NV_TYPE_BINARY:
802 case NV_TYPE_UUID:
803 ptr = nvpair_pack_binary(nvp, ptr, &left);
804 break;
805 default:
806 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
807 }
808 if (ptr == NULL) {
809 nv_free(buf);
810 return (NULL);
811 }
812 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
813 cookie = NULL;
814 nvl = nvlist_get_parent(nvl, &cookie);
815 if (nvl == NULL)
816 goto out;
817 nvp = cookie;
818 ptr = nvpair_pack_nvlist_up(ptr, &left);
819 if (ptr == NULL)
820 goto out;
821 }
822 }
823
824 out:
825 if (sizep != NULL)
826 *sizep = size;
827 return (buf);
828 }
829
830 void *
nvlist_pack(const nvlist_t * nvl,size_t * sizep)831 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
832 {
833
834 return (nvlist_pack_buffer(nvl, NULL, sizep));
835 }
836
837 void *
nvlist_pack_buffer(const nvlist_t * nvl,void * ubuf,size_t * sizep)838 nvlist_pack_buffer(const nvlist_t *nvl, void *ubuf, size_t *sizep)
839 {
840
841 NVLIST_ASSERT(nvl);
842
843 if (nvl->nvl_error != 0) {
844 RESTORE_ERRNO(nvl->nvl_error);
845 return (NULL);
846 }
847
848 if (nvlist_ndescriptors(nvl) > 0) {
849 RESTORE_ERRNO(EOPNOTSUPP);
850 return (NULL);
851 }
852
853 return (nvlist_xpack(nvl, ubuf, NULL, sizep));
854 }
855
856 static bool
nvlist_check_header(struct nvlist_header * nvlhdrp)857 nvlist_check_header(struct nvlist_header *nvlhdrp)
858 {
859
860 if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
861 RESTORE_ERRNO(EINVAL);
862 return (false);
863 }
864 if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
865 RESTORE_ERRNO(EINVAL);
866 return (false);
867 }
868 #if BYTE_ORDER == BIG_ENDIAN
869 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
870 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
871 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
872 }
873 #else
874 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
875 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
876 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
877 }
878 #endif
879 return (true);
880 }
881
882 const unsigned char *
nvlist_unpack_header(nvlist_t * nvl,const unsigned char * ptr,size_t nfds,bool * isbep,size_t * leftp)883 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
884 bool *isbep, size_t *leftp)
885 {
886 struct nvlist_header nvlhdr;
887
888 if (*leftp < sizeof(nvlhdr))
889 goto failed;
890
891 memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
892
893 if (!nvlist_check_header(&nvlhdr))
894 goto failed;
895
896 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
897 goto failed;
898
899 /*
900 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
901 */
902 if (nvlhdr.nvlh_descriptors > nfds)
903 goto failed;
904
905 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
906 goto failed;
907
908 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
909
910 ptr += sizeof(nvlhdr);
911 if (isbep != NULL)
912 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
913 *leftp -= sizeof(nvlhdr);
914
915 nvl->nvl_type = nvlhdr.nvlh_type;
916 return (ptr);
917 failed:
918 RESTORE_ERRNO(EINVAL);
919 return (NULL);
920 }
921
922 nvlist_t *
nvlist_xunpack(const void * buf,size_t size,const int * fds,size_t nfds)923 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
924 {
925 const unsigned char *ptr;
926 nvlist_t *nvl, *retnvl, *tmpnvl;
927 nvpair_t *nvp;
928 size_t left;
929 bool isbe;
930
931 left = size;
932 ptr = buf;
933
934 tmpnvl = NULL;
935 nvl = retnvl = nvlist_create(0);
936 if (nvl == NULL)
937 goto failed;
938
939 ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
940 if (ptr == NULL)
941 goto failed;
942
943 while (left > 0) {
944 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
945 if (ptr == NULL)
946 goto failed;
947 switch (nvpair_type(nvp)) {
948 case NV_TYPE_NULL:
949 ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
950 break;
951 case NV_TYPE_BOOL:
952 ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
953 break;
954 case NV_TYPE_NUMBER:
955 case NV_TYPE_PTR:
956 case NV_TYPE_UINT64:
957 case NV_TYPE_INT64:
958 case NV_TYPE_ENDPOINT:
959 ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
960 break;
961 case NV_TYPE_STRING:
962 ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
963 break;
964 case NV_TYPE_NVLIST:
965 case NV_TYPE_NVLIST_ARRAY:
966 case NV_TYPE_NVLIST_DICTIONARY:
967 ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
968 &tmpnvl);
969 nvlist_set_parent(tmpnvl, nvp);
970 break;
971 #ifndef _KERNEL
972 case NV_TYPE_DESCRIPTOR:
973 ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
974 fds, nfds);
975 break;
976 #endif
977 case NV_TYPE_BINARY:
978 case NV_TYPE_UUID:
979 ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
980 break;
981 case NV_TYPE_NVLIST_UP:
982 if (nvl->nvl_parent == NULL)
983 goto failed;
984 nvl = nvpair_nvlist(nvl->nvl_parent);
985 continue;
986 default:
987 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
988 }
989 if (ptr == NULL)
990 goto failed;
991 nvlist_move_nvpair(nvl, nvp);
992 if (tmpnvl != NULL) {
993 nvl = tmpnvl;
994 tmpnvl = NULL;
995 }
996 }
997
998 return (retnvl);
999 failed:
1000 nvlist_destroy(retnvl);
1001 return (NULL);
1002 }
1003
1004 nvlist_t *
nvlist_unpack(const void * buf,size_t size)1005 nvlist_unpack(const void *buf, size_t size)
1006 {
1007
1008 return (nvlist_xunpack(buf, size, NULL, 0));
1009 }
1010
1011 #ifndef _KERNEL
1012 int
nvlist_send(int sock,const nvlist_t * nvl)1013 nvlist_send(int sock, const nvlist_t *nvl)
1014 {
1015 size_t datasize, nfds;
1016 int *fds;
1017 void *data;
1018 int64_t fdidx;
1019 int serrno, ret;
1020
1021 if (nvlist_error(nvl) != 0) {
1022 errno = nvlist_error(nvl);
1023 return (-1);
1024 }
1025
1026 fds = nvlist_descriptors(nvl, &nfds);
1027 if (fds == NULL)
1028 return (-1);
1029
1030 ret = -1;
1031 data = NULL;
1032 fdidx = 0;
1033
1034 data = nvlist_xpack(nvl, NULL, &fdidx, &datasize);
1035 if (data == NULL)
1036 goto out;
1037
1038 if (buf_send(sock, data, datasize) == -1)
1039 goto out;
1040
1041 if (nfds > 0) {
1042 if (fd_send(sock, fds, nfds) == -1)
1043 goto out;
1044 }
1045
1046 ret = 0;
1047 out:
1048 serrno = errno;
1049 free(fds);
1050 free(data);
1051 errno = serrno;
1052 return (ret);
1053 }
1054
1055 nvlist_t *
nvlist_recv(int sock)1056 nvlist_recv(int sock)
1057 {
1058 struct nvlist_header nvlhdr;
1059 nvlist_t *nvl, *ret;
1060 unsigned char *buf;
1061 size_t nfds, size, i;
1062 int serrno, *fds;
1063
1064 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
1065 return (NULL);
1066
1067 if (!nvlist_check_header(&nvlhdr))
1068 return (NULL);
1069
1070 nfds = (size_t)nvlhdr.nvlh_descriptors;
1071 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
1072
1073 buf = malloc(size);
1074 if (buf == NULL)
1075 return (NULL);
1076
1077 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
1078
1079 ret = NULL;
1080 fds = NULL;
1081
1082 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
1083 goto out;
1084
1085 if (nfds > 0) {
1086 fds = malloc(nfds * sizeof(fds[0]));
1087 if (fds == NULL)
1088 goto out;
1089 if (fd_recv(sock, fds, nfds) == -1)
1090 goto out;
1091 }
1092
1093 nvl = nvlist_xunpack(buf, size, fds, nfds);
1094 if (nvl == NULL) {
1095 for (i = 0; i < nfds; i++)
1096 close(fds[i]);
1097 goto out;
1098 }
1099
1100 ret = nvl;
1101 out:
1102 serrno = errno;
1103 free(buf);
1104 free(fds);
1105 errno = serrno;
1106
1107 return (ret);
1108 }
1109
1110 nvlist_t *
nvlist_xfer(int sock,nvlist_t * nvl)1111 nvlist_xfer(int sock, nvlist_t *nvl)
1112 {
1113
1114 if (nvlist_send(sock, nvl) < 0) {
1115 nvlist_destroy(nvl);
1116 return (NULL);
1117 }
1118 nvlist_destroy(nvl);
1119 return (nvlist_recv(sock));
1120 }
1121 #endif
1122
1123 nvpair_t *
nvlist_first_nvpair(const nvlist_t * nvl)1124 nvlist_first_nvpair(const nvlist_t *nvl)
1125 {
1126
1127 NVLIST_ASSERT(nvl);
1128
1129 return (TAILQ_FIRST(&nvl->nvl_head));
1130 }
1131
1132 nvpair_t *
nvlist_next_nvpair(const nvlist_t * nvl,const nvpair_t * nvp)1133 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1134 {
1135 nvpair_t *retnvp;
1136
1137 NVLIST_ASSERT(nvl);
1138 NVPAIR_ASSERT(nvp);
1139 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1140
1141 retnvp = nvpair_next(nvp);
1142 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1143
1144 return (retnvp);
1145
1146 }
1147
1148 nvpair_t *
nvlist_prev_nvpair(const nvlist_t * nvl,const nvpair_t * nvp)1149 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1150 {
1151 nvpair_t *retnvp;
1152
1153 NVLIST_ASSERT(nvl);
1154 NVPAIR_ASSERT(nvp);
1155 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1156
1157 retnvp = nvpair_prev(nvp);
1158 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1159
1160 return (retnvp);
1161 }
1162
1163 const char *
nvlist_next(const nvlist_t * nvl,int * typep,void ** cookiep)1164 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1165 {
1166 nvpair_t *nvp;
1167
1168 NVLIST_ASSERT(nvl);
1169 PJDLOG_ASSERT(cookiep != NULL);
1170
1171 if (*cookiep == NULL)
1172 nvp = nvlist_first_nvpair(nvl);
1173 else
1174 nvp = nvlist_next_nvpair(nvl, *cookiep);
1175 if (nvp == NULL)
1176 return (NULL);
1177 if (typep != NULL)
1178 *typep = nvpair_type(nvp);
1179 *cookiep = nvp;
1180 return (nvpair_name(nvp));
1181 }
1182
1183 bool
nvlist_exists(const nvlist_t * nvl,const char * name)1184 nvlist_exists(const nvlist_t *nvl, const char *name)
1185 {
1186
1187 return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1188 }
1189
1190 #define NVLIST_EXISTS(type, TYPE) \
1191 bool \
1192 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
1193 { \
1194 \
1195 return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \
1196 }
1197
NVLIST_EXISTS(null,NULL)1198 NVLIST_EXISTS(null, NULL)
1199 NVLIST_EXISTS(bool, BOOL)
1200 NVLIST_EXISTS(number, NUMBER)
1201 NVLIST_EXISTS(ptr, PTR)
1202 NVLIST_EXISTS(uint64, UINT64)
1203 NVLIST_EXISTS(int64, INT64)
1204 NVLIST_EXISTS(endpoint, ENDPOINT)
1205 NVLIST_EXISTS(date, DATE)
1206 NVLIST_EXISTS(string, STRING)
1207 NVLIST_EXISTS(nvlist, NVLIST)
1208 #ifndef _KERNEL
1209 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1210 #endif
1211 NVLIST_EXISTS(binary, BINARY)
1212 NVLIST_EXISTS(uuid, UUID)
1213
1214 #undef NVLIST_EXISTS
1215
1216 #ifndef _KERNEL
1217 bool
1218 nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...)
1219 {
1220 va_list nameap;
1221 bool ret;
1222
1223 va_start(nameap, namefmt);
1224 ret = nvlist_existsv(nvl, namefmt, nameap);
1225 va_end(nameap);
1226 return (ret);
1227 }
1228
1229 #define NVLIST_EXISTSF(type) \
1230 bool \
1231 nvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...) \
1232 { \
1233 va_list nameap; \
1234 bool ret; \
1235 \
1236 va_start(nameap, namefmt); \
1237 ret = nvlist_existsv_##type(nvl, namefmt, nameap); \
1238 va_end(nameap); \
1239 return (ret); \
1240 }
1241
1242 NVLIST_EXISTSF(null)
NVLIST_EXISTSF(bool)1243 NVLIST_EXISTSF(bool)
1244 NVLIST_EXISTSF(number)
1245 NVLIST_EXISTSF(ptr)
1246 NVLIST_EXISTSF(uint64)
1247 NVLIST_EXISTSF(int64)
1248 NVLIST_EXISTSF(endpoint)
1249 NVLIST_EXISTSF(date)
1250 NVLIST_EXISTSF(string)
1251 NVLIST_EXISTSF(nvlist)
1252 #ifndef _KERNEL
1253 NVLIST_EXISTSF(descriptor)
1254 #endif
1255 NVLIST_EXISTSF(binary)
1256 NVLIST_EXISTSF(uuid)
1257
1258 #undef NVLIST_EXISTSF
1259
1260 bool
1261 nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap)
1262 {
1263 char *name;
1264 bool exists;
1265
1266 nv_vasprintf(&name, namefmt, nameap);
1267 if (name == NULL)
1268 return (false);
1269
1270 exists = nvlist_exists(nvl, name);
1271 nv_free(name);
1272 return (exists);
1273 }
1274
1275 #define NVLIST_EXISTSV(type) \
1276 bool \
1277 nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \
1278 va_list nameap) \
1279 { \
1280 char *name; \
1281 bool exists; \
1282 \
1283 vasprintf(&name, namefmt, nameap); \
1284 if (name == NULL) \
1285 return (false); \
1286 exists = nvlist_exists_##type(nvl, name); \
1287 free(name); \
1288 return (exists); \
1289 }
1290
1291 NVLIST_EXISTSV(null)
NVLIST_EXISTSV(bool)1292 NVLIST_EXISTSV(bool)
1293 NVLIST_EXISTSV(number)
1294 NVLIST_EXISTSV(ptr)
1295 NVLIST_EXISTSV(uint64)
1296 NVLIST_EXISTSV(int64)
1297 NVLIST_EXISTSV(endpoint)
1298 NVLIST_EXISTSV(date)
1299 NVLIST_EXISTSV(string)
1300 NVLIST_EXISTSV(nvlist)
1301 NVLIST_EXISTSV(descriptor)
1302 NVLIST_EXISTSV(binary)
1303 NVLIST_EXISTSV(uuid)
1304
1305 #undef NVLIST_EXISTSV
1306 #endif
1307
1308 void
1309 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1310 {
1311 nvpair_t *newnvp;
1312
1313 NVPAIR_ASSERT(nvp);
1314
1315 if (nvlist_error(nvl) != 0) {
1316 RESTORE_ERRNO(nvlist_error(nvl));
1317 return;
1318 }
1319 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1320 nvl->nvl_error = EEXIST;
1321 RESTORE_ERRNO(nvlist_error(nvl));
1322 return;
1323 }
1324
1325 newnvp = nvpair_clone(nvp);
1326 if (newnvp == NULL) {
1327 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1328 RESTORE_ERRNO(nvlist_error(nvl));
1329 return;
1330 }
1331
1332 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1333 }
1334
1335 void
nvlist_add_null(nvlist_t * nvl,const char * name)1336 nvlist_add_null(nvlist_t *nvl, const char *name)
1337 {
1338
1339 nvlist_addf_null(nvl, "%s", name);
1340 }
1341
1342 void
nvlist_add_bool(nvlist_t * nvl,const char * name,bool value)1343 nvlist_add_bool(nvlist_t *nvl, const char *name, bool value)
1344 {
1345
1346 nvlist_addf_bool(nvl, value, "%s", name);
1347 }
1348
1349 void
nvlist_add_number(nvlist_t * nvl,const char * name,uint64_t value)1350 nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value)
1351 {
1352
1353 nvlist_addf_number(nvl, value, "%s", name);
1354 }
1355
1356 void
nvlist_add_ptr(nvlist_t * nvl,const char * name,uintptr_t value)1357 nvlist_add_ptr(nvlist_t *nvl, const char *name, uintptr_t value)
1358 {
1359
1360 nvlist_addf_ptr(nvl, value, "%s", name);
1361 }
1362
1363 void
nvlist_add_uint64(nvlist_t * nvl,const char * name,uint64_t value)1364 nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t value)
1365 {
1366
1367 nvlist_addf_uint64(nvl, value, "%s", name);
1368 }
1369
1370 void
nvlist_add_int64(nvlist_t * nvl,const char * name,int64_t value)1371 nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t value)
1372 {
1373
1374 nvlist_addf_int64(nvl, value, "%s", name);
1375 }
1376
1377 void
nvlist_add_endpoint(nvlist_t * nvl,const char * name,int value)1378 nvlist_add_endpoint(nvlist_t *nvl, const char *name, int value)
1379 {
1380
1381 nvlist_addf_endpoint(nvl, value, "%s", name);
1382 }
1383
1384 void
nvlist_add_date(nvlist_t * nvl,const char * name,uint64_t value)1385 nvlist_add_date(nvlist_t *nvl, const char *name, uint64_t value)
1386 {
1387
1388 nvlist_addf_date(nvl, value, "%s", name);
1389 }
1390
1391 void
nvlist_add_string(nvlist_t * nvl,const char * name,const char * value)1392 nvlist_add_string(nvlist_t *nvl, const char *name, const char *value)
1393 {
1394
1395 nvlist_addf_string(nvl, value, "%s", name);
1396 }
1397
1398 void
nvlist_add_stringf(nvlist_t * nvl,const char * name,const char * valuefmt,...)1399 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1400 {
1401 va_list valueap;
1402
1403 va_start(valueap, valuefmt);
1404 nvlist_add_stringv(nvl, name, valuefmt, valueap);
1405 va_end(valueap);
1406 }
1407
1408 void
nvlist_add_stringv(nvlist_t * nvl,const char * name,const char * valuefmt,va_list valueap)1409 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1410 va_list valueap)
1411 {
1412 nvpair_t *nvp;
1413
1414 if (nvlist_error(nvl) != 0) {
1415 RESTORE_ERRNO(nvlist_error(nvl));
1416 return;
1417 }
1418
1419 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1420 if (nvp == NULL) {
1421 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1422 RESTORE_ERRNO(nvl->nvl_error);
1423 } else
1424 nvlist_move_nvpair(nvl, nvp);
1425 }
1426
1427 void
nvlist_add_nvlist(nvlist_t * nvl,const char * name,const nvlist_t * value)1428 nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value)
1429 {
1430
1431 nvlist_addf_nvlist(nvl, value, "%s", name);
1432 }
1433
1434 void
nvlist_add_nvlist_array(nvlist_t * nvl,const char * name,const nvlist_t * value)1435 nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, const nvlist_t *value)
1436 {
1437
1438 nvlist_addf_nvlist_array(nvl, value, "%s", name);
1439 }
1440
1441 void
nvlist_add_nvlist_dictionary(nvlist_t * nvl,const char * name,const nvlist_t * value)1442 nvlist_add_nvlist_dictionary(nvlist_t *nvl, const char *name, const nvlist_t *value)
1443 {
1444
1445 nvlist_addf_nvlist_dictionary(nvl, value, "%s", name);
1446 }
1447
1448 #ifndef _KERNEL
1449 void
nvlist_add_descriptor(nvlist_t * nvl,const char * name,int value)1450 nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value)
1451 {
1452
1453 nvlist_addf_descriptor(nvl, value, "%s", name);
1454 }
1455 #endif
1456
1457 void
nvlist_add_binary(nvlist_t * nvl,const char * name,const void * value,size_t size)1458 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1459 size_t size)
1460 {
1461
1462 nvlist_addf_binary(nvl, value, size, "%s", name);
1463 }
1464
1465 void
nvlist_add_uuid(nvlist_t * nvl,const char * name,const uuid_t * value)1466 nvlist_add_uuid(nvlist_t *nvl, const char *name, const uuid_t *value)
1467 {
1468
1469 nvlist_addf_uuid(nvl, value, "%s", name);
1470 }
1471
1472 void
nvlist_addf_null(nvlist_t * nvl,const char * namefmt,...)1473 nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...)
1474 {
1475 va_list nameap;
1476
1477 va_start(nameap, namefmt);
1478 nvlist_addv_null(nvl, namefmt, nameap);
1479 va_end(nameap);
1480 }
1481
1482 void
nvlist_addf_bool(nvlist_t * nvl,bool value,const char * namefmt,...)1483 nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...)
1484 {
1485 va_list nameap;
1486
1487 va_start(nameap, namefmt);
1488 nvlist_addv_bool(nvl, value, namefmt, nameap);
1489 va_end(nameap);
1490 }
1491
1492 void
nvlist_addf_number(nvlist_t * nvl,uint64_t value,const char * namefmt,...)1493 nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1494 {
1495 va_list nameap;
1496
1497 va_start(nameap, namefmt);
1498 nvlist_addv_number(nvl, value, namefmt, nameap);
1499 va_end(nameap);
1500 }
1501
1502 void
nvlist_addf_ptr(nvlist_t * nvl,uintptr_t value,const char * namefmt,...)1503 nvlist_addf_ptr(nvlist_t *nvl, uintptr_t value, const char *namefmt, ...)
1504 {
1505 va_list nameap;
1506
1507 va_start(nameap, namefmt);
1508 nvlist_addv_ptr(nvl, value, namefmt, nameap);
1509 va_end(nameap);
1510 }
1511
1512 void
nvlist_addf_uint64(nvlist_t * nvl,uint64_t value,const char * namefmt,...)1513 nvlist_addf_uint64(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1514 {
1515 va_list nameap;
1516
1517 va_start(nameap, namefmt);
1518 nvlist_addv_uint64(nvl, value, namefmt, nameap);
1519 va_end(nameap);
1520 }
1521
1522 void
nvlist_addf_int64(nvlist_t * nvl,int64_t value,const char * namefmt,...)1523 nvlist_addf_int64(nvlist_t *nvl, int64_t value, const char *namefmt, ...)
1524 {
1525 va_list nameap;
1526
1527 va_start(nameap, namefmt);
1528 nvlist_addv_int64(nvl, value, namefmt, nameap);
1529 va_end(nameap);
1530 }
1531
1532 void
nvlist_addf_endpoint(nvlist_t * nvl,int value,const char * namefmt,...)1533 nvlist_addf_endpoint(nvlist_t *nvl, int value, const char *namefmt, ...)
1534 {
1535 va_list nameap;
1536
1537 va_start(nameap, namefmt);
1538 nvlist_addv_endpoint(nvl, value, namefmt, nameap);
1539 va_end(nameap);
1540 }
1541
1542 void
nvlist_addf_date(nvlist_t * nvl,uint64_t value,const char * namefmt,...)1543 nvlist_addf_date(nvlist_t *nvl, uint64_t value, const char *namefmt, ...)
1544 {
1545 va_list nameap;
1546
1547 va_start(nameap, namefmt);
1548 nvlist_addv_date(nvl, value, namefmt, nameap);
1549 va_end(nameap);
1550 }
1551
1552
1553 void
nvlist_addf_string(nvlist_t * nvl,const char * value,const char * namefmt,...)1554 nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...)
1555 {
1556 va_list nameap;
1557
1558 va_start(nameap, namefmt);
1559 nvlist_addv_string(nvl, value, namefmt, nameap);
1560 va_end(nameap);
1561 }
1562
1563 void
nvlist_addf_nvlist(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,...)1564 nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1565 ...)
1566 {
1567 va_list nameap;
1568
1569 va_start(nameap, namefmt);
1570 nvlist_addv_nvlist(nvl, value, namefmt, nameap);
1571 va_end(nameap);
1572 }
1573
1574 void
nvlist_addf_nvlist_array(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,...)1575 nvlist_addf_nvlist_array(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1576 ...)
1577 {
1578 va_list nameap;
1579
1580 va_start(nameap, namefmt);
1581 nvlist_addv_nvlist_array(nvl, value, namefmt, nameap);
1582 va_end(nameap);
1583 }
1584
1585 void
nvlist_addf_nvlist_dictionary(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,...)1586 nvlist_addf_nvlist_dictionary(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1587 ...)
1588 {
1589 va_list nameap;
1590
1591 va_start(nameap, namefmt);
1592 nvlist_addv_nvlist_dictionary(nvl, value, namefmt, nameap);
1593 va_end(nameap);
1594 }
1595
1596 #ifndef _KERNEL
1597 void
nvlist_addf_descriptor(nvlist_t * nvl,int value,const char * namefmt,...)1598 nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...)
1599 {
1600 va_list nameap;
1601
1602 va_start(nameap, namefmt);
1603 nvlist_addv_descriptor(nvl, value, namefmt, nameap);
1604 va_end(nameap);
1605 }
1606 #endif
1607
1608 void
nvlist_addf_binary(nvlist_t * nvl,const void * value,size_t size,const char * namefmt,...)1609 nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size,
1610 const char *namefmt, ...)
1611 {
1612 va_list nameap;
1613
1614 va_start(nameap, namefmt);
1615 nvlist_addv_binary(nvl, value, size, namefmt, nameap);
1616 va_end(nameap);
1617 }
1618
1619 void
nvlist_addf_uuid(nvlist_t * nvl,const uuid_t * value,const char * namefmt,...)1620 nvlist_addf_uuid(nvlist_t *nvl, const uuid_t *value, const char *namefmt, ...)
1621 {
1622 va_list nameap;
1623
1624 va_start(nameap, namefmt);
1625 nvlist_addv_uuid(nvl, value, namefmt, nameap);
1626 va_end(nameap);
1627 }
1628
1629 void
nvlist_addv_null(nvlist_t * nvl,const char * namefmt,va_list nameap)1630 nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap)
1631 {
1632 nvpair_t *nvp;
1633
1634 if (nvlist_error(nvl) != 0) {
1635 RESTORE_ERRNO(nvlist_error(nvl));
1636 return;
1637 }
1638
1639 nvp = nvpair_createv_null(namefmt, nameap);
1640 if (nvp == NULL) {
1641 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1642 RESTORE_ERRNO(nvl->nvl_error);
1643 } else
1644 nvlist_move_nvpair(nvl, nvp);
1645 }
1646
1647 void
nvlist_addv_bool(nvlist_t * nvl,bool value,const char * namefmt,va_list nameap)1648 nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap)
1649 {
1650 nvpair_t *nvp;
1651
1652 if (nvlist_error(nvl) != 0) {
1653 RESTORE_ERRNO(nvlist_error(nvl));
1654 return;
1655 }
1656
1657 nvp = nvpair_createv_bool(value, namefmt, nameap);
1658 if (nvp == NULL) {
1659 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1660 RESTORE_ERRNO(nvl->nvl_error);
1661 } else
1662 nvlist_move_nvpair(nvl, nvp);
1663 }
1664
1665 void
nvlist_addv_number(nvlist_t * nvl,uint64_t value,const char * namefmt,va_list nameap)1666 nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt,
1667 va_list nameap)
1668 {
1669 nvpair_t *nvp;
1670
1671 if (nvlist_error(nvl) != 0) {
1672 RESTORE_ERRNO(nvlist_error(nvl));
1673 return;
1674 }
1675
1676 nvp = nvpair_createv_number_type(value, NV_TYPE_NUMBER, namefmt, nameap);
1677 if (nvp == NULL) {
1678 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1679 RESTORE_ERRNO(nvl->nvl_error);
1680 } else
1681 nvlist_move_nvpair(nvl, nvp);
1682 }
1683
1684 void
nvlist_addv_ptr(nvlist_t * nvl,uintptr_t value,const char * namefmt,va_list nameap)1685 nvlist_addv_ptr(nvlist_t *nvl, uintptr_t value, const char *namefmt,
1686 va_list nameap)
1687 {
1688 nvpair_t *nvp;
1689
1690 if (nvlist_error(nvl) != 0) {
1691 RESTORE_ERRNO(nvlist_error(nvl));
1692 return;
1693 }
1694
1695 nvp = nvpair_createv_number_type(value, NV_TYPE_PTR, namefmt, nameap);
1696 if (nvp == NULL) {
1697 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1698 RESTORE_ERRNO(nvl->nvl_error);
1699 } else
1700 nvlist_move_nvpair(nvl, nvp);
1701 }
1702
1703 void
nvlist_addv_uint64(nvlist_t * nvl,uint64_t value,const char * namefmt,va_list nameap)1704 nvlist_addv_uint64(nvlist_t *nvl, uint64_t value, const char *namefmt,
1705 va_list nameap)
1706 {
1707 nvpair_t *nvp;
1708
1709 if (nvlist_error(nvl) != 0) {
1710 RESTORE_ERRNO(nvlist_error(nvl));
1711 return;
1712 }
1713
1714 nvp = nvpair_createv_number_type(value, NV_TYPE_UINT64, namefmt, nameap);
1715 if (nvp == NULL) {
1716 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1717 RESTORE_ERRNO(nvl->nvl_error);
1718 } else
1719 nvlist_move_nvpair(nvl, nvp);
1720 }
1721
1722 void
nvlist_addv_int64(nvlist_t * nvl,int64_t value,const char * namefmt,va_list nameap)1723 nvlist_addv_int64(nvlist_t *nvl, int64_t value, const char *namefmt,
1724 va_list nameap)
1725 {
1726 nvpair_t *nvp;
1727
1728 if (nvlist_error(nvl) != 0) {
1729 RESTORE_ERRNO(nvlist_error(nvl));
1730 return;
1731 }
1732
1733 nvp = nvpair_createv_number_type(value, NV_TYPE_INT64, namefmt, nameap);
1734 if (nvp == NULL) {
1735 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1736 RESTORE_ERRNO(nvl->nvl_error);
1737 } else
1738 nvlist_move_nvpair(nvl, nvp);
1739 }
1740
1741 void
nvlist_addv_endpoint(nvlist_t * nvl,int value,const char * namefmt,va_list nameap)1742 nvlist_addv_endpoint(nvlist_t *nvl, int value, const char *namefmt,
1743 va_list nameap)
1744 {
1745 nvpair_t *nvp;
1746
1747 if (nvlist_error(nvl) != 0) {
1748 RESTORE_ERRNO(nvlist_error(nvl));
1749 return;
1750 }
1751
1752 nvp = nvpair_createv_number_type(value, NV_TYPE_ENDPOINT, namefmt, nameap);
1753 if (nvp == NULL) {
1754 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1755 RESTORE_ERRNO(nvl->nvl_error);
1756 } else
1757 nvlist_move_nvpair(nvl, nvp);
1758 }
1759
1760 void
nvlist_addv_date(nvlist_t * nvl,uint64_t value,const char * namefmt,va_list nameap)1761 nvlist_addv_date(nvlist_t *nvl, uint64_t value, const char *namefmt,
1762 va_list nameap)
1763 {
1764 nvpair_t *nvp;
1765
1766 if (nvlist_error(nvl) != 0) {
1767 RESTORE_ERRNO(nvlist_error(nvl));
1768 return;
1769 }
1770
1771 nvp = nvpair_createv_number_type(value, NV_TYPE_DATE, namefmt, nameap);
1772 if (nvp == NULL) {
1773 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1774 RESTORE_ERRNO(nvl->nvl_error);
1775 } else
1776 nvlist_move_nvpair(nvl, nvp);
1777 }
1778
1779 void
nvlist_addv_string(nvlist_t * nvl,const char * value,const char * namefmt,va_list nameap)1780 nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt,
1781 va_list nameap)
1782 {
1783 nvpair_t *nvp;
1784
1785 if (nvlist_error(nvl) != 0) {
1786 RESTORE_ERRNO(nvlist_error(nvl));
1787 return;
1788 }
1789
1790 nvp = nvpair_createv_string(value, namefmt, nameap);
1791 if (nvp == NULL) {
1792 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1793 RESTORE_ERRNO(nvl->nvl_error);
1794 } else
1795 nvlist_move_nvpair(nvl, nvp);
1796 }
1797
1798 void
nvlist_addv_nvlist(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,va_list nameap)1799 nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1800 va_list nameap)
1801 {
1802 nvpair_t *nvp;
1803
1804 if (nvlist_error(nvl) != 0) {
1805 RESTORE_ERRNO(nvlist_error(nvl));
1806 return;
1807 }
1808
1809 nvp = nvpair_createv_nvlist_type(value, NV_TYPE_NVLIST, namefmt, nameap);
1810 if (nvp == NULL) {
1811 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1812 RESTORE_ERRNO(nvl->nvl_error);
1813 } else
1814 nvlist_move_nvpair(nvl, nvp);
1815 }
1816
1817 void
nvlist_addv_nvlist_array(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,va_list nameap)1818 nvlist_addv_nvlist_array(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1819 va_list nameap)
1820 {
1821 nvpair_t *nvp;
1822
1823 if (nvlist_error(nvl) != 0) {
1824 RESTORE_ERRNO(nvlist_error(nvl));
1825 return;
1826 }
1827
1828 nvp = nvpair_createv_nvlist_type(value, NV_TYPE_NVLIST_ARRAY, namefmt, nameap);
1829 if (nvp == NULL) {
1830 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1831 RESTORE_ERRNO(nvl->nvl_error);
1832 } else
1833 nvlist_move_nvpair(nvl, nvp);
1834 }
1835
1836 void
nvlist_addv_nvlist_dictionary(nvlist_t * nvl,const nvlist_t * value,const char * namefmt,va_list nameap)1837 nvlist_addv_nvlist_dictionary(nvlist_t *nvl, const nvlist_t *value, const char *namefmt,
1838 va_list nameap)
1839 {
1840 nvpair_t *nvp;
1841
1842 if (nvlist_error(nvl) != 0) {
1843 RESTORE_ERRNO(nvlist_error(nvl));
1844 return;
1845 }
1846
1847 nvp = nvpair_createv_nvlist_type(value, NV_TYPE_NVLIST_DICTIONARY, namefmt, nameap);
1848 if (nvp == NULL) {
1849 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1850 RESTORE_ERRNO(nvl->nvl_error);
1851 } else
1852 nvlist_move_nvpair(nvl, nvp);
1853 }
1854
1855 #ifndef _KERNEL
1856 void
nvlist_addv_descriptor(nvlist_t * nvl,int value,const char * namefmt,va_list nameap)1857 nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt,
1858 va_list nameap)
1859 {
1860 nvpair_t *nvp;
1861
1862 if (nvlist_error(nvl) != 0) {
1863 errno = nvlist_error(nvl);
1864 return;
1865 }
1866
1867 nvp = nvpair_createv_descriptor(value, namefmt, nameap);
1868 if (nvp == NULL)
1869 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
1870 else
1871 nvlist_move_nvpair(nvl, nvp);
1872 }
1873 #endif
1874
1875 void
nvlist_addv_binary(nvlist_t * nvl,const void * value,size_t size,const char * namefmt,va_list nameap)1876 nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size,
1877 const char *namefmt, va_list nameap)
1878 {
1879 nvpair_t *nvp;
1880
1881 if (nvlist_error(nvl) != 0) {
1882 RESTORE_ERRNO(nvlist_error(nvl));
1883 return;
1884 }
1885
1886 nvp = nvpair_createv_binary(value, size, namefmt, nameap);
1887 if (nvp == NULL) {
1888 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1889 RESTORE_ERRNO(nvl->nvl_error);
1890 } else
1891 nvlist_move_nvpair(nvl, nvp);
1892 }
1893
1894 void
nvlist_addv_uuid(nvlist_t * nvl,const uuid_t * value,const char * namefmt,va_list nameap)1895 nvlist_addv_uuid(nvlist_t *nvl, const uuid_t *value,
1896 const char *namefmt, va_list nameap)
1897 {
1898 nvpair_t *nvp;
1899
1900 if (nvlist_error(nvl) != 0) {
1901 RESTORE_ERRNO(nvlist_error(nvl));
1902 return;
1903 }
1904
1905 nvp = nvpair_createv_uuid(value, namefmt, nameap);
1906 if (nvp == NULL)
1907 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1908 else
1909 nvlist_move_nvpair(nvl, nvp);
1910 }
1911
1912 void
nvlist_move_nvpair(nvlist_t * nvl,nvpair_t * nvp)1913 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1914 {
1915
1916 NVPAIR_ASSERT(nvp);
1917 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1918
1919 if (nvlist_error(nvl) != 0) {
1920 nvpair_free(nvp);
1921 RESTORE_ERRNO(nvlist_error(nvl));
1922 return;
1923 }
1924 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1925 nvpair_free(nvp);
1926 nvl->nvl_error = EEXIST;
1927 RESTORE_ERRNO(nvl->nvl_error);
1928 return;
1929 }
1930
1931 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1932 }
1933
1934 #define NVLIST_MOVE(vtype, type) \
1935 void \
1936 nvlist_move_##type(nvlist_t *nvl, const char *name, vtype value) \
1937 { \
1938 \
1939 nvlist_movef_##type(nvl, value, "%s", name); \
1940 }
1941
NVLIST_MOVE(char *,string)1942 NVLIST_MOVE(char *, string)
1943 NVLIST_MOVE(nvlist_t *, nvlist)
1944 NVLIST_MOVE(nvlist_t *, nvlist_array)
1945 NVLIST_MOVE(nvlist_t *, nvlist_dictionary)
1946 #ifndef _KERNEL
1947 NVLIST_MOVE(int, descriptor)
1948 #endif
1949
1950 #undef NVLIST_MOVE
1951
1952 void
1953 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1954 {
1955
1956 nvlist_movef_binary(nvl, value, size, "%s", name);
1957 }
1958
1959 void
nvlist_move_uuid(nvlist_t * nvl,const char * name,uuid_t * value)1960 nvlist_move_uuid(nvlist_t *nvl, const char *name, uuid_t *value)
1961 {
1962
1963 nvlist_movef_binary(nvl, value, sizeof(uuid_t), "%s", name);
1964 }
1965
1966 #define NVLIST_MOVEF(vtype, type) \
1967 void \
1968 nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt, \
1969 ...) \
1970 { \
1971 va_list nameap; \
1972 \
1973 va_start(nameap, namefmt); \
1974 nvlist_movev_##type(nvl, value, namefmt, nameap); \
1975 va_end(nameap); \
1976 }
1977
NVLIST_MOVEF(char *,string)1978 NVLIST_MOVEF(char *, string)
1979 NVLIST_MOVEF(nvlist_t *, nvlist)
1980 NVLIST_MOVEF(nvlist_t *, nvlist_array)
1981 NVLIST_MOVEF(nvlist_t *, nvlist_dictionary)
1982 #ifndef _KERNEL
1983 NVLIST_MOVEF(int, descriptor)
1984 #endif
1985
1986 #undef NVLIST_MOVEF
1987
1988 void
1989 nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size,
1990 const char *namefmt, ...)
1991 {
1992 va_list nameap;
1993
1994 va_start(nameap, namefmt);
1995 nvlist_movev_binary(nvl, value, size, namefmt, nameap);
1996 va_end(nameap);
1997 }
1998
1999 void
nvlist_movef_uuid(nvlist_t * nvl,uuid_t * value,const char * namefmt,...)2000 nvlist_movef_uuid(nvlist_t *nvl, uuid_t *value, const char *namefmt, ...)
2001 {
2002 va_list nameap;
2003
2004 va_start(nameap, namefmt);
2005 nvlist_movev_uuid(nvl, value, namefmt, nameap);
2006 va_end(nameap);
2007 }
2008
2009 void
nvlist_movev_string(nvlist_t * nvl,char * value,const char * namefmt,va_list nameap)2010 nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt,
2011 va_list nameap)
2012 {
2013 nvpair_t *nvp;
2014
2015 if (nvlist_error(nvl) != 0) {
2016 nv_free(value);
2017 RESTORE_ERRNO(nvlist_error(nvl));
2018 return;
2019 }
2020
2021 nvp = nvpair_movev_string(value, namefmt, nameap);
2022 if (nvp == NULL) {
2023 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2024 RESTORE_ERRNO(nvl->nvl_error);
2025 } else
2026 nvlist_move_nvpair(nvl, nvp);
2027 }
2028
2029 void
nvlist_movev_nvlist(nvlist_t * nvl,nvlist_t * value,const char * namefmt,va_list nameap)2030 nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
2031 va_list nameap)
2032 {
2033 nvpair_t *nvp;
2034
2035 if (nvlist_error(nvl) != 0) {
2036 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
2037 nvlist_destroy(value);
2038 RESTORE_ERRNO(nvlist_error(nvl));
2039 return;
2040 }
2041
2042 nvp = nvpair_movev_nvlist_type(value, NV_TYPE_NVLIST, namefmt, nameap);
2043 if (nvp == NULL) {
2044 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2045 RESTORE_ERRNO(nvl->nvl_error);
2046 } else
2047 nvlist_move_nvpair(nvl, nvp);
2048 }
2049
2050 void
nvlist_movev_nvlist_array(nvlist_t * nvl,nvlist_t * value,const char * namefmt,va_list nameap)2051 nvlist_movev_nvlist_array(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
2052 va_list nameap)
2053 {
2054 nvpair_t *nvp;
2055
2056 if (nvlist_error(nvl) != 0) {
2057 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
2058 nvlist_destroy(value);
2059 RESTORE_ERRNO(nvlist_error(nvl));
2060 return;
2061 }
2062
2063 nvp = nvpair_movev_nvlist_type(value, NV_TYPE_NVLIST_ARRAY, namefmt, nameap);
2064 if (nvp == NULL) {
2065 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2066 RESTORE_ERRNO(nvl->nvl_error);
2067 } else
2068 nvlist_move_nvpair(nvl, nvp);
2069 }
2070
2071 void
nvlist_movev_nvlist_dictionary(nvlist_t * nvl,nvlist_t * value,const char * namefmt,va_list nameap)2072 nvlist_movev_nvlist_dictionary(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
2073 va_list nameap)
2074 {
2075 nvpair_t *nvp;
2076
2077 if (nvlist_error(nvl) != 0) {
2078 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
2079 nvlist_destroy(value);
2080 RESTORE_ERRNO(nvlist_error(nvl));
2081 return;
2082 }
2083
2084 nvp = nvpair_movev_nvlist_type(value, NV_TYPE_NVLIST_DICTIONARY, namefmt, nameap);
2085 if (nvp == NULL) {
2086 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2087 RESTORE_ERRNO(nvl->nvl_error);
2088 } else
2089 nvlist_move_nvpair(nvl, nvp);
2090 }
2091
2092 #ifndef _KERNEL
2093 void
nvlist_movev_descriptor(nvlist_t * nvl,int value,const char * namefmt,va_list nameap)2094 nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt,
2095 va_list nameap)
2096 {
2097 nvpair_t *nvp;
2098
2099 if (nvlist_error(nvl) != 0) {
2100 close(value);
2101 errno = nvlist_error(nvl);
2102 return;
2103 }
2104
2105 nvp = nvpair_movev_descriptor(value, namefmt, nameap);
2106 if (nvp == NULL)
2107 nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM);
2108 else
2109 nvlist_move_nvpair(nvl, nvp);
2110 }
2111 #endif
2112
2113 void
nvlist_movev_binary(nvlist_t * nvl,void * value,size_t size,const char * namefmt,va_list nameap)2114 nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size,
2115 const char *namefmt, va_list nameap)
2116 {
2117 nvpair_t *nvp;
2118
2119 if (nvlist_error(nvl) != 0) {
2120 nv_free(value);
2121 RESTORE_ERRNO(nvlist_error(nvl));
2122 return;
2123 }
2124
2125 nvp = nvpair_movev_binary(value, size, namefmt, nameap);
2126 if (nvp == NULL) {
2127 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2128 RESTORE_ERRNO(nvl->nvl_error);
2129 } else
2130 nvlist_move_nvpair(nvl, nvp);
2131 }
2132
2133 void
nvlist_movev_uuid(nvlist_t * nvl,uuid_t * value,const char * namefmt,va_list nameap)2134 nvlist_movev_uuid(nvlist_t *nvl, uuid_t *value,
2135 const char *namefmt, va_list nameap)
2136 {
2137 nvpair_t *nvp;
2138
2139 if (nvlist_error(nvl) != 0) {
2140 nv_free(value);
2141 RESTORE_ERRNO(nvlist_error(nvl));
2142 return;
2143 }
2144
2145 nvp = nvpair_movev_uuid(value, namefmt, nameap);
2146 if (nvp == NULL)
2147 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
2148 else
2149 nvlist_move_nvpair(nvl, nvp);
2150 }
2151
2152 const nvpair_t *
nvlist_get_nvpair(const nvlist_t * nvl,const char * name)2153 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
2154 {
2155
2156 return (nvlist_find(nvl, NV_TYPE_NONE, name));
2157 }
2158
2159 #define NVLIST_GET(ftype, type, acc_type, TYPE) \
2160 ftype \
2161 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
2162 { \
2163 const nvpair_t *nvp; \
2164 \
2165 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
2166 if (nvp == NULL) \
2167 nvlist_report_missing(NV_TYPE_##TYPE, name); \
2168 return ((ftype)nvpair_get_##acc_type(nvp)); \
2169 }
2170
NVLIST_GET(bool,bool,bool,BOOL)2171 NVLIST_GET(bool, bool, bool, BOOL)
2172 NVLIST_GET(uint64_t, number, number, NUMBER)
2173 NVLIST_GET(uintptr_t, ptr, number, PTR)
2174 NVLIST_GET(uint64_t, uint64, number, UINT64)
2175 NVLIST_GET(int64_t, int64, number, INT64)
2176 NVLIST_GET(int, endpoint, number, ENDPOINT)
2177 NVLIST_GET(uint64_t, date, number, DATE)
2178 NVLIST_GET(const char *, string, string, STRING)
2179 NVLIST_GET(const nvlist_t *, nvlist, nvlist, NVLIST)
2180 NVLIST_GET(const nvlist_t *, nvlist_array, nvlist, NVLIST_ARRAY)
2181 NVLIST_GET(const nvlist_t *, nvlist_dictionary, nvlist, NVLIST_DICTIONARY)
2182 #ifndef _KERNEL
2183 NVLIST_GET(int, descriptor, descriptor, DESCRIPTOR)
2184 #endif
2185 NVLIST_GET(const uuid_t *, uuid, uuid, UUID)
2186
2187 #undef NVLIST_GET
2188
2189 const void *
2190 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
2191 {
2192 nvpair_t *nvp;
2193
2194 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
2195 if (nvp == NULL)
2196 nvlist_report_missing(NV_TYPE_BINARY, name);
2197
2198 return (nvpair_get_binary(nvp, sizep));
2199 }
2200
2201 #define NVLIST_GETF(ftype, type) \
2202 ftype \
2203 nvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...) \
2204 { \
2205 va_list nameap; \
2206 ftype value; \
2207 \
2208 va_start(nameap, namefmt); \
2209 value = nvlist_getv_##type(nvl, namefmt, nameap); \
2210 va_end(nameap); \
2211 \
2212 return (value); \
2213 }
2214
2215 #ifndef _KERNEL
NVLIST_GETF(bool,bool)2216 NVLIST_GETF(bool, bool)
2217 NVLIST_GETF(uint64_t, number)
2218 NVLIST_GETF(uintptr_t, ptr)
2219 NVLIST_GETF(uint64_t, uint64)
2220 NVLIST_GETF(int64_t, int64)
2221 NVLIST_GETF(int, endpoint)
2222 NVLIST_GETF(uint64_t, date)
2223 NVLIST_GETF(const char *, string)
2224 NVLIST_GETF(const nvlist_t *, nvlist)
2225 NVLIST_GETF(const nvlist_t *, nvlist_array)
2226 NVLIST_GETF(const nvlist_t *, nvlist_dictionary)
2227 NVLIST_GETF(int, descriptor)
2228 NVLIST_GETF(const uuid_t *, uuid)
2229
2230 #undef NVLIST_GETF
2231
2232 const void *
2233 nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
2234 {
2235 va_list nameap;
2236 const void *value;
2237
2238 va_start(nameap, namefmt);
2239 value = nvlist_getv_binary(nvl, sizep, namefmt, nameap);
2240 va_end(nameap);
2241
2242 return (value);
2243 }
2244
2245 #define NVLIST_GETV(ftype, type, TYPE) \
2246 ftype \
2247 nvlist_getv_##type(const nvlist_t *nvl, const char *namefmt, \
2248 va_list nameap) \
2249 { \
2250 char *name; \
2251 ftype value; \
2252 \
2253 vasprintf(&name, namefmt, nameap); \
2254 if (name == NULL) \
2255 nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \
2256 value = nvlist_get_##type(nvl, name); \
2257 free(name); \
2258 \
2259 return (value); \
2260 }
2261
NVLIST_GETV(bool,bool,BOOL)2262 NVLIST_GETV(bool, bool, BOOL)
2263 NVLIST_GETV(uint64_t, number, NUMBER)
2264 NVLIST_GETV(uintptr_t, ptr, PTR)
2265 NVLIST_GETV(uint64_t, uint64, UINT64)
2266 NVLIST_GETV(int64_t, int64, INT64)
2267 NVLIST_GETV(int, endpoint, ENDPOINT)
2268 NVLIST_GETV(uint64_t, date, DATE)
2269 NVLIST_GETV(const char *, string, STRING)
2270 NVLIST_GETV(const nvlist_t *, nvlist, NVLIST)
2271 NVLIST_GETV(const nvlist_t *, nvlist_array, NVLIST_ARRAY)
2272 NVLIST_GETV(const nvlist_t *, nvlist_dictionary, NVLIST_DICTIONARY)
2273 NVLIST_GETV(int, descriptor, DESCRIPTOR)
2274 NVLIST_GETV(const uuid_t *, uuid, UUID)
2275
2276 #undef NVLIST_GETV
2277
2278 const void *
2279 nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt,
2280 va_list nameap)
2281 {
2282 char *name;
2283 const void *binary;
2284
2285 nv_vasprintf(&name, namefmt, nameap);
2286 if (name == NULL)
2287 nvlist_report_missing(NV_TYPE_BINARY, "<unknown>");
2288
2289 binary = nvlist_get_binary(nvl, name, sizep);
2290 nv_free(name);
2291 return (binary);
2292 }
2293 #endif
2294
2295 #define NVLIST_TAKE(ftype, type, acc_type, TYPE) \
2296 ftype \
2297 nvlist_take_##type(nvlist_t *nvl, const char *name) \
2298 { \
2299 nvpair_t *nvp; \
2300 ftype value; \
2301 \
2302 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
2303 if (nvp == NULL) \
2304 nvlist_report_missing(NV_TYPE_##TYPE, name); \
2305 value = (ftype)(intptr_t)nvpair_get_##acc_type(nvp); \
2306 nvlist_remove_nvpair(nvl, nvp); \
2307 nvpair_free_structure(nvp); \
2308 return (value); \
2309 }
2310
NVLIST_TAKE(bool,bool,bool,BOOL)2311 NVLIST_TAKE(bool, bool, bool, BOOL)
2312 NVLIST_TAKE(uint64_t, number, number, NUMBER)
2313 NVLIST_TAKE(uintptr_t, ptr, number, PTR)
2314 NVLIST_TAKE(uint64_t, uint64, number, UINT64)
2315 NVLIST_TAKE(int64_t, int64, number, INT64)
2316 NVLIST_TAKE(int, endpoint, number, ENDPOINT)
2317 NVLIST_TAKE(uint64_t, date, number, DATE)
2318 NVLIST_TAKE(char *, string, string, STRING)
2319 NVLIST_TAKE(nvlist_t *, nvlist, nvlist, NVLIST)
2320 NVLIST_TAKE(nvlist_t *, nvlist_array, nvlist, NVLIST_ARRAY)
2321 NVLIST_TAKE(nvlist_t *, nvlist_dictionary, nvlist, NVLIST_DICTIONARY)
2322 #ifndef _KERNEL
2323 NVLIST_TAKE(int, descriptor, descriptor, DESCRIPTOR)
2324 #endif
2325 NVLIST_TAKE(uuid_t *, uuid, uuid, UUID)
2326
2327 #undef NVLIST_TAKE
2328
2329 void *
2330 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
2331 {
2332 nvpair_t *nvp;
2333 void *value;
2334
2335 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
2336 if (nvp == NULL)
2337 nvlist_report_missing(NV_TYPE_BINARY, name);
2338
2339 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
2340 nvlist_remove_nvpair(nvl, nvp);
2341 nvpair_free_structure(nvp);
2342 return (value);
2343 }
2344
2345 #define NVLIST_TAKEF(ftype, type) \
2346 ftype \
2347 nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...) \
2348 { \
2349 va_list nameap; \
2350 ftype value; \
2351 \
2352 va_start(nameap, namefmt); \
2353 value = nvlist_takev_##type(nvl, namefmt, nameap); \
2354 va_end(nameap); \
2355 \
2356 return (value); \
2357 }
2358
2359 #ifndef _KERNEL
NVLIST_TAKEF(bool,bool)2360 NVLIST_TAKEF(bool, bool)
2361 NVLIST_TAKEF(uint64_t, number)
2362 NVLIST_TAKEF(uintptr_t, ptr)
2363 NVLIST_TAKEF(uint64_t, uint64)
2364 NVLIST_TAKEF(int64_t, int64)
2365 NVLIST_TAKEF(int, endpoint)
2366 NVLIST_TAKEF(uint64_t, date)
2367 NVLIST_TAKEF(char *, string)
2368 NVLIST_TAKEF(nvlist_t *, nvlist)
2369 NVLIST_TAKEF(nvlist_t *, nvlist_array)
2370 NVLIST_TAKEF(nvlist_t *, nvlist_dictionary)
2371 NVLIST_TAKEF(int, descriptor)
2372 NVLIST_TAKEF(uuid_t *, uuid)
2373
2374 #undef NVLIST_TAKEF
2375
2376 void *
2377 nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...)
2378 {
2379 va_list nameap;
2380 void *value;
2381
2382 va_start(nameap, namefmt);
2383 value = nvlist_takev_binary(nvl, sizep, namefmt, nameap);
2384 va_end(nameap);
2385
2386 return (value);
2387 }
2388
2389 #define NVLIST_TAKEV(ftype, type, acc_type, TYPE) \
2390 ftype \
2391 nvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
2392 { \
2393 char *name; \
2394 ftype value; \
2395 \
2396 vasprintf(&name, namefmt, nameap); \
2397 if (name == NULL) \
2398 nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \
2399 value = nvlist_take_##type(nvl, name); \
2400 free(name); \
2401 return (value); \
2402 }
2403
NVLIST_TAKEV(bool,bool,bool,BOOL)2404 NVLIST_TAKEV(bool, bool, bool, BOOL)
2405 NVLIST_TAKEV(uint64_t, number, number, NUMBER)
2406 NVLIST_TAKEV(uintptr_t, ptr, number, PTR)
2407 NVLIST_TAKEV(uint64_t, uint64, number, UINT64)
2408 NVLIST_TAKEV(int64_t, int64, number, INT64)
2409 NVLIST_TAKEV(int, endpoint, number, ENDPOINT)
2410 NVLIST_TAKEV(uint64_t, date, number, DATE)
2411 NVLIST_TAKEV(char *, string, string, STRING)
2412 NVLIST_TAKEV(nvlist_t *, nvlist, nvlist, NVLIST)
2413 NVLIST_TAKEV(nvlist_t *, nvlist_array, nvlist, NVLIST_ARRAY)
2414 NVLIST_TAKEV(nvlist_t *, nvlist_dictionary, nvlist, NVLIST_DICTIONARY)
2415 NVLIST_TAKEV(int, descriptor, descriptor, DESCRIPTOR)
2416 NVLIST_TAKEV(uuid_t *, uuid, uuid, UUID)
2417
2418 #undef NVLIST_TAKEV
2419
2420 void *
2421 nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt,
2422 va_list nameap)
2423 {
2424 char *name;
2425 void *binary;
2426
2427 nv_vasprintf(&name, namefmt, nameap);
2428 if (name == NULL)
2429 nvlist_report_missing(NV_TYPE_BINARY, "<unknown>");
2430
2431 binary = nvlist_take_binary(nvl, name, sizep);
2432 nv_free(name);
2433 return (binary);
2434 }
2435 #endif
2436
2437 void
nvlist_remove_nvpair(nvlist_t * nvl,nvpair_t * nvp)2438 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
2439 {
2440
2441 NVLIST_ASSERT(nvl);
2442 NVPAIR_ASSERT(nvp);
2443 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
2444
2445 nvpair_remove(&nvl->nvl_head, nvp, nvl);
2446 }
2447
2448 void
nvlist_free(nvlist_t * nvl,const char * name)2449 nvlist_free(nvlist_t *nvl, const char *name)
2450 {
2451
2452 nvlist_free_type(nvl, name, NV_TYPE_NONE);
2453 }
2454
2455 #define NVLIST_FREE(type, TYPE) \
2456 void \
2457 nvlist_free_##type(nvlist_t *nvl, const char *name) \
2458 { \
2459 \
2460 nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \
2461 }
2462
NVLIST_FREE(null,NULL)2463 NVLIST_FREE(null, NULL)
2464 NVLIST_FREE(bool, BOOL)
2465 NVLIST_FREE(number, NUMBER)
2466 NVLIST_FREE(ptr, PTR)
2467 NVLIST_FREE(uint64, UINT64)
2468 NVLIST_FREE(int64, INT64)
2469 NVLIST_FREE(endpoint, ENDPOINT)
2470 NVLIST_FREE(date, DATE)
2471 NVLIST_FREE(string, STRING)
2472 NVLIST_FREE(nvlist, NVLIST)
2473 NVLIST_FREE(nvlist_array, NVLIST_ARRAY)
2474 NVLIST_FREE(nvlist_dictionary, NVLIST_DICTIONARY)
2475 #ifndef _KERNEL
2476 NVLIST_FREE(descriptor, DESCRIPTOR)
2477 #endif
2478 NVLIST_FREE(binary, BINARY)
2479 NVLIST_FREE(uuid, UUID)
2480
2481 #undef NVLIST_FREE
2482
2483 #ifndef _KERNEL
2484 void
2485 nvlist_freef(nvlist_t *nvl, const char *namefmt, ...)
2486 {
2487 va_list nameap;
2488
2489 va_start(nameap, namefmt);
2490 nvlist_freev(nvl, namefmt, nameap);
2491 va_end(nameap);
2492 }
2493
2494 #define NVLIST_FREEF(type) \
2495 void \
2496 nvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...) \
2497 { \
2498 va_list nameap; \
2499 \
2500 va_start(nameap, namefmt); \
2501 nvlist_freev_##type(nvl, namefmt, nameap); \
2502 va_end(nameap); \
2503 }
2504
2505 NVLIST_FREEF(null)
NVLIST_FREEF(bool)2506 NVLIST_FREEF(bool)
2507 NVLIST_FREEF(number)
2508 NVLIST_FREEF(ptr)
2509 NVLIST_FREEF(uint64)
2510 NVLIST_FREEF(int64)
2511 NVLIST_FREEF(endpoint)
2512 NVLIST_FREEF(date)
2513 NVLIST_FREEF(string)
2514 NVLIST_FREEF(nvlist)
2515 NVLIST_FREEF(nvlist_array)
2516 NVLIST_FREEF(nvlist_dictionary)
2517 NVLIST_FREEF(descriptor)
2518 NVLIST_FREEF(binary)
2519 NVLIST_FREEF(uuid)
2520
2521 #undef NVLIST_FREEF
2522
2523 void
2524 nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap)
2525 {
2526
2527 nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap);
2528 }
2529
2530 #define NVLIST_FREEV(type, TYPE) \
2531 void \
2532 nvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \
2533 { \
2534 char *name; \
2535 \
2536 vasprintf(&name, namefmt, nameap); \
2537 if (name == NULL) \
2538 nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \
2539 nvlist_free_##type(nvl, name); \
2540 free(name); \
2541 }
2542
NVLIST_FREEV(null,NULL)2543 NVLIST_FREEV(null, NULL)
2544 NVLIST_FREEV(bool, BOOL)
2545 NVLIST_FREEV(number, NUMBER)
2546 NVLIST_FREEV(ptr, PTR)
2547 NVLIST_FREEV(uint64, UINT64)
2548 NVLIST_FREEV(int64, INT64)
2549 NVLIST_FREEV(endpoint, ENDPOINT)
2550 NVLIST_FREEV(date, DATE)
2551 NVLIST_FREEV(string, STRING)
2552 NVLIST_FREEV(nvlist, NVLIST)
2553 NVLIST_FREEV(nvlist_array, NVLIST_ARRAY)
2554 NVLIST_FREEV(nvlist_dictionary, NVLIST_DICTIONARY)
2555 NVLIST_FREEV(descriptor, DESCRIPTOR)
2556 NVLIST_FREEV(binary, BINARY)
2557 NVLIST_FREEV(uuid, UUID)
2558 #undef NVLIST_FREEV
2559 #endif
2560
2561 void
2562 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
2563 {
2564
2565 NVLIST_ASSERT(nvl);
2566 NVPAIR_ASSERT(nvp);
2567 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
2568
2569 nvlist_remove_nvpair(nvl, nvp);
2570 nvpair_free(nvp);
2571 }
2572