1 /* $NetBSD: nvlist.c,v 1.11 2024/09/11 15:01:11 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@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.11 2024/09/11 15:01:11 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_calloc(nitems + 1, sizeof(fds[0])); 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_calloc(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