subr_nvpair.c revision 292973
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: stable/10/sys/kern/subr_nvpair.c 292973 2015-12-31 03:28:14Z ngie $"); 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/lock.h> 41#include <sys/malloc.h> 42#include <sys/systm.h> 43 44#include <machine/stdarg.h> 45 46#else 47#include <errno.h> 48#include <fcntl.h> 49#include <stdarg.h> 50#include <stdbool.h> 51#include <stdint.h> 52#include <stdlib.h> 53#include <string.h> 54#include <unistd.h> 55 56#include "common_impl.h" 57#endif 58 59#ifdef HAVE_PJDLOG 60#include <pjdlog.h> 61#endif 62 63#include <sys/nv.h> 64#include <sys/nv_impl.h> 65#include <sys/nvlist_impl.h> 66#include <sys/nvpair_impl.h> 67 68#ifndef HAVE_PJDLOG 69#ifdef _KERNEL 70#define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) 71#define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) 72#define PJDLOG_ABORT(...) panic(__VA_ARGS__) 73#else 74#include <assert.h> 75#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 76#define PJDLOG_RASSERT(expr, ...) assert(expr) 77#define PJDLOG_ABORT(...) abort() 78#endif 79#endif 80 81#define NVPAIR_MAGIC 0x6e7670 /* "nvp" */ 82struct nvpair { 83 int nvp_magic; 84 char *nvp_name; 85 int nvp_type; 86 uint64_t nvp_data; 87 size_t nvp_datasize; 88 nvlist_t *nvp_list; 89 TAILQ_ENTRY(nvpair) nvp_next; 90}; 91 92#define NVPAIR_ASSERT(nvp) do { \ 93 PJDLOG_ASSERT((nvp) != NULL); \ 94 PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \ 95} while (0) 96 97struct nvpair_header { 98 uint8_t nvph_type; 99 uint16_t nvph_namesize; 100 uint64_t nvph_datasize; 101} __packed; 102 103 104void 105nvpair_assert(const nvpair_t *nvp) 106{ 107 108 NVPAIR_ASSERT(nvp); 109} 110 111nvlist_t * 112nvpair_nvlist(const nvpair_t *nvp) 113{ 114 115 NVPAIR_ASSERT(nvp); 116 117 return (nvp->nvp_list); 118} 119 120nvpair_t * 121nvpair_next(const nvpair_t *nvp) 122{ 123 124 NVPAIR_ASSERT(nvp); 125 PJDLOG_ASSERT(nvp->nvp_list != NULL); 126 127 return (TAILQ_NEXT(nvp, nvp_next)); 128} 129 130nvpair_t * 131nvpair_prev(const nvpair_t *nvp) 132{ 133 134 NVPAIR_ASSERT(nvp); 135 PJDLOG_ASSERT(nvp->nvp_list != NULL); 136 137 return (TAILQ_PREV(nvp, nvl_head, nvp_next)); 138} 139 140void 141nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) 142{ 143 144 NVPAIR_ASSERT(nvp); 145 PJDLOG_ASSERT(nvp->nvp_list == NULL); 146 PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp))); 147 148 TAILQ_INSERT_TAIL(head, nvp, nvp_next); 149 nvp->nvp_list = nvl; 150} 151 152static void 153nvpair_remove_nvlist(nvpair_t *nvp) 154{ 155 nvlist_t *nvl; 156 157 /* XXX: DECONST is bad, mkay? */ 158 nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp)); 159 PJDLOG_ASSERT(nvl != NULL); 160 nvlist_set_parent(nvl, NULL); 161} 162 163void 164nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl) 165{ 166 167 NVPAIR_ASSERT(nvp); 168 PJDLOG_ASSERT(nvp->nvp_list == nvl); 169 170 if (nvpair_type(nvp) == NV_TYPE_NVLIST) 171 nvpair_remove_nvlist(nvp); 172 173 TAILQ_REMOVE(head, nvp, nvp_next); 174 nvp->nvp_list = NULL; 175} 176 177nvpair_t * 178nvpair_clone(const nvpair_t *nvp) 179{ 180 nvpair_t *newnvp; 181 const char *name; 182 const void *data; 183 size_t datasize; 184 185 NVPAIR_ASSERT(nvp); 186 187 name = nvpair_name(nvp); 188 189 switch (nvpair_type(nvp)) { 190 case NV_TYPE_NULL: 191 newnvp = nvpair_create_null(name); 192 break; 193 case NV_TYPE_BOOL: 194 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); 195 break; 196 case NV_TYPE_NUMBER: 197 newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); 198 break; 199 case NV_TYPE_STRING: 200 newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); 201 break; 202 case NV_TYPE_NVLIST: 203 newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); 204 break; 205#ifndef _KERNEL 206 case NV_TYPE_DESCRIPTOR: 207 newnvp = nvpair_create_descriptor(name, 208 nvpair_get_descriptor(nvp)); 209 break; 210#endif 211 case NV_TYPE_BINARY: 212 data = nvpair_get_binary(nvp, &datasize); 213 newnvp = nvpair_create_binary(name, data, datasize); 214 break; 215 default: 216 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 217 } 218 219 return (newnvp); 220} 221 222size_t 223nvpair_header_size(void) 224{ 225 226 return (sizeof(struct nvpair_header)); 227} 228 229size_t 230nvpair_size(const nvpair_t *nvp) 231{ 232 233 NVPAIR_ASSERT(nvp); 234 235 return (nvp->nvp_datasize); 236} 237 238unsigned char * 239nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 240{ 241 struct nvpair_header nvphdr; 242 size_t namesize; 243 244 NVPAIR_ASSERT(nvp); 245 246 nvphdr.nvph_type = nvp->nvp_type; 247 namesize = strlen(nvp->nvp_name) + 1; 248 PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX); 249 nvphdr.nvph_namesize = namesize; 250 nvphdr.nvph_datasize = nvp->nvp_datasize; 251 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 252 memcpy(ptr, &nvphdr, sizeof(nvphdr)); 253 ptr += sizeof(nvphdr); 254 *leftp -= sizeof(nvphdr); 255 256 PJDLOG_ASSERT(*leftp >= namesize); 257 memcpy(ptr, nvp->nvp_name, namesize); 258 ptr += namesize; 259 *leftp -= namesize; 260 261 return (ptr); 262} 263 264unsigned char * 265nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr, 266 size_t *leftp __unused) 267{ 268 269 NVPAIR_ASSERT(nvp); 270 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 271 272 return (ptr); 273} 274 275unsigned char * 276nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 277{ 278 uint8_t value; 279 280 NVPAIR_ASSERT(nvp); 281 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 282 283 value = (uint8_t)nvp->nvp_data; 284 285 PJDLOG_ASSERT(*leftp >= sizeof(value)); 286 memcpy(ptr, &value, sizeof(value)); 287 ptr += sizeof(value); 288 *leftp -= sizeof(value); 289 290 return (ptr); 291} 292 293unsigned char * 294nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 295{ 296 uint64_t value; 297 298 NVPAIR_ASSERT(nvp); 299 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 300 301 value = (uint64_t)nvp->nvp_data; 302 303 PJDLOG_ASSERT(*leftp >= sizeof(value)); 304 memcpy(ptr, &value, sizeof(value)); 305 ptr += sizeof(value); 306 *leftp -= sizeof(value); 307 308 return (ptr); 309} 310 311unsigned char * 312nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 313{ 314 315 NVPAIR_ASSERT(nvp); 316 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 317 318 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 319 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 320 ptr += nvp->nvp_datasize; 321 *leftp -= nvp->nvp_datasize; 322 323 return (ptr); 324} 325 326unsigned char * 327nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp) 328{ 329 struct nvpair_header nvphdr; 330 size_t namesize; 331 const char *name = ""; 332 333 namesize = 1; 334 nvphdr.nvph_type = NV_TYPE_NVLIST_UP; 335 nvphdr.nvph_namesize = namesize; 336 nvphdr.nvph_datasize = 0; 337 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 338 memcpy(ptr, &nvphdr, sizeof(nvphdr)); 339 ptr += sizeof(nvphdr); 340 *leftp -= sizeof(nvphdr); 341 342 PJDLOG_ASSERT(*leftp >= namesize); 343 memcpy(ptr, name, namesize); 344 ptr += namesize; 345 *leftp -= namesize; 346 347 return (ptr); 348} 349 350#ifndef _KERNEL 351unsigned char * 352nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, 353 size_t *leftp) 354{ 355 int64_t value; 356 357 NVPAIR_ASSERT(nvp); 358 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 359 360 value = (int64_t)nvp->nvp_data; 361 if (value != -1) { 362 /* 363 * If there is a real descriptor here, we change its number 364 * to position in the array of descriptors send via control 365 * message. 366 */ 367 PJDLOG_ASSERT(fdidxp != NULL); 368 369 value = *fdidxp; 370 (*fdidxp)++; 371 } 372 373 PJDLOG_ASSERT(*leftp >= sizeof(value)); 374 memcpy(ptr, &value, sizeof(value)); 375 ptr += sizeof(value); 376 *leftp -= sizeof(value); 377 378 return (ptr); 379} 380#endif 381 382unsigned char * 383nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 384{ 385 386 NVPAIR_ASSERT(nvp); 387 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 388 389 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 390 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 391 ptr += nvp->nvp_datasize; 392 *leftp -= nvp->nvp_datasize; 393 394 return (ptr); 395} 396 397void 398nvpair_init_datasize(nvpair_t *nvp) 399{ 400 401 NVPAIR_ASSERT(nvp); 402 403 if (nvp->nvp_type == NV_TYPE_NVLIST) { 404 if (nvp->nvp_data == 0) { 405 nvp->nvp_datasize = 0; 406 } else { 407 nvp->nvp_datasize = 408 nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); 409 } 410 } 411} 412 413const unsigned char * 414nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 415 size_t *leftp) 416{ 417 struct nvpair_header nvphdr; 418 419 if (*leftp < sizeof(nvphdr)) 420 goto failed; 421 422 memcpy(&nvphdr, ptr, sizeof(nvphdr)); 423 ptr += sizeof(nvphdr); 424 *leftp -= sizeof(nvphdr); 425 426#if NV_TYPE_FIRST > 0 427 if (nvphdr.nvph_type < NV_TYPE_FIRST) 428 goto failed; 429#endif 430 if (nvphdr.nvph_type > NV_TYPE_LAST && 431 nvphdr.nvph_type != NV_TYPE_NVLIST_UP) { 432 goto failed; 433 } 434 435#if BYTE_ORDER == BIG_ENDIAN 436 if (!isbe) { 437 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize); 438 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize); 439 } 440#else 441 if (isbe) { 442 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); 443 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); 444 } 445#endif 446 447 if (nvphdr.nvph_namesize > NV_NAME_MAX) 448 goto failed; 449 if (*leftp < nvphdr.nvph_namesize) 450 goto failed; 451 if (nvphdr.nvph_namesize < 1) 452 goto failed; 453 if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != 454 (size_t)(nvphdr.nvph_namesize - 1)) { 455 goto failed; 456 } 457 458 memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); 459 ptr += nvphdr.nvph_namesize; 460 *leftp -= nvphdr.nvph_namesize; 461 462 if (*leftp < nvphdr.nvph_datasize) 463 goto failed; 464 465 nvp->nvp_type = nvphdr.nvph_type; 466 nvp->nvp_data = 0; 467 nvp->nvp_datasize = nvphdr.nvph_datasize; 468 469 return (ptr); 470failed: 471 RESTORE_ERRNO(EINVAL); 472 return (NULL); 473} 474 475const unsigned char * 476nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, 477 size_t *leftp __unused) 478{ 479 480 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 481 482 if (nvp->nvp_datasize != 0) { 483 RESTORE_ERRNO(EINVAL); 484 return (NULL); 485 } 486 487 return (ptr); 488} 489 490const unsigned char * 491nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, 492 size_t *leftp) 493{ 494 uint8_t value; 495 496 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 497 498 if (nvp->nvp_datasize != sizeof(value)) { 499 RESTORE_ERRNO(EINVAL); 500 return (NULL); 501 } 502 if (*leftp < sizeof(value)) { 503 RESTORE_ERRNO(EINVAL); 504 return (NULL); 505 } 506 507 memcpy(&value, ptr, sizeof(value)); 508 ptr += sizeof(value); 509 *leftp -= sizeof(value); 510 511 if (value != 0 && value != 1) { 512 RESTORE_ERRNO(EINVAL); 513 return (NULL); 514 } 515 516 nvp->nvp_data = (uint64_t)value; 517 518 return (ptr); 519} 520 521const unsigned char * 522nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 523 size_t *leftp) 524{ 525 526 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 527 528 if (nvp->nvp_datasize != sizeof(uint64_t)) { 529 RESTORE_ERRNO(EINVAL); 530 return (NULL); 531 } 532 if (*leftp < sizeof(uint64_t)) { 533 RESTORE_ERRNO(EINVAL); 534 return (NULL); 535 } 536 537 if (isbe) 538 nvp->nvp_data = be64dec(ptr); 539 else 540 nvp->nvp_data = le64dec(ptr); 541 ptr += sizeof(uint64_t); 542 *leftp -= sizeof(uint64_t); 543 544 return (ptr); 545} 546 547const unsigned char * 548nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp, 549 const unsigned char *ptr, size_t *leftp) 550{ 551 552 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 553 554 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 555 RESTORE_ERRNO(EINVAL); 556 return (NULL); 557 } 558 559 if (strnlen((const char *)ptr, nvp->nvp_datasize) != 560 nvp->nvp_datasize - 1) { 561 RESTORE_ERRNO(EINVAL); 562 return (NULL); 563 } 564 565 nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr); 566 if (nvp->nvp_data == 0) 567 return (NULL); 568 569 ptr += nvp->nvp_datasize; 570 *leftp -= nvp->nvp_datasize; 571 572 return (ptr); 573} 574 575const unsigned char * 576nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp, 577 const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child) 578{ 579 nvlist_t *value; 580 581 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 582 583 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 584 RESTORE_ERRNO(EINVAL); 585 return (NULL); 586 } 587 588 value = nvlist_create(0); 589 if (value == NULL) 590 return (NULL); 591 592 ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp); 593 if (ptr == NULL) 594 return (NULL); 595 596 nvp->nvp_data = (uint64_t)(uintptr_t)value; 597 *child = value; 598 599 return (ptr); 600} 601 602#ifndef _KERNEL 603const unsigned char * 604nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 605 size_t *leftp, const int *fds, size_t nfds) 606{ 607 int64_t idx; 608 609 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 610 611 if (nvp->nvp_datasize != sizeof(idx)) { 612 errno = EINVAL; 613 return (NULL); 614 } 615 if (*leftp < sizeof(idx)) { 616 errno = EINVAL; 617 return (NULL); 618 } 619 620 if (isbe) 621 idx = be64dec(ptr); 622 else 623 idx = le64dec(ptr); 624 625 if (idx < 0) { 626 errno = EINVAL; 627 return (NULL); 628 } 629 630 if ((size_t)idx >= nfds) { 631 errno = EINVAL; 632 return (NULL); 633 } 634 635 nvp->nvp_data = (uint64_t)fds[idx]; 636 637 ptr += sizeof(idx); 638 *leftp -= sizeof(idx); 639 640 return (ptr); 641} 642#endif 643 644const unsigned char * 645nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp, 646 const unsigned char *ptr, size_t *leftp) 647{ 648 void *value; 649 650 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 651 652 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 653 RESTORE_ERRNO(EINVAL); 654 return (NULL); 655 } 656 657 value = nv_malloc(nvp->nvp_datasize); 658 if (value == NULL) 659 return (NULL); 660 661 memcpy(value, ptr, nvp->nvp_datasize); 662 ptr += nvp->nvp_datasize; 663 *leftp -= nvp->nvp_datasize; 664 665 nvp->nvp_data = (uint64_t)(uintptr_t)value; 666 667 return (ptr); 668} 669 670const unsigned char * 671nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, 672 nvpair_t **nvpp) 673{ 674 nvpair_t *nvp, *tmp; 675 676 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); 677 if (nvp == NULL) 678 return (NULL); 679 nvp->nvp_name = (char *)(nvp + 1); 680 681 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); 682 if (ptr == NULL) 683 goto failed; 684 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 685 if (tmp == NULL) 686 goto failed; 687 nvp = tmp; 688 689 /* Update nvp_name after realloc(). */ 690 nvp->nvp_name = (char *)(nvp + 1); 691 nvp->nvp_data = 0x00; 692 nvp->nvp_magic = NVPAIR_MAGIC; 693 *nvpp = nvp; 694 return (ptr); 695failed: 696 nv_free(nvp); 697 return (NULL); 698} 699 700int 701nvpair_type(const nvpair_t *nvp) 702{ 703 704 NVPAIR_ASSERT(nvp); 705 706 return (nvp->nvp_type); 707} 708 709const char * 710nvpair_name(const nvpair_t *nvp) 711{ 712 713 NVPAIR_ASSERT(nvp); 714 715 return (nvp->nvp_name); 716} 717 718static nvpair_t * 719nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize) 720{ 721 nvpair_t *nvp; 722 size_t namelen; 723 724 PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); 725 726 namelen = strlen(name); 727 if (namelen >= NV_NAME_MAX) { 728 RESTORE_ERRNO(ENAMETOOLONG); 729 return (NULL); 730 } 731 732 nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1); 733 if (nvp != NULL) { 734 nvp->nvp_name = (char *)(nvp + 1); 735 memcpy(nvp->nvp_name, name, namelen); 736 nvp->nvp_name[namelen + 1] = '\0'; 737 nvp->nvp_type = type; 738 nvp->nvp_data = data; 739 nvp->nvp_datasize = datasize; 740 nvp->nvp_magic = NVPAIR_MAGIC; 741 } 742 743 return (nvp); 744}; 745 746nvpair_t * 747nvpair_create_stringf(const char *name, const char *valuefmt, ...) 748{ 749 va_list valueap; 750 nvpair_t *nvp; 751 752 va_start(valueap, valuefmt); 753 nvp = nvpair_create_stringv(name, valuefmt, valueap); 754 va_end(valueap); 755 756 return (nvp); 757} 758 759nvpair_t * 760nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 761{ 762 nvpair_t *nvp; 763 char *str; 764 int len; 765 766 len = nv_vasprintf(&str, valuefmt, valueap); 767 if (len < 0) 768 return (NULL); 769 nvp = nvpair_create_string(name, str); 770 if (nvp == NULL) 771 nv_free(str); 772 return (nvp); 773} 774 775nvpair_t * 776nvpair_create_null(const char *name) 777{ 778 779 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0)); 780} 781 782nvpair_t * 783nvpair_create_bool(const char *name, bool value) 784{ 785 786 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0, 787 sizeof(uint8_t))); 788} 789 790nvpair_t * 791nvpair_create_number(const char *name, uint64_t value) 792{ 793 794 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value))); 795} 796 797nvpair_t * 798nvpair_create_string(const char *name, const char *value) 799{ 800 nvpair_t *nvp; 801 size_t size; 802 char *data; 803 804 if (value == NULL) { 805 RESTORE_ERRNO(EINVAL); 806 return (NULL); 807 } 808 809 data = nv_strdup(value); 810 if (data == NULL) 811 return (NULL); 812 size = strlen(value) + 1; 813 814 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data, 815 size); 816 if (nvp == NULL) 817 nv_free(data); 818 819 return (nvp); 820} 821 822nvpair_t * 823nvpair_create_nvlist(const char *name, const nvlist_t *value) 824{ 825 nvlist_t *nvl; 826 nvpair_t *nvp; 827 828 if (value == NULL) { 829 RESTORE_ERRNO(EINVAL); 830 return (NULL); 831 } 832 833 nvl = nvlist_clone(value); 834 if (nvl == NULL) 835 return (NULL); 836 837 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0); 838 if (nvp == NULL) 839 nvlist_destroy(nvl); 840 else 841 nvlist_set_parent(nvl, nvp); 842 843 return (nvp); 844} 845 846#ifndef _KERNEL 847nvpair_t * 848nvpair_create_descriptor(const char *name, int value) 849{ 850 nvpair_t *nvp; 851 852 if (value < 0 || !fd_is_valid(value)) { 853 errno = EBADF; 854 return (NULL); 855 } 856 857 value = fcntl(value, F_DUPFD_CLOEXEC, 0); 858 if (value < 0) 859 return (NULL); 860 861 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 862 sizeof(int64_t)); 863 if (nvp == NULL) 864 close(value); 865 866 return (nvp); 867} 868#endif 869 870nvpair_t * 871nvpair_create_binary(const char *name, const void *value, size_t size) 872{ 873 nvpair_t *nvp; 874 void *data; 875 876 if (value == NULL || size == 0) { 877 RESTORE_ERRNO(EINVAL); 878 return (NULL); 879 } 880 881 data = nv_malloc(size); 882 if (data == NULL) 883 return (NULL); 884 memcpy(data, value, size); 885 886 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, 887 size); 888 if (nvp == NULL) 889 nv_free(data); 890 891 return (nvp); 892} 893 894nvpair_t * 895nvpair_move_string(const char *name, char *value) 896{ 897 nvpair_t *nvp; 898 int serrno; 899 900 if (value == NULL) { 901 RESTORE_ERRNO(EINVAL); 902 return (NULL); 903 } 904 905 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 906 strlen(value) + 1); 907 if (nvp == NULL) { 908 SAVE_ERRNO(serrno); 909 nv_free(value); 910 RESTORE_ERRNO(serrno); 911 } 912 913 return (nvp); 914} 915 916nvpair_t * 917nvpair_move_nvlist(const char *name, nvlist_t *value) 918{ 919 nvpair_t *nvp; 920 921 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { 922 RESTORE_ERRNO(EINVAL); 923 return (NULL); 924 } 925 926 if (nvlist_error(value) != 0) { 927 RESTORE_ERRNO(nvlist_error(value)); 928 nvlist_destroy(value); 929 return (NULL); 930 } 931 932 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 933 0); 934 if (nvp == NULL) 935 nvlist_destroy(value); 936 else 937 nvlist_set_parent(value, nvp); 938 939 return (nvp); 940} 941 942#ifndef _KERNEL 943nvpair_t * 944nvpair_move_descriptor(const char *name, int value) 945{ 946 nvpair_t *nvp; 947 int serrno; 948 949 if (value < 0 || !fd_is_valid(value)) { 950 errno = EBADF; 951 return (NULL); 952 } 953 954 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 955 sizeof(int64_t)); 956 if (nvp == NULL) { 957 serrno = errno; 958 close(value); 959 errno = serrno; 960 } 961 962 return (nvp); 963} 964#endif 965 966nvpair_t * 967nvpair_move_binary(const char *name, void *value, size_t size) 968{ 969 nvpair_t *nvp; 970 int serrno; 971 972 if (value == NULL || size == 0) { 973 RESTORE_ERRNO(EINVAL); 974 return (NULL); 975 } 976 977 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, 978 size); 979 if (nvp == NULL) { 980 SAVE_ERRNO(serrno); 981 nv_free(value); 982 RESTORE_ERRNO(serrno); 983 } 984 985 return (nvp); 986} 987 988bool 989nvpair_get_bool(const nvpair_t *nvp) 990{ 991 992 NVPAIR_ASSERT(nvp); 993 994 return (nvp->nvp_data == 1); 995} 996 997uint64_t 998nvpair_get_number(const nvpair_t *nvp) 999{ 1000 1001 NVPAIR_ASSERT(nvp); 1002 1003 return (nvp->nvp_data); 1004} 1005 1006const char * 1007nvpair_get_string(const nvpair_t *nvp) 1008{ 1009 1010 NVPAIR_ASSERT(nvp); 1011 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1012 1013 return ((const char *)(intptr_t)nvp->nvp_data); 1014} 1015 1016const nvlist_t * 1017nvpair_get_nvlist(const nvpair_t *nvp) 1018{ 1019 1020 NVPAIR_ASSERT(nvp); 1021 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1022 1023 return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1024} 1025 1026#ifndef _KERNEL 1027int 1028nvpair_get_descriptor(const nvpair_t *nvp) 1029{ 1030 1031 NVPAIR_ASSERT(nvp); 1032 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1033 1034 return ((int)nvp->nvp_data); 1035} 1036#endif 1037 1038const void * 1039nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1040{ 1041 1042 NVPAIR_ASSERT(nvp); 1043 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1044 1045 if (sizep != NULL) 1046 *sizep = nvp->nvp_datasize; 1047 return ((const void *)(intptr_t)nvp->nvp_data); 1048} 1049 1050void 1051nvpair_free(nvpair_t *nvp) 1052{ 1053 1054 NVPAIR_ASSERT(nvp); 1055 PJDLOG_ASSERT(nvp->nvp_list == NULL); 1056 1057 nvp->nvp_magic = 0; 1058 switch (nvp->nvp_type) { 1059#ifndef _KERNEL 1060 case NV_TYPE_DESCRIPTOR: 1061 close((int)nvp->nvp_data); 1062 break; 1063#endif 1064 case NV_TYPE_NVLIST: 1065 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 1066 break; 1067 case NV_TYPE_STRING: 1068 nv_free((char *)(intptr_t)nvp->nvp_data); 1069 break; 1070 case NV_TYPE_BINARY: 1071 nv_free((void *)(intptr_t)nvp->nvp_data); 1072 break; 1073 } 1074 nv_free(nvp); 1075} 1076 1077void 1078nvpair_free_structure(nvpair_t *nvp) 1079{ 1080 1081 NVPAIR_ASSERT(nvp); 1082 PJDLOG_ASSERT(nvp->nvp_list == NULL); 1083 1084 nvp->nvp_magic = 0; 1085 nv_free(nvp); 1086} 1087 1088const char * 1089nvpair_type_string(int type) 1090{ 1091 1092 switch (type) { 1093 case NV_TYPE_NULL: 1094 return ("NULL"); 1095 case NV_TYPE_BOOL: 1096 return ("BOOL"); 1097 case NV_TYPE_NUMBER: 1098 return ("NUMBER"); 1099 case NV_TYPE_STRING: 1100 return ("STRING"); 1101 case NV_TYPE_NVLIST: 1102 return ("NVLIST"); 1103 case NV_TYPE_DESCRIPTOR: 1104 return ("DESCRIPTOR"); 1105 case NV_TYPE_BINARY: 1106 return ("BINARY"); 1107 default: 1108 return ("<UNKNOWN>"); 1109 } 1110} 1111 1112