1/* $NetBSD: nvpair.c,v 1.11 2019/07/24 14:25:56 martin 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.11 2019/07/24 14:25:56 martin 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" */ 109struct 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 125struct 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 133void 134nvpair_assert(const nvpair_t *nvp) 135{ 136 137 NVPAIR_ASSERT(nvp); 138} 139 140static nvpair_t * 141nvpair_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 170static int 171nvpair_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 192nvlist_t * 193nvpair_nvlist(const nvpair_t *nvp) 194{ 195 196 NVPAIR_ASSERT(nvp); 197 198 return (nvp->nvp_list); 199} 200 201nvpair_t * 202nvpair_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 211nvpair_t * 212nvpair_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 221void 222nvpair_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 234static void 235nvpair_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 245static void 246nvpair_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 260void 261nvpair_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 276nvpair_t * 277nvpair_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 341size_t 342nvpair_header_size(void) 343{ 344 345 return (sizeof(struct nvpair_header)); 346} 347 348size_t 349nvpair_size(const nvpair_t *nvp) 350{ 351 352 NVPAIR_ASSERT(nvp); 353 354 return (nvp->nvp_datasize); 355} 356 357unsigned char * 358nvpair_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 384unsigned char * 385nvpair_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 395unsigned char * 396nvpair_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 413unsigned char * 414nvpair_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 431unsigned char * 432nvpair_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 446unsigned char * 447nvpair_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 471unsigned char * 472nvpair_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) 497unsigned char * 498nvpair_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 528unsigned char * 529nvpair_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 543unsigned char * 544nvpair_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 558unsigned char * 559nvpair_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 573unsigned char * 574nvpair_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) 604unsigned char * 605nvpair_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 643void 644nvpair_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 659const unsigned char * 660nvpair_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); 718fail: 719 ERRNO_SET(EINVAL); 720 return (NULL); 721} 722 723const unsigned char * 724nvpair_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 738const unsigned char * 739nvpair_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 769const unsigned char * 770nvpair_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 796const unsigned char * 797nvpair_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 824const unsigned char * 825nvpair_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) 852const unsigned char * 853nvpair_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 893const unsigned char * 894nvpair_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 919const unsigned char * 920nvpair_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 952const unsigned char * 953nvpair_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 988const unsigned char * 989nvpair_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 (size < 0) { 1012 ERRNO_SET(EINVAL); 1013 return (NULL); 1014 } 1015 tmp += len; 1016 } 1017 if (size != 0) { 1018 ERRNO_SET(EINVAL); 1019 return (NULL); 1020 } 1021 1022 value = nv_malloc(sizeof(*value) * nvp->nvp_nitems); 1023 if (value == NULL) 1024 return (NULL); 1025 1026 for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1027 value[ii] = nv_strdup((const char *)ptr); 1028 if (value[ii] == NULL) 1029 goto out; 1030 len = strlen(value[ii]) + 1; 1031 ptr += len; 1032 *leftp -= len; 1033 } 1034 nvp->nvp_data = (uint64_t)(uintptr_t)value; 1035 1036 return (ptr); 1037out: 1038 for (j = 0; j < ii; j++) 1039 nv_free(value[j]); 1040 nv_free(value); 1041 return (NULL); 1042} 1043 1044#if !defined(_KERNEL) && !defined(_STANDALONE) && !defined(__NetBSD__) 1045const unsigned char * 1046nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp, 1047 const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds) 1048{ 1049 int64_t idx; 1050 size_t size; 1051 unsigned int ii; 1052 int *array; 1053 1054 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 1055 1056 size = sizeof(idx) * nvp->nvp_nitems; 1057 if (nvp->nvp_datasize != size || *leftp < size || 1058 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 1059 ERRNO_SET(EINVAL); 1060 return (NULL); 1061 } 1062 1063 array = (int *)nv_malloc(size); 1064 if (array == NULL) 1065 return (NULL); 1066 1067 for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1068 if (isbe) 1069 idx = be64dec(ptr); 1070 else 1071 idx = le64dec(ptr); 1072 1073 if (idx < 0) { 1074 ERRNO_SET(EINVAL); 1075 nv_free(array); 1076 return (NULL); 1077 } 1078 1079 if ((size_t)idx >= nfds) { 1080 ERRNO_SET(EINVAL); 1081 nv_free(array); 1082 return (NULL); 1083 } 1084 1085 array[ii] = (uint64_t)fds[idx]; 1086 1087 ptr += sizeof(idx); 1088 *leftp -= sizeof(idx); 1089 } 1090 1091 nvp->nvp_data = (uint64_t)(uintptr_t)array; 1092 1093 return (ptr); 1094} 1095#endif 1096 1097const unsigned char * 1098nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp, 1099 const unsigned char *ptr, size_t *leftp, nvlist_t **firstel) 1100{ 1101 nvlist_t **value; 1102 nvpair_t *tmpnvp; 1103 unsigned int ii, j; 1104 size_t sizeup; 1105 1106 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1107 1108 sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems; 1109 if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems || 1110 sizeup > *leftp) { 1111 ERRNO_SET(EINVAL); 1112 return (NULL); 1113 } 1114 1115 value = nv_malloc(nvp->nvp_nitems * sizeof(*value)); 1116 if (value == NULL) 1117 return (NULL); 1118 1119 for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1120 value[ii] = nvlist_create(0); 1121 if (value[ii] == NULL) 1122 goto fail; 1123 if (ii > 0) { 1124 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1125 (uint64_t)(uintptr_t)value[ii], 0, 0); 1126 if (tmpnvp == NULL) 1127 goto fail; 1128 nvlist_set_array_next(value[ii - 1], tmpnvp); 1129 } 1130 } 1131 nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY); 1132 1133 nvp->nvp_data = (uint64_t)(uintptr_t)value; 1134 *firstel = value[0]; 1135 1136 return (ptr); 1137fail: 1138 ERRNO_SAVE(); 1139 for (j = 0; j <= ii; j++) 1140 nvlist_destroy(value[j]); 1141 nv_free(value); 1142 ERRNO_RESTORE(); 1143 1144 return (NULL); 1145} 1146 1147const unsigned char * 1148nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, 1149 nvpair_t **nvpp) 1150{ 1151 nvpair_t *nvp, *tmp; 1152 1153 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); 1154 if (nvp == NULL) 1155 return (NULL); 1156 nvp->nvp_name = (char *)(nvp + 1); 1157 1158 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); 1159 if (ptr == NULL) 1160 goto fail; 1161 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 1162 if (tmp == NULL) 1163 goto fail; 1164 nvp = tmp; 1165 1166 /* Update nvp_name after realloc(). */ 1167 nvp->nvp_name = (char *)(nvp + 1); 1168 nvp->nvp_data = 0x00; 1169 nvp->nvp_magic = NVPAIR_MAGIC; 1170 *nvpp = nvp; 1171 return (ptr); 1172fail: 1173 nv_free(nvp); 1174 return (NULL); 1175} 1176 1177int 1178nvpair_type(const nvpair_t *nvp) 1179{ 1180 1181 NVPAIR_ASSERT(nvp); 1182 1183 return (nvp->nvp_type); 1184} 1185 1186const char * 1187nvpair_name(const nvpair_t *nvp) 1188{ 1189 1190 NVPAIR_ASSERT(nvp); 1191 1192 return (nvp->nvp_name); 1193} 1194 1195#if !defined(_STANDALONE) 1196nvpair_t * 1197nvpair_create_stringf(const char *name, const char *valuefmt, ...) 1198{ 1199 va_list valueap; 1200 nvpair_t *nvp; 1201 1202 va_start(valueap, valuefmt); 1203 nvp = nvpair_create_stringv(name, valuefmt, valueap); 1204 va_end(valueap); 1205 1206 return (nvp); 1207} 1208 1209nvpair_t * 1210nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 1211{ 1212 nvpair_t *nvp; 1213 char *str; 1214 int len; 1215 1216 len = vasprintf(&str, valuefmt, valueap); 1217 if (len < 0) 1218 return (NULL); 1219 nvp = nvpair_create_string(name, str); 1220 nv_kmem_free(str, len+1); 1221 return (nvp); 1222} 1223#endif 1224 1225nvpair_t * 1226nvpair_create_null(const char *name) 1227{ 1228 1229 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0)); 1230} 1231 1232nvpair_t * 1233nvpair_create_bool(const char *name, bool value) 1234{ 1235 1236 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0, 1237 sizeof(uint8_t), 0)); 1238} 1239 1240nvpair_t * 1241nvpair_create_number(const char *name, uint64_t value) 1242{ 1243 1244 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0)); 1245} 1246 1247nvpair_t * 1248nvpair_create_string(const char *name, const char *value) 1249{ 1250 nvpair_t *nvp; 1251 size_t size; 1252 char *data; 1253 1254 if (value == NULL) { 1255 ERRNO_SET(EINVAL); 1256 return (NULL); 1257 } 1258 1259 data = nv_strdup(value); 1260 if (data == NULL) 1261 return (NULL); 1262 size = strlen(value) + 1; 1263 1264 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data, 1265 size, 0); 1266 if (nvp == NULL) 1267 nv_free(data); 1268 1269 return (nvp); 1270} 1271 1272nvpair_t * 1273nvpair_create_nvlist(const char *name, const nvlist_t *value) 1274{ 1275 nvlist_t *nvl; 1276 nvpair_t *nvp; 1277 1278 if (value == NULL) { 1279 ERRNO_SET(EINVAL); 1280 return (NULL); 1281 } 1282 1283 nvl = nvlist_clone(value); 1284 if (nvl == NULL) 1285 return (NULL); 1286 1287 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 1288 0); 1289 if (nvp == NULL) 1290 nvlist_destroy(nvl); 1291 else 1292 nvlist_set_parent(nvl, nvp); 1293 1294 return (nvp); 1295} 1296 1297#if !defined(_KERNEL) && !defined(_STANDALONE) 1298nvpair_t * 1299nvpair_create_descriptor(const char *name, int value) 1300{ 1301 nvpair_t *nvp; 1302 1303 if (value < 0 || !fd_is_valid(value)) { 1304 ERRNO_SET(EBADF); 1305 return (NULL); 1306 } 1307 1308 value = fcntl(value, F_DUPFD_CLOEXEC, 0); 1309 if (value < 0) 1310 return (NULL); 1311 1312 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1313 sizeof(int64_t), 0); 1314 if (nvp == NULL) { 1315 ERRNO_SAVE(); 1316 close(value); 1317 ERRNO_RESTORE(); 1318 } 1319 1320 return (nvp); 1321} 1322#endif 1323 1324nvpair_t * 1325nvpair_create_binary(const char *name, const void *value, size_t size) 1326{ 1327 nvpair_t *nvp; 1328 void *data; 1329 1330 if (value == NULL || size == 0) { 1331 ERRNO_SET(EINVAL); 1332 return (NULL); 1333 } 1334 1335 data = nv_malloc(size); 1336 if (data == NULL) 1337 return (NULL); 1338 memcpy(data, value, size); 1339 1340 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, 1341 size, 0); 1342 if (nvp == NULL) 1343 nv_free(data); 1344 1345 return (nvp); 1346} 1347 1348nvpair_t * 1349nvpair_create_bool_array(const char *name, const bool *value, size_t nitems) 1350{ 1351 nvpair_t *nvp; 1352 size_t size; 1353 void *data; 1354 1355 if (value == NULL || nitems == 0) { 1356 ERRNO_SET(EINVAL); 1357 return (NULL); 1358 } 1359 1360 size = sizeof(value[0]) * nitems; 1361 data = nv_malloc(size); 1362 if (data == NULL) 1363 return (NULL); 1364 1365 memcpy(data, value, size); 1366 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data, 1367 size, nitems); 1368 if (nvp == NULL) { 1369 ERRNO_SAVE(); 1370 nv_free(data); 1371 ERRNO_RESTORE(); 1372 } 1373 1374 return (nvp); 1375} 1376 1377nvpair_t * 1378nvpair_create_number_array(const char *name, const uint64_t *value, 1379 size_t nitems) 1380{ 1381 nvpair_t *nvp; 1382 size_t size; 1383 void *data; 1384 1385 if (value == NULL || nitems == 0) { 1386 ERRNO_SET(EINVAL); 1387 return (NULL); 1388 } 1389 1390 size = sizeof(value[0]) * nitems; 1391 data = nv_malloc(size); 1392 if (data == NULL) 1393 return (NULL); 1394 1395 memcpy(data, value, size); 1396 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1397 (uint64_t)(uintptr_t)data, size, nitems); 1398 if (nvp == NULL) { 1399 ERRNO_SAVE(); 1400 nv_free(data); 1401 ERRNO_RESTORE(); 1402 } 1403 1404 return (nvp); 1405} 1406 1407nvpair_t * 1408nvpair_create_string_array(const char *name, const char * const *value, 1409 size_t nitems) 1410{ 1411 nvpair_t *nvp; 1412 unsigned int ii; 1413 size_t datasize, size; 1414 char **data; 1415 1416 if (value == NULL || nitems == 0) { 1417 ERRNO_SET(EINVAL); 1418 return (NULL); 1419 } 1420 1421 nvp = NULL; 1422 datasize = 0; 1423 data = nv_malloc(sizeof(value[0]) * nitems); 1424 if (data == NULL) 1425 return (NULL); 1426 1427 for (ii = 0; ii < nitems; ii++) { 1428 if (value[ii] == NULL) { 1429 ERRNO_SET(EINVAL); 1430 goto fail; 1431 } 1432 1433 size = strlen(value[ii]) + 1; 1434 datasize += size; 1435 data[ii] = nv_strdup(value[ii]); 1436 if (data[ii] == NULL) 1437 goto fail; 1438 } 1439 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1440 (uint64_t)(uintptr_t)data, datasize, nitems); 1441 1442fail: 1443 if (nvp == NULL) { 1444 ERRNO_SAVE(); 1445 for (; ii > 0; ii--) 1446 nv_free(data[ii - 1]); 1447 nv_free(data); 1448 ERRNO_RESTORE(); 1449 } 1450 1451 return (nvp); 1452} 1453 1454nvpair_t * 1455nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value, 1456 size_t nitems) 1457{ 1458 unsigned int ii; 1459 nvlist_t **nvls; 1460 nvpair_t *parent; 1461 int flags; 1462 1463 nvls = NULL; 1464 1465 if (value == NULL || nitems == 0) { 1466 ERRNO_SET(EINVAL); 1467 return (NULL); 1468 } 1469 1470 nvls = nv_malloc(sizeof(value[0]) * nitems); 1471 if (nvls == NULL) 1472 return (NULL); 1473 1474 for (ii = 0; ii < nitems; ii++) { 1475 if (value[ii] == NULL) { 1476 ERRNO_SET(EINVAL); 1477 goto fail; 1478 } 1479 1480 nvls[ii] = nvlist_clone(value[ii]); 1481 if (nvls[ii] == NULL) 1482 goto fail; 1483 1484 if (ii > 0) { 1485 nvpair_t *nvp; 1486 1487 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1488 (uint64_t)(uintptr_t)nvls[ii], 0, 0); 1489 if (nvp == NULL) { 1490 ERRNO_SAVE(); 1491 nvlist_destroy(nvls[ii]); 1492 ERRNO_RESTORE(); 1493 goto fail; 1494 } 1495 nvlist_set_array_next(nvls[ii - 1], nvp); 1496 } 1497 } 1498 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY; 1499 nvlist_set_flags(nvls[nitems - 1], flags); 1500 1501 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1502 (uint64_t)(uintptr_t)nvls, 0, nitems); 1503 if (parent == NULL) 1504 goto fail; 1505 1506 for (ii = 0; ii < nitems; ii++) 1507 nvlist_set_parent(nvls[ii], parent); 1508 1509 return (parent); 1510 1511fail: 1512 ERRNO_SAVE(); 1513 for (; ii > 0; ii--) 1514 nvlist_destroy(nvls[ii - 1]); 1515 nv_free(nvls); 1516 ERRNO_RESTORE(); 1517 1518 return (NULL); 1519} 1520 1521#if !defined(_KERNEL) && !defined(_STANDALONE) 1522nvpair_t * 1523nvpair_create_descriptor_array(const char *name, const int *value, 1524 size_t nitems) 1525{ 1526 unsigned int ii; 1527 nvpair_t *nvp; 1528 int *fds; 1529 1530 if (value == NULL) { 1531 ERRNO_SET(EINVAL); 1532 return (NULL); 1533 } 1534 1535 nvp = NULL; 1536 1537 fds = nv_malloc(sizeof(value[0]) * nitems); 1538 if (fds == NULL) 1539 return (NULL); 1540 for (ii = 0; ii < nitems; ii++) { 1541 if (value[ii] == -1) { 1542 fds[ii] = -1; 1543 } else { 1544 if (!fd_is_valid(value[ii])) { 1545 ERRNO_SET(EBADF); 1546 goto fail; 1547 } 1548 1549 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0); 1550 if (fds[ii] == -1) 1551 goto fail; 1552 } 1553 } 1554 1555 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1556 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems); 1557 1558fail: 1559 if (nvp == NULL) { 1560 ERRNO_SAVE(); 1561 for (; ii > 0; ii--) { 1562 if (fds[ii - 1] != -1) 1563 close(fds[ii - 1]); 1564 } 1565 nv_free(fds); 1566 ERRNO_RESTORE(); 1567 } 1568 1569 return (nvp); 1570} 1571#endif 1572 1573nvpair_t * 1574nvpair_move_string(const char *name, char *value) 1575{ 1576 nvpair_t *nvp; 1577 1578 if (value == NULL) { 1579 ERRNO_SET(EINVAL); 1580 return (NULL); 1581 } 1582 1583 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 1584 strlen(value) + 1, 0); 1585 if (nvp == NULL) { 1586 ERRNO_SAVE(); 1587 nv_free(value); 1588 ERRNO_RESTORE(); 1589 } 1590 1591 return (nvp); 1592} 1593 1594nvpair_t * 1595nvpair_move_nvlist(const char *name, nvlist_t *value) 1596{ 1597 nvpair_t *nvp; 1598 1599 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { 1600 ERRNO_SET(EINVAL); 1601 return (NULL); 1602 } 1603 1604 if (nvlist_error(value) != 0) { 1605 ERRNO_SET(nvlist_error(value)); 1606 nvlist_destroy(value); 1607 return (NULL); 1608 } 1609 1610 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 1611 0, 0); 1612 if (nvp == NULL) 1613 nvlist_destroy(value); 1614 else 1615 nvlist_set_parent(value, nvp); 1616 1617 return (nvp); 1618} 1619 1620#if !defined(_KERNEL) && !defined(_STANDALONE) 1621nvpair_t * 1622nvpair_move_descriptor(const char *name, int value) 1623{ 1624 nvpair_t *nvp; 1625 1626 if (value < 0 || !fd_is_valid(value)) { 1627 ERRNO_SET(EBADF); 1628 return (NULL); 1629 } 1630 1631 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1632 sizeof(int64_t), 0); 1633 if (nvp == NULL) { 1634 ERRNO_SAVE(); 1635 close(value); 1636 ERRNO_RESTORE(); 1637 } 1638 1639 return (nvp); 1640} 1641#endif 1642 1643nvpair_t * 1644nvpair_move_binary(const char *name, void *value, size_t size) 1645{ 1646 nvpair_t *nvp; 1647 1648 if (value == NULL || size == 0) { 1649 ERRNO_SET(EINVAL); 1650 return (NULL); 1651 } 1652 1653 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, 1654 size, 0); 1655 if (nvp == NULL) { 1656 ERRNO_SAVE(); 1657 nv_free(value); 1658 ERRNO_RESTORE(); 1659 } 1660 1661 return (nvp); 1662} 1663 1664nvpair_t * 1665nvpair_move_bool_array(const char *name, bool *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_BOOL_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_string_array(const char *name, char **value, size_t nitems) 1687{ 1688 nvpair_t *nvp; 1689 size_t i, size; 1690 1691 if (value == NULL || nitems == 0) { 1692 ERRNO_SET(EINVAL); 1693 return (NULL); 1694 } 1695 1696 size = 0; 1697 for (i = 0; i < nitems; i++) { 1698 if (value[i] == NULL) { 1699 ERRNO_SET(EINVAL); 1700 return (NULL); 1701 } 1702 1703 size += strlen(value[i]) + 1; 1704 } 1705 1706 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1707 (uint64_t)(uintptr_t)value, size, nitems); 1708 if (nvp == NULL) { 1709 ERRNO_SAVE(); 1710 for (i = 0; i < nitems; i++) 1711 nv_free(value[i]); 1712 nv_free(value); 1713 ERRNO_RESTORE(); 1714 } 1715 1716 return (nvp); 1717} 1718 1719nvpair_t * 1720nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems) 1721{ 1722 nvpair_t *nvp; 1723 1724 if (value == NULL || nitems == 0) { 1725 ERRNO_SET(EINVAL); 1726 return (NULL); 1727 } 1728 1729 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1730 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1731 if (nvp == NULL) { 1732 ERRNO_SAVE(); 1733 nv_free(value); 1734 ERRNO_RESTORE(); 1735 } 1736 1737 return (nvp); 1738} 1739 1740nvpair_t * 1741nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems) 1742{ 1743 nvpair_t *parent; 1744 unsigned int ii; 1745 int flags; 1746 1747 if (value == NULL || nitems == 0) { 1748 ERRNO_SET(EINVAL); 1749 return (NULL); 1750 } 1751 1752 for (ii = 0; ii < nitems; ii++) { 1753 if (value == NULL || nvlist_error(value[ii]) != 0 || 1754 nvlist_get_pararr(value[ii], NULL) != NULL) { 1755 ERRNO_SET(EINVAL); 1756 goto fail; 1757 } 1758 if (ii > 0) { 1759 nvpair_t *nvp; 1760 1761 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1762 (uint64_t)(uintptr_t)value[ii], 0, 0); 1763 if (nvp == NULL) 1764 goto fail; 1765 nvlist_set_array_next(value[ii - 1], nvp); 1766 } 1767 } 1768 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY; 1769 nvlist_set_flags(value[nitems - 1], flags); 1770 1771 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1772 (uint64_t)(uintptr_t)value, 0, nitems); 1773 if (parent == NULL) 1774 goto fail; 1775 1776 for (ii = 0; ii < nitems; ii++) 1777 nvlist_set_parent(value[ii], parent); 1778 1779 return (parent); 1780fail: 1781 ERRNO_SAVE(); 1782 for (ii = 0; ii < nitems; ii++) { 1783 if (value[ii] != NULL && 1784 nvlist_get_pararr(value[ii], NULL) != NULL) { 1785 nvlist_destroy(value[ii]); 1786 } 1787 } 1788 nv_free(value); 1789 ERRNO_RESTORE(); 1790 1791 return (NULL); 1792} 1793 1794#if !defined(_KERNEL) && !defined(_STANDALONE) 1795nvpair_t * 1796nvpair_move_descriptor_array(const char *name, int *value, size_t nitems) 1797{ 1798 nvpair_t *nvp; 1799 size_t i; 1800 1801 if (value == NULL || nitems == 0) { 1802 ERRNO_SET(EINVAL); 1803 return (NULL); 1804 } 1805 1806 for (i = 0; i < nitems; i++) { 1807 if (value[i] != -1 && !fd_is_valid(value[i])) { 1808 ERRNO_SET(EBADF); 1809 goto fail; 1810 } 1811 } 1812 1813 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1814 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1815 if (nvp == NULL) 1816 goto fail; 1817 1818 return (nvp); 1819fail: 1820 ERRNO_SAVE(); 1821 for (i = 0; i < nitems; i++) { 1822 if (fd_is_valid(value[i])) 1823 close(value[i]); 1824 } 1825 nv_free(value); 1826 ERRNO_RESTORE(); 1827 1828 return (NULL); 1829} 1830#endif 1831 1832bool 1833nvpair_get_bool(const nvpair_t *nvp) 1834{ 1835 1836 NVPAIR_ASSERT(nvp); 1837 1838 return (nvp->nvp_data == 1); 1839} 1840 1841uint64_t 1842nvpair_get_number(const nvpair_t *nvp) 1843{ 1844 1845 NVPAIR_ASSERT(nvp); 1846 1847 return (nvp->nvp_data); 1848} 1849 1850const char * 1851nvpair_get_string(const nvpair_t *nvp) 1852{ 1853 1854 NVPAIR_ASSERT(nvp); 1855 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1856 1857 return ((const char *)(intptr_t)nvp->nvp_data); 1858} 1859 1860const nvlist_t * 1861nvpair_get_nvlist(const nvpair_t *nvp) 1862{ 1863 1864 NVPAIR_ASSERT(nvp); 1865 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1866 1867 return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1868} 1869 1870#if !defined(_KERNEL) && !defined(_STANDALONE) 1871int 1872nvpair_get_descriptor(const nvpair_t *nvp) 1873{ 1874 1875 NVPAIR_ASSERT(nvp); 1876 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1877 1878 return ((int)nvp->nvp_data); 1879} 1880#endif 1881 1882const void * 1883nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1884{ 1885 1886 NVPAIR_ASSERT(nvp); 1887 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1888 1889 if (sizep != NULL) 1890 *sizep = nvp->nvp_datasize; 1891 1892 return ((const void *)(intptr_t)nvp->nvp_data); 1893} 1894 1895const bool * 1896nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems) 1897{ 1898 1899 NVPAIR_ASSERT(nvp); 1900 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1901 1902 if (nitems != NULL) 1903 *nitems = nvp->nvp_nitems; 1904 1905 return ((const bool *)(intptr_t)nvp->nvp_data); 1906} 1907 1908const uint64_t * 1909nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems) 1910{ 1911 1912 NVPAIR_ASSERT(nvp); 1913 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1914 1915 if (nitems != NULL) 1916 *nitems = nvp->nvp_nitems; 1917 1918 return ((const uint64_t *)(intptr_t)nvp->nvp_data); 1919} 1920 1921const char * const * 1922nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems) 1923{ 1924 1925 NVPAIR_ASSERT(nvp); 1926 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1927 1928 if (nitems != NULL) 1929 *nitems = nvp->nvp_nitems; 1930 1931 return ((const char * const *)(intptr_t)nvp->nvp_data); 1932} 1933 1934const nvlist_t * const * 1935nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems) 1936{ 1937 1938 NVPAIR_ASSERT(nvp); 1939 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1940 1941 if (nitems != NULL) 1942 *nitems = nvp->nvp_nitems; 1943 1944 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data)); 1945} 1946 1947#if !defined(_KERNEL) && !defined(_STANDALONE) 1948const int * 1949nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems) 1950{ 1951 1952 NVPAIR_ASSERT(nvp); 1953 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 1954 1955 if (nitems != NULL) 1956 *nitems = nvp->nvp_nitems; 1957 1958 return ((const int *)(intptr_t)nvp->nvp_data); 1959} 1960#endif 1961 1962int 1963nvpair_append_bool_array(nvpair_t *nvp, const bool value) 1964{ 1965 1966 NVPAIR_ASSERT(nvp); 1967 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1968 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 1969} 1970 1971int 1972nvpair_append_number_array(nvpair_t *nvp, const uint64_t value) 1973{ 1974 1975 NVPAIR_ASSERT(nvp); 1976 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1977 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 1978} 1979 1980int 1981nvpair_append_string_array(nvpair_t *nvp, const char *value) 1982{ 1983 char *str; 1984 1985 NVPAIR_ASSERT(nvp); 1986 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1987 if (value == NULL) { 1988 ERRNO_SET(EINVAL); 1989 return (-1); 1990 } 1991 str = nv_strdup(value); 1992 if (str == NULL) { 1993 return (-1); 1994 } 1995 if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) { 1996 nv_free(str); 1997 return (-1); 1998 } 1999 return (0); 2000} 2001 2002int 2003nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value) 2004{ 2005 nvpair_t *tmpnvp; 2006 nvlist_t *nvl, *prev; 2007 int flags; 2008 2009 NVPAIR_ASSERT(nvp); 2010 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 2011 if (value == NULL || nvlist_error(value) != 0 || 2012 nvlist_get_pararr(value, NULL) != NULL) { 2013 ERRNO_SET(EINVAL); 2014 return (-1); 2015 } 2016 nvl = nvlist_clone(value); 2017 if (nvl == NULL) { 2018 return (-1); 2019 } 2020 flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY; 2021 nvlist_set_flags(nvl, flags); 2022 2023 tmpnvp = NULL; 2024 prev = NULL; 2025 if (nvp->nvp_nitems > 0) { 2026 nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data; 2027 2028 prev = nvls[nvp->nvp_nitems - 1]; 2029 PJDLOG_ASSERT(prev != NULL); 2030 2031 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 2032 (uint64_t)(uintptr_t)nvl, 0, 0); 2033 if (tmpnvp == NULL) { 2034 goto fail; 2035 } 2036 } 2037 if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) { 2038 goto fail; 2039 } 2040 if (tmpnvp) { 2041 NVPAIR_ASSERT(tmpnvp); 2042 nvlist_set_array_next(prev, tmpnvp); 2043 } 2044 nvlist_set_parent(nvl, nvp); 2045 return (0); 2046fail: 2047 if (tmpnvp) { 2048 nvpair_free(tmpnvp); 2049 } 2050 nvlist_destroy(nvl); 2051 return (-1); 2052} 2053 2054#if !defined(_KERNEL) && !defined(_STANDALONE) 2055int 2056nvpair_append_descriptor_array(nvpair_t *nvp, const int value) 2057{ 2058 int fd; 2059 2060 NVPAIR_ASSERT(nvp); 2061 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 2062 if (value < 0 || !fd_is_valid(value)) { 2063 ERRNO_SET(EBADF); 2064 return -1; 2065 } 2066 fd = fcntl(value, F_DUPFD_CLOEXEC, 0); 2067 if (fd == -1) { 2068 return (-1); 2069 } 2070 if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) { 2071 close(fd); 2072 return (-1); 2073 } 2074 return (0); 2075} 2076#endif 2077 2078void 2079nvpair_free(nvpair_t *nvp) 2080{ 2081 size_t i; 2082 2083 NVPAIR_ASSERT(nvp); 2084 PJDLOG_ASSERT(nvp->nvp_list == NULL); 2085 2086 nvp->nvp_magic = 0; 2087 switch (nvp->nvp_type) { 2088#if !defined(_KERNEL) && !defined(_STANDALONE) 2089 case NV_TYPE_DESCRIPTOR: 2090 close((int)nvp->nvp_data); 2091 break; 2092 case NV_TYPE_DESCRIPTOR_ARRAY: 2093 for (i = 0; i < nvp->nvp_nitems; i++) 2094 close(((int *)(intptr_t)nvp->nvp_data)[i]); 2095 nv_free((int *)(intptr_t)nvp->nvp_data); 2096 break; 2097#endif 2098 case NV_TYPE_NVLIST: 2099 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 2100 break; 2101 case NV_TYPE_STRING: 2102 nv_free((char *)(intptr_t)nvp->nvp_data); 2103 break; 2104 case NV_TYPE_BINARY: 2105 nv_free((void *)(intptr_t)nvp->nvp_data); 2106 break; 2107 case NV_TYPE_NVLIST_ARRAY: 2108 for (i = 0; i < nvp->nvp_nitems; i++) { 2109 nvlist_destroy( 2110 ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]); 2111 } 2112 nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data)); 2113 break; 2114 case NV_TYPE_NUMBER_ARRAY: 2115 nv_free((uint64_t *)(intptr_t)nvp->nvp_data); 2116 break; 2117 case NV_TYPE_BOOL_ARRAY: 2118 nv_free((bool *)(intptr_t)nvp->nvp_data); 2119 break; 2120 case NV_TYPE_STRING_ARRAY: 2121 for (i = 0; i < nvp->nvp_nitems; i++) 2122 nv_free(((char **)(intptr_t)nvp->nvp_data)[i]); 2123 nv_free((char **)(intptr_t)nvp->nvp_data); 2124 break; 2125 } 2126 nv_free(nvp); 2127} 2128 2129void 2130nvpair_free_structure(nvpair_t *nvp) 2131{ 2132 2133 NVPAIR_ASSERT(nvp); 2134 PJDLOG_ASSERT(nvp->nvp_list == NULL); 2135 2136 nvp->nvp_magic = 0; 2137 nv_free(nvp); 2138} 2139 2140const char * 2141nvpair_type_string(int type) 2142{ 2143 2144 switch (type) { 2145 case NV_TYPE_NULL: 2146 return ("NULL"); 2147 case NV_TYPE_BOOL: 2148 return ("BOOL"); 2149 case NV_TYPE_NUMBER: 2150 return ("NUMBER"); 2151 case NV_TYPE_STRING: 2152 return ("STRING"); 2153 case NV_TYPE_NVLIST: 2154 return ("NVLIST"); 2155 case NV_TYPE_DESCRIPTOR: 2156 return ("DESCRIPTOR"); 2157 case NV_TYPE_BINARY: 2158 return ("BINARY"); 2159 case NV_TYPE_BOOL_ARRAY: 2160 return ("BOOL ARRAY"); 2161 case NV_TYPE_NUMBER_ARRAY: 2162 return ("NUMBER ARRAY"); 2163 case NV_TYPE_STRING_ARRAY: 2164 return ("STRING ARRAY"); 2165 case NV_TYPE_NVLIST_ARRAY: 2166 return ("NVLIST ARRAY"); 2167 case NV_TYPE_DESCRIPTOR_ARRAY: 2168 return ("DESCRIPTOR ARRAY"); 2169 default: 2170 return ("<UNKNOWN>"); 2171 } 2172} 2173 2174