subr_nvlist.c revision 260222
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/nvlist.c 260222 2014-01-03 09:07:03Z pjd $"); 32258065Spjd 33258065Spjd#include <sys/param.h> 34258065Spjd#include <sys/endian.h> 35258065Spjd#include <sys/queue.h> 36258065Spjd#include <sys/socket.h> 37258065Spjd 38258065Spjd#include <errno.h> 39258065Spjd#include <stdarg.h> 40258065Spjd#include <stdbool.h> 41258065Spjd#include <stdint.h> 42258065Spjd#define _WITH_DPRINTF 43258065Spjd#include <stdio.h> 44258065Spjd#include <stdlib.h> 45258065Spjd#include <string.h> 46258065Spjd#include <unistd.h> 47258065Spjd 48258065Spjd#ifdef HAVE_PJDLOG 49258065Spjd#include <pjdlog.h> 50258065Spjd#endif 51258065Spjd 52258065Spjd#include "msgio.h" 53258065Spjd#include "nv.h" 54258065Spjd#include "nv_impl.h" 55258065Spjd#include "nvlist_impl.h" 56258065Spjd#include "nvpair_impl.h" 57258065Spjd 58258065Spjd#ifndef HAVE_PJDLOG 59258065Spjd#include <assert.h> 60258065Spjd#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 61258065Spjd#define PJDLOG_RASSERT(expr, ...) assert(expr) 62258065Spjd#define PJDLOG_ABORT(...) do { \ 63258065Spjd fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \ 64258065Spjd fprintf(stderr, __VA_ARGS__); \ 65258065Spjd fprintf(stderr, "\n"); \ 66258065Spjd abort(); \ 67258065Spjd} while (0) 68258065Spjd#endif 69258065Spjd 70258065Spjd#define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN) 71258065Spjd#define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE) 72258065Spjd#define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK) 73258065Spjd 74258065Spjd#define NVLIST_MAGIC 0x6e766c /* "nvl" */ 75258065Spjdstruct nvlist { 76258065Spjd int nvl_magic; 77258065Spjd int nvl_error; 78258065Spjd int nvl_flags; 79258065Spjd struct nvl_head nvl_head; 80258065Spjd}; 81258065Spjd 82258065Spjd#define NVLIST_ASSERT(nvl) do { \ 83258065Spjd PJDLOG_ASSERT((nvl) != NULL); \ 84258065Spjd PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \ 85258065Spjd} while (0) 86258065Spjd 87258065Spjd#define NVPAIR_ASSERT(nvp) nvpair_assert(nvp) 88258065Spjd 89258065Spjd#define NVLIST_HEADER_MAGIC 0x6c 90258065Spjd#define NVLIST_HEADER_VERSION 0x00 91258065Spjdstruct nvlist_header { 92258065Spjd uint8_t nvlh_magic; 93258065Spjd uint8_t nvlh_version; 94258065Spjd uint8_t nvlh_flags; 95258065Spjd uint64_t nvlh_descriptors; 96258065Spjd uint64_t nvlh_size; 97258065Spjd} __packed; 98258065Spjd 99258065Spjdnvlist_t * 100258065Spjdnvlist_create(int flags) 101258065Spjd{ 102258065Spjd nvlist_t *nvl; 103258065Spjd 104258065Spjd PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 105258065Spjd 106258065Spjd nvl = malloc(sizeof(*nvl)); 107258065Spjd nvl->nvl_error = 0; 108258065Spjd nvl->nvl_flags = flags; 109258065Spjd TAILQ_INIT(&nvl->nvl_head); 110258065Spjd nvl->nvl_magic = NVLIST_MAGIC; 111258065Spjd 112258065Spjd return (nvl); 113258065Spjd} 114258065Spjd 115258065Spjdvoid 116258065Spjdnvlist_destroy(nvlist_t *nvl) 117258065Spjd{ 118258065Spjd nvpair_t *nvp; 119258065Spjd int serrno; 120258065Spjd 121258065Spjd if (nvl == NULL) 122258065Spjd return; 123258065Spjd 124258065Spjd serrno = errno; 125258065Spjd 126258065Spjd NVLIST_ASSERT(nvl); 127258065Spjd 128260222Spjd while ((nvp = nvlist_first_nvpair(nvl)) != NULL) { 129258065Spjd nvlist_remove_nvpair(nvl, nvp); 130260222Spjd nvpair_free(nvp); 131260222Spjd } 132258065Spjd nvl->nvl_magic = 0; 133258065Spjd free(nvl); 134258065Spjd 135258065Spjd errno = serrno; 136258065Spjd} 137258065Spjd 138258065Spjdint 139258065Spjdnvlist_error(const nvlist_t *nvl) 140258065Spjd{ 141258065Spjd 142258065Spjd if (nvl == NULL) 143258065Spjd return (ENOMEM); 144258065Spjd 145258065Spjd NVLIST_ASSERT(nvl); 146258065Spjd 147258065Spjd return (nvl->nvl_error); 148258065Spjd} 149258065Spjd 150258065Spjdbool 151258065Spjdnvlist_empty(const nvlist_t *nvl) 152258065Spjd{ 153258065Spjd 154258065Spjd NVLIST_ASSERT(nvl); 155258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 156258065Spjd 157258065Spjd return (nvlist_first_nvpair(nvl) == NULL); 158258065Spjd} 159258065Spjd 160258065Spjdstatic void 161258065Spjdnvlist_report_missing(int type, const char *namefmt, va_list nameap) 162258065Spjd{ 163258065Spjd char *name; 164258065Spjd 165258065Spjd vasprintf(&name, namefmt, nameap); 166258065Spjd PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", 167258065Spjd name != NULL ? name : "N/A", nvpair_type_string(type)); 168258065Spjd} 169258065Spjd 170258065Spjdstatic nvpair_t * 171258065Spjdnvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap) 172258065Spjd{ 173258065Spjd nvpair_t *nvp; 174258065Spjd char *name; 175258065Spjd 176258065Spjd NVLIST_ASSERT(nvl); 177258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 178258065Spjd PJDLOG_ASSERT(type == NV_TYPE_NONE || 179258065Spjd (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 180258065Spjd 181258065Spjd if (vasprintf(&name, namefmt, nameap) < 0) 182258065Spjd return (NULL); 183258065Spjd 184258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 185258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 186258065Spjd if (type != NV_TYPE_NONE && nvpair_type(nvp) != type) 187258065Spjd continue; 188258065Spjd if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) { 189258065Spjd if (strcasecmp(nvpair_name(nvp), name) != 0) 190258065Spjd continue; 191258065Spjd } else { 192258065Spjd if (strcmp(nvpair_name(nvp), name) != 0) 193258065Spjd continue; 194258065Spjd } 195258065Spjd break; 196258065Spjd } 197258065Spjd 198258065Spjd free(name); 199258065Spjd 200258065Spjd if (nvp == NULL) 201258065Spjd errno = ENOENT; 202258065Spjd 203258065Spjd return (nvp); 204258065Spjd} 205258065Spjd 206258065Spjdbool 207258065Spjdnvlist_exists_type(const nvlist_t *nvl, const char *name, int type) 208258065Spjd{ 209258065Spjd 210258065Spjd return (nvlist_existsf_type(nvl, type, "%s", name)); 211258065Spjd} 212258065Spjd 213258065Spjdbool 214258065Spjdnvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...) 215258065Spjd{ 216258065Spjd va_list nameap; 217258065Spjd bool ret; 218258065Spjd 219258065Spjd va_start(nameap, namefmt); 220258065Spjd ret = nvlist_existsv_type(nvl, type, namefmt, nameap); 221258065Spjd va_end(nameap); 222258065Spjd 223258065Spjd return (ret); 224258065Spjd} 225258065Spjd 226258065Spjdbool 227258065Spjdnvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt, 228258065Spjd va_list nameap) 229258065Spjd{ 230258065Spjd 231258065Spjd NVLIST_ASSERT(nvl); 232258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 233258065Spjd PJDLOG_ASSERT(type == NV_TYPE_NONE || 234258065Spjd (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 235258065Spjd 236258065Spjd return (nvlist_findv(nvl, type, namefmt, nameap) != NULL); 237258065Spjd} 238258065Spjd 239258065Spjdvoid 240258065Spjdnvlist_free_type(nvlist_t *nvl, const char *name, int type) 241258065Spjd{ 242258065Spjd 243258065Spjd nvlist_freef_type(nvl, type, "%s", name); 244258065Spjd} 245258065Spjd 246258065Spjdvoid 247258065Spjdnvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...) 248258065Spjd{ 249258065Spjd va_list nameap; 250258065Spjd 251258065Spjd va_start(nameap, namefmt); 252258065Spjd nvlist_freev_type(nvl, type, namefmt, nameap); 253258065Spjd va_end(nameap); 254258065Spjd} 255258065Spjd 256258065Spjdvoid 257258065Spjdnvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap) 258258065Spjd{ 259258065Spjd va_list cnameap; 260258065Spjd nvpair_t *nvp; 261258065Spjd 262258065Spjd NVLIST_ASSERT(nvl); 263258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 264258065Spjd PJDLOG_ASSERT(type == NV_TYPE_NONE || 265258065Spjd (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 266258065Spjd 267258065Spjd va_copy(cnameap, nameap); 268258065Spjd nvp = nvlist_findv(nvl, type, namefmt, cnameap); 269258065Spjd va_end(cnameap); 270258065Spjd if (nvp != NULL) 271258065Spjd nvlist_free_nvpair(nvl, nvp); 272258065Spjd else 273258065Spjd nvlist_report_missing(type, namefmt, nameap); 274258065Spjd} 275258065Spjd 276258065Spjdnvlist_t * 277258065Spjdnvlist_clone(const nvlist_t *nvl) 278258065Spjd{ 279258065Spjd nvlist_t *newnvl; 280258065Spjd nvpair_t *nvp, *newnvp; 281258065Spjd 282258065Spjd NVLIST_ASSERT(nvl); 283258065Spjd 284258065Spjd if (nvl->nvl_error != 0) { 285258065Spjd errno = nvl->nvl_error; 286258065Spjd return (NULL); 287258065Spjd } 288258065Spjd 289258065Spjd newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); 290258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 291258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 292258065Spjd newnvp = nvpair_clone(nvp); 293258065Spjd if (newnvp == NULL) 294258065Spjd break; 295258065Spjd nvlist_move_nvpair(newnvl, newnvp); 296258065Spjd } 297258065Spjd if (nvp != NULL) { 298258065Spjd nvlist_destroy(newnvl); 299258065Spjd return (NULL); 300258065Spjd } 301258065Spjd return (newnvl); 302258065Spjd} 303258065Spjd 304258065Spjd/* 305258065Spjd * Dump content of nvlist. 306258065Spjd */ 307258065Spjdstatic void 308258065Spjdnvlist_xdump(const nvlist_t *nvl, int fd, int level) 309258065Spjd{ 310258065Spjd nvpair_t *nvp; 311258065Spjd 312258065Spjd PJDLOG_ASSERT(level < 3); 313258065Spjd 314258065Spjd if (nvlist_error(nvl) != 0) { 315258065Spjd dprintf(fd, "%*serror: %d\n", level * 4, "", 316258065Spjd nvlist_error(nvl)); 317258065Spjd return; 318258065Spjd } 319258065Spjd 320258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 321258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 322258065Spjd dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), 323258065Spjd nvpair_type_string(nvpair_type(nvp))); 324258065Spjd switch (nvpair_type(nvp)) { 325258065Spjd case NV_TYPE_NULL: 326258065Spjd dprintf(fd, " null\n"); 327258065Spjd break; 328258065Spjd case NV_TYPE_BOOL: 329258065Spjd dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? 330258065Spjd "TRUE" : "FALSE"); 331258065Spjd break; 332258065Spjd case NV_TYPE_NUMBER: 333258065Spjd dprintf(fd, " %ju (%jd) (0x%jx)\n", 334258065Spjd (uintmax_t)nvpair_get_number(nvp), 335258065Spjd (intmax_t)nvpair_get_number(nvp), 336258065Spjd (uintmax_t)nvpair_get_number(nvp)); 337258065Spjd break; 338258065Spjd case NV_TYPE_STRING: 339258065Spjd dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); 340258065Spjd break; 341258065Spjd case NV_TYPE_NVLIST: 342258065Spjd dprintf(fd, "\n"); 343258065Spjd nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1); 344258065Spjd break; 345258065Spjd case NV_TYPE_DESCRIPTOR: 346258065Spjd dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); 347258065Spjd break; 348258065Spjd case NV_TYPE_BINARY: 349258065Spjd { 350258065Spjd const unsigned char *binary; 351258065Spjd unsigned int ii; 352258065Spjd size_t size; 353258065Spjd 354258065Spjd binary = nvpair_get_binary(nvp, &size); 355258065Spjd dprintf(fd, " %zu ", size); 356258065Spjd for (ii = 0; ii < size; ii++) 357258065Spjd dprintf(fd, "%02hhx", binary[ii]); 358258065Spjd dprintf(fd, "\n"); 359258065Spjd break; 360258065Spjd } 361258065Spjd default: 362258065Spjd PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 363258065Spjd } 364258065Spjd } 365258065Spjd} 366258065Spjd 367258065Spjdvoid 368258065Spjdnvlist_dump(const nvlist_t *nvl, int fd) 369258065Spjd{ 370258065Spjd 371258065Spjd nvlist_xdump(nvl, fd, 0); 372258065Spjd} 373258065Spjd 374258065Spjdvoid 375258065Spjdnvlist_fdump(const nvlist_t *nvl, FILE *fp) 376258065Spjd{ 377258065Spjd 378258065Spjd fflush(fp); 379258065Spjd nvlist_dump(nvl, fileno(fp)); 380258065Spjd} 381258065Spjd 382258065Spjd/* 383258065Spjd * The function obtains size of the nvlist after nvlist_pack(). 384258065Spjd * Additional argument 'level' allows to track how deep are we as we obtain 385258065Spjd * size of the NV_TYPE_NVLIST elements using recursion. We allow at most 386258065Spjd * three levels of recursion. 387258065Spjd */ 388258065Spjdstatic size_t 389258065Spjdnvlist_xsize(const nvlist_t *nvl, int level) 390258065Spjd{ 391258065Spjd const nvpair_t *nvp; 392258065Spjd size_t size; 393258065Spjd 394258065Spjd NVLIST_ASSERT(nvl); 395258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 396258065Spjd PJDLOG_ASSERT(level < 3); 397258065Spjd 398258065Spjd size = sizeof(struct nvlist_header); 399258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 400258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 401258065Spjd size += nvpair_header_size(); 402258065Spjd size += strlen(nvpair_name(nvp)) + 1; 403258065Spjd if (nvpair_type(nvp) == NV_TYPE_NVLIST) 404258065Spjd size += nvlist_xsize(nvpair_get_nvlist(nvp), level + 1); 405258065Spjd else 406258065Spjd size += nvpair_size(nvp); 407258065Spjd } 408258065Spjd 409258065Spjd return (size); 410258065Spjd} 411258065Spjd 412258065Spjdsize_t 413258065Spjdnvlist_size(const nvlist_t *nvl) 414258065Spjd{ 415258065Spjd 416258065Spjd return (nvlist_xsize(nvl, 0)); 417258065Spjd} 418258065Spjd 419258065Spjdstatic int * 420258065Spjdnvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level) 421258065Spjd{ 422258065Spjd const nvpair_t *nvp; 423258065Spjd 424258065Spjd NVLIST_ASSERT(nvl); 425258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 426258065Spjd PJDLOG_ASSERT(level < 3); 427258065Spjd 428258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 429258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 430258065Spjd switch (nvpair_type(nvp)) { 431258065Spjd case NV_TYPE_DESCRIPTOR: 432258065Spjd *descs = nvpair_get_descriptor(nvp); 433258065Spjd descs++; 434258065Spjd break; 435258065Spjd case NV_TYPE_NVLIST: 436258065Spjd descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp), 437258065Spjd descs, level + 1); 438258065Spjd break; 439258065Spjd } 440258065Spjd } 441258065Spjd 442258065Spjd return (descs); 443258065Spjd} 444258065Spjd 445258065Spjdint * 446258065Spjdnvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp) 447258065Spjd{ 448258065Spjd size_t nitems; 449258065Spjd int *fds; 450258065Spjd 451258065Spjd nitems = nvlist_ndescriptors(nvl); 452258065Spjd fds = malloc(sizeof(fds[0]) * (nitems + 1)); 453258065Spjd if (fds == NULL) 454258065Spjd return (NULL); 455258065Spjd if (nitems > 0) 456258065Spjd nvlist_xdescriptors(nvl, fds, 0); 457258065Spjd fds[nitems] = -1; 458258065Spjd if (nitemsp != NULL) 459258065Spjd *nitemsp = nitems; 460258065Spjd return (fds); 461258065Spjd} 462258065Spjd 463258065Spjdstatic size_t 464258065Spjdnvlist_xndescriptors(const nvlist_t *nvl, int level) 465258065Spjd{ 466258065Spjd const nvpair_t *nvp; 467258065Spjd size_t ndescs; 468258065Spjd 469258065Spjd NVLIST_ASSERT(nvl); 470258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 471258065Spjd PJDLOG_ASSERT(level < 3); 472258065Spjd 473258065Spjd ndescs = 0; 474258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 475258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 476258065Spjd switch (nvpair_type(nvp)) { 477258065Spjd case NV_TYPE_DESCRIPTOR: 478258065Spjd ndescs++; 479258065Spjd break; 480258065Spjd case NV_TYPE_NVLIST: 481258065Spjd ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp), 482258065Spjd level + 1); 483258065Spjd break; 484258065Spjd } 485258065Spjd } 486258065Spjd 487258065Spjd return (ndescs); 488258065Spjd} 489258065Spjd 490258065Spjdsize_t 491258065Spjdnvlist_ndescriptors(const nvlist_t *nvl) 492258065Spjd{ 493258065Spjd 494258065Spjd return (nvlist_xndescriptors(nvl, 0)); 495258065Spjd} 496258065Spjd 497258065Spjdstatic unsigned char * 498258065Spjdnvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp) 499258065Spjd{ 500258065Spjd struct nvlist_header nvlhdr; 501258065Spjd 502258065Spjd NVLIST_ASSERT(nvl); 503258065Spjd 504258065Spjd nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC; 505258065Spjd nvlhdr.nvlh_version = NVLIST_HEADER_VERSION; 506258065Spjd nvlhdr.nvlh_flags = nvl->nvl_flags; 507258065Spjd#if BYTE_ORDER == BIG_ENDIAN 508258065Spjd nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN; 509258065Spjd#endif 510258065Spjd nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl); 511258065Spjd nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr); 512258065Spjd PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr)); 513258065Spjd memcpy(ptr, &nvlhdr, sizeof(nvlhdr)); 514258065Spjd ptr += sizeof(nvlhdr); 515258065Spjd *leftp -= sizeof(nvlhdr); 516258065Spjd 517258065Spjd return (ptr); 518258065Spjd} 519258065Spjd 520258065Spjdvoid * 521258065Spjdnvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) 522258065Spjd{ 523258065Spjd unsigned char *buf, *ptr; 524258065Spjd size_t left, size; 525258065Spjd nvpair_t *nvp; 526258065Spjd 527258065Spjd NVLIST_ASSERT(nvl); 528258065Spjd 529258065Spjd if (nvl->nvl_error != 0) { 530258065Spjd errno = nvl->nvl_error; 531258065Spjd return (NULL); 532258065Spjd } 533258065Spjd 534258065Spjd size = nvlist_size(nvl); 535258065Spjd buf = malloc(size); 536258065Spjd if (buf == NULL) 537258065Spjd return (NULL); 538258065Spjd 539258065Spjd ptr = buf; 540258065Spjd left = size; 541258065Spjd 542258065Spjd ptr = nvlist_pack_header(nvl, ptr, &left); 543258065Spjd 544258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 545258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 546258065Spjd ptr = nvpair_pack(nvp, ptr, fdidxp, &left); 547258065Spjd if (ptr == NULL) { 548258065Spjd free(buf); 549258065Spjd return (NULL); 550258065Spjd } 551258065Spjd } 552258065Spjd 553258065Spjd if (sizep != NULL) 554258065Spjd *sizep = size; 555258065Spjd return (buf); 556258065Spjd} 557258065Spjd 558258065Spjdvoid * 559258065Spjdnvlist_pack(const nvlist_t *nvl, size_t *sizep) 560258065Spjd{ 561258065Spjd 562258065Spjd NVLIST_ASSERT(nvl); 563258065Spjd 564258065Spjd if (nvl->nvl_error != 0) { 565258065Spjd errno = nvl->nvl_error; 566258065Spjd return (NULL); 567258065Spjd } 568258065Spjd 569258065Spjd if (nvlist_ndescriptors(nvl) > 0) { 570258065Spjd errno = EOPNOTSUPP; 571258065Spjd return (NULL); 572258065Spjd } 573258065Spjd 574258065Spjd return (nvlist_xpack(nvl, NULL, sizep)); 575258065Spjd} 576258065Spjd 577258065Spjdstatic bool 578258065Spjdnvlist_check_header(struct nvlist_header *nvlhdrp) 579258065Spjd{ 580258065Spjd 581258065Spjd if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { 582258065Spjd errno = EINVAL; 583258065Spjd return (false); 584258065Spjd } 585258065Spjd if ((nvlhdrp->nvlh_flags &= ~NV_FLAG_ALL_MASK) != 0) { 586258065Spjd errno = EINVAL; 587258065Spjd return (false); 588258065Spjd } 589258065Spjd#if BYTE_ORDER == BIG_ENDIAN 590258065Spjd if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) { 591258065Spjd nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size); 592258065Spjd nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors); 593258065Spjd } 594258065Spjd#else 595258065Spjd if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) { 596258065Spjd nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size); 597258065Spjd nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); 598258065Spjd } 599258065Spjd#endif 600258065Spjd return (true); 601258065Spjd} 602258065Spjd 603258065Spjdstatic const unsigned char * 604258065Spjdnvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, 605258065Spjd int *flagsp, size_t *leftp) 606258065Spjd{ 607258065Spjd struct nvlist_header nvlhdr; 608258065Spjd 609258065Spjd if (*leftp < sizeof(nvlhdr)) 610258065Spjd goto failed; 611258065Spjd 612258065Spjd memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); 613258065Spjd 614258065Spjd if (!nvlist_check_header(&nvlhdr)) 615258065Spjd goto failed; 616258065Spjd 617258065Spjd if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) 618258065Spjd goto failed; 619258065Spjd 620258065Spjd /* 621258065Spjd * nvlh_descriptors might be smaller than nfds in embedded nvlists. 622258065Spjd */ 623258065Spjd if (nvlhdr.nvlh_descriptors > nfds) 624258065Spjd goto failed; 625258065Spjd 626258065Spjd if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) 627258065Spjd goto failed; 628258065Spjd 629258065Spjd nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK); 630258065Spjd 631258065Spjd ptr += sizeof(nvlhdr); 632258065Spjd *flagsp = (int)nvlhdr.nvlh_flags; 633258065Spjd *leftp -= sizeof(nvlhdr); 634258065Spjd 635258065Spjd return (ptr); 636258065Spjdfailed: 637258065Spjd errno = EINVAL; 638258065Spjd return (NULL); 639258065Spjd} 640258065Spjd 641258065Spjdnvlist_t * 642258065Spjdnvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) 643258065Spjd{ 644258065Spjd const unsigned char *ptr; 645258065Spjd nvlist_t *nvl; 646258065Spjd nvpair_t *nvp; 647258065Spjd size_t left; 648258065Spjd int flags; 649258065Spjd 650258065Spjd left = size; 651258065Spjd ptr = buf; 652258065Spjd 653258065Spjd nvl = nvlist_create(0); 654258065Spjd if (nvl == NULL) 655258065Spjd goto failed; 656258065Spjd 657258065Spjd ptr = nvlist_unpack_header(nvl, ptr, nfds, &flags, &left); 658258065Spjd if (ptr == NULL) 659258065Spjd goto failed; 660258065Spjd 661258065Spjd while (left > 0) { 662258065Spjd ptr = nvpair_unpack(flags, ptr, &left, fds, nfds, &nvp); 663258065Spjd if (ptr == NULL) 664258065Spjd goto failed; 665258065Spjd nvlist_move_nvpair(nvl, nvp); 666258065Spjd } 667258065Spjd 668258065Spjd return (nvl); 669258065Spjdfailed: 670258065Spjd nvlist_destroy(nvl); 671258065Spjd return (NULL); 672258065Spjd} 673258065Spjd 674258065Spjdnvlist_t * 675258065Spjdnvlist_unpack(const void *buf, size_t size) 676258065Spjd{ 677258065Spjd 678258065Spjd return (nvlist_xunpack(buf, size, NULL, 0)); 679258065Spjd} 680258065Spjd 681258065Spjdint 682258065Spjdnvlist_send(int sock, const nvlist_t *nvl) 683258065Spjd{ 684258065Spjd size_t datasize, nfds; 685258065Spjd int *fds; 686258065Spjd void *data; 687258065Spjd int64_t fdidx; 688258065Spjd int serrno, ret; 689258065Spjd 690258065Spjd if (nvlist_error(nvl) != 0) { 691258065Spjd errno = nvlist_error(nvl); 692258065Spjd return (-1); 693258065Spjd } 694258065Spjd 695258065Spjd fds = nvlist_descriptors(nvl, &nfds); 696258065Spjd if (fds == NULL) 697258065Spjd return (-1); 698258065Spjd 699258065Spjd ret = -1; 700258065Spjd data = NULL; 701258065Spjd fdidx = 0; 702258065Spjd 703258065Spjd data = nvlist_xpack(nvl, &fdidx, &datasize); 704258065Spjd if (data == NULL) 705258065Spjd goto out; 706258065Spjd 707258065Spjd if (buf_send(sock, data, datasize) == -1) 708258065Spjd goto out; 709258065Spjd 710258065Spjd if (nfds > 0) { 711258065Spjd if (fd_send(sock, fds, nfds) == -1) 712258065Spjd goto out; 713258065Spjd } 714258065Spjd 715258065Spjd ret = 0; 716258065Spjdout: 717258065Spjd serrno = errno; 718258065Spjd free(fds); 719258065Spjd free(data); 720258065Spjd errno = serrno; 721258065Spjd return (ret); 722258065Spjd} 723258065Spjd 724258065Spjdnvlist_t * 725258065Spjdnvlist_recv(int sock) 726258065Spjd{ 727258065Spjd struct nvlist_header nvlhdr; 728258065Spjd nvlist_t *nvl, *ret; 729259430Spjd unsigned char *buf; 730258065Spjd size_t nfds, size; 731258065Spjd int serrno, *fds; 732258065Spjd 733259430Spjd if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1) 734258065Spjd return (NULL); 735258065Spjd 736258065Spjd if (!nvlist_check_header(&nvlhdr)) 737258065Spjd return (NULL); 738258065Spjd 739258065Spjd nfds = (size_t)nvlhdr.nvlh_descriptors; 740258065Spjd size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size; 741258065Spjd 742258065Spjd buf = malloc(size); 743258065Spjd if (buf == NULL) 744258065Spjd return (NULL); 745258065Spjd 746259430Spjd memcpy(buf, &nvlhdr, sizeof(nvlhdr)); 747259430Spjd 748258065Spjd ret = NULL; 749258065Spjd fds = NULL; 750258065Spjd 751259430Spjd if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1) 752258065Spjd goto out; 753258065Spjd 754258065Spjd if (nfds > 0) { 755258065Spjd fds = malloc(nfds * sizeof(fds[0])); 756258065Spjd if (fds == NULL) 757258065Spjd goto out; 758258065Spjd if (fd_recv(sock, fds, nfds) == -1) 759258065Spjd goto out; 760258065Spjd } 761258065Spjd 762258065Spjd nvl = nvlist_xunpack(buf, size, fds, nfds); 763258065Spjd if (nvl == NULL) 764258065Spjd goto out; 765258065Spjd 766258065Spjd ret = nvl; 767258065Spjdout: 768258065Spjd serrno = errno; 769258065Spjd free(buf); 770258065Spjd free(fds); 771258065Spjd errno = serrno; 772258065Spjd 773258065Spjd return (ret); 774258065Spjd} 775258065Spjd 776258065Spjdnvlist_t * 777258065Spjdnvlist_xfer(int sock, nvlist_t *nvl) 778258065Spjd{ 779258065Spjd 780258065Spjd if (nvlist_send(sock, nvl) < 0) { 781258065Spjd nvlist_destroy(nvl); 782258065Spjd return (NULL); 783258065Spjd } 784258065Spjd nvlist_destroy(nvl); 785258065Spjd return (nvlist_recv(sock)); 786258065Spjd} 787258065Spjd 788258065Spjdnvpair_t * 789258065Spjdnvlist_first_nvpair(const nvlist_t *nvl) 790258065Spjd{ 791258065Spjd 792258065Spjd NVLIST_ASSERT(nvl); 793258065Spjd 794258065Spjd return (TAILQ_FIRST(&nvl->nvl_head)); 795258065Spjd} 796258065Spjd 797258065Spjdnvpair_t * 798258065Spjdnvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 799258065Spjd{ 800258065Spjd nvpair_t *retnvp; 801258065Spjd 802258065Spjd NVLIST_ASSERT(nvl); 803258065Spjd NVPAIR_ASSERT(nvp); 804258065Spjd PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 805258065Spjd 806258065Spjd retnvp = nvpair_next(nvp); 807258065Spjd PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl); 808258065Spjd 809258065Spjd return (retnvp); 810258065Spjd 811258065Spjd} 812258065Spjd 813258065Spjdnvpair_t * 814258065Spjdnvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 815258065Spjd{ 816258065Spjd nvpair_t *retnvp; 817258065Spjd 818258065Spjd NVLIST_ASSERT(nvl); 819258065Spjd NVPAIR_ASSERT(nvp); 820258065Spjd PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 821258065Spjd 822258065Spjd retnvp = nvpair_prev(nvp); 823258065Spjd PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl); 824258065Spjd 825258065Spjd return (retnvp); 826258065Spjd} 827258065Spjd 828258065Spjdconst char * 829258065Spjdnvlist_next(const nvlist_t *nvl, int *typep, void **cookiep) 830258065Spjd{ 831258065Spjd nvpair_t *nvp; 832258065Spjd 833258065Spjd NVLIST_ASSERT(nvl); 834258065Spjd PJDLOG_ASSERT(cookiep != NULL); 835258065Spjd 836258065Spjd if (*cookiep == NULL) 837258065Spjd nvp = nvlist_first_nvpair(nvl); 838258065Spjd else 839258065Spjd nvp = nvlist_next_nvpair(nvl, *cookiep); 840258065Spjd if (nvp == NULL) 841258065Spjd return (NULL); 842258065Spjd if (typep != NULL) 843258065Spjd *typep = nvpair_type(nvp); 844258065Spjd *cookiep = nvp; 845258065Spjd return (nvpair_name(nvp)); 846258065Spjd} 847258065Spjd 848258065Spjdbool 849258065Spjdnvlist_exists(const nvlist_t *nvl, const char *name) 850258065Spjd{ 851258065Spjd 852258065Spjd return (nvlist_existsf(nvl, "%s", name)); 853258065Spjd} 854258065Spjd 855258065Spjd#define NVLIST_EXISTS(type) \ 856258065Spjdbool \ 857258065Spjdnvlist_exists_##type(const nvlist_t *nvl, const char *name) \ 858258065Spjd{ \ 859258065Spjd \ 860258065Spjd return (nvlist_existsf_##type(nvl, "%s", name)); \ 861258065Spjd} 862258065Spjd 863258065SpjdNVLIST_EXISTS(null) 864258065SpjdNVLIST_EXISTS(bool) 865258065SpjdNVLIST_EXISTS(number) 866258065SpjdNVLIST_EXISTS(string) 867258065SpjdNVLIST_EXISTS(nvlist) 868258065SpjdNVLIST_EXISTS(descriptor) 869258065SpjdNVLIST_EXISTS(binary) 870258065Spjd 871258065Spjd#undef NVLIST_EXISTS 872258065Spjd 873258065Spjdbool 874258065Spjdnvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...) 875258065Spjd{ 876258065Spjd va_list nameap; 877258065Spjd bool ret; 878258065Spjd 879258065Spjd va_start(nameap, namefmt); 880258065Spjd ret = nvlist_existsv(nvl, namefmt, nameap); 881258065Spjd va_end(nameap); 882258065Spjd return (ret); 883258065Spjd} 884258065Spjd 885258065Spjd#define NVLIST_EXISTSF(type) \ 886258065Spjdbool \ 887258065Spjdnvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...) \ 888258065Spjd{ \ 889258065Spjd va_list nameap; \ 890258065Spjd bool ret; \ 891258065Spjd \ 892258065Spjd va_start(nameap, namefmt); \ 893258065Spjd ret = nvlist_existsv_##type(nvl, namefmt, nameap); \ 894258065Spjd va_end(nameap); \ 895258065Spjd return (ret); \ 896258065Spjd} 897258065Spjd 898258065SpjdNVLIST_EXISTSF(null) 899258065SpjdNVLIST_EXISTSF(bool) 900258065SpjdNVLIST_EXISTSF(number) 901258065SpjdNVLIST_EXISTSF(string) 902258065SpjdNVLIST_EXISTSF(nvlist) 903258065SpjdNVLIST_EXISTSF(descriptor) 904258065SpjdNVLIST_EXISTSF(binary) 905258065Spjd 906258065Spjd#undef NVLIST_EXISTSF 907258065Spjd 908258065Spjdbool 909258065Spjdnvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap) 910258065Spjd{ 911258065Spjd 912258065Spjd return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap) != NULL); 913258065Spjd} 914258065Spjd 915258065Spjd#define NVLIST_EXISTSV(type, TYPE) \ 916258065Spjdbool \ 917258065Spjdnvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \ 918258065Spjd va_list nameap) \ 919258065Spjd{ \ 920258065Spjd \ 921258065Spjd return (nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, nameap) != \ 922258065Spjd NULL); \ 923258065Spjd} 924258065Spjd 925258065SpjdNVLIST_EXISTSV(null, NULL) 926258065SpjdNVLIST_EXISTSV(bool, BOOL) 927258065SpjdNVLIST_EXISTSV(number, NUMBER) 928258065SpjdNVLIST_EXISTSV(string, STRING) 929258065SpjdNVLIST_EXISTSV(nvlist, NVLIST) 930258065SpjdNVLIST_EXISTSV(descriptor, DESCRIPTOR) 931258065SpjdNVLIST_EXISTSV(binary, BINARY) 932258065Spjd 933258065Spjd#undef NVLIST_EXISTSV 934258065Spjd 935258065Spjdvoid 936258065Spjdnvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) 937258065Spjd{ 938258065Spjd nvpair_t *newnvp; 939258065Spjd 940258065Spjd NVPAIR_ASSERT(nvp); 941258065Spjd 942258065Spjd if (nvlist_error(nvl) != 0) { 943258065Spjd errno = nvlist_error(nvl); 944258065Spjd return; 945258065Spjd } 946258065Spjd if (nvlist_exists(nvl, nvpair_name(nvp))) { 947258065Spjd nvl->nvl_error = errno = EEXIST; 948258065Spjd return; 949258065Spjd } 950258065Spjd 951258065Spjd newnvp = nvpair_clone(nvp); 952258065Spjd if (newnvp == NULL) { 953258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 954258065Spjd return; 955258065Spjd } 956258065Spjd 957258065Spjd nvpair_insert(&nvl->nvl_head, newnvp, nvl); 958258065Spjd} 959258065Spjd 960258065Spjdvoid 961258065Spjdnvlist_add_null(nvlist_t *nvl, const char *name) 962258065Spjd{ 963258065Spjd 964258065Spjd nvlist_addf_null(nvl, "%s", name); 965258065Spjd} 966258065Spjd 967258065Spjdvoid 968258065Spjdnvlist_add_bool(nvlist_t *nvl, const char *name, bool value) 969258065Spjd{ 970258065Spjd 971258065Spjd nvlist_addf_bool(nvl, value, "%s", name); 972258065Spjd} 973258065Spjd 974258065Spjdvoid 975258065Spjdnvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value) 976258065Spjd{ 977258065Spjd 978258065Spjd nvlist_addf_number(nvl, value, "%s", name); 979258065Spjd} 980258065Spjd 981258065Spjdvoid 982258065Spjdnvlist_add_string(nvlist_t *nvl, const char *name, const char *value) 983258065Spjd{ 984258065Spjd 985258065Spjd nvlist_addf_string(nvl, value, "%s", name); 986258065Spjd} 987258065Spjd 988258065Spjdvoid 989258065Spjdnvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) 990258065Spjd{ 991258065Spjd va_list valueap; 992258065Spjd 993258065Spjd va_start(valueap, valuefmt); 994258065Spjd nvlist_add_stringv(nvl, name, valuefmt, valueap); 995258065Spjd va_end(valueap); 996258065Spjd} 997258065Spjd 998258065Spjdvoid 999258065Spjdnvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, 1000258065Spjd va_list valueap) 1001258065Spjd{ 1002258065Spjd nvpair_t *nvp; 1003258065Spjd 1004258065Spjd if (nvlist_error(nvl) != 0) { 1005258065Spjd errno = nvlist_error(nvl); 1006258065Spjd return; 1007258065Spjd } 1008258065Spjd 1009258065Spjd nvp = nvpair_create_stringv(name, valuefmt, valueap); 1010258065Spjd if (nvp == NULL) 1011258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1012258065Spjd else 1013258065Spjd nvlist_move_nvpair(nvl, nvp); 1014258065Spjd} 1015258065Spjd 1016258065Spjdvoid 1017258065Spjdnvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value) 1018258065Spjd{ 1019258065Spjd 1020258065Spjd nvlist_addf_nvlist(nvl, value, "%s", name); 1021258065Spjd} 1022258065Spjd 1023258065Spjdvoid 1024258065Spjdnvlist_add_descriptor(nvlist_t *nvl, const char *name, int value) 1025258065Spjd{ 1026258065Spjd 1027258065Spjd nvlist_addf_descriptor(nvl, value, "%s", name); 1028258065Spjd} 1029258065Spjd 1030258065Spjdvoid 1031258065Spjdnvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, 1032258065Spjd size_t size) 1033258065Spjd{ 1034258065Spjd 1035258065Spjd nvlist_addf_binary(nvl, value, size, "%s", name); 1036258065Spjd} 1037258065Spjd 1038258065Spjdvoid 1039258065Spjdnvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...) 1040258065Spjd{ 1041258065Spjd va_list nameap; 1042258065Spjd 1043258065Spjd va_start(nameap, namefmt); 1044258065Spjd nvlist_addv_null(nvl, namefmt, nameap); 1045258065Spjd va_end(nameap); 1046258065Spjd} 1047258065Spjd 1048258065Spjdvoid 1049258065Spjdnvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...) 1050258065Spjd{ 1051258065Spjd va_list nameap; 1052258065Spjd 1053258065Spjd va_start(nameap, namefmt); 1054258065Spjd nvlist_addv_bool(nvl, value, namefmt, nameap); 1055258065Spjd va_end(nameap); 1056258065Spjd} 1057258065Spjd 1058258065Spjdvoid 1059258065Spjdnvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...) 1060258065Spjd{ 1061258065Spjd va_list nameap; 1062258065Spjd 1063258065Spjd va_start(nameap, namefmt); 1064258065Spjd nvlist_addv_number(nvl, value, namefmt, nameap); 1065258065Spjd va_end(nameap); 1066258065Spjd} 1067258065Spjd 1068258065Spjdvoid 1069258065Spjdnvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...) 1070258065Spjd{ 1071258065Spjd va_list nameap; 1072258065Spjd 1073258065Spjd va_start(nameap, namefmt); 1074258065Spjd nvlist_addv_string(nvl, value, namefmt, nameap); 1075258065Spjd va_end(nameap); 1076258065Spjd} 1077258065Spjd 1078258065Spjdvoid 1079258065Spjdnvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, 1080258065Spjd ...) 1081258065Spjd{ 1082258065Spjd va_list nameap; 1083258065Spjd 1084258065Spjd va_start(nameap, namefmt); 1085258065Spjd nvlist_addv_nvlist(nvl, value, namefmt, nameap); 1086258065Spjd va_end(nameap); 1087258065Spjd} 1088258065Spjd 1089258065Spjdvoid 1090258065Spjdnvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...) 1091258065Spjd{ 1092258065Spjd va_list nameap; 1093258065Spjd 1094258065Spjd va_start(nameap, namefmt); 1095258065Spjd nvlist_addv_descriptor(nvl, value, namefmt, nameap); 1096258065Spjd va_end(nameap); 1097258065Spjd} 1098258065Spjd 1099258065Spjdvoid 1100258065Spjdnvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size, 1101258065Spjd const char *namefmt, ...) 1102258065Spjd{ 1103258065Spjd va_list nameap; 1104258065Spjd 1105258065Spjd va_start(nameap, namefmt); 1106258065Spjd nvlist_addv_binary(nvl, value, size, namefmt, nameap); 1107258065Spjd va_end(nameap); 1108258065Spjd} 1109258065Spjd 1110258065Spjdvoid 1111258065Spjdnvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap) 1112258065Spjd{ 1113258065Spjd nvpair_t *nvp; 1114258065Spjd 1115258065Spjd if (nvlist_error(nvl) != 0) { 1116258065Spjd errno = nvlist_error(nvl); 1117258065Spjd return; 1118258065Spjd } 1119258065Spjd 1120258065Spjd nvp = nvpair_createv_null(namefmt, nameap); 1121258065Spjd if (nvp == NULL) 1122258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1123258065Spjd else 1124258065Spjd nvlist_move_nvpair(nvl, nvp); 1125258065Spjd} 1126258065Spjd 1127258065Spjdvoid 1128258065Spjdnvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap) 1129258065Spjd{ 1130258065Spjd nvpair_t *nvp; 1131258065Spjd 1132258065Spjd if (nvlist_error(nvl) != 0) { 1133258065Spjd errno = nvlist_error(nvl); 1134258065Spjd return; 1135258065Spjd } 1136258065Spjd 1137258065Spjd nvp = nvpair_createv_bool(value, namefmt, nameap); 1138258065Spjd if (nvp == NULL) 1139258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1140258065Spjd else 1141258065Spjd nvlist_move_nvpair(nvl, nvp); 1142258065Spjd} 1143258065Spjd 1144258065Spjdvoid 1145258065Spjdnvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt, 1146258065Spjd va_list nameap) 1147258065Spjd{ 1148258065Spjd nvpair_t *nvp; 1149258065Spjd 1150258065Spjd if (nvlist_error(nvl) != 0) { 1151258065Spjd errno = nvlist_error(nvl); 1152258065Spjd return; 1153258065Spjd } 1154258065Spjd 1155258065Spjd nvp = nvpair_createv_number(value, namefmt, nameap); 1156258065Spjd if (nvp == NULL) 1157258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1158258065Spjd else 1159258065Spjd nvlist_move_nvpair(nvl, nvp); 1160258065Spjd} 1161258065Spjd 1162258065Spjdvoid 1163258065Spjdnvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt, 1164258065Spjd va_list nameap) 1165258065Spjd{ 1166258065Spjd nvpair_t *nvp; 1167258065Spjd 1168258065Spjd if (nvlist_error(nvl) != 0) { 1169258065Spjd errno = nvlist_error(nvl); 1170258065Spjd return; 1171258065Spjd } 1172258065Spjd 1173258065Spjd nvp = nvpair_createv_string(value, namefmt, nameap); 1174258065Spjd if (nvp == NULL) 1175258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1176258065Spjd else 1177258065Spjd nvlist_move_nvpair(nvl, nvp); 1178258065Spjd} 1179258065Spjd 1180258065Spjdvoid 1181258065Spjdnvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, 1182258065Spjd va_list nameap) 1183258065Spjd{ 1184258065Spjd nvpair_t *nvp; 1185258065Spjd 1186258065Spjd if (nvlist_error(nvl) != 0) { 1187258065Spjd errno = nvlist_error(nvl); 1188258065Spjd return; 1189258065Spjd } 1190258065Spjd 1191258065Spjd nvp = nvpair_createv_nvlist(value, namefmt, nameap); 1192258065Spjd if (nvp == NULL) 1193258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1194258065Spjd else 1195258065Spjd nvlist_move_nvpair(nvl, nvp); 1196258065Spjd} 1197258065Spjd 1198258065Spjdvoid 1199258065Spjdnvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt, 1200258065Spjd va_list nameap) 1201258065Spjd{ 1202258065Spjd nvpair_t *nvp; 1203258065Spjd 1204258065Spjd if (nvlist_error(nvl) != 0) { 1205258065Spjd errno = nvlist_error(nvl); 1206258065Spjd return; 1207258065Spjd } 1208258065Spjd 1209258065Spjd nvp = nvpair_createv_descriptor(value, namefmt, nameap); 1210258065Spjd if (nvp == NULL) 1211258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1212258065Spjd else 1213258065Spjd nvlist_move_nvpair(nvl, nvp); 1214258065Spjd} 1215258065Spjd 1216258065Spjdvoid 1217258065Spjdnvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size, 1218258065Spjd const char *namefmt, va_list nameap) 1219258065Spjd{ 1220258065Spjd nvpair_t *nvp; 1221258065Spjd 1222258065Spjd if (nvlist_error(nvl) != 0) { 1223258065Spjd errno = nvlist_error(nvl); 1224258065Spjd return; 1225258065Spjd } 1226258065Spjd 1227258065Spjd nvp = nvpair_createv_binary(value, size, namefmt, nameap); 1228258065Spjd if (nvp == NULL) 1229258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1230258065Spjd else 1231258065Spjd nvlist_move_nvpair(nvl, nvp); 1232258065Spjd} 1233258065Spjd 1234258065Spjdvoid 1235258065Spjdnvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1236258065Spjd{ 1237258065Spjd 1238258065Spjd NVPAIR_ASSERT(nvp); 1239258065Spjd PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); 1240258065Spjd 1241258065Spjd if (nvlist_error(nvl) != 0) { 1242258065Spjd nvpair_free(nvp); 1243258065Spjd errno = nvlist_error(nvl); 1244258065Spjd return; 1245258065Spjd } 1246258065Spjd if (nvlist_exists(nvl, nvpair_name(nvp))) { 1247258065Spjd nvpair_free(nvp); 1248258065Spjd nvl->nvl_error = errno = EEXIST; 1249258065Spjd return; 1250258065Spjd } 1251258065Spjd 1252258065Spjd nvpair_insert(&nvl->nvl_head, nvp, nvl); 1253258065Spjd} 1254258065Spjd 1255258065Spjd#define NVLIST_MOVE(vtype, type) \ 1256258065Spjdvoid \ 1257258065Spjdnvlist_move_##type(nvlist_t *nvl, const char *name, vtype value) \ 1258258065Spjd{ \ 1259258065Spjd \ 1260258065Spjd nvlist_movef_##type(nvl, value, "%s", name); \ 1261258065Spjd} 1262258065Spjd 1263258065SpjdNVLIST_MOVE(char *, string) 1264258065SpjdNVLIST_MOVE(nvlist_t *, nvlist) 1265258065SpjdNVLIST_MOVE(int, descriptor) 1266258065Spjd 1267258065Spjd#undef NVLIST_MOVE 1268258065Spjd 1269258065Spjdvoid 1270258065Spjdnvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size) 1271258065Spjd{ 1272258065Spjd 1273258065Spjd nvlist_movef_binary(nvl, value, size, "%s", name); 1274258065Spjd} 1275258065Spjd 1276258065Spjd#define NVLIST_MOVEF(vtype, type) \ 1277258065Spjdvoid \ 1278258065Spjdnvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt, \ 1279258065Spjd ...) \ 1280258065Spjd{ \ 1281258065Spjd va_list nameap; \ 1282258065Spjd \ 1283258065Spjd va_start(nameap, namefmt); \ 1284258065Spjd nvlist_movev_##type(nvl, value, namefmt, nameap); \ 1285258065Spjd va_end(nameap); \ 1286258065Spjd} 1287258065Spjd 1288258065SpjdNVLIST_MOVEF(char *, string) 1289258065SpjdNVLIST_MOVEF(nvlist_t *, nvlist) 1290258065SpjdNVLIST_MOVEF(int, descriptor) 1291258065Spjd 1292258065Spjd#undef NVLIST_MOVEF 1293258065Spjd 1294258065Spjdvoid 1295258065Spjdnvlist_movef_binary(nvlist_t *nvl, void *value, size_t size, 1296258065Spjd const char *namefmt, ...) 1297258065Spjd{ 1298258065Spjd va_list nameap; 1299258065Spjd 1300258065Spjd va_start(nameap, namefmt); 1301258065Spjd nvlist_movev_binary(nvl, value, size, namefmt, nameap); 1302258065Spjd va_end(nameap); 1303258065Spjd} 1304258065Spjd 1305258065Spjdvoid 1306258065Spjdnvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt, 1307258065Spjd va_list nameap) 1308258065Spjd{ 1309258065Spjd nvpair_t *nvp; 1310258065Spjd 1311258065Spjd if (nvlist_error(nvl) != 0) { 1312258065Spjd free(value); 1313258065Spjd errno = nvlist_error(nvl); 1314258065Spjd return; 1315258065Spjd } 1316258065Spjd 1317258065Spjd nvp = nvpair_movev_string(value, namefmt, nameap); 1318258065Spjd if (nvp == NULL) 1319258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1320258065Spjd else 1321258065Spjd nvlist_move_nvpair(nvl, nvp); 1322258065Spjd} 1323258065Spjd 1324258065Spjdvoid 1325258065Spjdnvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt, 1326258065Spjd va_list nameap) 1327258065Spjd{ 1328258065Spjd nvpair_t *nvp; 1329258065Spjd 1330258065Spjd if (nvlist_error(nvl) != 0) { 1331258065Spjd nvlist_destroy(value); 1332258065Spjd errno = nvlist_error(nvl); 1333258065Spjd return; 1334258065Spjd } 1335258065Spjd 1336258065Spjd nvp = nvpair_movev_nvlist(value, namefmt, nameap); 1337258065Spjd if (nvp == NULL) 1338258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1339258065Spjd else 1340258065Spjd nvlist_move_nvpair(nvl, nvp); 1341258065Spjd} 1342258065Spjd 1343258065Spjdvoid 1344258065Spjdnvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt, 1345258065Spjd va_list nameap) 1346258065Spjd{ 1347258065Spjd nvpair_t *nvp; 1348258065Spjd 1349258065Spjd if (nvlist_error(nvl) != 0) { 1350258065Spjd close(value); 1351258065Spjd errno = nvlist_error(nvl); 1352258065Spjd return; 1353258065Spjd } 1354258065Spjd 1355258065Spjd nvp = nvpair_movev_descriptor(value, namefmt, nameap); 1356258065Spjd if (nvp == NULL) 1357258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1358258065Spjd else 1359258065Spjd nvlist_move_nvpair(nvl, nvp); 1360258065Spjd} 1361258065Spjd 1362258065Spjdvoid 1363258065Spjdnvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, 1364258065Spjd const char *namefmt, va_list nameap) 1365258065Spjd{ 1366258065Spjd nvpair_t *nvp; 1367258065Spjd 1368258065Spjd if (nvlist_error(nvl) != 0) { 1369258065Spjd free(value); 1370258065Spjd errno = nvlist_error(nvl); 1371258065Spjd return; 1372258065Spjd } 1373258065Spjd 1374258065Spjd nvp = nvpair_movev_binary(value, size, namefmt, nameap); 1375258065Spjd if (nvp == NULL) 1376258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1377258065Spjd else 1378258065Spjd nvlist_move_nvpair(nvl, nvp); 1379258065Spjd} 1380258065Spjd 1381258065Spjd#define NVLIST_GET(ftype, type) \ 1382258065Spjdftype \ 1383258065Spjdnvlist_get_##type(const nvlist_t *nvl, const char *name) \ 1384258065Spjd{ \ 1385258065Spjd \ 1386258065Spjd return (nvlist_getf_##type(nvl, "%s", name)); \ 1387258065Spjd} 1388258065Spjd 1389258065SpjdNVLIST_GET(const nvpair_t *, nvpair) 1390258065SpjdNVLIST_GET(bool, bool) 1391258065SpjdNVLIST_GET(uint64_t, number) 1392258065SpjdNVLIST_GET(const char *, string) 1393258065SpjdNVLIST_GET(const nvlist_t *, nvlist) 1394258065SpjdNVLIST_GET(int, descriptor) 1395258065Spjd 1396258065Spjd#undef NVLIST_GET 1397258065Spjd 1398258065Spjdconst void * 1399258065Spjdnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) 1400258065Spjd{ 1401258065Spjd 1402258065Spjd return (nvlist_getf_binary(nvl, sizep, "%s", name)); 1403258065Spjd} 1404258065Spjd 1405258065Spjd#define NVLIST_GETF(ftype, type) \ 1406258065Spjdftype \ 1407258065Spjdnvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...) \ 1408258065Spjd{ \ 1409258065Spjd va_list nameap; \ 1410258065Spjd ftype value; \ 1411258065Spjd \ 1412258065Spjd va_start(nameap, namefmt); \ 1413258065Spjd value = nvlist_getv_##type(nvl, namefmt, nameap); \ 1414258065Spjd va_end(nameap); \ 1415258065Spjd \ 1416258065Spjd return (value); \ 1417258065Spjd} 1418258065Spjd 1419258065SpjdNVLIST_GETF(const nvpair_t *, nvpair) 1420258065SpjdNVLIST_GETF(bool, bool) 1421258065SpjdNVLIST_GETF(uint64_t, number) 1422258065SpjdNVLIST_GETF(const char *, string) 1423258065SpjdNVLIST_GETF(const nvlist_t *, nvlist) 1424258065SpjdNVLIST_GETF(int, descriptor) 1425258065Spjd 1426258065Spjd#undef NVLIST_GETF 1427258065Spjd 1428258065Spjdconst void * 1429258065Spjdnvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) 1430258065Spjd{ 1431258065Spjd va_list nameap; 1432258065Spjd const void *value; 1433258065Spjd 1434258065Spjd va_start(nameap, namefmt); 1435258065Spjd value = nvlist_getv_binary(nvl, sizep, namefmt, nameap); 1436258065Spjd va_end(nameap); 1437258065Spjd 1438258065Spjd return (value); 1439258065Spjd} 1440258065Spjd 1441258065Spjdconst nvpair_t * 1442258065Spjdnvlist_getv_nvpair(const nvlist_t *nvl, const char *namefmt, va_list nameap) 1443258065Spjd{ 1444258065Spjd 1445258065Spjd return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap)); 1446258065Spjd} 1447258065Spjd 1448258065Spjd#define NVLIST_GETV(ftype, type, TYPE) \ 1449258065Spjdftype \ 1450258065Spjdnvlist_getv_##type(const nvlist_t *nvl, const char *namefmt, \ 1451258065Spjd va_list nameap) \ 1452258065Spjd{ \ 1453258065Spjd va_list cnameap; \ 1454258065Spjd const nvpair_t *nvp; \ 1455258065Spjd \ 1456258065Spjd va_copy(cnameap, nameap); \ 1457258065Spjd nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \ 1458258065Spjd va_end(cnameap); \ 1459258065Spjd if (nvp == NULL) \ 1460258065Spjd nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \ 1461258065Spjd return (nvpair_get_##type(nvp)); \ 1462258065Spjd} 1463258065Spjd 1464258065SpjdNVLIST_GETV(bool, bool, BOOL) 1465258065SpjdNVLIST_GETV(uint64_t, number, NUMBER) 1466258065SpjdNVLIST_GETV(const char *, string, STRING) 1467258065SpjdNVLIST_GETV(const nvlist_t *, nvlist, NVLIST) 1468258065SpjdNVLIST_GETV(int, descriptor, DESCRIPTOR) 1469258065Spjd 1470258065Spjd#undef NVLIST_GETV 1471258065Spjd 1472258065Spjdconst void * 1473258065Spjdnvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, 1474258065Spjd va_list nameap) 1475258065Spjd{ 1476258065Spjd va_list cnameap; 1477258065Spjd const nvpair_t *nvp; 1478258065Spjd 1479258065Spjd va_copy(cnameap, nameap); 1480258065Spjd nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap); 1481258065Spjd va_end(cnameap); 1482258065Spjd if (nvp == NULL) 1483258065Spjd nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap); 1484258065Spjd 1485258065Spjd return (nvpair_get_binary(nvp, sizep)); 1486258065Spjd} 1487258065Spjd 1488258065Spjd#define NVLIST_TAKE(ftype, type) \ 1489258065Spjdftype \ 1490258065Spjdnvlist_take_##type(nvlist_t *nvl, const char *name) \ 1491258065Spjd{ \ 1492258065Spjd \ 1493258065Spjd return (nvlist_takef_##type(nvl, "%s", name)); \ 1494258065Spjd} 1495258065Spjd 1496258065SpjdNVLIST_TAKE(nvpair_t *, nvpair) 1497258065SpjdNVLIST_TAKE(bool, bool) 1498258065SpjdNVLIST_TAKE(uint64_t, number) 1499258065SpjdNVLIST_TAKE(char *, string) 1500258065SpjdNVLIST_TAKE(nvlist_t *, nvlist) 1501258065SpjdNVLIST_TAKE(int, descriptor) 1502258065Spjd 1503258065Spjd#undef NVLIST_TAKE 1504258065Spjd 1505258065Spjdvoid * 1506258065Spjdnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) 1507258065Spjd{ 1508258065Spjd 1509258065Spjd return (nvlist_takef_binary(nvl, sizep, "%s", name)); 1510258065Spjd} 1511258065Spjd 1512258065Spjd#define NVLIST_TAKEF(ftype, type) \ 1513258065Spjdftype \ 1514258065Spjdnvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...) \ 1515258065Spjd{ \ 1516258065Spjd va_list nameap; \ 1517258065Spjd ftype value; \ 1518258065Spjd \ 1519258065Spjd va_start(nameap, namefmt); \ 1520258065Spjd value = nvlist_takev_##type(nvl, namefmt, nameap); \ 1521258065Spjd va_end(nameap); \ 1522258065Spjd \ 1523258065Spjd return (value); \ 1524258065Spjd} 1525258065Spjd 1526258065SpjdNVLIST_TAKEF(nvpair_t *, nvpair) 1527258065SpjdNVLIST_TAKEF(bool, bool) 1528258065SpjdNVLIST_TAKEF(uint64_t, number) 1529258065SpjdNVLIST_TAKEF(char *, string) 1530258065SpjdNVLIST_TAKEF(nvlist_t *, nvlist) 1531258065SpjdNVLIST_TAKEF(int, descriptor) 1532258065Spjd 1533258065Spjd#undef NVLIST_TAKEF 1534258065Spjd 1535258065Spjdvoid * 1536258065Spjdnvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) 1537258065Spjd{ 1538258065Spjd va_list nameap; 1539258065Spjd void *value; 1540258065Spjd 1541258065Spjd va_start(nameap, namefmt); 1542258065Spjd value = nvlist_takev_binary(nvl, sizep, namefmt, nameap); 1543258065Spjd va_end(nameap); 1544258065Spjd 1545258065Spjd return (value); 1546258065Spjd} 1547258065Spjd 1548258065Spjdnvpair_t * 1549258065Spjdnvlist_takev_nvpair(nvlist_t *nvl, const char *namefmt, va_list nameap) 1550258065Spjd{ 1551258065Spjd nvpair_t *nvp; 1552258065Spjd 1553258065Spjd nvp = nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap); 1554258065Spjd if (nvp != NULL) 1555258065Spjd nvlist_remove_nvpair(nvl, nvp); 1556258065Spjd return (nvp); 1557258065Spjd} 1558258065Spjd 1559258065Spjd#define NVLIST_TAKEV(ftype, type, TYPE) \ 1560258065Spjdftype \ 1561258065Spjdnvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \ 1562258065Spjd{ \ 1563258065Spjd va_list cnameap; \ 1564258065Spjd nvpair_t *nvp; \ 1565258065Spjd ftype value; \ 1566258065Spjd \ 1567258065Spjd va_copy(cnameap, nameap); \ 1568258065Spjd nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \ 1569258065Spjd va_end(cnameap); \ 1570258065Spjd if (nvp == NULL) \ 1571258065Spjd nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \ 1572258065Spjd value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ 1573258065Spjd nvlist_remove_nvpair(nvl, nvp); \ 1574258065Spjd nvpair_free_structure(nvp); \ 1575258065Spjd return (value); \ 1576258065Spjd} 1577258065Spjd 1578258065SpjdNVLIST_TAKEV(bool, bool, BOOL) 1579258065SpjdNVLIST_TAKEV(uint64_t, number, NUMBER) 1580258065SpjdNVLIST_TAKEV(char *, string, STRING) 1581258065SpjdNVLIST_TAKEV(nvlist_t *, nvlist, NVLIST) 1582258065SpjdNVLIST_TAKEV(int, descriptor, DESCRIPTOR) 1583258065Spjd 1584258065Spjd#undef NVLIST_TAKEV 1585258065Spjd 1586258065Spjdvoid * 1587258065Spjdnvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, 1588258065Spjd va_list nameap) 1589258065Spjd{ 1590258065Spjd va_list cnameap; 1591258065Spjd nvpair_t *nvp; 1592258065Spjd void *value; 1593258065Spjd 1594258065Spjd va_copy(cnameap, nameap); 1595258065Spjd nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap); 1596258065Spjd va_end(cnameap); 1597258065Spjd if (nvp == NULL) 1598258065Spjd nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap); 1599258065Spjd 1600258065Spjd value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); 1601258065Spjd nvlist_remove_nvpair(nvl, nvp); 1602258065Spjd nvpair_free_structure(nvp); 1603258065Spjd return (value); 1604258065Spjd} 1605258065Spjd 1606258065Spjdvoid 1607258065Spjdnvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1608258065Spjd{ 1609258065Spjd 1610258065Spjd NVLIST_ASSERT(nvl); 1611258065Spjd NVPAIR_ASSERT(nvp); 1612258065Spjd PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 1613258065Spjd 1614258065Spjd nvpair_remove(&nvl->nvl_head, nvp, nvl); 1615258065Spjd} 1616258065Spjd 1617258065Spjdvoid 1618258065Spjdnvlist_free(nvlist_t *nvl, const char *name) 1619258065Spjd{ 1620258065Spjd 1621258065Spjd nvlist_freef(nvl, "%s", name); 1622258065Spjd} 1623258065Spjd 1624258065Spjd#define NVLIST_FREE(type) \ 1625258065Spjdvoid \ 1626258065Spjdnvlist_free_##type(nvlist_t *nvl, const char *name) \ 1627258065Spjd{ \ 1628258065Spjd \ 1629258065Spjd nvlist_freef_##type(nvl, "%s", name); \ 1630258065Spjd} 1631258065Spjd 1632258065SpjdNVLIST_FREE(null) 1633258065SpjdNVLIST_FREE(bool) 1634258065SpjdNVLIST_FREE(number) 1635258065SpjdNVLIST_FREE(string) 1636258065SpjdNVLIST_FREE(nvlist) 1637258065SpjdNVLIST_FREE(descriptor) 1638258065SpjdNVLIST_FREE(binary) 1639258065Spjd 1640258065Spjd#undef NVLIST_FREE 1641258065Spjd 1642258065Spjdvoid 1643258065Spjdnvlist_freef(nvlist_t *nvl, const char *namefmt, ...) 1644258065Spjd{ 1645258065Spjd va_list nameap; 1646258065Spjd 1647258065Spjd va_start(nameap, namefmt); 1648258065Spjd nvlist_freev(nvl, namefmt, nameap); 1649258065Spjd va_end(nameap); 1650258065Spjd} 1651258065Spjd 1652258065Spjd#define NVLIST_FREEF(type) \ 1653258065Spjdvoid \ 1654258065Spjdnvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...) \ 1655258065Spjd{ \ 1656258065Spjd va_list nameap; \ 1657258065Spjd \ 1658258065Spjd va_start(nameap, namefmt); \ 1659258065Spjd nvlist_freev_##type(nvl, namefmt, nameap); \ 1660258065Spjd va_end(nameap); \ 1661258065Spjd} 1662258065Spjd 1663258065SpjdNVLIST_FREEF(null) 1664258065SpjdNVLIST_FREEF(bool) 1665258065SpjdNVLIST_FREEF(number) 1666258065SpjdNVLIST_FREEF(string) 1667258065SpjdNVLIST_FREEF(nvlist) 1668258065SpjdNVLIST_FREEF(descriptor) 1669258065SpjdNVLIST_FREEF(binary) 1670258065Spjd 1671258065Spjd#undef NVLIST_FREEF 1672258065Spjd 1673258065Spjdvoid 1674258065Spjdnvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap) 1675258065Spjd{ 1676258065Spjd 1677258065Spjd nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap); 1678258065Spjd} 1679258065Spjd 1680258065Spjd#define NVLIST_FREEV(type, TYPE) \ 1681258065Spjdvoid \ 1682258065Spjdnvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \ 1683258065Spjd{ \ 1684258065Spjd \ 1685258065Spjd nvlist_freev_type(nvl, NV_TYPE_##TYPE, namefmt, nameap); \ 1686258065Spjd} 1687258065Spjd 1688258065SpjdNVLIST_FREEV(null, NULL) 1689258065SpjdNVLIST_FREEV(bool, BOOL) 1690258065SpjdNVLIST_FREEV(number, NUMBER) 1691258065SpjdNVLIST_FREEV(string, STRING) 1692258065SpjdNVLIST_FREEV(nvlist, NVLIST) 1693258065SpjdNVLIST_FREEV(descriptor, DESCRIPTOR) 1694258065SpjdNVLIST_FREEV(binary, BINARY) 1695258065Spjd#undef NVLIST_FREEV 1696258065Spjd 1697258065Spjdvoid 1698258065Spjdnvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1699258065Spjd{ 1700258065Spjd 1701258065Spjd NVLIST_ASSERT(nvl); 1702258065Spjd NVPAIR_ASSERT(nvp); 1703258065Spjd PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 1704258065Spjd 1705258065Spjd nvlist_remove_nvpair(nvl, nvp); 1706258065Spjd nvpair_free(nvp); 1707258065Spjd} 1708