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