1258065Spjd/*- 2258065Spjd * Copyright (c) 2009-2013 The FreeBSD Foundation 3258065Spjd * All rights reserved. 4258065Spjd * 5258065Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from 6258065Spjd * the FreeBSD Foundation. 7258065Spjd * 8258065Spjd * Redistribution and use in source and binary forms, with or without 9258065Spjd * modification, are permitted provided that the following conditions 10258065Spjd * are met: 11258065Spjd * 1. Redistributions of source code must retain the above copyright 12258065Spjd * notice, this list of conditions and the following disclaimer. 13258065Spjd * 2. Redistributions in binary form must reproduce the above copyright 14258065Spjd * notice, this list of conditions and the following disclaimer in the 15258065Spjd * documentation and/or other materials provided with the distribution. 16258065Spjd * 17258065Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18258065Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19258065Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20258065Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21258065Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22258065Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23258065Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24258065Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25258065Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26258065Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27258065Spjd * SUCH DAMAGE. 28258065Spjd */ 29258065Spjd 30258065Spjd#include <sys/cdefs.h> 31258065Spjd__FBSDID("$FreeBSD$"); 32258065Spjd 33258065Spjd#include <sys/param.h> 34258065Spjd#include <sys/endian.h> 35258065Spjd#include <sys/queue.h> 36258065Spjd 37279438Srstone#ifdef _KERNEL 38279438Srstone 39279438Srstone#include <sys/errno.h> 40279438Srstone#include <sys/lock.h> 41279438Srstone#include <sys/malloc.h> 42279438Srstone#include <sys/systm.h> 43279438Srstone 44279438Srstone#include <machine/stdarg.h> 45279438Srstone 46279438Srstone#else 47258065Spjd#include <errno.h> 48258065Spjd#include <fcntl.h> 49258065Spjd#include <stdarg.h> 50258065Spjd#include <stdbool.h> 51258065Spjd#include <stdint.h> 52258065Spjd#include <stdlib.h> 53258065Spjd#include <string.h> 54258065Spjd#include <unistd.h> 55279439Srstone 56279439Srstone#include "common_impl.h" 57279438Srstone#endif 58258065Spjd 59258065Spjd#ifdef HAVE_PJDLOG 60258065Spjd#include <pjdlog.h> 61258065Spjd#endif 62258065Spjd 63279439Srstone#include <sys/nv.h> 64279439Srstone#include <sys/nv_impl.h> 65279439Srstone#include <sys/nvlist_impl.h> 66279439Srstone#include <sys/nvpair_impl.h> 67258065Spjd 68258065Spjd#ifndef HAVE_PJDLOG 69279438Srstone#ifdef _KERNEL 70279438Srstone#define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) 71279438Srstone#define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) 72279438Srstone#define PJDLOG_ABORT(...) panic(__VA_ARGS__) 73279438Srstone#else 74258065Spjd#include <assert.h> 75258065Spjd#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 76258065Spjd#define PJDLOG_RASSERT(expr, ...) assert(expr) 77258065Spjd#define PJDLOG_ABORT(...) abort() 78258065Spjd#endif 79279438Srstone#endif 80258065Spjd 81258065Spjd#define NVPAIR_MAGIC 0x6e7670 /* "nvp" */ 82258065Spjdstruct nvpair { 83258065Spjd int nvp_magic; 84258065Spjd char *nvp_name; 85258065Spjd int nvp_type; 86258065Spjd uint64_t nvp_data; 87258065Spjd size_t nvp_datasize; 88271579Spjd nvlist_t *nvp_list; 89258065Spjd TAILQ_ENTRY(nvpair) nvp_next; 90258065Spjd}; 91258065Spjd 92258065Spjd#define NVPAIR_ASSERT(nvp) do { \ 93258065Spjd PJDLOG_ASSERT((nvp) != NULL); \ 94258065Spjd PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \ 95258065Spjd} while (0) 96258065Spjd 97258065Spjdstruct nvpair_header { 98258065Spjd uint8_t nvph_type; 99258065Spjd uint16_t nvph_namesize; 100258065Spjd uint64_t nvph_datasize; 101258065Spjd} __packed; 102258065Spjd 103258065Spjd 104258065Spjdvoid 105258065Spjdnvpair_assert(const nvpair_t *nvp) 106258065Spjd{ 107258065Spjd 108258065Spjd NVPAIR_ASSERT(nvp); 109258065Spjd} 110258065Spjd 111271579Spjdnvlist_t * 112258065Spjdnvpair_nvlist(const nvpair_t *nvp) 113258065Spjd{ 114258065Spjd 115258065Spjd NVPAIR_ASSERT(nvp); 116258065Spjd 117258065Spjd return (nvp->nvp_list); 118258065Spjd} 119258065Spjd 120258065Spjdnvpair_t * 121258065Spjdnvpair_next(const nvpair_t *nvp) 122258065Spjd{ 123258065Spjd 124258065Spjd NVPAIR_ASSERT(nvp); 125258065Spjd PJDLOG_ASSERT(nvp->nvp_list != NULL); 126258065Spjd 127258065Spjd return (TAILQ_NEXT(nvp, nvp_next)); 128258065Spjd} 129258065Spjd 130258065Spjdnvpair_t * 131258065Spjdnvpair_prev(const nvpair_t *nvp) 132258065Spjd{ 133258065Spjd 134258065Spjd NVPAIR_ASSERT(nvp); 135258065Spjd PJDLOG_ASSERT(nvp->nvp_list != NULL); 136258065Spjd 137258065Spjd return (TAILQ_PREV(nvp, nvl_head, nvp_next)); 138258065Spjd} 139258065Spjd 140258065Spjdvoid 141258065Spjdnvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) 142258065Spjd{ 143258065Spjd 144258065Spjd NVPAIR_ASSERT(nvp); 145258065Spjd PJDLOG_ASSERT(nvp->nvp_list == NULL); 146258065Spjd PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp))); 147258065Spjd 148258065Spjd TAILQ_INSERT_TAIL(head, nvp, nvp_next); 149258065Spjd nvp->nvp_list = nvl; 150258065Spjd} 151258065Spjd 152271579Spjdstatic void 153271579Spjdnvpair_remove_nvlist(nvpair_t *nvp) 154271579Spjd{ 155271579Spjd nvlist_t *nvl; 156271579Spjd 157271579Spjd /* XXX: DECONST is bad, mkay? */ 158271579Spjd nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp)); 159271579Spjd PJDLOG_ASSERT(nvl != NULL); 160271579Spjd nvlist_set_parent(nvl, NULL); 161271579Spjd} 162271579Spjd 163258065Spjdvoid 164258065Spjdnvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl) 165258065Spjd{ 166258065Spjd 167258065Spjd NVPAIR_ASSERT(nvp); 168258065Spjd PJDLOG_ASSERT(nvp->nvp_list == nvl); 169258065Spjd 170271579Spjd if (nvpair_type(nvp) == NV_TYPE_NVLIST) 171271579Spjd nvpair_remove_nvlist(nvp); 172271579Spjd 173258065Spjd TAILQ_REMOVE(head, nvp, nvp_next); 174258065Spjd nvp->nvp_list = NULL; 175258065Spjd} 176258065Spjd 177258065Spjdnvpair_t * 178258065Spjdnvpair_clone(const nvpair_t *nvp) 179258065Spjd{ 180258065Spjd nvpair_t *newnvp; 181258065Spjd const char *name; 182258065Spjd const void *data; 183258065Spjd size_t datasize; 184258065Spjd 185258065Spjd NVPAIR_ASSERT(nvp); 186258065Spjd 187258065Spjd name = nvpair_name(nvp); 188258065Spjd 189258065Spjd switch (nvpair_type(nvp)) { 190258065Spjd case NV_TYPE_NULL: 191258065Spjd newnvp = nvpair_create_null(name); 192258065Spjd break; 193258065Spjd case NV_TYPE_BOOL: 194258065Spjd newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); 195258065Spjd break; 196258065Spjd case NV_TYPE_NUMBER: 197258065Spjd newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); 198258065Spjd break; 199258065Spjd case NV_TYPE_STRING: 200258065Spjd newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); 201258065Spjd break; 202258065Spjd case NV_TYPE_NVLIST: 203258065Spjd newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); 204258065Spjd break; 205279438Srstone#ifndef _KERNEL 206258065Spjd case NV_TYPE_DESCRIPTOR: 207258065Spjd newnvp = nvpair_create_descriptor(name, 208258065Spjd nvpair_get_descriptor(nvp)); 209258065Spjd break; 210279438Srstone#endif 211258065Spjd case NV_TYPE_BINARY: 212258065Spjd data = nvpair_get_binary(nvp, &datasize); 213258065Spjd newnvp = nvpair_create_binary(name, data, datasize); 214258065Spjd break; 215258065Spjd default: 216258065Spjd PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 217258065Spjd } 218258065Spjd 219258065Spjd return (newnvp); 220258065Spjd} 221258065Spjd 222258065Spjdsize_t 223258065Spjdnvpair_header_size(void) 224258065Spjd{ 225258065Spjd 226258065Spjd return (sizeof(struct nvpair_header)); 227258065Spjd} 228258065Spjd 229258065Spjdsize_t 230258065Spjdnvpair_size(const nvpair_t *nvp) 231258065Spjd{ 232258065Spjd 233258065Spjd NVPAIR_ASSERT(nvp); 234258065Spjd 235258065Spjd return (nvp->nvp_datasize); 236258065Spjd} 237258065Spjd 238271579Spjdunsigned char * 239258065Spjdnvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 240258065Spjd{ 241258065Spjd struct nvpair_header nvphdr; 242258065Spjd size_t namesize; 243258065Spjd 244258065Spjd NVPAIR_ASSERT(nvp); 245258065Spjd 246258065Spjd nvphdr.nvph_type = nvp->nvp_type; 247258065Spjd namesize = strlen(nvp->nvp_name) + 1; 248258065Spjd PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX); 249258065Spjd nvphdr.nvph_namesize = namesize; 250258065Spjd nvphdr.nvph_datasize = nvp->nvp_datasize; 251258065Spjd PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 252258065Spjd memcpy(ptr, &nvphdr, sizeof(nvphdr)); 253258065Spjd ptr += sizeof(nvphdr); 254258065Spjd *leftp -= sizeof(nvphdr); 255258065Spjd 256258065Spjd PJDLOG_ASSERT(*leftp >= namesize); 257258065Spjd memcpy(ptr, nvp->nvp_name, namesize); 258258065Spjd ptr += namesize; 259258065Spjd *leftp -= namesize; 260258065Spjd 261258065Spjd return (ptr); 262258065Spjd} 263258065Spjd 264271579Spjdunsigned char * 265258065Spjdnvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr, 266258065Spjd size_t *leftp __unused) 267258065Spjd{ 268258065Spjd 269258065Spjd NVPAIR_ASSERT(nvp); 270258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 271258065Spjd 272258065Spjd return (ptr); 273258065Spjd} 274258065Spjd 275271579Spjdunsigned char * 276258065Spjdnvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 277258065Spjd{ 278258065Spjd uint8_t value; 279258065Spjd 280258065Spjd NVPAIR_ASSERT(nvp); 281258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 282258065Spjd 283258065Spjd value = (uint8_t)nvp->nvp_data; 284258065Spjd 285258065Spjd PJDLOG_ASSERT(*leftp >= sizeof(value)); 286258065Spjd memcpy(ptr, &value, sizeof(value)); 287258065Spjd ptr += sizeof(value); 288258065Spjd *leftp -= sizeof(value); 289258065Spjd 290258065Spjd return (ptr); 291258065Spjd} 292258065Spjd 293271579Spjdunsigned char * 294258065Spjdnvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 295258065Spjd{ 296258065Spjd uint64_t value; 297258065Spjd 298258065Spjd NVPAIR_ASSERT(nvp); 299258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 300258065Spjd 301258065Spjd value = (uint64_t)nvp->nvp_data; 302258065Spjd 303258065Spjd PJDLOG_ASSERT(*leftp >= sizeof(value)); 304258065Spjd memcpy(ptr, &value, sizeof(value)); 305258065Spjd ptr += sizeof(value); 306258065Spjd *leftp -= sizeof(value); 307258065Spjd 308258065Spjd return (ptr); 309258065Spjd} 310258065Spjd 311271579Spjdunsigned char * 312258065Spjdnvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 313258065Spjd{ 314258065Spjd 315258065Spjd NVPAIR_ASSERT(nvp); 316258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 317258065Spjd 318258065Spjd PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 319258065Spjd memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 320258065Spjd ptr += nvp->nvp_datasize; 321258065Spjd *leftp -= nvp->nvp_datasize; 322258065Spjd 323258065Spjd return (ptr); 324258065Spjd} 325258065Spjd 326271579Spjdunsigned char * 327271579Spjdnvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp) 328258065Spjd{ 329271579Spjd struct nvpair_header nvphdr; 330271579Spjd size_t namesize; 331271579Spjd const char *name = ""; 332258065Spjd 333271579Spjd namesize = 1; 334271579Spjd nvphdr.nvph_type = NV_TYPE_NVLIST_UP; 335271579Spjd nvphdr.nvph_namesize = namesize; 336271579Spjd nvphdr.nvph_datasize = 0; 337271579Spjd PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 338271579Spjd memcpy(ptr, &nvphdr, sizeof(nvphdr)); 339271579Spjd ptr += sizeof(nvphdr); 340271579Spjd *leftp -= sizeof(nvphdr); 341258065Spjd 342271579Spjd PJDLOG_ASSERT(*leftp >= namesize); 343271579Spjd memcpy(ptr, name, namesize); 344271579Spjd ptr += namesize; 345271579Spjd *leftp -= namesize; 346258065Spjd 347258065Spjd return (ptr); 348258065Spjd} 349258065Spjd 350279438Srstone#ifndef _KERNEL 351271579Spjdunsigned char * 352258065Spjdnvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, 353258065Spjd size_t *leftp) 354258065Spjd{ 355258065Spjd int64_t value; 356258065Spjd 357258065Spjd NVPAIR_ASSERT(nvp); 358258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 359258065Spjd 360258065Spjd value = (int64_t)nvp->nvp_data; 361258065Spjd if (value != -1) { 362258065Spjd /* 363258065Spjd * If there is a real descriptor here, we change its number 364258065Spjd * to position in the array of descriptors send via control 365258065Spjd * message. 366258065Spjd */ 367258065Spjd PJDLOG_ASSERT(fdidxp != NULL); 368258065Spjd 369258065Spjd value = *fdidxp; 370258065Spjd (*fdidxp)++; 371258065Spjd } 372258065Spjd 373258065Spjd PJDLOG_ASSERT(*leftp >= sizeof(value)); 374258065Spjd memcpy(ptr, &value, sizeof(value)); 375258065Spjd ptr += sizeof(value); 376258065Spjd *leftp -= sizeof(value); 377258065Spjd 378258065Spjd return (ptr); 379258065Spjd} 380279438Srstone#endif 381258065Spjd 382271579Spjdunsigned char * 383258065Spjdnvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 384258065Spjd{ 385258065Spjd 386258065Spjd NVPAIR_ASSERT(nvp); 387258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 388258065Spjd 389258065Spjd PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 390258065Spjd memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 391258065Spjd ptr += nvp->nvp_datasize; 392258065Spjd *leftp -= nvp->nvp_datasize; 393258065Spjd 394258065Spjd return (ptr); 395258065Spjd} 396258065Spjd 397271579Spjdvoid 398271579Spjdnvpair_init_datasize(nvpair_t *nvp) 399258065Spjd{ 400258065Spjd 401258065Spjd NVPAIR_ASSERT(nvp); 402258065Spjd 403258065Spjd if (nvp->nvp_type == NV_TYPE_NVLIST) { 404258065Spjd if (nvp->nvp_data == 0) { 405258065Spjd nvp->nvp_datasize = 0; 406258065Spjd } else { 407258065Spjd nvp->nvp_datasize = 408258065Spjd nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); 409258065Spjd } 410258065Spjd } 411258065Spjd} 412258065Spjd 413271579Spjdconst unsigned char * 414272843Spjdnvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 415258065Spjd size_t *leftp) 416258065Spjd{ 417258065Spjd struct nvpair_header nvphdr; 418258065Spjd 419258065Spjd if (*leftp < sizeof(nvphdr)) 420258065Spjd goto failed; 421258065Spjd 422258065Spjd memcpy(&nvphdr, ptr, sizeof(nvphdr)); 423258065Spjd ptr += sizeof(nvphdr); 424258065Spjd *leftp -= sizeof(nvphdr); 425258065Spjd 426258065Spjd#if NV_TYPE_FIRST > 0 427258065Spjd if (nvphdr.nvph_type < NV_TYPE_FIRST) 428258065Spjd goto failed; 429258065Spjd#endif 430271579Spjd if (nvphdr.nvph_type > NV_TYPE_LAST && 431271579Spjd nvphdr.nvph_type != NV_TYPE_NVLIST_UP) { 432258065Spjd goto failed; 433271579Spjd } 434258065Spjd 435258065Spjd#if BYTE_ORDER == BIG_ENDIAN 436272843Spjd if (!isbe) { 437258065Spjd nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize); 438258065Spjd nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize); 439258065Spjd } 440258065Spjd#else 441272843Spjd if (isbe) { 442258065Spjd nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); 443258065Spjd nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); 444258065Spjd } 445258065Spjd#endif 446258065Spjd 447258065Spjd if (nvphdr.nvph_namesize > NV_NAME_MAX) 448258065Spjd goto failed; 449258065Spjd if (*leftp < nvphdr.nvph_namesize) 450258065Spjd goto failed; 451258065Spjd if (nvphdr.nvph_namesize < 1) 452258065Spjd goto failed; 453258065Spjd if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != 454258065Spjd (size_t)(nvphdr.nvph_namesize - 1)) { 455258065Spjd goto failed; 456258065Spjd } 457258065Spjd 458258065Spjd memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); 459258065Spjd ptr += nvphdr.nvph_namesize; 460258065Spjd *leftp -= nvphdr.nvph_namesize; 461258065Spjd 462258065Spjd if (*leftp < nvphdr.nvph_datasize) 463258065Spjd goto failed; 464258065Spjd 465258065Spjd nvp->nvp_type = nvphdr.nvph_type; 466258065Spjd nvp->nvp_data = 0; 467258065Spjd nvp->nvp_datasize = nvphdr.nvph_datasize; 468258065Spjd 469258065Spjd return (ptr); 470258065Spjdfailed: 471279438Srstone RESTORE_ERRNO(EINVAL); 472258065Spjd return (NULL); 473258065Spjd} 474258065Spjd 475271579Spjdconst unsigned char * 476272843Spjdnvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, 477258065Spjd size_t *leftp __unused) 478258065Spjd{ 479258065Spjd 480258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 481258065Spjd 482258065Spjd if (nvp->nvp_datasize != 0) { 483279438Srstone RESTORE_ERRNO(EINVAL); 484258065Spjd return (NULL); 485258065Spjd } 486258065Spjd 487258065Spjd return (ptr); 488258065Spjd} 489258065Spjd 490271579Spjdconst unsigned char * 491272843Spjdnvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, 492258065Spjd size_t *leftp) 493258065Spjd{ 494258065Spjd uint8_t value; 495258065Spjd 496258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 497258065Spjd 498258065Spjd if (nvp->nvp_datasize != sizeof(value)) { 499279438Srstone RESTORE_ERRNO(EINVAL); 500258065Spjd return (NULL); 501258065Spjd } 502258065Spjd if (*leftp < sizeof(value)) { 503279438Srstone RESTORE_ERRNO(EINVAL); 504258065Spjd return (NULL); 505258065Spjd } 506258065Spjd 507258065Spjd memcpy(&value, ptr, sizeof(value)); 508258065Spjd ptr += sizeof(value); 509258065Spjd *leftp -= sizeof(value); 510258065Spjd 511258065Spjd if (value != 0 && value != 1) { 512279438Srstone RESTORE_ERRNO(EINVAL); 513258065Spjd return (NULL); 514258065Spjd } 515258065Spjd 516258065Spjd nvp->nvp_data = (uint64_t)value; 517258065Spjd 518258065Spjd return (ptr); 519258065Spjd} 520258065Spjd 521271579Spjdconst unsigned char * 522272843Spjdnvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 523271579Spjd size_t *leftp) 524258065Spjd{ 525258065Spjd 526258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 527258065Spjd 528258065Spjd if (nvp->nvp_datasize != sizeof(uint64_t)) { 529279438Srstone RESTORE_ERRNO(EINVAL); 530258065Spjd return (NULL); 531258065Spjd } 532258065Spjd if (*leftp < sizeof(uint64_t)) { 533279438Srstone RESTORE_ERRNO(EINVAL); 534258065Spjd return (NULL); 535258065Spjd } 536258065Spjd 537272843Spjd if (isbe) 538258065Spjd nvp->nvp_data = be64dec(ptr); 539258065Spjd else 540258065Spjd nvp->nvp_data = le64dec(ptr); 541258065Spjd ptr += sizeof(uint64_t); 542258065Spjd *leftp -= sizeof(uint64_t); 543258065Spjd 544258065Spjd return (ptr); 545258065Spjd} 546258065Spjd 547271579Spjdconst unsigned char * 548272843Spjdnvpair_unpack_string(bool isbe __unused, nvpair_t *nvp, 549258065Spjd const unsigned char *ptr, size_t *leftp) 550258065Spjd{ 551258065Spjd 552258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 553258065Spjd 554258065Spjd if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 555279438Srstone RESTORE_ERRNO(EINVAL); 556258065Spjd return (NULL); 557258065Spjd } 558258065Spjd 559258065Spjd if (strnlen((const char *)ptr, nvp->nvp_datasize) != 560258065Spjd nvp->nvp_datasize - 1) { 561279438Srstone RESTORE_ERRNO(EINVAL); 562258065Spjd return (NULL); 563258065Spjd } 564258065Spjd 565279438Srstone nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr); 566258065Spjd if (nvp->nvp_data == 0) 567258065Spjd return (NULL); 568258065Spjd 569258065Spjd ptr += nvp->nvp_datasize; 570258065Spjd *leftp -= nvp->nvp_datasize; 571258065Spjd 572258065Spjd return (ptr); 573258065Spjd} 574258065Spjd 575271579Spjdconst unsigned char * 576272843Spjdnvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp, 577272843Spjd const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child) 578258065Spjd{ 579258065Spjd nvlist_t *value; 580258065Spjd 581258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 582258065Spjd 583258065Spjd if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 584279438Srstone RESTORE_ERRNO(EINVAL); 585258065Spjd return (NULL); 586258065Spjd } 587258065Spjd 588271579Spjd value = nvlist_create(0); 589258065Spjd if (value == NULL) 590258065Spjd return (NULL); 591258065Spjd 592272843Spjd ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp); 593271579Spjd if (ptr == NULL) 594271579Spjd return (NULL); 595271579Spjd 596258065Spjd nvp->nvp_data = (uint64_t)(uintptr_t)value; 597271579Spjd *child = value; 598258065Spjd 599258065Spjd return (ptr); 600258065Spjd} 601258065Spjd 602279438Srstone#ifndef _KERNEL 603271579Spjdconst unsigned char * 604272843Spjdnvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 605258065Spjd size_t *leftp, const int *fds, size_t nfds) 606258065Spjd{ 607258065Spjd int64_t idx; 608258065Spjd 609258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 610258065Spjd 611258065Spjd if (nvp->nvp_datasize != sizeof(idx)) { 612258065Spjd errno = EINVAL; 613258065Spjd return (NULL); 614258065Spjd } 615258065Spjd if (*leftp < sizeof(idx)) { 616258065Spjd errno = EINVAL; 617258065Spjd return (NULL); 618258065Spjd } 619258065Spjd 620272843Spjd if (isbe) 621258065Spjd idx = be64dec(ptr); 622258065Spjd else 623258065Spjd idx = le64dec(ptr); 624258065Spjd 625258065Spjd if (idx < 0) { 626258065Spjd errno = EINVAL; 627258065Spjd return (NULL); 628258065Spjd } 629258065Spjd 630258065Spjd if ((size_t)idx >= nfds) { 631258065Spjd errno = EINVAL; 632258065Spjd return (NULL); 633258065Spjd } 634258065Spjd 635258065Spjd nvp->nvp_data = (uint64_t)fds[idx]; 636258065Spjd 637258065Spjd ptr += sizeof(idx); 638258065Spjd *leftp -= sizeof(idx); 639258065Spjd 640258065Spjd return (ptr); 641258065Spjd} 642279438Srstone#endif 643258065Spjd 644271579Spjdconst unsigned char * 645272843Spjdnvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp, 646258065Spjd const unsigned char *ptr, size_t *leftp) 647258065Spjd{ 648258065Spjd void *value; 649258065Spjd 650258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 651258065Spjd 652258065Spjd if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 653279438Srstone RESTORE_ERRNO(EINVAL); 654258065Spjd return (NULL); 655258065Spjd } 656258065Spjd 657279438Srstone value = nv_malloc(nvp->nvp_datasize); 658258065Spjd if (value == NULL) 659258065Spjd return (NULL); 660258065Spjd 661258065Spjd memcpy(value, ptr, nvp->nvp_datasize); 662258065Spjd ptr += nvp->nvp_datasize; 663258065Spjd *leftp -= nvp->nvp_datasize; 664258065Spjd 665258065Spjd nvp->nvp_data = (uint64_t)(uintptr_t)value; 666258065Spjd 667258065Spjd return (ptr); 668258065Spjd} 669258065Spjd 670258065Spjdconst unsigned char * 671272843Spjdnvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, 672271579Spjd nvpair_t **nvpp) 673258065Spjd{ 674258065Spjd nvpair_t *nvp, *tmp; 675258065Spjd 676279438Srstone nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); 677258065Spjd if (nvp == NULL) 678258065Spjd return (NULL); 679258065Spjd nvp->nvp_name = (char *)(nvp + 1); 680258065Spjd 681272843Spjd ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); 682258065Spjd if (ptr == NULL) 683258065Spjd goto failed; 684279438Srstone tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 685258594Spjd if (tmp == NULL) 686258065Spjd goto failed; 687258065Spjd nvp = tmp; 688271579Spjd 689258065Spjd /* Update nvp_name after realloc(). */ 690258065Spjd nvp->nvp_name = (char *)(nvp + 1); 691271579Spjd nvp->nvp_data = 0x00; 692258065Spjd nvp->nvp_magic = NVPAIR_MAGIC; 693258065Spjd *nvpp = nvp; 694258065Spjd return (ptr); 695258065Spjdfailed: 696279438Srstone nv_free(nvp); 697258065Spjd return (NULL); 698258065Spjd} 699258065Spjd 700258065Spjdint 701258065Spjdnvpair_type(const nvpair_t *nvp) 702258065Spjd{ 703258065Spjd 704258065Spjd NVPAIR_ASSERT(nvp); 705258065Spjd 706258065Spjd return (nvp->nvp_type); 707258065Spjd} 708258065Spjd 709258065Spjdconst char * 710258065Spjdnvpair_name(const nvpair_t *nvp) 711258065Spjd{ 712258065Spjd 713258065Spjd NVPAIR_ASSERT(nvp); 714258065Spjd 715258065Spjd return (nvp->nvp_name); 716258065Spjd} 717258065Spjd 718258065Spjdstatic nvpair_t * 719292637Sngienvpair_allocv(const char *name, int type, uint64_t data, size_t datasize) 720258065Spjd{ 721258065Spjd nvpair_t *nvp; 722292637Sngie size_t namelen; 723258065Spjd 724258065Spjd PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); 725258065Spjd 726292637Sngie namelen = strlen(name); 727258065Spjd if (namelen >= NV_NAME_MAX) { 728279438Srstone RESTORE_ERRNO(ENAMETOOLONG); 729258065Spjd return (NULL); 730258065Spjd } 731258065Spjd 732279438Srstone nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1); 733258065Spjd if (nvp != NULL) { 734258065Spjd nvp->nvp_name = (char *)(nvp + 1); 735292637Sngie memcpy(nvp->nvp_name, name, namelen); 736292637Sngie nvp->nvp_name[namelen + 1] = '\0'; 737258065Spjd nvp->nvp_type = type; 738258065Spjd nvp->nvp_data = data; 739258065Spjd nvp->nvp_datasize = datasize; 740258065Spjd nvp->nvp_magic = NVPAIR_MAGIC; 741258065Spjd } 742258065Spjd 743258065Spjd return (nvp); 744258065Spjd}; 745258065Spjd 746258065Spjdnvpair_t * 747258065Spjdnvpair_create_stringf(const char *name, const char *valuefmt, ...) 748258065Spjd{ 749258065Spjd va_list valueap; 750258065Spjd nvpair_t *nvp; 751258065Spjd 752258065Spjd va_start(valueap, valuefmt); 753258065Spjd nvp = nvpair_create_stringv(name, valuefmt, valueap); 754258065Spjd va_end(valueap); 755258065Spjd 756258065Spjd return (nvp); 757258065Spjd} 758258065Spjd 759258065Spjdnvpair_t * 760258065Spjdnvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 761258065Spjd{ 762258065Spjd nvpair_t *nvp; 763258065Spjd char *str; 764258065Spjd int len; 765258065Spjd 766279438Srstone len = nv_vasprintf(&str, valuefmt, valueap); 767258065Spjd if (len < 0) 768258065Spjd return (NULL); 769258065Spjd nvp = nvpair_create_string(name, str); 770258065Spjd if (nvp == NULL) 771279438Srstone nv_free(str); 772258065Spjd return (nvp); 773258065Spjd} 774258065Spjd 775258065Spjdnvpair_t * 776292637Sngienvpair_create_null(const char *name) 777258065Spjd{ 778258065Spjd 779292637Sngie return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0)); 780258065Spjd} 781258065Spjd 782258065Spjdnvpair_t * 783292637Sngienvpair_create_bool(const char *name, bool value) 784258065Spjd{ 785258065Spjd 786292637Sngie return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0, 787292637Sngie sizeof(uint8_t))); 788258065Spjd} 789258065Spjd 790258065Spjdnvpair_t * 791292637Sngienvpair_create_number(const char *name, uint64_t value) 792258065Spjd{ 793258065Spjd 794292637Sngie return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value))); 795258065Spjd} 796258065Spjd 797258065Spjdnvpair_t * 798292637Sngienvpair_create_string(const char *name, const char *value) 799258065Spjd{ 800258065Spjd nvpair_t *nvp; 801258065Spjd size_t size; 802258065Spjd char *data; 803258065Spjd 804258065Spjd if (value == NULL) { 805279438Srstone RESTORE_ERRNO(EINVAL); 806258065Spjd return (NULL); 807258065Spjd } 808258065Spjd 809279438Srstone data = nv_strdup(value); 810258065Spjd if (data == NULL) 811258065Spjd return (NULL); 812258065Spjd size = strlen(value) + 1; 813258065Spjd 814292637Sngie nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data, 815292637Sngie size); 816258065Spjd if (nvp == NULL) 817279438Srstone nv_free(data); 818258065Spjd 819258065Spjd return (nvp); 820258065Spjd} 821258065Spjd 822258065Spjdnvpair_t * 823292637Sngienvpair_create_nvlist(const char *name, const nvlist_t *value) 824258065Spjd{ 825258065Spjd nvlist_t *nvl; 826258065Spjd nvpair_t *nvp; 827258065Spjd 828258065Spjd if (value == NULL) { 829279438Srstone RESTORE_ERRNO(EINVAL); 830258065Spjd return (NULL); 831258065Spjd } 832258065Spjd 833258065Spjd nvl = nvlist_clone(value); 834258065Spjd if (nvl == NULL) 835258065Spjd return (NULL); 836258065Spjd 837292637Sngie nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0); 838258065Spjd if (nvp == NULL) 839258065Spjd nvlist_destroy(nvl); 840271847Spjd else 841271847Spjd nvlist_set_parent(nvl, nvp); 842258065Spjd 843258065Spjd return (nvp); 844258065Spjd} 845258065Spjd 846279438Srstone#ifndef _KERNEL 847258065Spjdnvpair_t * 848292637Sngienvpair_create_descriptor(const char *name, int value) 849258065Spjd{ 850258065Spjd nvpair_t *nvp; 851258065Spjd 852258065Spjd if (value < 0 || !fd_is_valid(value)) { 853258065Spjd errno = EBADF; 854258065Spjd return (NULL); 855258065Spjd } 856258065Spjd 857258065Spjd value = fcntl(value, F_DUPFD_CLOEXEC, 0); 858258065Spjd if (value < 0) 859258065Spjd return (NULL); 860258065Spjd 861292637Sngie nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 862292637Sngie sizeof(int64_t)); 863258065Spjd if (nvp == NULL) 864258065Spjd close(value); 865258065Spjd 866258065Spjd return (nvp); 867258065Spjd} 868279438Srstone#endif 869258065Spjd 870258065Spjdnvpair_t * 871292637Sngienvpair_create_binary(const char *name, const void *value, size_t size) 872258065Spjd{ 873258065Spjd nvpair_t *nvp; 874258065Spjd void *data; 875258065Spjd 876258065Spjd if (value == NULL || size == 0) { 877279438Srstone RESTORE_ERRNO(EINVAL); 878258065Spjd return (NULL); 879258065Spjd } 880258065Spjd 881279438Srstone data = nv_malloc(size); 882258065Spjd if (data == NULL) 883258065Spjd return (NULL); 884258065Spjd memcpy(data, value, size); 885258065Spjd 886292637Sngie nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, 887292637Sngie size); 888258065Spjd if (nvp == NULL) 889279438Srstone nv_free(data); 890258065Spjd 891258065Spjd return (nvp); 892258065Spjd} 893258065Spjd 894258065Spjdnvpair_t * 895258065Spjdnvpair_move_string(const char *name, char *value) 896258065Spjd{ 897258065Spjd nvpair_t *nvp; 898277920Spjd int serrno; 899258065Spjd 900258065Spjd if (value == NULL) { 901279438Srstone RESTORE_ERRNO(EINVAL); 902258065Spjd return (NULL); 903258065Spjd } 904258065Spjd 905292637Sngie nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 906292637Sngie strlen(value) + 1); 907277920Spjd if (nvp == NULL) { 908279438Srstone SAVE_ERRNO(serrno); 909279438Srstone nv_free(value); 910279438Srstone RESTORE_ERRNO(serrno); 911277920Spjd } 912258065Spjd 913258065Spjd return (nvp); 914258065Spjd} 915258065Spjd 916258065Spjdnvpair_t * 917292637Sngienvpair_move_nvlist(const char *name, nvlist_t *value) 918258065Spjd{ 919258065Spjd nvpair_t *nvp; 920258065Spjd 921271579Spjd if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { 922279438Srstone RESTORE_ERRNO(EINVAL); 923258065Spjd return (NULL); 924258065Spjd } 925258065Spjd 926279436Srstone if (nvlist_error(value) != 0) { 927279438Srstone RESTORE_ERRNO(nvlist_error(value)); 928279436Srstone nvlist_destroy(value); 929279436Srstone return (NULL); 930279436Srstone } 931279436Srstone 932292637Sngie nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 933292637Sngie 0); 934258065Spjd if (nvp == NULL) 935258065Spjd nvlist_destroy(value); 936271579Spjd else 937271579Spjd nvlist_set_parent(value, nvp); 938258065Spjd 939258065Spjd return (nvp); 940258065Spjd} 941258065Spjd 942279438Srstone#ifndef _KERNEL 943258065Spjdnvpair_t * 944292637Sngienvpair_move_descriptor(const char *name, int value) 945258065Spjd{ 946277920Spjd nvpair_t *nvp; 947277920Spjd int serrno; 948258065Spjd 949258065Spjd if (value < 0 || !fd_is_valid(value)) { 950258065Spjd errno = EBADF; 951258065Spjd return (NULL); 952258065Spjd } 953258065Spjd 954292637Sngie nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 955292637Sngie sizeof(int64_t)); 956277920Spjd if (nvp == NULL) { 957277920Spjd serrno = errno; 958277920Spjd close(value); 959277920Spjd errno = serrno; 960277920Spjd } 961277920Spjd 962277920Spjd return (nvp); 963258065Spjd} 964279438Srstone#endif 965258065Spjd 966258065Spjdnvpair_t * 967292637Sngienvpair_move_binary(const char *name, void *value, size_t size) 968258065Spjd{ 969277920Spjd nvpair_t *nvp; 970277920Spjd int serrno; 971258065Spjd 972258065Spjd if (value == NULL || size == 0) { 973279438Srstone RESTORE_ERRNO(EINVAL); 974258065Spjd return (NULL); 975258065Spjd } 976258065Spjd 977292637Sngie nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, 978292637Sngie size); 979277920Spjd if (nvp == NULL) { 980279438Srstone SAVE_ERRNO(serrno); 981279438Srstone nv_free(value); 982279438Srstone RESTORE_ERRNO(serrno); 983277920Spjd } 984277920Spjd 985277920Spjd return (nvp); 986258065Spjd} 987258065Spjd 988258065Spjdbool 989258065Spjdnvpair_get_bool(const nvpair_t *nvp) 990258065Spjd{ 991258065Spjd 992258065Spjd NVPAIR_ASSERT(nvp); 993258065Spjd 994258065Spjd return (nvp->nvp_data == 1); 995258065Spjd} 996258065Spjd 997258065Spjduint64_t 998258065Spjdnvpair_get_number(const nvpair_t *nvp) 999258065Spjd{ 1000258065Spjd 1001258065Spjd NVPAIR_ASSERT(nvp); 1002258065Spjd 1003258065Spjd return (nvp->nvp_data); 1004258065Spjd} 1005258065Spjd 1006258065Spjdconst char * 1007258065Spjdnvpair_get_string(const nvpair_t *nvp) 1008258065Spjd{ 1009258065Spjd 1010258065Spjd NVPAIR_ASSERT(nvp); 1011258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1012258065Spjd 1013258065Spjd return ((const char *)(intptr_t)nvp->nvp_data); 1014258065Spjd} 1015258065Spjd 1016258065Spjdconst nvlist_t * 1017258065Spjdnvpair_get_nvlist(const nvpair_t *nvp) 1018258065Spjd{ 1019258065Spjd 1020258065Spjd NVPAIR_ASSERT(nvp); 1021258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1022258065Spjd 1023258065Spjd return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1024258065Spjd} 1025258065Spjd 1026279438Srstone#ifndef _KERNEL 1027258065Spjdint 1028258065Spjdnvpair_get_descriptor(const nvpair_t *nvp) 1029258065Spjd{ 1030258065Spjd 1031258065Spjd NVPAIR_ASSERT(nvp); 1032258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1033258065Spjd 1034258065Spjd return ((int)nvp->nvp_data); 1035258065Spjd} 1036279438Srstone#endif 1037258065Spjd 1038258065Spjdconst void * 1039258065Spjdnvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1040258065Spjd{ 1041258065Spjd 1042258065Spjd NVPAIR_ASSERT(nvp); 1043258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1044258065Spjd 1045258065Spjd if (sizep != NULL) 1046258065Spjd *sizep = nvp->nvp_datasize; 1047258065Spjd return ((const void *)(intptr_t)nvp->nvp_data); 1048258065Spjd} 1049258065Spjd 1050258065Spjdvoid 1051258065Spjdnvpair_free(nvpair_t *nvp) 1052258065Spjd{ 1053258065Spjd 1054258065Spjd NVPAIR_ASSERT(nvp); 1055258065Spjd PJDLOG_ASSERT(nvp->nvp_list == NULL); 1056258065Spjd 1057258065Spjd nvp->nvp_magic = 0; 1058258065Spjd switch (nvp->nvp_type) { 1059279438Srstone#ifndef _KERNEL 1060258065Spjd case NV_TYPE_DESCRIPTOR: 1061258065Spjd close((int)nvp->nvp_data); 1062258065Spjd break; 1063279438Srstone#endif 1064258065Spjd case NV_TYPE_NVLIST: 1065258065Spjd nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 1066258065Spjd break; 1067258065Spjd case NV_TYPE_STRING: 1068279438Srstone nv_free((char *)(intptr_t)nvp->nvp_data); 1069258065Spjd break; 1070258065Spjd case NV_TYPE_BINARY: 1071279438Srstone nv_free((void *)(intptr_t)nvp->nvp_data); 1072258065Spjd break; 1073258065Spjd } 1074279438Srstone nv_free(nvp); 1075258065Spjd} 1076258065Spjd 1077258065Spjdvoid 1078258065Spjdnvpair_free_structure(nvpair_t *nvp) 1079258065Spjd{ 1080258065Spjd 1081258065Spjd NVPAIR_ASSERT(nvp); 1082258065Spjd PJDLOG_ASSERT(nvp->nvp_list == NULL); 1083258065Spjd 1084258065Spjd nvp->nvp_magic = 0; 1085279438Srstone nv_free(nvp); 1086258065Spjd} 1087258065Spjd 1088258065Spjdconst char * 1089258065Spjdnvpair_type_string(int type) 1090258065Spjd{ 1091258065Spjd 1092258065Spjd switch (type) { 1093258065Spjd case NV_TYPE_NULL: 1094258065Spjd return ("NULL"); 1095258065Spjd case NV_TYPE_BOOL: 1096258065Spjd return ("BOOL"); 1097258065Spjd case NV_TYPE_NUMBER: 1098258065Spjd return ("NUMBER"); 1099258065Spjd case NV_TYPE_STRING: 1100258065Spjd return ("STRING"); 1101258065Spjd case NV_TYPE_NVLIST: 1102258065Spjd return ("NVLIST"); 1103258065Spjd case NV_TYPE_DESCRIPTOR: 1104258065Spjd return ("DESCRIPTOR"); 1105258065Spjd case NV_TYPE_BINARY: 1106258065Spjd return ("BINARY"); 1107258065Spjd default: 1108258065Spjd return ("<UNKNOWN>"); 1109258065Spjd } 1110258065Spjd} 1111292637Sngie 1112