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