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