subr_nvpair.c revision 258594
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: head/lib/libnv/nvpair.c 258594 2013-11-25 20:45:30Z pjd $"); 32258065Spjd 33258065Spjd#include <sys/param.h> 34258065Spjd#include <sys/endian.h> 35258065Spjd#include <sys/queue.h> 36258065Spjd 37258065Spjd#include <errno.h> 38258065Spjd#include <fcntl.h> 39258065Spjd#include <stdarg.h> 40258065Spjd#include <stdbool.h> 41258065Spjd#include <stdint.h> 42258065Spjd#include <stdlib.h> 43258065Spjd#include <string.h> 44258065Spjd#include <unistd.h> 45258065Spjd 46258065Spjd#ifdef HAVE_PJDLOG 47258065Spjd#include <pjdlog.h> 48258065Spjd#endif 49258065Spjd 50258065Spjd#include "common_impl.h" 51258065Spjd#include "nv.h" 52258065Spjd#include "nv_impl.h" 53258065Spjd#include "nvlist_impl.h" 54258065Spjd#include "nvpair_impl.h" 55258065Spjd 56258065Spjd#ifndef HAVE_PJDLOG 57258065Spjd#include <assert.h> 58258065Spjd#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 59258065Spjd#define PJDLOG_RASSERT(expr, ...) assert(expr) 60258065Spjd#define PJDLOG_ABORT(...) abort() 61258065Spjd#endif 62258065Spjd 63258065Spjd#define NVPAIR_MAGIC 0x6e7670 /* "nvp" */ 64258065Spjdstruct nvpair { 65258065Spjd int nvp_magic; 66258065Spjd char *nvp_name; 67258065Spjd int nvp_type; 68258065Spjd uint64_t nvp_data; 69258065Spjd size_t nvp_datasize; 70258065Spjd nvlist_t *nvp_list; /* Used for sanity checks. */ 71258065Spjd TAILQ_ENTRY(nvpair) nvp_next; 72258065Spjd}; 73258065Spjd 74258065Spjd#define NVPAIR_ASSERT(nvp) do { \ 75258065Spjd PJDLOG_ASSERT((nvp) != NULL); \ 76258065Spjd PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \ 77258065Spjd} while (0) 78258065Spjd 79258065Spjdstruct nvpair_header { 80258065Spjd uint8_t nvph_type; 81258065Spjd uint16_t nvph_namesize; 82258065Spjd uint64_t nvph_datasize; 83258065Spjd} __packed; 84258065Spjd 85258065Spjd 86258065Spjdvoid 87258065Spjdnvpair_assert(const nvpair_t *nvp) 88258065Spjd{ 89258065Spjd 90258065Spjd NVPAIR_ASSERT(nvp); 91258065Spjd} 92258065Spjd 93258065Spjdconst nvlist_t * 94258065Spjdnvpair_nvlist(const nvpair_t *nvp) 95258065Spjd{ 96258065Spjd 97258065Spjd NVPAIR_ASSERT(nvp); 98258065Spjd 99258065Spjd return (nvp->nvp_list); 100258065Spjd} 101258065Spjd 102258065Spjdnvpair_t * 103258065Spjdnvpair_next(const nvpair_t *nvp) 104258065Spjd{ 105258065Spjd 106258065Spjd NVPAIR_ASSERT(nvp); 107258065Spjd PJDLOG_ASSERT(nvp->nvp_list != NULL); 108258065Spjd 109258065Spjd return (TAILQ_NEXT(nvp, nvp_next)); 110258065Spjd} 111258065Spjd 112258065Spjdnvpair_t * 113258065Spjdnvpair_prev(const nvpair_t *nvp) 114258065Spjd{ 115258065Spjd 116258065Spjd NVPAIR_ASSERT(nvp); 117258065Spjd PJDLOG_ASSERT(nvp->nvp_list != NULL); 118258065Spjd 119258065Spjd return (TAILQ_PREV(nvp, nvl_head, nvp_next)); 120258065Spjd} 121258065Spjd 122258065Spjdvoid 123258065Spjdnvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) 124258065Spjd{ 125258065Spjd 126258065Spjd NVPAIR_ASSERT(nvp); 127258065Spjd PJDLOG_ASSERT(nvp->nvp_list == NULL); 128258065Spjd PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp))); 129258065Spjd 130258065Spjd TAILQ_INSERT_TAIL(head, nvp, nvp_next); 131258065Spjd nvp->nvp_list = nvl; 132258065Spjd} 133258065Spjd 134258065Spjdvoid 135258065Spjdnvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl) 136258065Spjd{ 137258065Spjd 138258065Spjd NVPAIR_ASSERT(nvp); 139258065Spjd PJDLOG_ASSERT(nvp->nvp_list == nvl); 140258065Spjd 141258065Spjd TAILQ_REMOVE(head, nvp, nvp_next); 142258065Spjd nvp->nvp_list = NULL; 143258065Spjd} 144258065Spjd 145258065Spjdnvpair_t * 146258065Spjdnvpair_clone(const nvpair_t *nvp) 147258065Spjd{ 148258065Spjd nvpair_t *newnvp; 149258065Spjd const char *name; 150258065Spjd const void *data; 151258065Spjd size_t datasize; 152258065Spjd 153258065Spjd NVPAIR_ASSERT(nvp); 154258065Spjd 155258065Spjd name = nvpair_name(nvp); 156258065Spjd 157258065Spjd switch (nvpair_type(nvp)) { 158258065Spjd case NV_TYPE_NULL: 159258065Spjd newnvp = nvpair_create_null(name); 160258065Spjd break; 161258065Spjd case NV_TYPE_BOOL: 162258065Spjd newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); 163258065Spjd break; 164258065Spjd case NV_TYPE_NUMBER: 165258065Spjd newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); 166258065Spjd break; 167258065Spjd case NV_TYPE_STRING: 168258065Spjd newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); 169258065Spjd break; 170258065Spjd case NV_TYPE_NVLIST: 171258065Spjd newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); 172258065Spjd break; 173258065Spjd case NV_TYPE_DESCRIPTOR: 174258065Spjd newnvp = nvpair_create_descriptor(name, 175258065Spjd nvpair_get_descriptor(nvp)); 176258065Spjd break; 177258065Spjd case NV_TYPE_BINARY: 178258065Spjd data = nvpair_get_binary(nvp, &datasize); 179258065Spjd newnvp = nvpair_create_binary(name, data, datasize); 180258065Spjd break; 181258065Spjd default: 182258065Spjd PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 183258065Spjd } 184258065Spjd 185258065Spjd return (newnvp); 186258065Spjd} 187258065Spjd 188258065Spjdsize_t 189258065Spjdnvpair_header_size(void) 190258065Spjd{ 191258065Spjd 192258065Spjd return (sizeof(struct nvpair_header)); 193258065Spjd} 194258065Spjd 195258065Spjdsize_t 196258065Spjdnvpair_size(const nvpair_t *nvp) 197258065Spjd{ 198258065Spjd 199258065Spjd NVPAIR_ASSERT(nvp); 200258065Spjd 201258065Spjd return (nvp->nvp_datasize); 202258065Spjd} 203258065Spjd 204258065Spjdstatic unsigned char * 205258065Spjdnvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 206258065Spjd{ 207258065Spjd struct nvpair_header nvphdr; 208258065Spjd size_t namesize; 209258065Spjd 210258065Spjd NVPAIR_ASSERT(nvp); 211258065Spjd 212258065Spjd nvphdr.nvph_type = nvp->nvp_type; 213258065Spjd namesize = strlen(nvp->nvp_name) + 1; 214258065Spjd PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX); 215258065Spjd nvphdr.nvph_namesize = namesize; 216258065Spjd nvphdr.nvph_datasize = nvp->nvp_datasize; 217258065Spjd PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 218258065Spjd memcpy(ptr, &nvphdr, sizeof(nvphdr)); 219258065Spjd ptr += sizeof(nvphdr); 220258065Spjd *leftp -= sizeof(nvphdr); 221258065Spjd 222258065Spjd PJDLOG_ASSERT(*leftp >= namesize); 223258065Spjd memcpy(ptr, nvp->nvp_name, namesize); 224258065Spjd ptr += namesize; 225258065Spjd *leftp -= namesize; 226258065Spjd 227258065Spjd return (ptr); 228258065Spjd} 229258065Spjd 230258065Spjdstatic unsigned char * 231258065Spjdnvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr, 232258065Spjd size_t *leftp __unused) 233258065Spjd{ 234258065Spjd 235258065Spjd NVPAIR_ASSERT(nvp); 236258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 237258065Spjd 238258065Spjd return (ptr); 239258065Spjd} 240258065Spjd 241258065Spjdstatic unsigned char * 242258065Spjdnvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 243258065Spjd{ 244258065Spjd uint8_t value; 245258065Spjd 246258065Spjd NVPAIR_ASSERT(nvp); 247258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 248258065Spjd 249258065Spjd value = (uint8_t)nvp->nvp_data; 250258065Spjd 251258065Spjd PJDLOG_ASSERT(*leftp >= sizeof(value)); 252258065Spjd memcpy(ptr, &value, sizeof(value)); 253258065Spjd ptr += sizeof(value); 254258065Spjd *leftp -= sizeof(value); 255258065Spjd 256258065Spjd return (ptr); 257258065Spjd} 258258065Spjd 259258065Spjdstatic unsigned char * 260258065Spjdnvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 261258065Spjd{ 262258065Spjd uint64_t value; 263258065Spjd 264258065Spjd NVPAIR_ASSERT(nvp); 265258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 266258065Spjd 267258065Spjd value = (uint64_t)nvp->nvp_data; 268258065Spjd 269258065Spjd PJDLOG_ASSERT(*leftp >= sizeof(value)); 270258065Spjd memcpy(ptr, &value, sizeof(value)); 271258065Spjd ptr += sizeof(value); 272258065Spjd *leftp -= sizeof(value); 273258065Spjd 274258065Spjd return (ptr); 275258065Spjd} 276258065Spjd 277258065Spjdstatic unsigned char * 278258065Spjdnvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 279258065Spjd{ 280258065Spjd 281258065Spjd NVPAIR_ASSERT(nvp); 282258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 283258065Spjd 284258065Spjd PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 285258065Spjd memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 286258065Spjd ptr += nvp->nvp_datasize; 287258065Spjd *leftp -= nvp->nvp_datasize; 288258065Spjd 289258065Spjd return (ptr); 290258065Spjd} 291258065Spjd 292258065Spjdstatic unsigned char * 293258065Spjdnvpair_pack_nvlist(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, 294258065Spjd size_t *leftp) 295258065Spjd{ 296258065Spjd unsigned char *data; 297258065Spjd size_t size; 298258065Spjd 299258065Spjd NVPAIR_ASSERT(nvp); 300258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 301258065Spjd 302258065Spjd if (nvp->nvp_datasize == 0) 303258065Spjd return (ptr); 304258065Spjd 305258065Spjd data = nvlist_xpack((const nvlist_t *)(intptr_t)nvp->nvp_data, fdidxp, 306258065Spjd &size); 307258065Spjd if (data == NULL) 308258065Spjd return (NULL); 309258065Spjd 310258065Spjd PJDLOG_ASSERT(size == nvp->nvp_datasize); 311258065Spjd PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 312258065Spjd 313258065Spjd memcpy(ptr, data, nvp->nvp_datasize); 314258065Spjd free(data); 315258065Spjd 316258065Spjd ptr += nvp->nvp_datasize; 317258065Spjd *leftp -= nvp->nvp_datasize; 318258065Spjd 319258065Spjd return (ptr); 320258065Spjd} 321258065Spjd 322258065Spjdstatic unsigned char * 323258065Spjdnvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, 324258065Spjd size_t *leftp) 325258065Spjd{ 326258065Spjd int64_t value; 327258065Spjd 328258065Spjd NVPAIR_ASSERT(nvp); 329258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 330258065Spjd 331258065Spjd value = (int64_t)nvp->nvp_data; 332258065Spjd if (value != -1) { 333258065Spjd /* 334258065Spjd * If there is a real descriptor here, we change its number 335258065Spjd * to position in the array of descriptors send via control 336258065Spjd * message. 337258065Spjd */ 338258065Spjd PJDLOG_ASSERT(fdidxp != NULL); 339258065Spjd 340258065Spjd value = *fdidxp; 341258065Spjd (*fdidxp)++; 342258065Spjd } 343258065Spjd 344258065Spjd PJDLOG_ASSERT(*leftp >= sizeof(value)); 345258065Spjd memcpy(ptr, &value, sizeof(value)); 346258065Spjd ptr += sizeof(value); 347258065Spjd *leftp -= sizeof(value); 348258065Spjd 349258065Spjd return (ptr); 350258065Spjd} 351258065Spjd 352258065Spjdstatic unsigned char * 353258065Spjdnvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 354258065Spjd{ 355258065Spjd 356258065Spjd NVPAIR_ASSERT(nvp); 357258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 358258065Spjd 359258065Spjd PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 360258065Spjd memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 361258065Spjd ptr += nvp->nvp_datasize; 362258065Spjd *leftp -= nvp->nvp_datasize; 363258065Spjd 364258065Spjd return (ptr); 365258065Spjd} 366258065Spjd 367258065Spjdunsigned char * 368258065Spjdnvpair_pack(nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, size_t *leftp) 369258065Spjd{ 370258065Spjd 371258065Spjd NVPAIR_ASSERT(nvp); 372258065Spjd 373258065Spjd /* 374258065Spjd * We have to update datasize for NV_TYPE_NVLIST on every pack, 375258065Spjd * so that proper datasize is placed into nvpair_header 376258065Spjd * during the nvpair_pack_header() call below. 377258065Spjd */ 378258065Spjd if (nvp->nvp_type == NV_TYPE_NVLIST) { 379258065Spjd if (nvp->nvp_data == 0) { 380258065Spjd nvp->nvp_datasize = 0; 381258065Spjd } else { 382258065Spjd nvp->nvp_datasize = 383258065Spjd nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); 384258065Spjd } 385258065Spjd } 386258065Spjd 387258065Spjd ptr = nvpair_pack_header(nvp, ptr, leftp); 388258065Spjd if (ptr == NULL) 389258065Spjd return (NULL); 390258065Spjd 391258065Spjd switch (nvp->nvp_type) { 392258065Spjd case NV_TYPE_NULL: 393258065Spjd ptr = nvpair_pack_null(nvp, ptr, leftp); 394258065Spjd break; 395258065Spjd case NV_TYPE_BOOL: 396258065Spjd ptr = nvpair_pack_bool(nvp, ptr, leftp); 397258065Spjd break; 398258065Spjd case NV_TYPE_NUMBER: 399258065Spjd ptr = nvpair_pack_number(nvp, ptr, leftp); 400258065Spjd break; 401258065Spjd case NV_TYPE_STRING: 402258065Spjd ptr = nvpair_pack_string(nvp, ptr, leftp); 403258065Spjd break; 404258065Spjd case NV_TYPE_NVLIST: 405258065Spjd ptr = nvpair_pack_nvlist(nvp, ptr, fdidxp, leftp); 406258065Spjd break; 407258065Spjd case NV_TYPE_DESCRIPTOR: 408258065Spjd ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, leftp); 409258065Spjd break; 410258065Spjd case NV_TYPE_BINARY: 411258065Spjd ptr = nvpair_pack_binary(nvp, ptr, leftp); 412258065Spjd break; 413258065Spjd default: 414258065Spjd PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type); 415258065Spjd } 416258065Spjd 417258065Spjd return (ptr); 418258065Spjd} 419258065Spjd 420258065Spjdstatic const unsigned char * 421258065Spjdnvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr, 422258065Spjd size_t *leftp) 423258065Spjd{ 424258065Spjd struct nvpair_header nvphdr; 425258065Spjd 426258065Spjd if (*leftp < sizeof(nvphdr)) 427258065Spjd goto failed; 428258065Spjd 429258065Spjd memcpy(&nvphdr, ptr, sizeof(nvphdr)); 430258065Spjd ptr += sizeof(nvphdr); 431258065Spjd *leftp -= sizeof(nvphdr); 432258065Spjd 433258065Spjd#if NV_TYPE_FIRST > 0 434258065Spjd if (nvphdr.nvph_type < NV_TYPE_FIRST) 435258065Spjd goto failed; 436258065Spjd#endif 437258065Spjd if (nvphdr.nvph_type > NV_TYPE_LAST) 438258065Spjd goto failed; 439258065Spjd 440258065Spjd#if BYTE_ORDER == BIG_ENDIAN 441258065Spjd if ((flags & NV_FLAG_BIG_ENDIAN) == 0) { 442258065Spjd nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize); 443258065Spjd nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize); 444258065Spjd } 445258065Spjd#else 446258065Spjd if ((flags & NV_FLAG_BIG_ENDIAN) != 0) { 447258065Spjd nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); 448258065Spjd nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); 449258065Spjd } 450258065Spjd#endif 451258065Spjd 452258065Spjd if (nvphdr.nvph_namesize > NV_NAME_MAX) 453258065Spjd goto failed; 454258065Spjd if (*leftp < nvphdr.nvph_namesize) 455258065Spjd goto failed; 456258065Spjd if (nvphdr.nvph_namesize < 1) 457258065Spjd goto failed; 458258065Spjd if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != 459258065Spjd (size_t)(nvphdr.nvph_namesize - 1)) { 460258065Spjd goto failed; 461258065Spjd } 462258065Spjd 463258065Spjd memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); 464258065Spjd ptr += nvphdr.nvph_namesize; 465258065Spjd *leftp -= nvphdr.nvph_namesize; 466258065Spjd 467258065Spjd if (*leftp < nvphdr.nvph_datasize) 468258065Spjd goto failed; 469258065Spjd 470258065Spjd nvp->nvp_type = nvphdr.nvph_type; 471258065Spjd nvp->nvp_data = 0; 472258065Spjd nvp->nvp_datasize = nvphdr.nvph_datasize; 473258065Spjd 474258065Spjd return (ptr); 475258065Spjdfailed: 476258065Spjd errno = EINVAL; 477258065Spjd return (NULL); 478258065Spjd} 479258065Spjd 480258065Spjdstatic const unsigned char * 481258065Spjdnvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr, 482258065Spjd size_t *leftp __unused) 483258065Spjd{ 484258065Spjd 485258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 486258065Spjd 487258065Spjd if (nvp->nvp_datasize != 0) { 488258065Spjd errno = EINVAL; 489258065Spjd return (NULL); 490258065Spjd } 491258065Spjd 492258065Spjd return (ptr); 493258065Spjd} 494258065Spjd 495258065Spjdstatic const unsigned char * 496258065Spjdnvpair_unpack_bool(int flags __unused, nvpair_t *nvp, const unsigned char *ptr, 497258065Spjd size_t *leftp) 498258065Spjd{ 499258065Spjd uint8_t value; 500258065Spjd 501258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 502258065Spjd 503258065Spjd if (nvp->nvp_datasize != sizeof(value)) { 504258065Spjd errno = EINVAL; 505258065Spjd return (NULL); 506258065Spjd } 507258065Spjd if (*leftp < sizeof(value)) { 508258065Spjd errno = EINVAL; 509258065Spjd return (NULL); 510258065Spjd } 511258065Spjd 512258065Spjd memcpy(&value, ptr, sizeof(value)); 513258065Spjd ptr += sizeof(value); 514258065Spjd *leftp -= sizeof(value); 515258065Spjd 516258065Spjd if (value != 0 && value != 1) { 517258065Spjd errno = EINVAL; 518258065Spjd return (NULL); 519258065Spjd } 520258065Spjd 521258065Spjd nvp->nvp_data = (uint64_t)value; 522258065Spjd 523258065Spjd return (ptr); 524258065Spjd} 525258065Spjd 526258065Spjdstatic const unsigned char * 527258065Spjdnvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr, 528258065Spjd size_t *leftp) 529258065Spjd{ 530258065Spjd 531258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 532258065Spjd 533258065Spjd if (nvp->nvp_datasize != sizeof(uint64_t)) { 534258065Spjd errno = EINVAL; 535258065Spjd return (NULL); 536258065Spjd } 537258065Spjd if (*leftp < sizeof(uint64_t)) { 538258065Spjd errno = EINVAL; 539258065Spjd return (NULL); 540258065Spjd } 541258065Spjd 542258065Spjd if ((flags & NV_FLAG_BIG_ENDIAN) != 0) 543258065Spjd nvp->nvp_data = be64dec(ptr); 544258065Spjd else 545258065Spjd nvp->nvp_data = le64dec(ptr); 546258065Spjd ptr += sizeof(uint64_t); 547258065Spjd *leftp -= sizeof(uint64_t); 548258065Spjd 549258065Spjd return (ptr); 550258065Spjd} 551258065Spjd 552258065Spjdstatic const unsigned char * 553258065Spjdnvpair_unpack_string(int flags __unused, nvpair_t *nvp, 554258065Spjd const unsigned char *ptr, size_t *leftp) 555258065Spjd{ 556258065Spjd 557258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 558258065Spjd 559258065Spjd if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 560258065Spjd errno = EINVAL; 561258065Spjd return (NULL); 562258065Spjd } 563258065Spjd 564258065Spjd if (strnlen((const char *)ptr, nvp->nvp_datasize) != 565258065Spjd nvp->nvp_datasize - 1) { 566258065Spjd errno = EINVAL; 567258065Spjd return (NULL); 568258065Spjd } 569258065Spjd 570258065Spjd nvp->nvp_data = (uint64_t)(uintptr_t)strdup((const char *)ptr); 571258065Spjd if (nvp->nvp_data == 0) 572258065Spjd return (NULL); 573258065Spjd 574258065Spjd ptr += nvp->nvp_datasize; 575258065Spjd *leftp -= nvp->nvp_datasize; 576258065Spjd 577258065Spjd return (ptr); 578258065Spjd} 579258065Spjd 580258065Spjdstatic const unsigned char * 581258065Spjdnvpair_unpack_nvlist(int flags __unused, nvpair_t *nvp, 582258065Spjd const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds) 583258065Spjd{ 584258065Spjd nvlist_t *value; 585258065Spjd 586258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 587258065Spjd 588258065Spjd if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 589258065Spjd errno = EINVAL; 590258065Spjd return (NULL); 591258065Spjd } 592258065Spjd 593258065Spjd value = nvlist_xunpack(ptr, nvp->nvp_datasize, fds, nfds); 594258065Spjd if (value == NULL) 595258065Spjd return (NULL); 596258065Spjd 597258065Spjd nvp->nvp_data = (uint64_t)(uintptr_t)value; 598258065Spjd 599258065Spjd ptr += nvp->nvp_datasize; 600258065Spjd *leftp -= nvp->nvp_datasize; 601258065Spjd 602258065Spjd return (ptr); 603258065Spjd} 604258065Spjd 605258065Spjdstatic const unsigned char * 606258065Spjdnvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr, 607258065Spjd size_t *leftp, const int *fds, size_t nfds) 608258065Spjd{ 609258065Spjd int64_t idx; 610258065Spjd 611258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 612258065Spjd 613258065Spjd if (nvp->nvp_datasize != sizeof(idx)) { 614258065Spjd errno = EINVAL; 615258065Spjd return (NULL); 616258065Spjd } 617258065Spjd if (*leftp < sizeof(idx)) { 618258065Spjd errno = EINVAL; 619258065Spjd return (NULL); 620258065Spjd } 621258065Spjd 622258065Spjd if ((flags & NV_FLAG_BIG_ENDIAN) != 0) 623258065Spjd idx = be64dec(ptr); 624258065Spjd else 625258065Spjd idx = le64dec(ptr); 626258065Spjd 627258065Spjd if (idx < 0) { 628258065Spjd errno = EINVAL; 629258065Spjd return (NULL); 630258065Spjd } 631258065Spjd 632258065Spjd if ((size_t)idx >= nfds) { 633258065Spjd errno = EINVAL; 634258065Spjd return (NULL); 635258065Spjd } 636258065Spjd 637258065Spjd nvp->nvp_data = (uint64_t)fds[idx]; 638258065Spjd 639258065Spjd ptr += sizeof(idx); 640258065Spjd *leftp -= sizeof(idx); 641258065Spjd 642258065Spjd return (ptr); 643258065Spjd} 644258065Spjd 645258065Spjdstatic const unsigned char * 646258065Spjdnvpair_unpack_binary(int flags __unused, nvpair_t *nvp, 647258065Spjd const unsigned char *ptr, size_t *leftp) 648258065Spjd{ 649258065Spjd void *value; 650258065Spjd 651258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 652258065Spjd 653258065Spjd if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 654258065Spjd errno = EINVAL; 655258065Spjd return (NULL); 656258065Spjd } 657258065Spjd 658258065Spjd value = malloc(nvp->nvp_datasize); 659258065Spjd if (value == NULL) 660258065Spjd return (NULL); 661258065Spjd 662258065Spjd memcpy(value, ptr, nvp->nvp_datasize); 663258065Spjd ptr += nvp->nvp_datasize; 664258065Spjd *leftp -= nvp->nvp_datasize; 665258065Spjd 666258065Spjd nvp->nvp_data = (uint64_t)(uintptr_t)value; 667258065Spjd 668258065Spjd return (ptr); 669258065Spjd} 670258065Spjd 671258065Spjdconst unsigned char * 672258065Spjdnvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp, 673258065Spjd const int *fds, size_t nfds, nvpair_t **nvpp) 674258065Spjd{ 675258065Spjd nvpair_t *nvp, *tmp; 676258065Spjd 677258065Spjd nvp = calloc(1, sizeof(*nvp) + NV_NAME_MAX); 678258065Spjd if (nvp == NULL) 679258065Spjd return (NULL); 680258065Spjd nvp->nvp_name = (char *)(nvp + 1); 681258065Spjd 682258065Spjd ptr = nvpair_unpack_header(flags, nvp, ptr, leftp); 683258065Spjd if (ptr == NULL) 684258065Spjd goto failed; 685258065Spjd tmp = realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 686258594Spjd if (tmp == NULL) 687258065Spjd goto failed; 688258065Spjd nvp = tmp; 689258065Spjd /* Update nvp_name after realloc(). */ 690258065Spjd nvp->nvp_name = (char *)(nvp + 1); 691258065Spjd 692258065Spjd switch (nvp->nvp_type) { 693258065Spjd case NV_TYPE_NULL: 694258065Spjd ptr = nvpair_unpack_null(flags, nvp, ptr, leftp); 695258065Spjd break; 696258065Spjd case NV_TYPE_BOOL: 697258065Spjd ptr = nvpair_unpack_bool(flags, nvp, ptr, leftp); 698258065Spjd break; 699258065Spjd case NV_TYPE_NUMBER: 700258065Spjd ptr = nvpair_unpack_number(flags, nvp, ptr, leftp); 701258065Spjd break; 702258065Spjd case NV_TYPE_STRING: 703258065Spjd ptr = nvpair_unpack_string(flags, nvp, ptr, leftp); 704258065Spjd break; 705258065Spjd case NV_TYPE_NVLIST: 706258065Spjd ptr = nvpair_unpack_nvlist(flags, nvp, ptr, leftp, fds, 707258065Spjd nfds); 708258065Spjd break; 709258065Spjd case NV_TYPE_DESCRIPTOR: 710258065Spjd ptr = nvpair_unpack_descriptor(flags, nvp, ptr, leftp, fds, 711258065Spjd nfds); 712258065Spjd break; 713258065Spjd case NV_TYPE_BINARY: 714258065Spjd ptr = nvpair_unpack_binary(flags, nvp, ptr, leftp); 715258065Spjd break; 716258065Spjd default: 717258065Spjd PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type); 718258065Spjd } 719258065Spjd 720258065Spjd if (ptr == NULL) 721258065Spjd goto failed; 722258065Spjd 723258065Spjd nvp->nvp_magic = NVPAIR_MAGIC; 724258065Spjd *nvpp = nvp; 725258065Spjd return (ptr); 726258065Spjdfailed: 727258065Spjd free(nvp); 728258065Spjd return (NULL); 729258065Spjd} 730258065Spjd 731258065Spjdint 732258065Spjdnvpair_type(const nvpair_t *nvp) 733258065Spjd{ 734258065Spjd 735258065Spjd NVPAIR_ASSERT(nvp); 736258065Spjd 737258065Spjd return (nvp->nvp_type); 738258065Spjd} 739258065Spjd 740258065Spjdconst char * 741258065Spjdnvpair_name(const nvpair_t *nvp) 742258065Spjd{ 743258065Spjd 744258065Spjd NVPAIR_ASSERT(nvp); 745258065Spjd 746258065Spjd return (nvp->nvp_name); 747258065Spjd} 748258065Spjd 749258065Spjdstatic nvpair_t * 750258065Spjdnvpair_allocv(int type, uint64_t data, size_t datasize, const char *namefmt, 751258065Spjd va_list nameap) 752258065Spjd{ 753258065Spjd nvpair_t *nvp; 754258065Spjd char *name; 755258065Spjd int namelen; 756258065Spjd 757258065Spjd PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); 758258065Spjd 759258065Spjd namelen = vasprintf(&name, namefmt, nameap); 760258065Spjd if (namelen < 0) 761258065Spjd return (NULL); 762258065Spjd 763258065Spjd PJDLOG_ASSERT(namelen > 0); 764258065Spjd if (namelen >= NV_NAME_MAX) { 765258065Spjd free(name); 766258065Spjd errno = ENAMETOOLONG; 767258065Spjd return (NULL); 768258065Spjd } 769258065Spjd 770258065Spjd nvp = calloc(1, sizeof(*nvp) + namelen + 1); 771258065Spjd if (nvp != NULL) { 772258065Spjd nvp->nvp_name = (char *)(nvp + 1); 773258065Spjd memcpy(nvp->nvp_name, name, namelen + 1); 774258065Spjd nvp->nvp_type = type; 775258065Spjd nvp->nvp_data = data; 776258065Spjd nvp->nvp_datasize = datasize; 777258065Spjd nvp->nvp_magic = NVPAIR_MAGIC; 778258065Spjd } 779258065Spjd free(name); 780258065Spjd 781258065Spjd return (nvp); 782258065Spjd}; 783258065Spjd 784258065Spjdnvpair_t * 785258065Spjdnvpair_create_null(const char *name) 786258065Spjd{ 787258065Spjd 788258065Spjd return (nvpair_createf_null("%s", name)); 789258065Spjd} 790258065Spjd 791258065Spjdnvpair_t * 792258065Spjdnvpair_create_bool(const char *name, bool value) 793258065Spjd{ 794258065Spjd 795258065Spjd return (nvpair_createf_bool(value, "%s", name)); 796258065Spjd} 797258065Spjd 798258065Spjdnvpair_t * 799258065Spjdnvpair_create_number(const char *name, uint64_t value) 800258065Spjd{ 801258065Spjd 802258065Spjd return (nvpair_createf_number(value, "%s", name)); 803258065Spjd} 804258065Spjd 805258065Spjdnvpair_t * 806258065Spjdnvpair_create_string(const char *name, const char *value) 807258065Spjd{ 808258065Spjd 809258065Spjd return (nvpair_createf_string(value, "%s", name)); 810258065Spjd} 811258065Spjd 812258065Spjdnvpair_t * 813258065Spjdnvpair_create_stringf(const char *name, const char *valuefmt, ...) 814258065Spjd{ 815258065Spjd va_list valueap; 816258065Spjd nvpair_t *nvp; 817258065Spjd 818258065Spjd va_start(valueap, valuefmt); 819258065Spjd nvp = nvpair_create_stringv(name, valuefmt, valueap); 820258065Spjd va_end(valueap); 821258065Spjd 822258065Spjd return (nvp); 823258065Spjd} 824258065Spjd 825258065Spjdnvpair_t * 826258065Spjdnvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 827258065Spjd{ 828258065Spjd nvpair_t *nvp; 829258065Spjd char *str; 830258065Spjd int len; 831258065Spjd 832258065Spjd len = vasprintf(&str, valuefmt, valueap); 833258065Spjd if (len < 0) 834258065Spjd return (NULL); 835258065Spjd nvp = nvpair_create_string(name, str); 836258065Spjd if (nvp == NULL) 837258065Spjd free(str); 838258065Spjd return (nvp); 839258065Spjd} 840258065Spjd 841258065Spjdnvpair_t * 842258065Spjdnvpair_create_nvlist(const char *name, const nvlist_t *value) 843258065Spjd{ 844258065Spjd 845258065Spjd return (nvpair_createf_nvlist(value, "%s", name)); 846258065Spjd} 847258065Spjd 848258065Spjdnvpair_t * 849258065Spjdnvpair_create_descriptor(const char *name, int value) 850258065Spjd{ 851258065Spjd 852258065Spjd return (nvpair_createf_descriptor(value, "%s", name)); 853258065Spjd} 854258065Spjd 855258065Spjdnvpair_t * 856258065Spjdnvpair_create_binary(const char *name, const void *value, size_t size) 857258065Spjd{ 858258065Spjd 859258065Spjd return (nvpair_createf_binary(value, size, "%s", name)); 860258065Spjd} 861258065Spjd 862258065Spjdnvpair_t * 863258065Spjdnvpair_createf_null(const char *namefmt, ...) 864258065Spjd{ 865258065Spjd va_list nameap; 866258065Spjd nvpair_t *nvp; 867258065Spjd 868258065Spjd va_start(nameap, namefmt); 869258065Spjd nvp = nvpair_createv_null(namefmt, nameap); 870258065Spjd va_end(nameap); 871258065Spjd 872258065Spjd return (nvp); 873258065Spjd} 874258065Spjd 875258065Spjdnvpair_t * 876258065Spjdnvpair_createf_bool(bool value, const char *namefmt, ...) 877258065Spjd{ 878258065Spjd va_list nameap; 879258065Spjd nvpair_t *nvp; 880258065Spjd 881258065Spjd va_start(nameap, namefmt); 882258065Spjd nvp = nvpair_createv_bool(value, namefmt, nameap); 883258065Spjd va_end(nameap); 884258065Spjd 885258065Spjd return (nvp); 886258065Spjd} 887258065Spjd 888258065Spjdnvpair_t * 889258065Spjdnvpair_createf_number(uint64_t value, const char *namefmt, ...) 890258065Spjd{ 891258065Spjd va_list nameap; 892258065Spjd nvpair_t *nvp; 893258065Spjd 894258065Spjd va_start(nameap, namefmt); 895258065Spjd nvp = nvpair_createv_number(value, namefmt, nameap); 896258065Spjd va_end(nameap); 897258065Spjd 898258065Spjd return (nvp); 899258065Spjd} 900258065Spjd 901258065Spjdnvpair_t * 902258065Spjdnvpair_createf_string(const char *value, const char *namefmt, ...) 903258065Spjd{ 904258065Spjd va_list nameap; 905258065Spjd nvpair_t *nvp; 906258065Spjd 907258065Spjd va_start(nameap, namefmt); 908258065Spjd nvp = nvpair_createv_string(value, namefmt, nameap); 909258065Spjd va_end(nameap); 910258065Spjd 911258065Spjd return (nvp); 912258065Spjd} 913258065Spjd 914258065Spjdnvpair_t * 915258065Spjdnvpair_createf_nvlist(const nvlist_t *value, const char *namefmt, ...) 916258065Spjd{ 917258065Spjd va_list nameap; 918258065Spjd nvpair_t *nvp; 919258065Spjd 920258065Spjd va_start(nameap, namefmt); 921258065Spjd nvp = nvpair_createv_nvlist(value, namefmt, nameap); 922258065Spjd va_end(nameap); 923258065Spjd 924258065Spjd return (nvp); 925258065Spjd} 926258065Spjd 927258065Spjdnvpair_t * 928258065Spjdnvpair_createf_descriptor(int value, const char *namefmt, ...) 929258065Spjd{ 930258065Spjd va_list nameap; 931258065Spjd nvpair_t *nvp; 932258065Spjd 933258065Spjd va_start(nameap, namefmt); 934258065Spjd nvp = nvpair_createv_descriptor(value, namefmt, nameap); 935258065Spjd va_end(nameap); 936258065Spjd 937258065Spjd return (nvp); 938258065Spjd} 939258065Spjd 940258065Spjdnvpair_t * 941258065Spjdnvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...) 942258065Spjd{ 943258065Spjd va_list nameap; 944258065Spjd nvpair_t *nvp; 945258065Spjd 946258065Spjd va_start(nameap, namefmt); 947258065Spjd nvp = nvpair_createv_binary(value, size, namefmt, nameap); 948258065Spjd va_end(nameap); 949258065Spjd 950258065Spjd return (nvp); 951258065Spjd} 952258065Spjd 953258065Spjdnvpair_t * 954258065Spjdnvpair_createv_null(const char *namefmt, va_list nameap) 955258065Spjd{ 956258065Spjd 957258065Spjd return (nvpair_allocv(NV_TYPE_NULL, 0, 0, namefmt, nameap)); 958258065Spjd} 959258065Spjd 960258065Spjdnvpair_t * 961258065Spjdnvpair_createv_bool(bool value, const char *namefmt, va_list nameap) 962258065Spjd{ 963258065Spjd 964258065Spjd return (nvpair_allocv(NV_TYPE_BOOL, value ? 1 : 0, sizeof(uint8_t), 965258065Spjd namefmt, nameap)); 966258065Spjd} 967258065Spjd 968258065Spjdnvpair_t * 969258065Spjdnvpair_createv_number(uint64_t value, const char *namefmt, va_list nameap) 970258065Spjd{ 971258065Spjd 972258065Spjd return (nvpair_allocv(NV_TYPE_NUMBER, value, sizeof(value), namefmt, 973258065Spjd nameap)); 974258065Spjd} 975258065Spjd 976258065Spjdnvpair_t * 977258065Spjdnvpair_createv_string(const char *value, const char *namefmt, va_list nameap) 978258065Spjd{ 979258065Spjd nvpair_t *nvp; 980258065Spjd size_t size; 981258065Spjd char *data; 982258065Spjd 983258065Spjd if (value == NULL) { 984258065Spjd errno = EINVAL; 985258065Spjd return (NULL); 986258065Spjd } 987258065Spjd 988258065Spjd data = strdup(value); 989258065Spjd if (data == NULL) 990258065Spjd return (NULL); 991258065Spjd size = strlen(value) + 1; 992258065Spjd 993258065Spjd nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)data, size, 994258065Spjd namefmt, nameap); 995258065Spjd if (nvp == NULL) 996258065Spjd free(data); 997258065Spjd 998258065Spjd return (nvp); 999258065Spjd} 1000258065Spjd 1001258065Spjdnvpair_t * 1002258065Spjdnvpair_createv_nvlist(const nvlist_t *value, const char *namefmt, 1003258065Spjd va_list nameap) 1004258065Spjd{ 1005258065Spjd nvlist_t *nvl; 1006258065Spjd nvpair_t *nvp; 1007258065Spjd 1008258065Spjd if (value == NULL) { 1009258065Spjd errno = EINVAL; 1010258065Spjd return (NULL); 1011258065Spjd } 1012258065Spjd 1013258065Spjd nvl = nvlist_clone(value); 1014258065Spjd if (nvl == NULL) 1015258065Spjd return (NULL); 1016258065Spjd 1017258065Spjd nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 1018258065Spjd namefmt, nameap); 1019258065Spjd if (nvp == NULL) 1020258065Spjd nvlist_destroy(nvl); 1021258065Spjd 1022258065Spjd return (nvp); 1023258065Spjd} 1024258065Spjd 1025258065Spjdnvpair_t * 1026258065Spjdnvpair_createv_descriptor(int value, const char *namefmt, va_list nameap) 1027258065Spjd{ 1028258065Spjd nvpair_t *nvp; 1029258065Spjd 1030258065Spjd if (value < 0 || !fd_is_valid(value)) { 1031258065Spjd errno = EBADF; 1032258065Spjd return (NULL); 1033258065Spjd } 1034258065Spjd 1035258065Spjd value = fcntl(value, F_DUPFD_CLOEXEC, 0); 1036258065Spjd if (value < 0) 1037258065Spjd return (NULL); 1038258065Spjd 1039258065Spjd nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, 1040258065Spjd sizeof(int64_t), namefmt, nameap); 1041258065Spjd if (nvp == NULL) 1042258065Spjd close(value); 1043258065Spjd 1044258065Spjd return (nvp); 1045258065Spjd} 1046258065Spjd 1047258065Spjdnvpair_t * 1048258065Spjdnvpair_createv_binary(const void *value, size_t size, const char *namefmt, 1049258065Spjd va_list nameap) 1050258065Spjd{ 1051258065Spjd nvpair_t *nvp; 1052258065Spjd void *data; 1053258065Spjd 1054258065Spjd if (value == NULL || size == 0) { 1055258065Spjd errno = EINVAL; 1056258065Spjd return (NULL); 1057258065Spjd } 1058258065Spjd 1059258065Spjd data = malloc(size); 1060258065Spjd if (data == NULL) 1061258065Spjd return (NULL); 1062258065Spjd memcpy(data, value, size); 1063258065Spjd 1064258065Spjd nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, size, 1065258065Spjd namefmt, nameap); 1066258065Spjd if (nvp == NULL) 1067258065Spjd free(data); 1068258065Spjd 1069258065Spjd return (nvp); 1070258065Spjd} 1071258065Spjd 1072258065Spjdnvpair_t * 1073258065Spjdnvpair_move_string(const char *name, char *value) 1074258065Spjd{ 1075258065Spjd 1076258065Spjd return (nvpair_movef_string(value, "%s", name)); 1077258065Spjd} 1078258065Spjd 1079258065Spjdnvpair_t * 1080258065Spjdnvpair_move_nvlist(const char *name, nvlist_t *value) 1081258065Spjd{ 1082258065Spjd 1083258065Spjd return (nvpair_movef_nvlist(value, "%s", name)); 1084258065Spjd} 1085258065Spjd 1086258065Spjdnvpair_t * 1087258065Spjdnvpair_move_descriptor(const char *name, int value) 1088258065Spjd{ 1089258065Spjd 1090258065Spjd return (nvpair_movef_descriptor(value, "%s", name)); 1091258065Spjd} 1092258065Spjd 1093258065Spjdnvpair_t * 1094258065Spjdnvpair_move_binary(const char *name, void *value, size_t size) 1095258065Spjd{ 1096258065Spjd 1097258065Spjd return (nvpair_movef_binary(value, size, "%s", name)); 1098258065Spjd} 1099258065Spjd 1100258065Spjdnvpair_t * 1101258065Spjdnvpair_movef_string(char *value, const char *namefmt, ...) 1102258065Spjd{ 1103258065Spjd va_list nameap; 1104258065Spjd nvpair_t *nvp; 1105258065Spjd 1106258065Spjd va_start(nameap, namefmt); 1107258065Spjd nvp = nvpair_movev_string(value, namefmt, nameap); 1108258065Spjd va_end(nameap); 1109258065Spjd 1110258065Spjd return (nvp); 1111258065Spjd} 1112258065Spjd 1113258065Spjdnvpair_t * 1114258065Spjdnvpair_movef_nvlist(nvlist_t *value, const char *namefmt, ...) 1115258065Spjd{ 1116258065Spjd va_list nameap; 1117258065Spjd nvpair_t *nvp; 1118258065Spjd 1119258065Spjd va_start(nameap, namefmt); 1120258065Spjd nvp = nvpair_movev_nvlist(value, namefmt, nameap); 1121258065Spjd va_end(nameap); 1122258065Spjd 1123258065Spjd return (nvp); 1124258065Spjd} 1125258065Spjd 1126258065Spjdnvpair_t * 1127258065Spjdnvpair_movef_descriptor(int value, const char *namefmt, ...) 1128258065Spjd{ 1129258065Spjd va_list nameap; 1130258065Spjd nvpair_t *nvp; 1131258065Spjd 1132258065Spjd va_start(nameap, namefmt); 1133258065Spjd nvp = nvpair_movev_descriptor(value, namefmt, nameap); 1134258065Spjd va_end(nameap); 1135258065Spjd 1136258065Spjd return (nvp); 1137258065Spjd} 1138258065Spjd 1139258065Spjdnvpair_t * 1140258065Spjdnvpair_movef_binary(void *value, size_t size, const char *namefmt, ...) 1141258065Spjd{ 1142258065Spjd va_list nameap; 1143258065Spjd nvpair_t *nvp; 1144258065Spjd 1145258065Spjd va_start(nameap, namefmt); 1146258065Spjd nvp = nvpair_movev_binary(value, size, namefmt, nameap); 1147258065Spjd va_end(nameap); 1148258065Spjd 1149258065Spjd return (nvp); 1150258065Spjd} 1151258065Spjd 1152258065Spjdnvpair_t * 1153258065Spjdnvpair_movev_string(char *value, const char *namefmt, va_list nameap) 1154258065Spjd{ 1155258065Spjd nvpair_t *nvp; 1156258065Spjd 1157258065Spjd if (value == NULL) { 1158258065Spjd errno = EINVAL; 1159258065Spjd return (NULL); 1160258065Spjd } 1161258065Spjd 1162258065Spjd nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 1163258065Spjd strlen(value) + 1, namefmt, nameap); 1164258065Spjd if (nvp == NULL) 1165258065Spjd free(value); 1166258065Spjd 1167258065Spjd return (nvp); 1168258065Spjd} 1169258065Spjd 1170258065Spjdnvpair_t * 1171258065Spjdnvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap) 1172258065Spjd{ 1173258065Spjd nvpair_t *nvp; 1174258065Spjd 1175258065Spjd if (value == NULL) { 1176258065Spjd errno = EINVAL; 1177258065Spjd return (NULL); 1178258065Spjd } 1179258065Spjd 1180258065Spjd nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 0, 1181258065Spjd namefmt, nameap); 1182258065Spjd if (nvp == NULL) 1183258065Spjd nvlist_destroy(value); 1184258065Spjd 1185258065Spjd return (nvp); 1186258065Spjd} 1187258065Spjd 1188258065Spjdnvpair_t * 1189258065Spjdnvpair_movev_descriptor(int value, const char *namefmt, va_list nameap) 1190258065Spjd{ 1191258065Spjd 1192258065Spjd if (value < 0 || !fd_is_valid(value)) { 1193258065Spjd errno = EBADF; 1194258065Spjd return (NULL); 1195258065Spjd } 1196258065Spjd 1197258065Spjd return (nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, 1198258065Spjd sizeof(int64_t), namefmt, nameap)); 1199258065Spjd} 1200258065Spjd 1201258065Spjdnvpair_t * 1202258065Spjdnvpair_movev_binary(void *value, size_t size, const char *namefmt, 1203258065Spjd va_list nameap) 1204258065Spjd{ 1205258065Spjd 1206258065Spjd if (value == NULL || size == 0) { 1207258065Spjd errno = EINVAL; 1208258065Spjd return (NULL); 1209258065Spjd } 1210258065Spjd 1211258065Spjd return (nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size, 1212258065Spjd namefmt, nameap)); 1213258065Spjd} 1214258065Spjd 1215258065Spjdbool 1216258065Spjdnvpair_get_bool(const nvpair_t *nvp) 1217258065Spjd{ 1218258065Spjd 1219258065Spjd NVPAIR_ASSERT(nvp); 1220258065Spjd 1221258065Spjd return (nvp->nvp_data == 1); 1222258065Spjd} 1223258065Spjd 1224258065Spjduint64_t 1225258065Spjdnvpair_get_number(const nvpair_t *nvp) 1226258065Spjd{ 1227258065Spjd 1228258065Spjd NVPAIR_ASSERT(nvp); 1229258065Spjd 1230258065Spjd return (nvp->nvp_data); 1231258065Spjd} 1232258065Spjd 1233258065Spjdconst char * 1234258065Spjdnvpair_get_string(const nvpair_t *nvp) 1235258065Spjd{ 1236258065Spjd 1237258065Spjd NVPAIR_ASSERT(nvp); 1238258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1239258065Spjd 1240258065Spjd return ((const char *)(intptr_t)nvp->nvp_data); 1241258065Spjd} 1242258065Spjd 1243258065Spjdconst nvlist_t * 1244258065Spjdnvpair_get_nvlist(const nvpair_t *nvp) 1245258065Spjd{ 1246258065Spjd 1247258065Spjd NVPAIR_ASSERT(nvp); 1248258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1249258065Spjd 1250258065Spjd return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1251258065Spjd} 1252258065Spjd 1253258065Spjdint 1254258065Spjdnvpair_get_descriptor(const nvpair_t *nvp) 1255258065Spjd{ 1256258065Spjd 1257258065Spjd NVPAIR_ASSERT(nvp); 1258258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1259258065Spjd 1260258065Spjd return ((int)nvp->nvp_data); 1261258065Spjd} 1262258065Spjd 1263258065Spjdconst void * 1264258065Spjdnvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1265258065Spjd{ 1266258065Spjd 1267258065Spjd NVPAIR_ASSERT(nvp); 1268258065Spjd PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1269258065Spjd 1270258065Spjd if (sizep != NULL) 1271258065Spjd *sizep = nvp->nvp_datasize; 1272258065Spjd return ((const void *)(intptr_t)nvp->nvp_data); 1273258065Spjd} 1274258065Spjd 1275258065Spjdvoid 1276258065Spjdnvpair_free(nvpair_t *nvp) 1277258065Spjd{ 1278258065Spjd 1279258065Spjd NVPAIR_ASSERT(nvp); 1280258065Spjd PJDLOG_ASSERT(nvp->nvp_list == NULL); 1281258065Spjd 1282258065Spjd nvp->nvp_magic = 0; 1283258065Spjd switch (nvp->nvp_type) { 1284258065Spjd case NV_TYPE_DESCRIPTOR: 1285258065Spjd close((int)nvp->nvp_data); 1286258065Spjd break; 1287258065Spjd case NV_TYPE_NVLIST: 1288258065Spjd nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 1289258065Spjd break; 1290258065Spjd case NV_TYPE_STRING: 1291258065Spjd free((char *)(intptr_t)nvp->nvp_data); 1292258065Spjd break; 1293258065Spjd case NV_TYPE_BINARY: 1294258065Spjd free((void *)(intptr_t)nvp->nvp_data); 1295258065Spjd break; 1296258065Spjd } 1297258065Spjd free(nvp); 1298258065Spjd} 1299258065Spjd 1300258065Spjdvoid 1301258065Spjdnvpair_free_structure(nvpair_t *nvp) 1302258065Spjd{ 1303258065Spjd 1304258065Spjd NVPAIR_ASSERT(nvp); 1305258065Spjd PJDLOG_ASSERT(nvp->nvp_list == NULL); 1306258065Spjd 1307258065Spjd nvp->nvp_magic = 0; 1308258065Spjd free(nvp); 1309258065Spjd} 1310258065Spjd 1311258065Spjdconst char * 1312258065Spjdnvpair_type_string(int type) 1313258065Spjd{ 1314258065Spjd 1315258065Spjd switch (type) { 1316258065Spjd case NV_TYPE_NULL: 1317258065Spjd return ("NULL"); 1318258065Spjd case NV_TYPE_BOOL: 1319258065Spjd return ("BOOL"); 1320258065Spjd case NV_TYPE_NUMBER: 1321258065Spjd return ("NUMBER"); 1322258065Spjd case NV_TYPE_STRING: 1323258065Spjd return ("STRING"); 1324258065Spjd case NV_TYPE_NVLIST: 1325258065Spjd return ("NVLIST"); 1326258065Spjd case NV_TYPE_DESCRIPTOR: 1327258065Spjd return ("DESCRIPTOR"); 1328258065Spjd case NV_TYPE_BINARY: 1329258065Spjd return ("BINARY"); 1330258065Spjd default: 1331258065Spjd return ("<UNKNOWN>"); 1332258065Spjd } 1333258065Spjd} 1334