1 /* $NetBSD: nvlist.c,v 1.8 2019/07/23 00:49:16 rmind 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.8 2019/07/23 00:49:16 rmind 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_magic != NVLIST_HEADER_MAGIC) { 1078 ERRNO_SET(EINVAL); 1079 return (false); 1080 } 1081 if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { 1082 ERRNO_SET(EINVAL); 1083 return (false); 1084 } 1085 #if BYTE_ORDER == BIG_ENDIAN 1086 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) { 1087 nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size); 1088 nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors); 1089 } 1090 #else 1091 if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) { 1092 nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size); 1093 nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); 1094 } 1095 #endif 1096 return (true); 1097 } 1098 1099 const unsigned char * 1100 nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, 1101 bool *isbep, size_t *leftp) 1102 { 1103 struct nvlist_header nvlhdr; 1104 int inarrayf; 1105 1106 if (*leftp < sizeof(nvlhdr)) 1107 goto fail; 1108 1109 memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); 1110 1111 if (!nvlist_check_header(&nvlhdr)) 1112 goto fail; 1113 1114 if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) 1115 goto fail; 1116 1117 /* 1118 * nvlh_descriptors might be smaller than nfds in embedded nvlists. 1119 */ 1120 if (nvlhdr.nvlh_descriptors > nfds) 1121 goto fail; 1122 1123 if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) 1124 goto fail; 1125 1126 inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY); 1127 nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf; 1128 1129 ptr += sizeof(nvlhdr); 1130 if (isbep != NULL) 1131 *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0); 1132 *leftp -= sizeof(nvlhdr); 1133 1134 return (ptr); 1135 fail: 1136 ERRNO_SET(EINVAL); 1137 return (NULL); 1138 } 1139 1140 static nvlist_t * 1141 nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds, 1142 int flags) 1143 { 1144 const unsigned char *ptr; 1145 nvlist_t *nvl, *retnvl, *tmpnvl, *array; 1146 nvpair_t *nvp; 1147 size_t left; 1148 bool isbe; 1149 1150 PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 1151 1152 left = size; 1153 ptr = buf; 1154 1155 tmpnvl = array = NULL; 1156 nvl = retnvl = nvlist_create(0); 1157 if (nvl == NULL) 1158 goto fail; 1159 1160 ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); 1161 if (ptr == NULL) 1162 goto fail; 1163 if (nvl->nvl_flags != flags) { 1164 ERRNO_SET(EILSEQ); 1165 goto fail; 1166 } 1167 1168 while (left > 0) { 1169 ptr = nvpair_unpack(isbe, ptr, &left, &nvp); 1170 if (ptr == NULL) 1171 goto fail; 1172 switch (nvpair_type(nvp)) { 1173 case NV_TYPE_NULL: 1174 ptr = nvpair_unpack_null(isbe, nvp, ptr, &left); 1175 break; 1176 case NV_TYPE_BOOL: 1177 ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left); 1178 break; 1179 case NV_TYPE_NUMBER: 1180 ptr = nvpair_unpack_number(isbe, nvp, ptr, &left); 1181 break; 1182 case NV_TYPE_STRING: 1183 ptr = nvpair_unpack_string(isbe, nvp, ptr, &left); 1184 break; 1185 case NV_TYPE_NVLIST: 1186 ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds, 1187 &tmpnvl); 1188 if (tmpnvl == NULL || ptr == NULL) 1189 goto fail; 1190 nvlist_set_parent(tmpnvl, nvp); 1191 break; 1192 #if !defined(_KERNEL) && !defined(_STANDALONE) && !defined(__NetBSD__) 1193 case NV_TYPE_DESCRIPTOR: 1194 ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left, 1195 fds, nfds); 1196 break; 1197 case NV_TYPE_DESCRIPTOR_ARRAY: 1198 ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr, 1199 &left, fds, nfds); 1200 break; 1201 #endif 1202 case NV_TYPE_BINARY: 1203 ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left); 1204 break; 1205 case NV_TYPE_NVLIST_UP: 1206 if (nvl->nvl_parent == NULL) 1207 goto fail; 1208 nvl = nvpair_nvlist(nvl->nvl_parent); 1209 nvpair_free_structure(nvp); 1210 continue; 1211 case NV_TYPE_NVLIST_ARRAY_NEXT: 1212 if (nvl->nvl_array_next == NULL) { 1213 if (nvl->nvl_parent == NULL) 1214 goto fail; 1215 nvl = nvpair_nvlist(nvl->nvl_parent); 1216 } else { 1217 nvl = __DECONST(nvlist_t *, 1218 nvlist_get_array_next(nvl)); 1219 ptr = nvlist_unpack_header(nvl, ptr, nfds, 1220 &isbe, &left); 1221 if (ptr == NULL) 1222 goto fail; 1223 } 1224 nvpair_free_structure(nvp); 1225 continue; 1226 case NV_TYPE_BOOL_ARRAY: 1227 ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left); 1228 break; 1229 case NV_TYPE_NUMBER_ARRAY: 1230 ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left); 1231 break; 1232 case NV_TYPE_STRING_ARRAY: 1233 ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left); 1234 break; 1235 case NV_TYPE_NVLIST_ARRAY: 1236 ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left, 1237 &array); 1238 if (ptr == NULL) 1239 goto fail; 1240 PJDLOG_ASSERT(array != NULL); 1241 tmpnvl = array; 1242 do { 1243 nvlist_set_parent(array, nvp); 1244 array = __DECONST(nvlist_t *, 1245 nvlist_get_array_next(array)); 1246 } while (array != NULL); 1247 ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe, 1248 &left); 1249 break; 1250 default: 1251 PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 1252 } 1253 if (ptr == NULL) 1254 goto fail; 1255 if (!nvlist_move_nvpair(nvl, nvp)) 1256 goto fail; 1257 if (tmpnvl != NULL) { 1258 nvl = tmpnvl; 1259 tmpnvl = NULL; 1260 } 1261 } 1262 1263 return (retnvl); 1264 fail: 1265 nvlist_destroy(retnvl); 1266 return (NULL); 1267 } 1268 1269 nvlist_t * 1270 nvlist_unpack(const void *buf, size_t size, int flags) 1271 { 1272 1273 return (nvlist_xunpack(buf, size, NULL, 0, flags)); 1274 } 1275 1276 #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(WITH_MSGIO) 1277 int 1278 nvlist_send(int sock, const nvlist_t *nvl) 1279 { 1280 size_t datasize, nfds; 1281 int *fds; 1282 void *data; 1283 int64_t fdidx; 1284 int ret; 1285 1286 if (nvlist_error(nvl) != 0) { 1287 ERRNO_SET(nvlist_error(nvl)); 1288 return (-1); 1289 } 1290 1291 fds = nvlist_descriptors(nvl, &nfds); 1292 if (fds == NULL) 1293 return (-1); 1294 1295 ret = -1; 1296 fdidx = 0; 1297 1298 data = nvlist_xpack(nvl, &fdidx, &datasize); 1299 if (data == NULL) 1300 goto out; 1301 1302 if (buf_send(sock, data, datasize) == -1) 1303 goto out; 1304 1305 if (nfds > 0) { 1306 if (fd_send(sock, fds, nfds) == -1) 1307 goto out; 1308 } 1309 1310 ret = 0; 1311 out: 1312 ERRNO_SAVE(); 1313 nv_free(fds); 1314 nv_free(data); 1315 ERRNO_RESTORE(); 1316 return (ret); 1317 } 1318 1319 nvlist_t * 1320 nvlist_recv(int sock, int flags) 1321 { 1322 struct nvlist_header nvlhdr; 1323 nvlist_t *nvl, *ret; 1324 unsigned char *buf; 1325 size_t nfds, size, i; 1326 int *fds; 1327 1328 if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1) 1329 return (NULL); 1330 1331 if (!nvlist_check_header(&nvlhdr)) 1332 return (NULL); 1333 1334 nfds = (size_t)nvlhdr.nvlh_descriptors; 1335 size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size; 1336 1337 buf = nv_malloc(size); 1338 if (buf == NULL) 1339 return (NULL); 1340 1341 memcpy(buf, &nvlhdr, sizeof(nvlhdr)); 1342 1343 ret = NULL; 1344 fds = NULL; 1345 1346 if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1) 1347 goto out; 1348 1349 if (nfds > 0) { 1350 fds = nv_malloc(nfds * sizeof(fds[0])); 1351 if (fds == NULL) 1352 goto out; 1353 if (fd_recv(sock, fds, nfds) == -1) 1354 goto out; 1355 } 1356 1357 nvl = nvlist_xunpack(buf, size, fds, nfds, flags); 1358 if (nvl == NULL) { 1359 ERRNO_SAVE(); 1360 for (i = 0; i < nfds; i++) 1361 close(fds[i]); 1362 ERRNO_RESTORE(); 1363 goto out; 1364 } 1365 1366 ret = nvl; 1367 out: 1368 ERRNO_SAVE(); 1369 nv_free(buf); 1370 nv_free(fds); 1371 ERRNO_RESTORE(); 1372 1373 return (ret); 1374 } 1375 1376 nvlist_t * 1377 nvlist_xfer(int sock, nvlist_t *nvl, int flags) 1378 { 1379 1380 if (nvlist_send(sock, nvl) < 0) { 1381 nvlist_destroy(nvl); 1382 return (NULL); 1383 } 1384 nvlist_destroy(nvl); 1385 return (nvlist_recv(sock, flags)); 1386 } 1387 #endif 1388 1389 nvpair_t * 1390 nvlist_first_nvpair(const nvlist_t *nvl) 1391 { 1392 1393 NVLIST_ASSERT(nvl); 1394 1395 return (TAILQ_FIRST(&nvl->nvl_head)); 1396 } 1397 1398 nvpair_t * 1399 nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 1400 { 1401 nvpair_t *retnvp; 1402 1403 NVLIST_ASSERT(nvl); 1404 NVPAIR_ASSERT(nvp); 1405 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 1406 1407 retnvp = nvpair_next(nvp); 1408 PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl); 1409 1410 return (retnvp); 1411 1412 } 1413 1414 nvpair_t * 1415 nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 1416 { 1417 nvpair_t *retnvp; 1418 1419 NVLIST_ASSERT(nvl); 1420 NVPAIR_ASSERT(nvp); 1421 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 1422 1423 retnvp = nvpair_prev(nvp); 1424 PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl); 1425 1426 return (retnvp); 1427 } 1428 1429 const char * 1430 nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep) 1431 { 1432 nvpair_t *nvp; 1433 1434 NVLIST_ASSERT(nvl); 1435 1436 if (cookiep == NULL || *cookiep == NULL) 1437 nvp = nvlist_first_nvpair(nvl); 1438 else 1439 nvp = nvlist_next_nvpair(nvl, *cookiep); 1440 if (nvp == NULL) 1441 return (NULL); 1442 if (typep != NULL) 1443 *typep = nvpair_type(nvp); 1444 if (cookiep != NULL) 1445 *cookiep = nvp; 1446 return (nvpair_name(nvp)); 1447 } 1448 1449 bool 1450 nvlist_exists(const nvlist_t *nvl, const char *name) 1451 { 1452 1453 return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL); 1454 } 1455 1456 #define NVLIST_EXISTS(type, TYPE) \ 1457 bool \ 1458 nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ 1459 { \ 1460 \ 1461 return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \ 1462 } 1463 1464 NVLIST_EXISTS(null, NULL) 1465 NVLIST_EXISTS(bool, BOOL) 1466 NVLIST_EXISTS(number, NUMBER) 1467 NVLIST_EXISTS(string, STRING) 1468 NVLIST_EXISTS(nvlist, NVLIST) 1469 NVLIST_EXISTS(binary, BINARY) 1470 NVLIST_EXISTS(bool_array, BOOL_ARRAY) 1471 NVLIST_EXISTS(number_array, NUMBER_ARRAY) 1472 NVLIST_EXISTS(string_array, STRING_ARRAY) 1473 NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY) 1474 #if !defined(_KERNEL) && !defined(_STANDALONE) 1475 NVLIST_EXISTS(descriptor, DESCRIPTOR) 1476 NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY) 1477 #endif 1478 1479 #undef NVLIST_EXISTS 1480 1481 void 1482 nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) 1483 { 1484 nvpair_t *newnvp; 1485 1486 NVPAIR_ASSERT(nvp); 1487 1488 if (nvlist_error(nvl) != 0) { 1489 ERRNO_SET(nvlist_error(nvl)); 1490 return; 1491 } 1492 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { 1493 if (nvlist_exists(nvl, nvpair_name(nvp))) { 1494 nvl->nvl_error = EEXIST; 1495 ERRNO_SET(nvlist_error(nvl)); 1496 return; 1497 } 1498 } 1499 1500 newnvp = nvpair_clone(nvp); 1501 if (newnvp == NULL) { 1502 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1503 ERRNO_SET(nvlist_error(nvl)); 1504 return; 1505 } 1506 1507 nvpair_insert(&nvl->nvl_head, newnvp, nvl); 1508 } 1509 1510 #if !defined(_STANDALONE) 1511 void 1512 nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) 1513 { 1514 va_list valueap; 1515 1516 va_start(valueap, valuefmt); 1517 nvlist_add_stringv(nvl, name, valuefmt, valueap); 1518 va_end(valueap); 1519 } 1520 1521 void 1522 nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, 1523 va_list valueap) 1524 { 1525 nvpair_t *nvp; 1526 1527 if (nvlist_error(nvl) != 0) { 1528 ERRNO_SET(nvlist_error(nvl)); 1529 return; 1530 } 1531 1532 nvp = nvpair_create_stringv(name, valuefmt, valueap); 1533 if (nvp == NULL) { 1534 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1535 ERRNO_SET(nvl->nvl_error); 1536 } else { 1537 (void)nvlist_move_nvpair(nvl, nvp); 1538 } 1539 } 1540 #endif 1541 1542 void 1543 nvlist_add_null(nvlist_t *nvl, const char *name) 1544 { 1545 nvpair_t *nvp; 1546 1547 if (nvlist_error(nvl) != 0) { 1548 ERRNO_SET(nvlist_error(nvl)); 1549 return; 1550 } 1551 1552 nvp = nvpair_create_null(name); 1553 if (nvp == NULL) { 1554 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1555 ERRNO_SET(nvl->nvl_error); 1556 } else { 1557 (void)nvlist_move_nvpair(nvl, nvp); 1558 } 1559 } 1560 1561 void 1562 nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, 1563 size_t size) 1564 { 1565 nvpair_t *nvp; 1566 1567 if (nvlist_error(nvl) != 0) { 1568 ERRNO_SET(nvlist_error(nvl)); 1569 return; 1570 } 1571 1572 nvp = nvpair_create_binary(name, value, size); 1573 if (nvp == NULL) { 1574 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1575 ERRNO_SET(nvl->nvl_error); 1576 } else { 1577 (void)nvlist_move_nvpair(nvl, nvp); 1578 } 1579 } 1580 1581 1582 #define NVLIST_ADD(vtype, type) \ 1583 void \ 1584 nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \ 1585 { \ 1586 nvpair_t *nvp; \ 1587 \ 1588 if (nvlist_error(nvl) != 0) { \ 1589 ERRNO_SET(nvlist_error(nvl)); \ 1590 return; \ 1591 } \ 1592 \ 1593 nvp = nvpair_create_##type(name, value); \ 1594 if (nvp == NULL) { \ 1595 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 1596 ERRNO_SET(nvl->nvl_error); \ 1597 } else { \ 1598 (void)nvlist_move_nvpair(nvl, nvp); \ 1599 } \ 1600 } 1601 1602 NVLIST_ADD(bool, bool) 1603 NVLIST_ADD(uint64_t, number) 1604 NVLIST_ADD(const char *, string) 1605 NVLIST_ADD(const nvlist_t *, nvlist) 1606 #if !defined(_KERNEL) && !defined(_STANDALONE) 1607 NVLIST_ADD(int, descriptor); 1608 #endif 1609 1610 #undef NVLIST_ADD 1611 1612 #define NVLIST_ADD_ARRAY(vtype, type) \ 1613 void \ 1614 nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value, \ 1615 size_t nitems) \ 1616 { \ 1617 nvpair_t *nvp; \ 1618 \ 1619 if (nvlist_error(nvl) != 0) { \ 1620 ERRNO_SET(nvlist_error(nvl)); \ 1621 return; \ 1622 } \ 1623 \ 1624 nvp = nvpair_create_##type##_array(name, value, nitems); \ 1625 if (nvp == NULL) { \ 1626 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 1627 ERRNO_SET(nvl->nvl_error); \ 1628 } else { \ 1629 (void)nvlist_move_nvpair(nvl, nvp); \ 1630 } \ 1631 } 1632 1633 NVLIST_ADD_ARRAY(const bool *, bool) 1634 NVLIST_ADD_ARRAY(const uint64_t *, number) 1635 NVLIST_ADD_ARRAY(const char * const *, string) 1636 NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist) 1637 #if !defined(_KERNEL) && !defined(_STANDALONE) 1638 NVLIST_ADD_ARRAY(const int *, descriptor) 1639 #endif 1640 1641 #undef NVLIST_ADD_ARRAY 1642 1643 #define NVLIST_APPEND_ARRAY(vtype, type, TYPE) \ 1644 void \ 1645 nvlist_append_##type##_array(nvlist_t *nvl, const char *name, vtype value)\ 1646 { \ 1647 nvpair_t *nvp; \ 1648 \ 1649 if (nvlist_error(nvl) != 0) { \ 1650 ERRNO_SET(nvlist_error(nvl)); \ 1651 return; \ 1652 } \ 1653 nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 1654 if (nvp == NULL) { \ 1655 nvlist_add_##type##_array(nvl, name, &value, 1); \ 1656 return; \ 1657 } \ 1658 if (nvpair_append_##type##_array(nvp, value) == -1) { \ 1659 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 1660 ERRNO_SET(nvl->nvl_error); \ 1661 } \ 1662 } 1663 1664 NVLIST_APPEND_ARRAY(const bool, bool, BOOL) 1665 NVLIST_APPEND_ARRAY(const uint64_t, number, NUMBER) 1666 NVLIST_APPEND_ARRAY(const char *, string, STRING) 1667 NVLIST_APPEND_ARRAY(const nvlist_t *, nvlist, NVLIST) 1668 #if !defined(_KERNEL) && !defined(_STANDALONE) 1669 NVLIST_APPEND_ARRAY(const int, descriptor, DESCRIPTOR) 1670 #endif 1671 1672 #undef NVLIST_APPEND_ARRAY 1673 1674 bool 1675 nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1676 { 1677 1678 NVPAIR_ASSERT(nvp); 1679 PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); 1680 1681 if (nvlist_error(nvl) != 0) { 1682 nvpair_free(nvp); 1683 ERRNO_SET(nvlist_error(nvl)); 1684 return (false); 1685 } 1686 if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { 1687 if (nvlist_exists(nvl, nvpair_name(nvp))) { 1688 nvpair_free(nvp); 1689 nvl->nvl_error = EEXIST; 1690 ERRNO_SET(nvl->nvl_error); 1691 return (false); 1692 } 1693 } 1694 1695 nvpair_insert(&nvl->nvl_head, nvp, nvl); 1696 return (true); 1697 } 1698 1699 void 1700 nvlist_move_string(nvlist_t *nvl, const char *name, char *value) 1701 { 1702 nvpair_t *nvp; 1703 1704 if (nvlist_error(nvl) != 0) { 1705 nv_free(value); 1706 ERRNO_SET(nvlist_error(nvl)); 1707 return; 1708 } 1709 1710 nvp = nvpair_move_string(name, value); 1711 if (nvp == NULL) { 1712 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1713 ERRNO_SET(nvl->nvl_error); 1714 } else { 1715 (void)nvlist_move_nvpair(nvl, nvp); 1716 } 1717 } 1718 1719 void 1720 nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value) 1721 { 1722 nvpair_t *nvp; 1723 1724 if (nvlist_error(nvl) != 0) { 1725 if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) 1726 nvlist_destroy(value); 1727 ERRNO_SET(nvlist_error(nvl)); 1728 return; 1729 } 1730 1731 nvp = nvpair_move_nvlist(name, value); 1732 if (nvp == NULL) { 1733 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1734 ERRNO_SET(nvl->nvl_error); 1735 } else { 1736 (void)nvlist_move_nvpair(nvl, nvp); 1737 } 1738 } 1739 1740 #if !defined(_KERNEL) && !defined(_STANDALONE) 1741 void 1742 nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value) 1743 { 1744 nvpair_t *nvp; 1745 1746 if (nvlist_error(nvl) != 0) { 1747 close(value); 1748 ERRNO_SET(nvlist_error(nvl)); 1749 return; 1750 } 1751 1752 nvp = nvpair_move_descriptor(name, value); 1753 if (nvp == NULL) { 1754 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1755 ERRNO_SET(nvl->nvl_error); 1756 } else { 1757 (void)nvlist_move_nvpair(nvl, nvp); 1758 } 1759 } 1760 #endif 1761 1762 void 1763 nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size) 1764 { 1765 nvpair_t *nvp; 1766 1767 if (nvlist_error(nvl) != 0) { 1768 nv_free(value); 1769 ERRNO_SET(nvlist_error(nvl)); 1770 return; 1771 } 1772 1773 nvp = nvpair_move_binary(name, value, size); 1774 if (nvp == NULL) { 1775 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1776 ERRNO_SET(nvl->nvl_error); 1777 } else { 1778 (void)nvlist_move_nvpair(nvl, nvp); 1779 } 1780 } 1781 1782 void 1783 nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value, 1784 size_t nitems) 1785 { 1786 nvpair_t *nvp; 1787 1788 if (nvlist_error(nvl) != 0) { 1789 nv_free(value); 1790 ERRNO_SET(nvlist_error(nvl)); 1791 return; 1792 } 1793 1794 nvp = nvpair_move_bool_array(name, value, nitems); 1795 if (nvp == NULL) { 1796 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1797 ERRNO_SET(nvl->nvl_error); 1798 } else { 1799 (void)nvlist_move_nvpair(nvl, nvp); 1800 } 1801 } 1802 1803 void 1804 nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value, 1805 size_t nitems) 1806 { 1807 nvpair_t *nvp; 1808 size_t i; 1809 1810 if (nvlist_error(nvl) != 0) { 1811 if (value != NULL) { 1812 for (i = 0; i < nitems; i++) 1813 nv_free(value[i]); 1814 nv_free(value); 1815 } 1816 ERRNO_SET(nvlist_error(nvl)); 1817 return; 1818 } 1819 1820 nvp = nvpair_move_string_array(name, value, nitems); 1821 if (nvp == NULL) { 1822 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1823 ERRNO_SET(nvl->nvl_error); 1824 } else { 1825 (void)nvlist_move_nvpair(nvl, nvp); 1826 } 1827 } 1828 1829 void 1830 nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value, 1831 size_t nitems) 1832 { 1833 nvpair_t *nvp; 1834 size_t i; 1835 1836 if (nvlist_error(nvl) != 0) { 1837 if (value != NULL) { 1838 for (i = 0; i < nitems; i++) { 1839 if (nvlist_get_pararr(value[i], NULL) == NULL) 1840 nvlist_destroy(value[i]); 1841 } 1842 } 1843 nv_free(value); 1844 ERRNO_SET(nvlist_error(nvl)); 1845 return; 1846 } 1847 1848 nvp = nvpair_move_nvlist_array(name, value, nitems); 1849 if (nvp == NULL) { 1850 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1851 ERRNO_SET(nvl->nvl_error); 1852 } else { 1853 (void)nvlist_move_nvpair(nvl, nvp); 1854 } 1855 } 1856 1857 void 1858 nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value, 1859 size_t nitems) 1860 { 1861 nvpair_t *nvp; 1862 1863 if (nvlist_error(nvl) != 0) { 1864 nv_free(value); 1865 ERRNO_SET(nvlist_error(nvl)); 1866 return; 1867 } 1868 1869 nvp = nvpair_move_number_array(name, value, nitems); 1870 if (nvp == NULL) { 1871 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1872 ERRNO_SET(nvl->nvl_error); 1873 } else { 1874 (void)nvlist_move_nvpair(nvl, nvp); 1875 } 1876 } 1877 1878 #if !defined(_KERNEL) && !defined(_STANDALONE) 1879 void 1880 nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value, 1881 size_t nitems) 1882 { 1883 nvpair_t *nvp; 1884 size_t i; 1885 1886 if (nvlist_error(nvl) != 0) { 1887 if (value != 0) { 1888 for (i = 0; i < nitems; i++) 1889 close(value[i]); 1890 nv_free(value); 1891 } 1892 1893 ERRNO_SET(nvlist_error(nvl)); 1894 return; 1895 } 1896 1897 nvp = nvpair_move_descriptor_array(name, value, nitems); 1898 if (nvp == NULL) { 1899 nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1900 ERRNO_SET(nvl->nvl_error); 1901 } else { 1902 (void)nvlist_move_nvpair(nvl, nvp); 1903 } 1904 } 1905 #endif 1906 1907 const nvpair_t * 1908 nvlist_get_nvpair(const nvlist_t *nvl, const char *name) 1909 { 1910 1911 return (nvlist_find(nvl, NV_TYPE_NONE, name)); 1912 } 1913 1914 #define NVLIST_GET(ftype, type, TYPE) \ 1915 ftype \ 1916 nvlist_get_##type(const nvlist_t *nvl, const char *name) \ 1917 { \ 1918 const nvpair_t *nvp; \ 1919 \ 1920 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 1921 if (nvp == NULL) \ 1922 nvlist_report_missing(NV_TYPE_##TYPE, name); \ 1923 return (nvpair_get_##type(nvp)); \ 1924 } 1925 1926 NVLIST_GET(bool, bool, BOOL) 1927 NVLIST_GET(uint64_t, number, NUMBER) 1928 NVLIST_GET(const char *, string, STRING) 1929 NVLIST_GET(const nvlist_t *, nvlist, NVLIST) 1930 #if !defined(_KERNEL) && !defined(_STANDALONE) 1931 NVLIST_GET(int, descriptor, DESCRIPTOR) 1932 #endif 1933 1934 #undef NVLIST_GET 1935 1936 const void * 1937 nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) 1938 { 1939 nvpair_t *nvp; 1940 1941 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 1942 if (nvp == NULL) 1943 nvlist_report_missing(NV_TYPE_BINARY, name); 1944 1945 return (nvpair_get_binary(nvp, sizep)); 1946 } 1947 1948 #define NVLIST_GET_ARRAY(ftype, type, TYPE) \ 1949 ftype \ 1950 nvlist_get_##type##_array(const nvlist_t *nvl, const char *name, \ 1951 size_t *nitems) \ 1952 { \ 1953 const nvpair_t *nvp; \ 1954 \ 1955 nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 1956 if (nvp == NULL) \ 1957 nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ 1958 return (nvpair_get_##type##_array(nvp, nitems)); \ 1959 } 1960 1961 NVLIST_GET_ARRAY(const bool *, bool, BOOL) 1962 NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER) 1963 NVLIST_GET_ARRAY(const char * const *, string, STRING) 1964 NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST) 1965 #if !defined(_KERNEL) && !defined(_STANDALONE) 1966 NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR) 1967 #endif 1968 1969 #undef NVLIST_GET_ARRAY 1970 1971 #define NVLIST_TAKE(ftype, type, TYPE) \ 1972 ftype \ 1973 nvlist_take_##type(nvlist_t *nvl, const char *name) \ 1974 { \ 1975 nvpair_t *nvp; \ 1976 ftype value; \ 1977 \ 1978 nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 1979 if (nvp == NULL) \ 1980 nvlist_report_missing(NV_TYPE_##TYPE, name); \ 1981 value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ 1982 nvlist_remove_nvpair(nvl, nvp); \ 1983 nvpair_free_structure(nvp); \ 1984 return (value); \ 1985 } 1986 1987 NVLIST_TAKE(bool, bool, BOOL) 1988 NVLIST_TAKE(uint64_t, number, NUMBER) 1989 NVLIST_TAKE(char *, string, STRING) 1990 NVLIST_TAKE(nvlist_t *, nvlist, NVLIST) 1991 #if !defined(_KERNEL) && !defined(_STANDALONE) 1992 NVLIST_TAKE(int, descriptor, DESCRIPTOR) 1993 #endif 1994 1995 #undef NVLIST_TAKE 1996 1997 void * 1998 nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) 1999 { 2000 nvpair_t *nvp; 2001 void *value; 2002 2003 nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 2004 if (nvp == NULL) 2005 nvlist_report_missing(NV_TYPE_BINARY, name); 2006 2007 value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); 2008 nvlist_remove_nvpair(nvl, nvp); 2009 nvpair_free_structure(nvp); 2010 return (value); 2011 } 2012 2013 #define NVLIST_TAKE_ARRAY(ftype, type, TYPE) \ 2014 ftype \ 2015 nvlist_take_##type##_array(nvlist_t *nvl, const char *name, \ 2016 size_t *nitems) \ 2017 { \ 2018 nvpair_t *nvp; \ 2019 ftype value; \ 2020 \ 2021 nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 2022 if (nvp == NULL) \ 2023 nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ 2024 value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\ 2025 nvlist_remove_nvpair(nvl, nvp); \ 2026 nvpair_free_structure(nvp); \ 2027 return (value); \ 2028 } 2029 2030 NVLIST_TAKE_ARRAY(bool *, bool, BOOL) 2031 NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER) 2032 NVLIST_TAKE_ARRAY(char **, string, STRING) 2033 NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST) 2034 #if !defined(_KERNEL) && !defined(_STANDALONE) 2035 NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR) 2036 #endif 2037 2038 void 2039 nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) 2040 { 2041 2042 NVLIST_ASSERT(nvl); 2043 NVPAIR_ASSERT(nvp); 2044 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 2045 2046 nvpair_remove(&nvl->nvl_head, nvp, nvl); 2047 } 2048 2049 void 2050 nvlist_free(nvlist_t *nvl, const char *name) 2051 { 2052 2053 nvlist_free_type(nvl, name, NV_TYPE_NONE); 2054 } 2055 2056 #define NVLIST_FREE(type, TYPE) \ 2057 void \ 2058 nvlist_free_##type(nvlist_t *nvl, const char *name) \ 2059 { \ 2060 \ 2061 nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ 2062 } 2063 2064 NVLIST_FREE(null, NULL) 2065 NVLIST_FREE(bool, BOOL) 2066 NVLIST_FREE(number, NUMBER) 2067 NVLIST_FREE(string, STRING) 2068 NVLIST_FREE(nvlist, NVLIST) 2069 NVLIST_FREE(binary, BINARY) 2070 NVLIST_FREE(bool_array, BOOL_ARRAY) 2071 NVLIST_FREE(number_array, NUMBER_ARRAY) 2072 NVLIST_FREE(string_array, STRING_ARRAY) 2073 NVLIST_FREE(nvlist_array, NVLIST_ARRAY) 2074 #if !defined(_KERNEL) && !defined(_STANDALONE) 2075 NVLIST_FREE(descriptor, DESCRIPTOR) 2076 NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY) 2077 #endif 2078 2079 #undef NVLIST_FREE 2080 2081 void 2082 nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) 2083 { 2084 2085 NVLIST_ASSERT(nvl); 2086 NVPAIR_ASSERT(nvp); 2087 PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 2088 2089 nvlist_remove_nvpair(nvl, nvp); 2090 nvpair_free(nvp); 2091 } 2092 2093