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