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