nvpair.c revision 303825
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 303825 2016-08-08 06:29:25Z 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 failed; 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 failed; 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 failed; 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 failed; 647 if (*leftp < nvphdr.nvph_namesize) 648 goto failed; 649 if (nvphdr.nvph_namesize < 1) 650 goto failed; 651 if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != 652 (size_t)(nvphdr.nvph_namesize - 1)) { 653 goto failed; 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 failed; 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); 669failed: 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 failed; 1112 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 1113 if (tmp == NULL) 1114 goto failed; 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); 1123failed: 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 *nvp; 1411 int flags; 1412 1413 nvp = NULL; 1414 nvls = NULL; 1415 ii = 0; 1416 1417 if (value == NULL || nitems == 0) { 1418 ERRNO_SET(EINVAL); 1419 return (NULL); 1420 } 1421 1422 nvls = nv_malloc(sizeof(value[0]) * nitems); 1423 if (nvls == NULL) 1424 return (NULL); 1425 1426 for (ii = 0; ii < nitems; ii++) { 1427 if (value[ii] == NULL) { 1428 ERRNO_SET(EINVAL); 1429 goto fail; 1430 } 1431 1432 nvls[ii] = nvlist_clone(value[ii]); 1433 if (nvls[ii] == NULL) 1434 goto fail; 1435 1436 if (ii > 0) { 1437 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1438 (uint64_t)(uintptr_t)nvls[ii], 0, 0); 1439 if (nvp == NULL) 1440 goto fail; 1441 nvlist_set_array_next(nvls[ii - 1], nvp); 1442 } 1443 } 1444 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY; 1445 nvlist_set_flags(nvls[nitems - 1], flags); 1446 1447 nvp = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1448 (uint64_t)(uintptr_t)nvls, 0, nitems); 1449 1450fail: 1451 if (nvp == NULL) { 1452 ERRNO_SAVE(); 1453 for (; ii > 0; ii--) 1454 nvlist_destroy(nvls[ii - 1]); 1455 1456 nv_free(nvls); 1457 ERRNO_RESTORE(); 1458 } else { 1459 for (ii = 0; ii < nitems; ii++) 1460 nvlist_set_parent(nvls[ii], nvp); 1461 } 1462 1463 return (nvp); 1464} 1465 1466#ifndef _KERNEL 1467nvpair_t * 1468nvpair_create_descriptor_array(const char *name, const int *value, 1469 size_t nitems) 1470{ 1471 unsigned int ii; 1472 nvpair_t *nvp; 1473 int *fds; 1474 1475 if (value == NULL) { 1476 ERRNO_SET(EINVAL); 1477 return (NULL); 1478 } 1479 1480 nvp = NULL; 1481 1482 fds = nv_malloc(sizeof(value[0]) * nitems); 1483 if (fds == NULL) 1484 return (NULL); 1485 for (ii = 0; ii < nitems; ii++) { 1486 if (value[ii] == -1) { 1487 fds[ii] = -1; 1488 } else { 1489 if (!fd_is_valid(value[ii])) { 1490 ERRNO_SET(EBADF); 1491 goto fail; 1492 } 1493 1494 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0); 1495 if (fds[ii] == -1) 1496 goto fail; 1497 } 1498 } 1499 1500 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1501 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems); 1502 1503fail: 1504 if (nvp == NULL) { 1505 ERRNO_SAVE(); 1506 for (; ii > 0; ii--) { 1507 if (fds[ii - 1] != -1) 1508 close(fds[ii - 1]); 1509 } 1510 nv_free(fds); 1511 ERRNO_RESTORE(); 1512 } 1513 1514 return (nvp); 1515} 1516#endif 1517 1518nvpair_t * 1519nvpair_move_string(const char *name, char *value) 1520{ 1521 nvpair_t *nvp; 1522 1523 if (value == NULL) { 1524 ERRNO_SET(EINVAL); 1525 return (NULL); 1526 } 1527 1528 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 1529 strlen(value) + 1, 0); 1530 if (nvp == NULL) { 1531 ERRNO_SAVE(); 1532 nv_free(value); 1533 ERRNO_RESTORE(); 1534 } 1535 1536 return (nvp); 1537} 1538 1539nvpair_t * 1540nvpair_move_nvlist(const char *name, nvlist_t *value) 1541{ 1542 nvpair_t *nvp; 1543 1544 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { 1545 ERRNO_SET(EINVAL); 1546 return (NULL); 1547 } 1548 1549 if (nvlist_error(value) != 0) { 1550 ERRNO_SET(nvlist_error(value)); 1551 nvlist_destroy(value); 1552 return (NULL); 1553 } 1554 1555 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 1556 0, 0); 1557 if (nvp == NULL) 1558 nvlist_destroy(value); 1559 else 1560 nvlist_set_parent(value, nvp); 1561 1562 return (nvp); 1563} 1564 1565#ifndef _KERNEL 1566nvpair_t * 1567nvpair_move_descriptor(const char *name, int value) 1568{ 1569 nvpair_t *nvp; 1570 1571 if (value < 0 || !fd_is_valid(value)) { 1572 ERRNO_SET(EBADF); 1573 return (NULL); 1574 } 1575 1576 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1577 sizeof(int64_t), 0); 1578 if (nvp == NULL) { 1579 ERRNO_SAVE(); 1580 close(value); 1581 ERRNO_RESTORE(); 1582 } 1583 1584 return (nvp); 1585} 1586#endif 1587 1588nvpair_t * 1589nvpair_move_binary(const char *name, void *value, size_t size) 1590{ 1591 nvpair_t *nvp; 1592 1593 if (value == NULL || size == 0) { 1594 ERRNO_SET(EINVAL); 1595 return (NULL); 1596 } 1597 1598 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, 1599 size, 0); 1600 if (nvp == NULL) { 1601 ERRNO_SAVE(); 1602 nv_free(value); 1603 ERRNO_RESTORE(); 1604 } 1605 1606 return (nvp); 1607} 1608 1609nvpair_t * 1610nvpair_move_bool_array(const char *name, bool *value, size_t nitems) 1611{ 1612 nvpair_t *nvp; 1613 1614 if (value == NULL || nitems == 0) { 1615 ERRNO_SET(EINVAL); 1616 return (NULL); 1617 } 1618 1619 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, 1620 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1621 if (nvp == NULL) { 1622 ERRNO_SAVE(); 1623 nv_free(value); 1624 ERRNO_RESTORE(); 1625 } 1626 1627 return (nvp); 1628} 1629 1630nvpair_t * 1631nvpair_move_string_array(const char *name, char **value, size_t nitems) 1632{ 1633 nvpair_t *nvp; 1634 size_t i, size; 1635 1636 if (value == NULL || nitems == 0) { 1637 ERRNO_SET(EINVAL); 1638 return (NULL); 1639 } 1640 1641 size = 0; 1642 for (i = 0; i < nitems; i++) { 1643 if (value[i] == NULL) { 1644 ERRNO_SET(EINVAL); 1645 return (NULL); 1646 } 1647 1648 size += strlen(value[i]) + 1; 1649 } 1650 1651 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1652 (uint64_t)(uintptr_t)value, size, nitems); 1653 if (nvp == NULL) { 1654 ERRNO_SAVE(); 1655 for (i = 0; i < nitems; i++) 1656 nv_free(value[i]); 1657 nv_free(value); 1658 ERRNO_RESTORE(); 1659 } 1660 1661 return (nvp); 1662} 1663 1664nvpair_t * 1665nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems) 1666{ 1667 nvpair_t *nvp; 1668 1669 if (value == NULL || nitems == 0) { 1670 ERRNO_SET(EINVAL); 1671 return (NULL); 1672 } 1673 1674 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1675 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1676 if (nvp == NULL) { 1677 ERRNO_SAVE(); 1678 nv_free(value); 1679 ERRNO_RESTORE(); 1680 } 1681 1682 return (nvp); 1683} 1684 1685nvpair_t * 1686nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems) 1687{ 1688 unsigned int ii; 1689 nvpair_t *nvp; 1690 int flags; 1691 1692 nvp = NULL; 1693 if (value == NULL || nitems == 0) { 1694 ERRNO_SET(EINVAL); 1695 return (NULL); 1696 } 1697 1698 for (ii = 0; ii < nitems; ii++) { 1699 if (value == NULL || nvlist_error(value[ii]) != 0 || 1700 nvlist_get_pararr(value[ii], NULL) != NULL) { 1701 ERRNO_SET(EINVAL); 1702 goto fail; 1703 } 1704 if (ii > 0) { 1705 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1706 (uint64_t)(uintptr_t)value[ii], 0, 0); 1707 if (nvp == NULL) 1708 goto fail; 1709 nvlist_set_array_next(value[ii - 1], nvp); 1710 } 1711 } 1712 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY; 1713 nvlist_set_flags(value[nitems - 1], flags); 1714 1715 nvp = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1716 (uint64_t)(uintptr_t)value, 0, nitems); 1717fail: 1718 if (nvp == NULL) { 1719 ERRNO_SAVE(); 1720 for (ii = 0; ii < nitems; ii++) { 1721 if (value[ii] != NULL && 1722 nvlist_get_pararr(value[ii], NULL) != NULL) { 1723 nvlist_destroy(value[ii]); 1724 } 1725 nv_free(value); 1726 } 1727 ERRNO_RESTORE(); 1728 } else { 1729 for (ii = 0; ii < nitems; ii++) 1730 nvlist_set_parent(value[ii], nvp); 1731 } 1732 1733 return (nvp); 1734} 1735 1736#ifndef _KERNEL 1737nvpair_t * 1738nvpair_move_descriptor_array(const char *name, int *value, size_t nitems) 1739{ 1740 nvpair_t *nvp; 1741 size_t i; 1742 1743 nvp = NULL; 1744 if (value == NULL || nitems == 0) { 1745 ERRNO_SET(EINVAL); 1746 return (NULL); 1747 } 1748 1749 for (i = 0; i < nitems; i++) { 1750 if (value[i] != -1 && !fd_is_valid(value[i])) { 1751 ERRNO_SET(EBADF); 1752 goto fail; 1753 } 1754 } 1755 1756 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1757 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1758 1759fail: 1760 if (nvp == NULL) { 1761 ERRNO_SAVE(); 1762 for (i = 0; i < nitems; i++) { 1763 if (fd_is_valid(value[i])) 1764 close(value[i]); 1765 } 1766 nv_free(value); 1767 ERRNO_RESTORE(); 1768 } 1769 1770 return (nvp); 1771} 1772#endif 1773 1774bool 1775nvpair_get_bool(const nvpair_t *nvp) 1776{ 1777 1778 NVPAIR_ASSERT(nvp); 1779 1780 return (nvp->nvp_data == 1); 1781} 1782 1783uint64_t 1784nvpair_get_number(const nvpair_t *nvp) 1785{ 1786 1787 NVPAIR_ASSERT(nvp); 1788 1789 return (nvp->nvp_data); 1790} 1791 1792const char * 1793nvpair_get_string(const nvpair_t *nvp) 1794{ 1795 1796 NVPAIR_ASSERT(nvp); 1797 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1798 1799 return ((const char *)(intptr_t)nvp->nvp_data); 1800} 1801 1802const nvlist_t * 1803nvpair_get_nvlist(const nvpair_t *nvp) 1804{ 1805 1806 NVPAIR_ASSERT(nvp); 1807 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1808 1809 return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1810} 1811 1812#ifndef _KERNEL 1813int 1814nvpair_get_descriptor(const nvpair_t *nvp) 1815{ 1816 1817 NVPAIR_ASSERT(nvp); 1818 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1819 1820 return ((int)nvp->nvp_data); 1821} 1822#endif 1823 1824const void * 1825nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1826{ 1827 1828 NVPAIR_ASSERT(nvp); 1829 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1830 1831 if (sizep != NULL) 1832 *sizep = nvp->nvp_datasize; 1833 1834 return ((const void *)(intptr_t)nvp->nvp_data); 1835} 1836 1837const bool * 1838nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems) 1839{ 1840 1841 NVPAIR_ASSERT(nvp); 1842 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1843 1844 if (nitems != NULL) 1845 *nitems = nvp->nvp_nitems; 1846 1847 return ((const bool *)(intptr_t)nvp->nvp_data); 1848} 1849 1850const uint64_t * 1851nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems) 1852{ 1853 1854 NVPAIR_ASSERT(nvp); 1855 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1856 1857 if (nitems != NULL) 1858 *nitems = nvp->nvp_nitems; 1859 1860 return ((const uint64_t *)(intptr_t)nvp->nvp_data); 1861} 1862 1863const char * const * 1864nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems) 1865{ 1866 1867 NVPAIR_ASSERT(nvp); 1868 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1869 1870 if (nitems != NULL) 1871 *nitems = nvp->nvp_nitems; 1872 1873 return ((const char * const *)(intptr_t)nvp->nvp_data); 1874} 1875 1876const nvlist_t * const * 1877nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems) 1878{ 1879 1880 NVPAIR_ASSERT(nvp); 1881 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1882 1883 if (nitems != NULL) 1884 *nitems = nvp->nvp_nitems; 1885 1886 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data)); 1887} 1888 1889#ifndef _KERNEL 1890const int * 1891nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems) 1892{ 1893 1894 NVPAIR_ASSERT(nvp); 1895 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 1896 1897 if (nitems != NULL) 1898 *nitems = nvp->nvp_nitems; 1899 1900 return ((const int *)(intptr_t)nvp->nvp_data); 1901} 1902#endif 1903 1904void 1905nvpair_free(nvpair_t *nvp) 1906{ 1907 size_t i; 1908 1909 NVPAIR_ASSERT(nvp); 1910 PJDLOG_ASSERT(nvp->nvp_list == NULL); 1911 1912 nvp->nvp_magic = 0; 1913 switch (nvp->nvp_type) { 1914#ifndef _KERNEL 1915 case NV_TYPE_DESCRIPTOR: 1916 close((int)nvp->nvp_data); 1917 break; 1918 case NV_TYPE_DESCRIPTOR_ARRAY: 1919 for (i = 0; i < nvp->nvp_nitems; i++) 1920 close(((int *)(intptr_t)nvp->nvp_data)[i]); 1921 break; 1922#endif 1923 case NV_TYPE_NVLIST: 1924 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 1925 break; 1926 case NV_TYPE_STRING: 1927 nv_free((char *)(intptr_t)nvp->nvp_data); 1928 break; 1929 case NV_TYPE_BINARY: 1930 nv_free((void *)(intptr_t)nvp->nvp_data); 1931 break; 1932 case NV_TYPE_NVLIST_ARRAY: 1933 for (i = 0; i < nvp->nvp_nitems; i++) { 1934 nvlist_destroy( 1935 ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]); 1936 } 1937 nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data)); 1938 break; 1939 case NV_TYPE_NUMBER_ARRAY: 1940 nv_free((uint64_t *)(intptr_t)nvp->nvp_data); 1941 break; 1942 case NV_TYPE_BOOL_ARRAY: 1943 nv_free((bool *)(intptr_t)nvp->nvp_data); 1944 break; 1945 case NV_TYPE_STRING_ARRAY: 1946 for (i = 0; i < nvp->nvp_nitems; i++) 1947 nv_free(((char **)(intptr_t)nvp->nvp_data)[i]); 1948 nv_free((char **)(intptr_t)nvp->nvp_data); 1949 break; 1950 } 1951 nv_free(nvp); 1952} 1953 1954void 1955nvpair_free_structure(nvpair_t *nvp) 1956{ 1957 1958 NVPAIR_ASSERT(nvp); 1959 PJDLOG_ASSERT(nvp->nvp_list == NULL); 1960 1961 nvp->nvp_magic = 0; 1962 nv_free(nvp); 1963} 1964 1965const char * 1966nvpair_type_string(int type) 1967{ 1968 1969 switch (type) { 1970 case NV_TYPE_NULL: 1971 return ("NULL"); 1972 case NV_TYPE_BOOL: 1973 return ("BOOL"); 1974 case NV_TYPE_NUMBER: 1975 return ("NUMBER"); 1976 case NV_TYPE_STRING: 1977 return ("STRING"); 1978 case NV_TYPE_NVLIST: 1979 return ("NVLIST"); 1980 case NV_TYPE_DESCRIPTOR: 1981 return ("DESCRIPTOR"); 1982 case NV_TYPE_BINARY: 1983 return ("BINARY"); 1984 case NV_TYPE_BOOL_ARRAY: 1985 return ("BOOL ARRAY"); 1986 case NV_TYPE_NUMBER_ARRAY: 1987 return ("NUMBER ARRAY"); 1988 case NV_TYPE_STRING_ARRAY: 1989 return ("STRING ARRAY"); 1990 case NV_TYPE_NVLIST_ARRAY: 1991 return ("NVLIST ARRAY"); 1992 case NV_TYPE_DESCRIPTOR_ARRAY: 1993 return ("DESCRIPTOR ARRAY"); 1994 default: 1995 return ("<UNKNOWN>"); 1996 } 1997} 1998 1999