nvlist.c revision 1.9 1 /* $NetBSD: nvlist.c,v 1.9 2024/09/04 12:56:47 riastradh Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 *
6 * Copyright (c) 2009-2013 The FreeBSD Foundation
7 * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo (at) FreeBSD.org>
8 * All rights reserved.
9 *
10 * This software was developed by Pawel Jakub Dawidek under sponsorship from
11 * the FreeBSD Foundation.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #ifdef __FreeBSD__
37 __FBSDID("$FreeBSD: head/sys/contrib/libnv/nvlist.c 335347 2018-06-18 22:57:32Z oshogbo $");
38 #else
39 __RCSID("$NetBSD: nvlist.c,v 1.9 2024/09/04 12:56:47 riastradh Exp $");
40 #endif
41
42 #include <sys/param.h>
43 #include <sys/endian.h>
44 #include <sys/queue.h>
45
46 #if defined(_KERNEL) || defined(_STANDALONE)
47
48 #include <sys/errno.h>
49 #include <sys/kernel.h>
50 #include <sys/lock.h>
51 #include <sys/malloc.h>
52 #include <sys/systm.h>
53
54 #ifdef __FreeBSD__
55 #include <machine/stdarg.h>
56 #endif
57
58 #else
59 #include <sys/socket.h>
60
61 #include <errno.h>
62 #include <stdarg.h>
63 #include <stdbool.h>
64 #include <stdint.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <unistd.h>
69
70 #include "msgio.h"
71 #endif
72
73 #ifdef HAVE_PJDLOG
74 #include <pjdlog.h>
75 #endif
76
77 #ifdef __FreeBSD__
78 #include <sys/nv.h>
79 #else
80 #include "nv.h"
81 #endif
82
83 #include "nv_impl.h"
84 #include "nvlist_impl.h"
85 #include "nvpair_impl.h"
86
87 #ifndef HAVE_PJDLOG
88 #if defined(_KERNEL) || defined(_STANDALONE)
89 #ifdef __FreeBSD__
90 #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
91 #else
92 #define PJDLOG_ASSERT(...) KASSERT(__VA_ARGS__)
93 #endif
94 #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
95 #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
96 #else
97 #ifndef __lint__
98 #include <assert.h>
99 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
100 #define PJDLOG_RASSERT(expr, ...) assert(expr)
101 #define PJDLOG_ABORT(...) do { \
102 fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \
103 fprintf(stderr, __VA_ARGS__); \
104 fprintf(stderr, "\n"); \
105 abort(); \
106 } while (/*CONSTCOND*/0)
107 #else
108 #define PJDLOG_ASSERT(...)
109 #define PJDLOG_RASSERT(expr, ...)
110 #define PJDLOG_ABORT(...)
111 #endif
112 #endif
113 #endif
114
115 #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN | NV_FLAG_IN_ARRAY)
116 #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE)
117 #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
118
119 #define NVLIST_MAGIC 0x6e766c /* "nvl" */
120 struct nvlist {
121 int nvl_magic;
122 int nvl_error;
123 int nvl_flags;
124 nvpair_t *nvl_parent;
125 nvpair_t *nvl_array_next;
126 struct nvl_head nvl_head;
127 };
128
129 #define NVLIST_ASSERT(nvl) do { \
130 PJDLOG_ASSERT((nvl) != NULL); \
131 PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \
132 } while (/*CONSTCOND*/0)
133
134 #ifdef _KERNEL
135 MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
136 #endif
137
138 #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp)
139
140 #define NVLIST_HEADER_MAGIC 0x6c
141 #define NVLIST_HEADER_VERSION 0x00
142 struct nvlist_header {
143 uint8_t nvlh_magic;
144 uint8_t nvlh_version;
145 uint8_t nvlh_flags;
146 uint64_t nvlh_descriptors;
147 uint64_t nvlh_size;
148 } __packed;
149
150 nvlist_t *
151 nvlist_create(int flags)
152 {
153 nvlist_t *nvl;
154
155 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
156
157 nvl = nv_malloc(sizeof(*nvl));
158 if (nvl == NULL)
159 return (NULL);
160 nvl->nvl_error = 0;
161 nvl->nvl_flags = flags;
162 nvl->nvl_parent = NULL;
163 nvl->nvl_array_next = NULL;
164 TAILQ_INIT(&nvl->nvl_head);
165 nvl->nvl_magic = NVLIST_MAGIC;
166
167 return (nvl);
168 }
169
170 void
171 nvlist_destroy(nvlist_t *nvl)
172 {
173 nvpair_t *nvp;
174
175 if (nvl == NULL)
176 return;
177
178 ERRNO_SAVE();
179
180 NVLIST_ASSERT(nvl);
181
182 while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
183 nvlist_remove_nvpair(nvl, nvp);
184 nvpair_free(nvp);
185 }
186 if (nvl->nvl_array_next != NULL)
187 nvpair_free_structure(nvl->nvl_array_next);
188 nvl->nvl_array_next = NULL;
189 nvl->nvl_parent = NULL;
190 nvl->nvl_magic = 0;
191 nv_free(nvl);
192
193 ERRNO_RESTORE();
194 }
195
196 void
197 nvlist_set_error(nvlist_t *nvl, int error)
198 {
199
200 PJDLOG_ASSERT(error != 0);
201
202 /*
203 * Check for error != 0 so that we don't do the wrong thing if somebody
204 * tries to abuse this API when asserts are disabled.
205 */
206 if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
207 nvl->nvl_error = error;
208 }
209
210 int
211 nvlist_error(const nvlist_t *nvl)
212 {
213
214 if (nvl == NULL)
215 return (ENOMEM);
216
217 NVLIST_ASSERT(nvl);
218
219 return (nvl->nvl_error);
220 }
221
222 nvpair_t *
223 nvlist_get_nvpair_parent(const nvlist_t *nvl)
224 {
225
226 NVLIST_ASSERT(nvl);
227
228 return (nvl->nvl_parent);
229 }
230
231 const nvlist_t *
232 nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
233 {
234 nvpair_t *nvp;
235
236 NVLIST_ASSERT(nvl);
237
238 nvp = nvl->nvl_parent;
239 if (cookiep != NULL)
240 *cookiep = nvp;
241 if (nvp == NULL)
242 return (NULL);
243
244 return (nvpair_nvlist(nvp));
245 }
246
247 void
248 nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
249 {
250
251 NVLIST_ASSERT(nvl);
252
253 nvl->nvl_parent = parent;
254 }
255
256 void
257 nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele)
258 {
259
260 NVLIST_ASSERT(nvl);
261
262 if (ele != NULL) {
263 nvl->nvl_flags |= NV_FLAG_IN_ARRAY;
264 } else {
265 nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY;
266 nv_free(nvl->nvl_array_next);
267 }
268
269 nvl->nvl_array_next = ele;
270 }
271
272 nvpair_t *
273 nvlist_get_array_next_nvpair(nvlist_t *nvl)
274 {
275
276 NVLIST_ASSERT(nvl);
277
278 return (nvl->nvl_array_next);
279 }
280
281 bool
282 nvlist_in_array(const nvlist_t *nvl)
283 {
284
285 NVLIST_ASSERT(nvl);
286
287 return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0);
288 }
289
290 const nvlist_t *
291 nvlist_get_array_next(const nvlist_t *nvl)
292 {
293 nvpair_t *nvp;
294
295 NVLIST_ASSERT(nvl);
296
297 nvp = nvl->nvl_array_next;
298 if (nvp == NULL)
299 return (NULL);
300
301 return (nvpair_get_nvlist(nvp));
302 }
303
304 const nvlist_t *
305 nvlist_get_pararr(const nvlist_t *nvl, void **cookiep)
306 {
307 const nvlist_t *ret;
308
309 ret = nvlist_get_array_next(nvl);
310 if (ret != NULL) {
311 if (cookiep != NULL)
312 *cookiep = NULL;
313 return (ret);
314 }
315
316 return (nvlist_get_parent(nvl, cookiep));
317 }
318
319 bool
320 nvlist_empty(const nvlist_t *nvl)
321 {
322
323 NVLIST_ASSERT(nvl);
324 PJDLOG_ASSERT(nvl->nvl_error == 0);
325
326 return (nvlist_first_nvpair(nvl) == NULL);
327 }
328
329 int
330 nvlist_flags(const nvlist_t *nvl)
331 {
332
333 NVLIST_ASSERT(nvl);
334 PJDLOG_ASSERT(nvl->nvl_error == 0);
335
336 return (nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
337 }
338
339 void
340 nvlist_set_flags(nvlist_t *nvl, int flags)
341 {
342
343 NVLIST_ASSERT(nvl);
344 PJDLOG_ASSERT(nvl->nvl_error == 0);
345
346 nvl->nvl_flags = flags;
347 }
348
349 __dead void
350 nvlist_report_missing(int type, const char *name)
351 {
352
353 PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
354 name, nvpair_type_string(type));
355 }
356
357 static nvpair_t *
358 nvlist_find(const nvlist_t *nvl, int type, const char *name)
359 {
360 nvpair_t *nvp;
361
362 NVLIST_ASSERT(nvl);
363 PJDLOG_ASSERT(nvl->nvl_error == 0);
364 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
365 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
366
367 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
368 nvp = nvlist_next_nvpair(nvl, nvp)) {
369 if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
370 continue;
371 if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
372 if (strcasecmp(nvpair_name(nvp), name) != 0)
373 continue;
374 } else {
375 if (strcmp(nvpair_name(nvp), name) != 0)
376 continue;
377 }
378 break;
379 }
380
381 if (nvp == NULL)
382 ERRNO_SET(ENOENT);
383
384 return (nvp);
385 }
386
387 bool
388 nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
389 {
390
391 NVLIST_ASSERT(nvl);
392 PJDLOG_ASSERT(nvl->nvl_error == 0);
393 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
394 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
395
396 return (nvlist_find(nvl, type, name) != NULL);
397 }
398
399 void
400 nvlist_free_type(nvlist_t *nvl, const char *name, int type)
401 {
402 nvpair_t *nvp;
403
404 NVLIST_ASSERT(nvl);
405 PJDLOG_ASSERT(nvl->nvl_error == 0);
406 PJDLOG_ASSERT(type == NV_TYPE_NONE ||
407 (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
408
409 nvp = nvlist_find(nvl, type, name);
410 if (nvp != NULL)
411 nvlist_free_nvpair(nvl, nvp);
412 else
413 nvlist_report_missing(type, name);
414 }
415
416 nvlist_t *
417 nvlist_clone(const nvlist_t *nvl)
418 {
419 nvlist_t *newnvl;
420 nvpair_t *nvp, *newnvp;
421
422 NVLIST_ASSERT(nvl);
423
424 if (nvl->nvl_error != 0) {
425 ERRNO_SET(nvl->nvl_error);
426 return (NULL);
427 }
428
429 newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
430 for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
431 nvp = nvlist_next_nvpair(nvl, nvp)) {
432 newnvp = nvpair_clone(nvp);
433 if (newnvp == NULL)
434 break;
435 (void)nvlist_move_nvpair(newnvl, newnvp);
436 }
437 if (nvp != NULL) {
438 nvlist_destroy(newnvl);
439 return (NULL);
440 }
441 return (newnvl);
442 }
443
444 #if !defined(_KERNEL) && !defined(_STANDALONE)
445 static bool
446 nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
447 {
448
449 if (nvlist_error(nvl) != 0) {
450 dprintf(fd, "%*serror: %d\n", level * 4, "",
451 nvlist_error(nvl));
452 return (true);
453 }
454
455 return (false);
456 }
457
458 /*
459 * Dump content of nvlist.
460 */
461 void
462 nvlist_dump(const nvlist_t *nvl, int fd)
463 {
464 const nvlist_t *tmpnvl;
465 nvpair_t *nvp, *tmpnvp;
466 void *cookie;
467 int level;
468
469 level = 0;
470 if (nvlist_dump_error_check(nvl, fd, level))
471 return;
472
473 nvp = nvlist_first_nvpair(nvl);
474 while (nvp != NULL) {
475 dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
476 nvpair_type_string(nvpair_type(nvp)));
477 switch (nvpair_type(nvp)) {
478 case NV_TYPE_NULL:
479 dprintf(fd, " null\n");
480 break;
481 case NV_TYPE_BOOL:
482 dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
483 "TRUE" : "FALSE");
484 break;
485 case NV_TYPE_NUMBER:
486 dprintf(fd, " %ju (%jd) (0x%jx)\n",
487 (uintmax_t)nvpair_get_number(nvp),
488 (intmax_t)nvpair_get_number(nvp),
489 (uintmax_t)nvpair_get_number(nvp));
490 break;
491 case NV_TYPE_STRING:
492 dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
493 break;
494 case NV_TYPE_NVLIST:
495 dprintf(fd, "\n");
496 tmpnvl = nvpair_get_nvlist(nvp);
497 if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
498 break;
499 tmpnvp = nvlist_first_nvpair(tmpnvl);
500 if (tmpnvp != NULL) {
501 nvl = tmpnvl;
502 nvp = tmpnvp;
503 level++;
504 continue;
505 }
506 break;
507 case NV_TYPE_DESCRIPTOR:
508 dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
509 break;
510 case NV_TYPE_BINARY:
511 {
512 const unsigned char *binary;
513 unsigned int ii;
514 size_t size;
515
516 binary = nvpair_get_binary(nvp, &size);
517 dprintf(fd, " %zu ", size);
518 for (ii = 0; ii < size; ii++)
519 dprintf(fd, "%02hhx", binary[ii]);
520 dprintf(fd, "\n");
521 break;
522 }
523 case NV_TYPE_BOOL_ARRAY:
524 {
525 const bool *value;
526 unsigned int ii;
527 size_t nitems;
528
529 value = nvpair_get_bool_array(nvp, &nitems);
530 dprintf(fd, " [ ");
531 for (ii = 0; ii < nitems; ii++) {
532 dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE");
533 if (ii != nitems - 1)
534 dprintf(fd, ", ");
535 }
536 dprintf(fd, " ]\n");
537 break;
538 }
539 case NV_TYPE_STRING_ARRAY:
540 {
541 const char * const *value;
542 unsigned int ii;
543 size_t nitems;
544
545 value = nvpair_get_string_array(nvp, &nitems);
546 dprintf(fd, " [ ");
547 for (ii = 0; ii < nitems; ii++) {
548 if (value[ii] == NULL)
549 dprintf(fd, "NULL");
550 else
551 dprintf(fd, "\"%s\"", value[ii]);
552 if (ii != nitems - 1)
553 dprintf(fd, ", ");
554 }
555 dprintf(fd, " ]\n");
556 break;
557 }
558 case NV_TYPE_NUMBER_ARRAY:
559 {
560 const uint64_t *value;
561 unsigned int ii;
562 size_t nitems;
563
564 value = nvpair_get_number_array(nvp, &nitems);
565 dprintf(fd, " [ ");
566 for (ii = 0; ii < nitems; ii++) {
567 dprintf(fd, "%ju (%jd) (0x%jx)",
568 value[ii], value[ii], value[ii]);
569 if (ii != nitems - 1)
570 dprintf(fd, ", ");
571 }
572 dprintf(fd, " ]\n");
573 break;
574 }
575 case NV_TYPE_DESCRIPTOR_ARRAY:
576 {
577 const int *value;
578 unsigned int ii;
579 size_t nitems;
580
581 value = nvpair_get_descriptor_array(nvp, &nitems);
582 dprintf(fd, " [ ");
583 for (ii = 0; ii < nitems; ii++) {
584 dprintf(fd, "%d", value[ii]);
585 if (ii != nitems - 1)
586 dprintf(fd, ", ");
587 }
588 dprintf(fd, " ]\n");
589 break;
590 }
591 case NV_TYPE_NVLIST_ARRAY:
592 {
593 const nvlist_t * const *value;
594 unsigned int ii;
595 size_t nitems;
596
597 value = nvpair_get_nvlist_array(nvp, &nitems);
598 dprintf(fd, " %zu\n", nitems);
599 tmpnvl = NULL;
600 tmpnvp = NULL;
601 for (ii = 0; ii < nitems; ii++) {
602 if (nvlist_dump_error_check(value[ii], fd,
603 level + 1)) {
604 break;
605 }
606
607 if (tmpnvl == NULL) {
608 tmpnvp = nvlist_first_nvpair(value[ii]);
609 if (tmpnvp != NULL) {
610 tmpnvl = value[ii];
611 } else {
612 dprintf(fd, "%*s,\n",
613 (level + 1) * 4, "");
614 }
615 }
616 }
617 if (tmpnvp != NULL) {
618 nvl = tmpnvl;
619 nvp = tmpnvp;
620 level++;
621 continue;
622 }
623 break;
624 }
625 default:
626 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
627 }
628
629 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
630 do {
631 cookie = NULL;
632 if (nvlist_in_array(nvl))
633 dprintf(fd, "%*s,\n", level * 4, "");
634 nvl = nvlist_get_pararr(nvl, &cookie);
635 if (nvl == NULL)
636 return;
637 if (nvlist_in_array(nvl) && cookie == NULL) {
638 nvp = nvlist_first_nvpair(nvl);
639 } else {
640 nvp = cookie;
641 level--;
642 }
643 } while (nvp == NULL);
644 if (nvlist_in_array(nvl) && cookie == NULL)
645 break;
646 }
647 }
648 }
649
650 void
651 nvlist_fdump(const nvlist_t *nvl, FILE *fp)
652 {
653
654 fflush(fp);
655 nvlist_dump(nvl, fileno(fp));
656 }
657 #endif
658
659 /*
660 * The function obtains size of the nvlist after nvlist_pack().
661 */
662 size_t
663 nvlist_size(const nvlist_t *nvl)
664 {
665 const nvlist_t *tmpnvl;
666 const nvlist_t * const *nvlarray;
667 const nvpair_t *nvp, *tmpnvp;
668 void *cookie;
669 size_t size, nitems;
670 unsigned int ii;
671
672 NVLIST_ASSERT(nvl);
673 PJDLOG_ASSERT(nvl->nvl_error == 0);
674
675 size = sizeof(struct nvlist_header);
676 nvp = nvlist_first_nvpair(nvl);
677 while (nvp != NULL) {
678 size += nvpair_header_size();
679 size += strlen(nvpair_name(nvp)) + 1;
680 if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
681 size += sizeof(struct nvlist_header);
682 size += nvpair_header_size() + 1;
683 tmpnvl = nvpair_get_nvlist(nvp);
684 PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
685 tmpnvp = nvlist_first_nvpair(tmpnvl);
686 if (tmpnvp != NULL) {
687 nvl = tmpnvl;
688 nvp = tmpnvp;
689 continue;
690 }
691 } else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) {
692 nvlarray = nvpair_get_nvlist_array(nvp, &nitems);
693 PJDLOG_ASSERT(nitems > 0);
694
695 size += (nvpair_header_size() + 1) * nitems;
696 size += sizeof(struct nvlist_header) * nitems;
697
698 tmpnvl = NULL;
699 tmpnvp = NULL;
700 for (ii = 0; ii < nitems; ii++) {
701 PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0);
702 tmpnvp = nvlist_first_nvpair(nvlarray[ii]);
703 if (tmpnvp != NULL) {
704 tmpnvl = nvlarray[ii];
705 break;
706 }
707 }
708 if (tmpnvp != NULL) {
709 nvp = tmpnvp;
710 nvl = tmpnvl;
711 continue;
712 }
713
714 } else {
715 size += nvpair_size(nvp);
716 }
717
718 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
719 do {
720 cookie = NULL;
721 nvl = nvlist_get_pararr(nvl, &cookie);
722 if (nvl == NULL)
723 goto out;
724 if (nvlist_in_array(nvl) && cookie == NULL) {
725 nvp = nvlist_first_nvpair(nvl);
726 } else {
727 nvp = cookie;
728 }
729 } while (nvp == NULL);
730 if (nvlist_in_array(nvl) && cookie == NULL)
731 break;
732 }
733 }
734
735 out:
736 return (size);
737 }
738
739 #if !defined(_KERNEL) && !defined(_STANDALONE)
740 static int *
741 nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
742 {
743 void *cookie;
744 nvpair_t *nvp;
745 int type;
746
747 NVLIST_ASSERT(nvl);
748 PJDLOG_ASSERT(nvl->nvl_error == 0);
749
750 cookie = NULL;
751 do {
752 while (nvlist_next(nvl, &type, &cookie) != NULL) {
753 nvp = cookie;
754 switch (type) {
755 case NV_TYPE_DESCRIPTOR:
756 *descs = nvpair_get_descriptor(nvp);
757 descs++;
758 break;
759 case NV_TYPE_DESCRIPTOR_ARRAY:
760 {
761 const int *value;
762 size_t nitems;
763 unsigned int ii;
764
765 value = nvpair_get_descriptor_array(nvp,
766 &nitems);
767 for (ii = 0; ii < nitems; ii++) {
768 *descs = value[ii];
769 descs++;
770 }
771 break;
772 }
773 case NV_TYPE_NVLIST:
774 nvl = nvpair_get_nvlist(nvp);
775 cookie = NULL;
776 break;
777 case NV_TYPE_NVLIST_ARRAY:
778 {
779 const nvlist_t * const *value;
780 size_t nitems;
781
782 value = nvpair_get_nvlist_array(nvp, &nitems);
783 PJDLOG_ASSERT(value != NULL);
784 PJDLOG_ASSERT(nitems > 0);
785
786 nvl = value[0];
787 cookie = NULL;
788 break;
789 }
790 }
791 }
792 } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
793
794 return (descs);
795 }
796 #endif
797
798 #if !defined(_KERNEL) && !defined(_STANDALONE)
799 int *
800 nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
801 {
802 size_t nitems;
803 int *fds;
804
805 nitems = nvlist_ndescriptors(nvl);
806 fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
807 if (fds == NULL)
808 return (NULL);
809 if (nitems > 0)
810 nvlist_xdescriptors(nvl, fds);
811 fds[nitems] = -1;
812 if (nitemsp != NULL)
813 *nitemsp = nitems;
814 return (fds);
815 }
816 #endif
817
818 size_t
819 nvlist_ndescriptors(const nvlist_t *nvl)
820 {
821 #if !defined(_KERNEL) && !defined(_STANDALONE)
822 void *cookie;
823 nvpair_t *nvp;
824 size_t ndescs;
825 int type;
826
827 NVLIST_ASSERT(nvl);
828 PJDLOG_ASSERT(nvl->nvl_error == 0);
829
830 ndescs = 0;
831 cookie = NULL;
832 do {
833 while (nvlist_next(nvl, &type, &cookie) != NULL) {
834 nvp = cookie;
835 switch (type) {
836 case NV_TYPE_DESCRIPTOR:
837 ndescs++;
838 break;
839 case NV_TYPE_NVLIST:
840 nvl = nvpair_get_nvlist(nvp);
841 cookie = NULL;
842 break;
843 case NV_TYPE_NVLIST_ARRAY:
844 {
845 const nvlist_t * const *value;
846 size_t nitems;
847
848 value = nvpair_get_nvlist_array(nvp, &nitems);
849 PJDLOG_ASSERT(value != NULL);
850 PJDLOG_ASSERT(nitems > 0);
851
852 nvl = value[0];
853 cookie = NULL;
854 break;
855 }
856 case NV_TYPE_DESCRIPTOR_ARRAY:
857 {
858 size_t nitems;
859
860 (void)nvpair_get_descriptor_array(nvp,
861 &nitems);
862 ndescs += nitems;
863 break;
864 }
865 }
866 }
867 } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
868
869 return (ndescs);
870 #else
871 return (0);
872 #endif
873 }
874
875 static unsigned char *
876 nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
877 {
878 struct nvlist_header nvlhdr;
879
880 NVLIST_ASSERT(nvl);
881
882 nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
883 nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
884 nvlhdr.nvlh_flags = nvl->nvl_flags;
885 #if BYTE_ORDER == BIG_ENDIAN
886 nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
887 #endif
888 nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
889 nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
890 PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
891 memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
892 ptr += sizeof(nvlhdr);
893 *leftp -= sizeof(nvlhdr);
894
895 return (ptr);
896 }
897
898 static void *
899 nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
900 {
901 unsigned char *buf, *ptr;
902 size_t left, size;
903 const nvlist_t *tmpnvl;
904 nvpair_t *nvp, *tmpnvp;
905 void *cookie;
906
907 NVLIST_ASSERT(nvl);
908
909 if (nvl->nvl_error != 0) {
910 ERRNO_SET(nvl->nvl_error);
911 return (NULL);
912 }
913
914 size = nvlist_size(nvl);
915 buf = nv_malloc(size);
916 if (buf == NULL)
917 return (NULL);
918
919 ptr = buf;
920 left = size;
921
922 ptr = nvlist_pack_header(nvl, ptr, &left);
923
924 nvp = nvlist_first_nvpair(nvl);
925 while (nvp != NULL) {
926 NVPAIR_ASSERT(nvp);
927
928 nvpair_init_datasize(nvp);
929 ptr = nvpair_pack_header(nvp, ptr, &left);
930 if (ptr == NULL)
931 goto fail;
932 switch (nvpair_type(nvp)) {
933 case NV_TYPE_NULL:
934 ptr = nvpair_pack_null(nvp, ptr, &left);
935 break;
936 case NV_TYPE_BOOL:
937 ptr = nvpair_pack_bool(nvp, ptr, &left);
938 break;
939 case NV_TYPE_NUMBER:
940 ptr = nvpair_pack_number(nvp, ptr, &left);
941 break;
942 case NV_TYPE_STRING:
943 ptr = nvpair_pack_string(nvp, ptr, &left);
944 break;
945 case NV_TYPE_NVLIST:
946 tmpnvl = nvpair_get_nvlist(nvp);
947 ptr = nvlist_pack_header(tmpnvl, ptr, &left);
948 if (ptr == NULL)
949 goto fail;
950 tmpnvp = nvlist_first_nvpair(tmpnvl);
951 if (tmpnvp != NULL) {
952 nvl = tmpnvl;
953 nvp = tmpnvp;
954 continue;
955 }
956 ptr = nvpair_pack_nvlist_up(ptr, &left);
957 break;
958 #if !defined(_KERNEL) && !defined(_STANDALONE)
959 case NV_TYPE_DESCRIPTOR:
960 ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
961 break;
962 case NV_TYPE_DESCRIPTOR_ARRAY:
963 ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp,
964 &left);
965 break;
966 #endif
967 case NV_TYPE_BINARY:
968 ptr = nvpair_pack_binary(nvp, ptr, &left);
969 break;
970 case NV_TYPE_BOOL_ARRAY:
971 ptr = nvpair_pack_bool_array(nvp, ptr, &left);
972 break;
973 case NV_TYPE_NUMBER_ARRAY:
974 ptr = nvpair_pack_number_array(nvp, ptr, &left);
975 break;
976 case NV_TYPE_STRING_ARRAY:
977 ptr = nvpair_pack_string_array(nvp, ptr, &left);
978 break;
979 case NV_TYPE_NVLIST_ARRAY:
980 {
981 const nvlist_t * const * value;
982 size_t nitems;
983 unsigned int ii;
984
985 tmpnvl = NULL;
986 value = nvpair_get_nvlist_array(nvp, &nitems);
987 for (ii = 0; ii < nitems; ii++) {
988 ptr = nvlist_pack_header(value[ii], ptr, &left);
989 if (ptr == NULL)
990 goto out;
991 tmpnvp = nvlist_first_nvpair(value[ii]);
992 if (tmpnvp != NULL) {
993 tmpnvl = value[ii];
994 break;
995 }
996 ptr = nvpair_pack_nvlist_array_next(ptr, &left);
997 if (ptr == NULL)
998 goto out;
999 }
1000 if (tmpnvl != NULL) {
1001 nvl = tmpnvl;
1002 nvp = tmpnvp;
1003 continue;
1004 }
1005 break;
1006 }
1007 default:
1008 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
1009 }
1010 if (ptr == NULL)
1011 goto fail;
1012 while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
1013 do {
1014 cookie = NULL;
1015 if (nvlist_in_array(nvl)) {
1016 ptr = nvpair_pack_nvlist_array_next(ptr,
1017 &left);
1018 if (ptr == NULL)
1019 goto fail;
1020 }
1021 nvl = nvlist_get_pararr(nvl, &cookie);
1022 if (nvl == NULL)
1023 goto out;
1024 if (nvlist_in_array(nvl) && cookie == NULL) {
1025 nvp = nvlist_first_nvpair(nvl);
1026 ptr = nvlist_pack_header(nvl, ptr,
1027 &left);
1028 if (ptr == NULL)
1029 goto fail;
1030 } else if (nvpair_type((nvpair_t *)cookie) !=
1031 NV_TYPE_NVLIST_ARRAY) {
1032 ptr = nvpair_pack_nvlist_up(ptr, &left);
1033 if (ptr == NULL)
1034 goto fail;
1035 nvp = cookie;
1036 } else {
1037 nvp = cookie;
1038 }
1039 } while (nvp == NULL);
1040 if (nvlist_in_array(nvl) && cookie == NULL)
1041 break;
1042 }
1043 }
1044
1045 out:
1046 if (sizep != NULL)
1047 *sizep = size;
1048 return (buf);
1049 fail:
1050 nv_free(buf);
1051 return (NULL);
1052 }
1053
1054 void *
1055 nvlist_pack(const nvlist_t *nvl, size_t *sizep)
1056 {
1057
1058 NVLIST_ASSERT(nvl);
1059
1060 if (nvl->nvl_error != 0) {
1061 ERRNO_SET(nvl->nvl_error);
1062 return (NULL);
1063 }
1064
1065 if (nvlist_ndescriptors(nvl) > 0) {
1066 ERRNO_SET(EOPNOTSUPP);
1067 return (NULL);
1068 }
1069
1070 return (nvlist_xpack(nvl, NULL, sizep));
1071 }
1072
1073 static bool
1074 nvlist_check_header(struct nvlist_header *nvlhdrp)
1075 {
1076
1077 if (nvlhdrp->nvlh_size > SIZE_MAX - sizeof(nvlhdrp)) {
1078 ERRNO_SET(EINVAL);
1079 return (false);
1080 }
1081 if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
1082 ERRNO_SET(EINVAL);
1083 return (false);
1084 }
1085 if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
1086 ERRNO_SET(EINVAL);
1087 return (false);
1088 }
1089 #if BYTE_ORDER == BIG_ENDIAN
1090 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
1091 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
1092 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
1093 }
1094 #else
1095 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
1096 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
1097 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
1098 }
1099 #endif
1100 return (true);
1101 }
1102
1103 const unsigned char *
1104 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
1105 bool *isbep, size_t *leftp)
1106 {
1107 struct nvlist_header nvlhdr;
1108 int inarrayf;
1109
1110 if (*leftp < sizeof(nvlhdr))
1111 goto fail;
1112
1113 memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
1114
1115 if (!nvlist_check_header(&nvlhdr))
1116 goto fail;
1117
1118 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
1119 goto fail;
1120
1121 /*
1122 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
1123 */
1124 if (nvlhdr.nvlh_descriptors > nfds)
1125 goto fail;
1126
1127 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
1128 goto fail;
1129
1130 inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY);
1131 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf;
1132
1133 ptr += sizeof(nvlhdr);
1134 if (isbep != NULL)
1135 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
1136 *leftp -= sizeof(nvlhdr);
1137
1138 return (ptr);
1139 fail:
1140 ERRNO_SET(EINVAL);
1141 return (NULL);
1142 }
1143
1144 static nvlist_t *
1145 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
1146 int flags)
1147 {
1148 const unsigned char *ptr;
1149 nvlist_t *nvl, *retnvl, *tmpnvl, *array;
1150 nvpair_t *nvp;
1151 size_t left;
1152 bool isbe;
1153
1154 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
1155
1156 left = size;
1157 ptr = buf;
1158
1159 tmpnvl = array = NULL;
1160 nvl = retnvl = nvlist_create(0);
1161 if (nvl == NULL)
1162 goto fail;
1163
1164 ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
1165 if (ptr == NULL)
1166 goto fail;
1167 if (nvl->nvl_flags != flags) {
1168 ERRNO_SET(EILSEQ);
1169 goto fail;
1170 }
1171
1172 while (left > 0) {
1173 ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
1174 if (ptr == NULL)
1175 goto fail;
1176 switch (nvpair_type(nvp)) {
1177 case NV_TYPE_NULL:
1178 ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
1179 break;
1180 case NV_TYPE_BOOL:
1181 ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
1182 break;
1183 case NV_TYPE_NUMBER:
1184 ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
1185 break;
1186 case NV_TYPE_STRING:
1187 ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
1188 break;
1189 case NV_TYPE_NVLIST:
1190 ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
1191 &tmpnvl);
1192 if (tmpnvl == NULL || ptr == NULL)
1193 goto fail;
1194 nvlist_set_parent(tmpnvl, nvp);
1195 break;
1196 #if !defined(_KERNEL) && !defined(_STANDALONE) && !defined(__NetBSD__)
1197 case NV_TYPE_DESCRIPTOR:
1198 ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
1199 fds, nfds);
1200 break;
1201 case NV_TYPE_DESCRIPTOR_ARRAY:
1202 ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr,
1203 &left, fds, nfds);
1204 break;
1205 #endif
1206 case NV_TYPE_BINARY:
1207 ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
1208 break;
1209 case NV_TYPE_NVLIST_UP:
1210 if (nvl->nvl_parent == NULL)
1211 goto fail;
1212 nvl = nvpair_nvlist(nvl->nvl_parent);
1213 nvpair_free_structure(nvp);
1214 continue;
1215 case NV_TYPE_NVLIST_ARRAY_NEXT:
1216 if (nvl->nvl_array_next == NULL) {
1217 if (nvl->nvl_parent == NULL)
1218 goto fail;
1219 nvl = nvpair_nvlist(nvl->nvl_parent);
1220 } else {
1221 nvl = __DECONST(nvlist_t *,
1222 nvlist_get_array_next(nvl));
1223 ptr = nvlist_unpack_header(nvl, ptr, nfds,
1224 &isbe, &left);
1225 if (ptr == NULL)
1226 goto fail;
1227 }
1228 nvpair_free_structure(nvp);
1229 continue;
1230 case NV_TYPE_BOOL_ARRAY:
1231 ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left);
1232 break;
1233 case NV_TYPE_NUMBER_ARRAY:
1234 ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left);
1235 break;
1236 case NV_TYPE_STRING_ARRAY:
1237 ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left);
1238 break;
1239 case NV_TYPE_NVLIST_ARRAY:
1240 ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left,
1241 &array);
1242 if (ptr == NULL)
1243 goto fail;
1244 PJDLOG_ASSERT(array != NULL);
1245 tmpnvl = array;
1246 do {
1247 nvlist_set_parent(array, nvp);
1248 array = __DECONST(nvlist_t *,
1249 nvlist_get_array_next(array));
1250 } while (array != NULL);
1251 ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe,
1252 &left);
1253 break;
1254 default:
1255 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
1256 }
1257 if (ptr == NULL)
1258 goto fail;
1259 if (!nvlist_move_nvpair(nvl, nvp))
1260 goto fail;
1261 if (tmpnvl != NULL) {
1262 nvl = tmpnvl;
1263 tmpnvl = NULL;
1264 }
1265 }
1266
1267 return (retnvl);
1268 fail:
1269 nvlist_destroy(retnvl);
1270 return (NULL);
1271 }
1272
1273 nvlist_t *
1274 nvlist_unpack(const void *buf, size_t size, int flags)
1275 {
1276
1277 return (nvlist_xunpack(buf, size, NULL, 0, flags));
1278 }
1279
1280 #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(WITH_MSGIO)
1281 int
1282 nvlist_send(int sock, const nvlist_t *nvl)
1283 {
1284 size_t datasize, nfds;
1285 int *fds;
1286 void *data;
1287 int64_t fdidx;
1288 int ret;
1289
1290 if (nvlist_error(nvl) != 0) {
1291 ERRNO_SET(nvlist_error(nvl));
1292 return (-1);
1293 }
1294
1295 fds = nvlist_descriptors(nvl, &nfds);
1296 if (fds == NULL)
1297 return (-1);
1298
1299 ret = -1;
1300 fdidx = 0;
1301
1302 data = nvlist_xpack(nvl, &fdidx, &datasize);
1303 if (data == NULL)
1304 goto out;
1305
1306 if (buf_send(sock, data, datasize) == -1)
1307 goto out;
1308
1309 if (nfds > 0) {
1310 if (fd_send(sock, fds, nfds) == -1)
1311 goto out;
1312 }
1313
1314 ret = 0;
1315 out:
1316 ERRNO_SAVE();
1317 nv_free(fds);
1318 nv_free(data);
1319 ERRNO_RESTORE();
1320 return (ret);
1321 }
1322
1323 nvlist_t *
1324 nvlist_recv(int sock, int flags)
1325 {
1326 struct nvlist_header nvlhdr;
1327 nvlist_t *nvl, *ret;
1328 unsigned char *buf;
1329 size_t nfds, size, i;
1330 int *fds;
1331
1332 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
1333 return (NULL);
1334
1335 if (!nvlist_check_header(&nvlhdr))
1336 return (NULL);
1337
1338 nfds = (size_t)nvlhdr.nvlh_descriptors;
1339 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
1340
1341 buf = nv_malloc(size);
1342 if (buf == NULL)
1343 return (NULL);
1344
1345 memcpy(buf, &nvlhdr, sizeof(nvlhdr));
1346
1347 ret = NULL;
1348 fds = NULL;
1349
1350 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
1351 goto out;
1352
1353 if (nfds > 0) {
1354 fds = nv_malloc(nfds * sizeof(fds[0]));
1355 if (fds == NULL)
1356 goto out;
1357 if (fd_recv(sock, fds, nfds) == -1)
1358 goto out;
1359 }
1360
1361 nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
1362 if (nvl == NULL) {
1363 ERRNO_SAVE();
1364 for (i = 0; i < nfds; i++)
1365 close(fds[i]);
1366 ERRNO_RESTORE();
1367 goto out;
1368 }
1369
1370 ret = nvl;
1371 out:
1372 ERRNO_SAVE();
1373 nv_free(buf);
1374 nv_free(fds);
1375 ERRNO_RESTORE();
1376
1377 return (ret);
1378 }
1379
1380 nvlist_t *
1381 nvlist_xfer(int sock, nvlist_t *nvl, int flags)
1382 {
1383
1384 if (nvlist_send(sock, nvl) < 0) {
1385 nvlist_destroy(nvl);
1386 return (NULL);
1387 }
1388 nvlist_destroy(nvl);
1389 return (nvlist_recv(sock, flags));
1390 }
1391 #endif
1392
1393 nvpair_t *
1394 nvlist_first_nvpair(const nvlist_t *nvl)
1395 {
1396
1397 NVLIST_ASSERT(nvl);
1398
1399 return (TAILQ_FIRST(&nvl->nvl_head));
1400 }
1401
1402 nvpair_t *
1403 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1404 {
1405 nvpair_t *retnvp;
1406
1407 NVLIST_ASSERT(nvl);
1408 NVPAIR_ASSERT(nvp);
1409 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1410
1411 retnvp = nvpair_next(nvp);
1412 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1413
1414 return (retnvp);
1415
1416 }
1417
1418 nvpair_t *
1419 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1420 {
1421 nvpair_t *retnvp;
1422
1423 NVLIST_ASSERT(nvl);
1424 NVPAIR_ASSERT(nvp);
1425 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1426
1427 retnvp = nvpair_prev(nvp);
1428 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1429
1430 return (retnvp);
1431 }
1432
1433 const char *
1434 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1435 {
1436 nvpair_t *nvp;
1437
1438 NVLIST_ASSERT(nvl);
1439
1440 if (cookiep == NULL || *cookiep == NULL)
1441 nvp = nvlist_first_nvpair(nvl);
1442 else
1443 nvp = nvlist_next_nvpair(nvl, *cookiep);
1444 if (nvp == NULL)
1445 return (NULL);
1446 if (typep != NULL)
1447 *typep = nvpair_type(nvp);
1448 if (cookiep != NULL)
1449 *cookiep = nvp;
1450 return (nvpair_name(nvp));
1451 }
1452
1453 bool
1454 nvlist_exists(const nvlist_t *nvl, const char *name)
1455 {
1456
1457 return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1458 }
1459
1460 #define NVLIST_EXISTS(type, TYPE) \
1461 bool \
1462 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
1463 { \
1464 \
1465 return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \
1466 }
1467
1468 NVLIST_EXISTS(null, NULL)
1469 NVLIST_EXISTS(bool, BOOL)
1470 NVLIST_EXISTS(number, NUMBER)
1471 NVLIST_EXISTS(string, STRING)
1472 NVLIST_EXISTS(nvlist, NVLIST)
1473 NVLIST_EXISTS(binary, BINARY)
1474 NVLIST_EXISTS(bool_array, BOOL_ARRAY)
1475 NVLIST_EXISTS(number_array, NUMBER_ARRAY)
1476 NVLIST_EXISTS(string_array, STRING_ARRAY)
1477 NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY)
1478 #if !defined(_KERNEL) && !defined(_STANDALONE)
1479 NVLIST_EXISTS(descriptor, DESCRIPTOR)
1480 NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY)
1481 #endif
1482
1483 #undef NVLIST_EXISTS
1484
1485 void
1486 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1487 {
1488 nvpair_t *newnvp;
1489
1490 NVPAIR_ASSERT(nvp);
1491
1492 if (nvlist_error(nvl) != 0) {
1493 ERRNO_SET(nvlist_error(nvl));
1494 return;
1495 }
1496 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1497 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1498 nvl->nvl_error = EEXIST;
1499 ERRNO_SET(nvlist_error(nvl));
1500 return;
1501 }
1502 }
1503
1504 newnvp = nvpair_clone(nvp);
1505 if (newnvp == NULL) {
1506 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1507 ERRNO_SET(nvlist_error(nvl));
1508 return;
1509 }
1510
1511 nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1512 }
1513
1514 #if !defined(_STANDALONE)
1515 void
1516 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1517 {
1518 va_list valueap;
1519
1520 va_start(valueap, valuefmt);
1521 nvlist_add_stringv(nvl, name, valuefmt, valueap);
1522 va_end(valueap);
1523 }
1524
1525 void
1526 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1527 va_list valueap)
1528 {
1529 nvpair_t *nvp;
1530
1531 if (nvlist_error(nvl) != 0) {
1532 ERRNO_SET(nvlist_error(nvl));
1533 return;
1534 }
1535
1536 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1537 if (nvp == NULL) {
1538 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1539 ERRNO_SET(nvl->nvl_error);
1540 } else {
1541 (void)nvlist_move_nvpair(nvl, nvp);
1542 }
1543 }
1544 #endif
1545
1546 void
1547 nvlist_add_null(nvlist_t *nvl, const char *name)
1548 {
1549 nvpair_t *nvp;
1550
1551 if (nvlist_error(nvl) != 0) {
1552 ERRNO_SET(nvlist_error(nvl));
1553 return;
1554 }
1555
1556 nvp = nvpair_create_null(name);
1557 if (nvp == NULL) {
1558 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1559 ERRNO_SET(nvl->nvl_error);
1560 } else {
1561 (void)nvlist_move_nvpair(nvl, nvp);
1562 }
1563 }
1564
1565 void
1566 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1567 size_t size)
1568 {
1569 nvpair_t *nvp;
1570
1571 if (nvlist_error(nvl) != 0) {
1572 ERRNO_SET(nvlist_error(nvl));
1573 return;
1574 }
1575
1576 nvp = nvpair_create_binary(name, value, size);
1577 if (nvp == NULL) {
1578 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1579 ERRNO_SET(nvl->nvl_error);
1580 } else {
1581 (void)nvlist_move_nvpair(nvl, nvp);
1582 }
1583 }
1584
1585
1586 #define NVLIST_ADD(vtype, type) \
1587 void \
1588 nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \
1589 { \
1590 nvpair_t *nvp; \
1591 \
1592 if (nvlist_error(nvl) != 0) { \
1593 ERRNO_SET(nvlist_error(nvl)); \
1594 return; \
1595 } \
1596 \
1597 nvp = nvpair_create_##type(name, value); \
1598 if (nvp == NULL) { \
1599 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1600 ERRNO_SET(nvl->nvl_error); \
1601 } else { \
1602 (void)nvlist_move_nvpair(nvl, nvp); \
1603 } \
1604 }
1605
1606 NVLIST_ADD(bool, bool)
1607 NVLIST_ADD(uint64_t, number)
1608 NVLIST_ADD(const char *, string)
1609 NVLIST_ADD(const nvlist_t *, nvlist)
1610 #if !defined(_KERNEL) && !defined(_STANDALONE)
1611 NVLIST_ADD(int, descriptor);
1612 #endif
1613
1614 #undef NVLIST_ADD
1615
1616 #define NVLIST_ADD_ARRAY(vtype, type) \
1617 void \
1618 nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value, \
1619 size_t nitems) \
1620 { \
1621 nvpair_t *nvp; \
1622 \
1623 if (nvlist_error(nvl) != 0) { \
1624 ERRNO_SET(nvlist_error(nvl)); \
1625 return; \
1626 } \
1627 \
1628 nvp = nvpair_create_##type##_array(name, value, nitems); \
1629 if (nvp == NULL) { \
1630 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1631 ERRNO_SET(nvl->nvl_error); \
1632 } else { \
1633 (void)nvlist_move_nvpair(nvl, nvp); \
1634 } \
1635 }
1636
1637 NVLIST_ADD_ARRAY(const bool *, bool)
1638 NVLIST_ADD_ARRAY(const uint64_t *, number)
1639 NVLIST_ADD_ARRAY(const char * const *, string)
1640 NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist)
1641 #if !defined(_KERNEL) && !defined(_STANDALONE)
1642 NVLIST_ADD_ARRAY(const int *, descriptor)
1643 #endif
1644
1645 #undef NVLIST_ADD_ARRAY
1646
1647 #define NVLIST_APPEND_ARRAY(vtype, type, TYPE) \
1648 void \
1649 nvlist_append_##type##_array(nvlist_t *nvl, const char *name, vtype value)\
1650 { \
1651 nvpair_t *nvp; \
1652 \
1653 if (nvlist_error(nvl) != 0) { \
1654 ERRNO_SET(nvlist_error(nvl)); \
1655 return; \
1656 } \
1657 nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \
1658 if (nvp == NULL) { \
1659 nvlist_add_##type##_array(nvl, name, &value, 1); \
1660 return; \
1661 } \
1662 if (nvpair_append_##type##_array(nvp, value) == -1) { \
1663 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1664 ERRNO_SET(nvl->nvl_error); \
1665 } \
1666 }
1667
1668 NVLIST_APPEND_ARRAY(const bool, bool, BOOL)
1669 NVLIST_APPEND_ARRAY(const uint64_t, number, NUMBER)
1670 NVLIST_APPEND_ARRAY(const char *, string, STRING)
1671 NVLIST_APPEND_ARRAY(const nvlist_t *, nvlist, NVLIST)
1672 #if !defined(_KERNEL) && !defined(_STANDALONE)
1673 NVLIST_APPEND_ARRAY(const int, descriptor, DESCRIPTOR)
1674 #endif
1675
1676 #undef NVLIST_APPEND_ARRAY
1677
1678 bool
1679 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1680 {
1681
1682 NVPAIR_ASSERT(nvp);
1683 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1684
1685 if (nvlist_error(nvl) != 0) {
1686 nvpair_free(nvp);
1687 ERRNO_SET(nvlist_error(nvl));
1688 return (false);
1689 }
1690 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1691 if (nvlist_exists(nvl, nvpair_name(nvp))) {
1692 nvpair_free(nvp);
1693 nvl->nvl_error = EEXIST;
1694 ERRNO_SET(nvl->nvl_error);
1695 return (false);
1696 }
1697 }
1698
1699 nvpair_insert(&nvl->nvl_head, nvp, nvl);
1700 return (true);
1701 }
1702
1703 void
1704 nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1705 {
1706 nvpair_t *nvp;
1707
1708 if (nvlist_error(nvl) != 0) {
1709 nv_free(value);
1710 ERRNO_SET(nvlist_error(nvl));
1711 return;
1712 }
1713
1714 nvp = nvpair_move_string(name, value);
1715 if (nvp == NULL) {
1716 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1717 ERRNO_SET(nvl->nvl_error);
1718 } else {
1719 (void)nvlist_move_nvpair(nvl, nvp);
1720 }
1721 }
1722
1723 void
1724 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1725 {
1726 nvpair_t *nvp;
1727
1728 if (nvlist_error(nvl) != 0) {
1729 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1730 nvlist_destroy(value);
1731 ERRNO_SET(nvlist_error(nvl));
1732 return;
1733 }
1734
1735 nvp = nvpair_move_nvlist(name, value);
1736 if (nvp == NULL) {
1737 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1738 ERRNO_SET(nvl->nvl_error);
1739 } else {
1740 (void)nvlist_move_nvpair(nvl, nvp);
1741 }
1742 }
1743
1744 #if !defined(_KERNEL) && !defined(_STANDALONE)
1745 void
1746 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1747 {
1748 nvpair_t *nvp;
1749
1750 if (nvlist_error(nvl) != 0) {
1751 close(value);
1752 ERRNO_SET(nvlist_error(nvl));
1753 return;
1754 }
1755
1756 nvp = nvpair_move_descriptor(name, value);
1757 if (nvp == NULL) {
1758 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1759 ERRNO_SET(nvl->nvl_error);
1760 } else {
1761 (void)nvlist_move_nvpair(nvl, nvp);
1762 }
1763 }
1764 #endif
1765
1766 void
1767 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1768 {
1769 nvpair_t *nvp;
1770
1771 if (nvlist_error(nvl) != 0) {
1772 nv_free(value);
1773 ERRNO_SET(nvlist_error(nvl));
1774 return;
1775 }
1776
1777 nvp = nvpair_move_binary(name, value, size);
1778 if (nvp == NULL) {
1779 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1780 ERRNO_SET(nvl->nvl_error);
1781 } else {
1782 (void)nvlist_move_nvpair(nvl, nvp);
1783 }
1784 }
1785
1786 void
1787 nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value,
1788 size_t nitems)
1789 {
1790 nvpair_t *nvp;
1791
1792 if (nvlist_error(nvl) != 0) {
1793 nv_free(value);
1794 ERRNO_SET(nvlist_error(nvl));
1795 return;
1796 }
1797
1798 nvp = nvpair_move_bool_array(name, value, nitems);
1799 if (nvp == NULL) {
1800 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1801 ERRNO_SET(nvl->nvl_error);
1802 } else {
1803 (void)nvlist_move_nvpair(nvl, nvp);
1804 }
1805 }
1806
1807 void
1808 nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value,
1809 size_t nitems)
1810 {
1811 nvpair_t *nvp;
1812 size_t i;
1813
1814 if (nvlist_error(nvl) != 0) {
1815 if (value != NULL) {
1816 for (i = 0; i < nitems; i++)
1817 nv_free(value[i]);
1818 nv_free(value);
1819 }
1820 ERRNO_SET(nvlist_error(nvl));
1821 return;
1822 }
1823
1824 nvp = nvpair_move_string_array(name, value, nitems);
1825 if (nvp == NULL) {
1826 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1827 ERRNO_SET(nvl->nvl_error);
1828 } else {
1829 (void)nvlist_move_nvpair(nvl, nvp);
1830 }
1831 }
1832
1833 void
1834 nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value,
1835 size_t nitems)
1836 {
1837 nvpair_t *nvp;
1838 size_t i;
1839
1840 if (nvlist_error(nvl) != 0) {
1841 if (value != NULL) {
1842 for (i = 0; i < nitems; i++) {
1843 if (nvlist_get_pararr(value[i], NULL) == NULL)
1844 nvlist_destroy(value[i]);
1845 }
1846 }
1847 nv_free(value);
1848 ERRNO_SET(nvlist_error(nvl));
1849 return;
1850 }
1851
1852 nvp = nvpair_move_nvlist_array(name, value, nitems);
1853 if (nvp == NULL) {
1854 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1855 ERRNO_SET(nvl->nvl_error);
1856 } else {
1857 (void)nvlist_move_nvpair(nvl, nvp);
1858 }
1859 }
1860
1861 void
1862 nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value,
1863 size_t nitems)
1864 {
1865 nvpair_t *nvp;
1866
1867 if (nvlist_error(nvl) != 0) {
1868 nv_free(value);
1869 ERRNO_SET(nvlist_error(nvl));
1870 return;
1871 }
1872
1873 nvp = nvpair_move_number_array(name, value, nitems);
1874 if (nvp == NULL) {
1875 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1876 ERRNO_SET(nvl->nvl_error);
1877 } else {
1878 (void)nvlist_move_nvpair(nvl, nvp);
1879 }
1880 }
1881
1882 #if !defined(_KERNEL) && !defined(_STANDALONE)
1883 void
1884 nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value,
1885 size_t nitems)
1886 {
1887 nvpair_t *nvp;
1888 size_t i;
1889
1890 if (nvlist_error(nvl) != 0) {
1891 if (value != 0) {
1892 for (i = 0; i < nitems; i++)
1893 close(value[i]);
1894 nv_free(value);
1895 }
1896
1897 ERRNO_SET(nvlist_error(nvl));
1898 return;
1899 }
1900
1901 nvp = nvpair_move_descriptor_array(name, value, nitems);
1902 if (nvp == NULL) {
1903 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1904 ERRNO_SET(nvl->nvl_error);
1905 } else {
1906 (void)nvlist_move_nvpair(nvl, nvp);
1907 }
1908 }
1909 #endif
1910
1911 const nvpair_t *
1912 nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1913 {
1914
1915 return (nvlist_find(nvl, NV_TYPE_NONE, name));
1916 }
1917
1918 #define NVLIST_GET(ftype, type, TYPE) \
1919 ftype \
1920 nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1921 { \
1922 const nvpair_t *nvp; \
1923 \
1924 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1925 if (nvp == NULL) \
1926 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1927 return (nvpair_get_##type(nvp)); \
1928 }
1929
1930 NVLIST_GET(bool, bool, BOOL)
1931 NVLIST_GET(uint64_t, number, NUMBER)
1932 NVLIST_GET(const char *, string, STRING)
1933 NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1934 #if !defined(_KERNEL) && !defined(_STANDALONE)
1935 NVLIST_GET(int, descriptor, DESCRIPTOR)
1936 #endif
1937
1938 #undef NVLIST_GET
1939
1940 const void *
1941 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1942 {
1943 nvpair_t *nvp;
1944
1945 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1946 if (nvp == NULL)
1947 nvlist_report_missing(NV_TYPE_BINARY, name);
1948
1949 return (nvpair_get_binary(nvp, sizep));
1950 }
1951
1952 #define NVLIST_GET_ARRAY(ftype, type, TYPE) \
1953 ftype \
1954 nvlist_get_##type##_array(const nvlist_t *nvl, const char *name, \
1955 size_t *nitems) \
1956 { \
1957 const nvpair_t *nvp; \
1958 \
1959 nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \
1960 if (nvp == NULL) \
1961 nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \
1962 return (nvpair_get_##type##_array(nvp, nitems)); \
1963 }
1964
1965 NVLIST_GET_ARRAY(const bool *, bool, BOOL)
1966 NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER)
1967 NVLIST_GET_ARRAY(const char * const *, string, STRING)
1968 NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST)
1969 #if !defined(_KERNEL) && !defined(_STANDALONE)
1970 NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR)
1971 #endif
1972
1973 #undef NVLIST_GET_ARRAY
1974
1975 #define NVLIST_TAKE(ftype, type, TYPE) \
1976 ftype \
1977 nvlist_take_##type(nvlist_t *nvl, const char *name) \
1978 { \
1979 nvpair_t *nvp; \
1980 ftype value; \
1981 \
1982 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1983 if (nvp == NULL) \
1984 nvlist_report_missing(NV_TYPE_##TYPE, name); \
1985 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1986 nvlist_remove_nvpair(nvl, nvp); \
1987 nvpair_free_structure(nvp); \
1988 return (value); \
1989 }
1990
1991 NVLIST_TAKE(bool, bool, BOOL)
1992 NVLIST_TAKE(uint64_t, number, NUMBER)
1993 NVLIST_TAKE(char *, string, STRING)
1994 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1995 #if !defined(_KERNEL) && !defined(_STANDALONE)
1996 NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1997 #endif
1998
1999 #undef NVLIST_TAKE
2000
2001 void *
2002 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
2003 {
2004 nvpair_t *nvp;
2005 void *value;
2006
2007 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
2008 if (nvp == NULL)
2009 nvlist_report_missing(NV_TYPE_BINARY, name);
2010
2011 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
2012 nvlist_remove_nvpair(nvl, nvp);
2013 nvpair_free_structure(nvp);
2014 return (value);
2015 }
2016
2017 #define NVLIST_TAKE_ARRAY(ftype, type, TYPE) \
2018 ftype \
2019 nvlist_take_##type##_array(nvlist_t *nvl, const char *name, \
2020 size_t *nitems) \
2021 { \
2022 nvpair_t *nvp; \
2023 ftype value; \
2024 \
2025 nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \
2026 if (nvp == NULL) \
2027 nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \
2028 value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\
2029 nvlist_remove_nvpair(nvl, nvp); \
2030 nvpair_free_structure(nvp); \
2031 return (value); \
2032 }
2033
2034 NVLIST_TAKE_ARRAY(bool *, bool, BOOL)
2035 NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER)
2036 NVLIST_TAKE_ARRAY(char **, string, STRING)
2037 NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST)
2038 #if !defined(_KERNEL) && !defined(_STANDALONE)
2039 NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR)
2040 #endif
2041
2042 void
2043 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
2044 {
2045
2046 NVLIST_ASSERT(nvl);
2047 NVPAIR_ASSERT(nvp);
2048 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
2049
2050 nvpair_remove(&nvl->nvl_head, nvp, nvl);
2051 }
2052
2053 void
2054 nvlist_free(nvlist_t *nvl, const char *name)
2055 {
2056
2057 nvlist_free_type(nvl, name, NV_TYPE_NONE);
2058 }
2059
2060 #define NVLIST_FREE(type, TYPE) \
2061 void \
2062 nvlist_free_##type(nvlist_t *nvl, const char *name) \
2063 { \
2064 \
2065 nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \
2066 }
2067
2068 NVLIST_FREE(null, NULL)
2069 NVLIST_FREE(bool, BOOL)
2070 NVLIST_FREE(number, NUMBER)
2071 NVLIST_FREE(string, STRING)
2072 NVLIST_FREE(nvlist, NVLIST)
2073 NVLIST_FREE(binary, BINARY)
2074 NVLIST_FREE(bool_array, BOOL_ARRAY)
2075 NVLIST_FREE(number_array, NUMBER_ARRAY)
2076 NVLIST_FREE(string_array, STRING_ARRAY)
2077 NVLIST_FREE(nvlist_array, NVLIST_ARRAY)
2078 #if !defined(_KERNEL) && !defined(_STANDALONE)
2079 NVLIST_FREE(descriptor, DESCRIPTOR)
2080 NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY)
2081 #endif
2082
2083 #undef NVLIST_FREE
2084
2085 void
2086 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
2087 {
2088
2089 NVLIST_ASSERT(nvl);
2090 NVPAIR_ASSERT(nvp);
2091 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
2092
2093 nvlist_remove_nvpair(nvl, nvp);
2094 nvpair_free(nvp);
2095 }
2096
2097