subr_nvlist.c revision 279439
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/sys/kern/subr_nvlist.c 279439 2015-03-01 00:34:27Z rstone $"); 32258065Spjd 33258065Spjd#include <sys/param.h> 34258065Spjd#include <sys/endian.h> 35258065Spjd#include <sys/queue.h> 36279438Srstone 37279438Srstone#ifdef _KERNEL 38279438Srstone 39279438Srstone#include <sys/errno.h> 40279438Srstone#include <sys/kernel.h> 41279438Srstone#include <sys/lock.h> 42279438Srstone#include <sys/malloc.h> 43279438Srstone#include <sys/systm.h> 44279438Srstone 45279438Srstone#include <machine/stdarg.h> 46279438Srstone 47279438Srstone#else 48258065Spjd#include <sys/socket.h> 49258065Spjd 50258065Spjd#include <errno.h> 51258065Spjd#include <stdarg.h> 52258065Spjd#include <stdbool.h> 53258065Spjd#include <stdint.h> 54258065Spjd#define _WITH_DPRINTF 55258065Spjd#include <stdio.h> 56258065Spjd#include <stdlib.h> 57258065Spjd#include <string.h> 58258065Spjd#include <unistd.h> 59279439Srstone 60279439Srstone#include "msgio.h" 61279438Srstone#endif 62258065Spjd 63258065Spjd#ifdef HAVE_PJDLOG 64258065Spjd#include <pjdlog.h> 65258065Spjd#endif 66258065Spjd 67279439Srstone#include <sys/nv.h> 68279439Srstone#include <sys/nv_impl.h> 69279439Srstone#include <sys/nvlist_impl.h> 70279439Srstone#include <sys/nvpair_impl.h> 71258065Spjd 72258065Spjd#ifndef HAVE_PJDLOG 73279438Srstone#ifdef _KERNEL 74279438Srstone#define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) 75279438Srstone#define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) 76279438Srstone#define PJDLOG_ABORT(...) panic(__VA_ARGS__) 77279438Srstone#else 78258065Spjd#include <assert.h> 79258065Spjd#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 80258065Spjd#define PJDLOG_RASSERT(expr, ...) assert(expr) 81258065Spjd#define PJDLOG_ABORT(...) do { \ 82258065Spjd fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \ 83258065Spjd fprintf(stderr, __VA_ARGS__); \ 84258065Spjd fprintf(stderr, "\n"); \ 85258065Spjd abort(); \ 86258065Spjd} while (0) 87258065Spjd#endif 88279438Srstone#endif 89258065Spjd 90258065Spjd#define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN) 91258065Spjd#define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE) 92258065Spjd#define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK) 93258065Spjd 94258065Spjd#define NVLIST_MAGIC 0x6e766c /* "nvl" */ 95258065Spjdstruct nvlist { 96271579Spjd int nvl_magic; 97271579Spjd int nvl_error; 98271579Spjd int nvl_flags; 99271579Spjd nvpair_t *nvl_parent; 100271579Spjd struct nvl_head nvl_head; 101258065Spjd}; 102258065Spjd 103258065Spjd#define NVLIST_ASSERT(nvl) do { \ 104258065Spjd PJDLOG_ASSERT((nvl) != NULL); \ 105258065Spjd PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \ 106258065Spjd} while (0) 107258065Spjd 108279438Srstone#ifdef _KERNEL 109279438SrstoneMALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist"); 110279438Srstone#endif 111279438Srstone 112258065Spjd#define NVPAIR_ASSERT(nvp) nvpair_assert(nvp) 113258065Spjd 114258065Spjd#define NVLIST_HEADER_MAGIC 0x6c 115258065Spjd#define NVLIST_HEADER_VERSION 0x00 116258065Spjdstruct nvlist_header { 117258065Spjd uint8_t nvlh_magic; 118258065Spjd uint8_t nvlh_version; 119258065Spjd uint8_t nvlh_flags; 120258065Spjd uint64_t nvlh_descriptors; 121258065Spjd uint64_t nvlh_size; 122258065Spjd} __packed; 123258065Spjd 124258065Spjdnvlist_t * 125258065Spjdnvlist_create(int flags) 126258065Spjd{ 127258065Spjd nvlist_t *nvl; 128258065Spjd 129258065Spjd PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 130258065Spjd 131279438Srstone nvl = nv_malloc(sizeof(*nvl)); 132258065Spjd nvl->nvl_error = 0; 133258065Spjd nvl->nvl_flags = flags; 134271579Spjd nvl->nvl_parent = NULL; 135258065Spjd TAILQ_INIT(&nvl->nvl_head); 136258065Spjd nvl->nvl_magic = NVLIST_MAGIC; 137258065Spjd 138258065Spjd return (nvl); 139258065Spjd} 140258065Spjd 141258065Spjdvoid 142258065Spjdnvlist_destroy(nvlist_t *nvl) 143258065Spjd{ 144258065Spjd nvpair_t *nvp; 145258065Spjd int serrno; 146258065Spjd 147258065Spjd if (nvl == NULL) 148258065Spjd return; 149258065Spjd 150279438Srstone SAVE_ERRNO(serrno); 151258065Spjd 152258065Spjd NVLIST_ASSERT(nvl); 153258065Spjd 154260222Spjd while ((nvp = nvlist_first_nvpair(nvl)) != NULL) { 155258065Spjd nvlist_remove_nvpair(nvl, nvp); 156260222Spjd nvpair_free(nvp); 157260222Spjd } 158258065Spjd nvl->nvl_magic = 0; 159279438Srstone nv_free(nvl); 160258065Spjd 161279438Srstone RESTORE_ERRNO(serrno); 162258065Spjd} 163258065Spjd 164279434Srstonevoid 165279434Srstonenvlist_set_error(nvlist_t *nvl, int error) 166279434Srstone{ 167279434Srstone 168279434Srstone PJDLOG_ASSERT(error != 0); 169279434Srstone 170279434Srstone /* 171279434Srstone * Check for error != 0 so that we don't do the wrong thing if somebody 172279434Srstone * tries to abuse this API when asserts are disabled. 173279434Srstone */ 174279434Srstone if (nvl != NULL && error != 0 && nvl->nvl_error == 0) 175279434Srstone nvl->nvl_error = error; 176279434Srstone} 177279434Srstone 178258065Spjdint 179258065Spjdnvlist_error(const nvlist_t *nvl) 180258065Spjd{ 181258065Spjd 182258065Spjd if (nvl == NULL) 183258065Spjd return (ENOMEM); 184258065Spjd 185258065Spjd NVLIST_ASSERT(nvl); 186258065Spjd 187258065Spjd return (nvl->nvl_error); 188258065Spjd} 189258065Spjd 190271579Spjdnvpair_t * 191271579Spjdnvlist_get_nvpair_parent(const nvlist_t *nvl) 192271579Spjd{ 193271579Spjd 194271579Spjd NVLIST_ASSERT(nvl); 195271579Spjd 196271579Spjd return (nvl->nvl_parent); 197271579Spjd} 198271579Spjd 199271579Spjdconst nvlist_t * 200277921Spjdnvlist_get_parent(const nvlist_t *nvl, void **cookiep) 201271579Spjd{ 202277921Spjd nvpair_t *nvp; 203271579Spjd 204271579Spjd NVLIST_ASSERT(nvl); 205271579Spjd 206277921Spjd nvp = nvl->nvl_parent; 207277921Spjd if (cookiep != NULL) 208277921Spjd *cookiep = nvp; 209277921Spjd if (nvp == NULL) 210271579Spjd return (NULL); 211271579Spjd 212277921Spjd return (nvpair_nvlist(nvp)); 213271579Spjd} 214271579Spjd 215271579Spjdvoid 216271579Spjdnvlist_set_parent(nvlist_t *nvl, nvpair_t *parent) 217271579Spjd{ 218271579Spjd 219271579Spjd NVLIST_ASSERT(nvl); 220271579Spjd 221271579Spjd nvl->nvl_parent = parent; 222271579Spjd} 223271579Spjd 224258065Spjdbool 225258065Spjdnvlist_empty(const nvlist_t *nvl) 226258065Spjd{ 227258065Spjd 228258065Spjd NVLIST_ASSERT(nvl); 229258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 230258065Spjd 231258065Spjd return (nvlist_first_nvpair(nvl) == NULL); 232258065Spjd} 233258065Spjd 234258065Spjdstatic void 235279435Srstonenvlist_report_missing(int type, const char *name) 236258065Spjd{ 237258065Spjd 238258065Spjd PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", 239279435Srstone name, nvpair_type_string(type)); 240258065Spjd} 241258065Spjd 242258065Spjdstatic nvpair_t * 243279435Srstonenvlist_find(const nvlist_t *nvl, int type, const char *name) 244258065Spjd{ 245258065Spjd nvpair_t *nvp; 246258065Spjd 247258065Spjd NVLIST_ASSERT(nvl); 248258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 249258065Spjd PJDLOG_ASSERT(type == NV_TYPE_NONE || 250258065Spjd (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 251258065Spjd 252258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 253258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 254258065Spjd if (type != NV_TYPE_NONE && nvpair_type(nvp) != type) 255258065Spjd continue; 256258065Spjd if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) { 257258065Spjd if (strcasecmp(nvpair_name(nvp), name) != 0) 258258065Spjd continue; 259258065Spjd } else { 260258065Spjd if (strcmp(nvpair_name(nvp), name) != 0) 261258065Spjd continue; 262258065Spjd } 263258065Spjd break; 264258065Spjd } 265258065Spjd 266258065Spjd if (nvp == NULL) 267279438Srstone RESTORE_ERRNO(ENOENT); 268258065Spjd 269258065Spjd return (nvp); 270258065Spjd} 271258065Spjd 272258065Spjdbool 273258065Spjdnvlist_exists_type(const nvlist_t *nvl, const char *name, int type) 274258065Spjd{ 275258065Spjd 276279435Srstone NVLIST_ASSERT(nvl); 277279435Srstone PJDLOG_ASSERT(nvl->nvl_error == 0); 278279435Srstone PJDLOG_ASSERT(type == NV_TYPE_NONE || 279279435Srstone (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 280279435Srstone 281279435Srstone return (nvlist_find(nvl, type, name) != NULL); 282258065Spjd} 283258065Spjd 284279438Srstone#ifndef _KERNEL 285258065Spjdbool 286258065Spjdnvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...) 287258065Spjd{ 288258065Spjd va_list nameap; 289258065Spjd bool ret; 290258065Spjd 291258065Spjd va_start(nameap, namefmt); 292258065Spjd ret = nvlist_existsv_type(nvl, type, namefmt, nameap); 293258065Spjd va_end(nameap); 294258065Spjd 295258065Spjd return (ret); 296258065Spjd} 297258065Spjd 298258065Spjdbool 299258065Spjdnvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt, 300258065Spjd va_list nameap) 301258065Spjd{ 302279435Srstone char *name; 303279435Srstone bool exists; 304258065Spjd 305279438Srstone nv_vasprintf(&name, namefmt, nameap); 306279435Srstone if (name == NULL) 307279435Srstone return (false); 308258065Spjd 309279435Srstone exists = nvlist_exists_type(nvl, name, type); 310279438Srstone nv_free(name); 311279435Srstone return (exists); 312258065Spjd} 313279438Srstone#endif 314258065Spjd 315258065Spjdvoid 316258065Spjdnvlist_free_type(nvlist_t *nvl, const char *name, int type) 317258065Spjd{ 318279435Srstone nvpair_t *nvp; 319258065Spjd 320279435Srstone NVLIST_ASSERT(nvl); 321279435Srstone PJDLOG_ASSERT(nvl->nvl_error == 0); 322279435Srstone PJDLOG_ASSERT(type == NV_TYPE_NONE || 323279435Srstone (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 324279435Srstone 325279435Srstone nvp = nvlist_find(nvl, type, name); 326279435Srstone if (nvp != NULL) 327279435Srstone nvlist_free_nvpair(nvl, nvp); 328279435Srstone else 329279435Srstone nvlist_report_missing(type, name); 330258065Spjd} 331258065Spjd 332279438Srstone#ifndef _KERNEL 333258065Spjdvoid 334258065Spjdnvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...) 335258065Spjd{ 336258065Spjd va_list nameap; 337258065Spjd 338258065Spjd va_start(nameap, namefmt); 339258065Spjd nvlist_freev_type(nvl, type, namefmt, nameap); 340258065Spjd va_end(nameap); 341258065Spjd} 342258065Spjd 343258065Spjdvoid 344258065Spjdnvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap) 345258065Spjd{ 346279435Srstone char *name; 347258065Spjd 348279438Srstone nv_vasprintf(&name, namefmt, nameap); 349279435Srstone if (name == NULL) 350279435Srstone nvlist_report_missing(type, "<unknown>"); 351279435Srstone nvlist_free_type(nvl, name, type); 352279438Srstone nv_free(name); 353258065Spjd} 354279438Srstone#endif 355258065Spjd 356258065Spjdnvlist_t * 357258065Spjdnvlist_clone(const nvlist_t *nvl) 358258065Spjd{ 359258065Spjd nvlist_t *newnvl; 360258065Spjd nvpair_t *nvp, *newnvp; 361258065Spjd 362258065Spjd NVLIST_ASSERT(nvl); 363258065Spjd 364258065Spjd if (nvl->nvl_error != 0) { 365279438Srstone RESTORE_ERRNO(nvl->nvl_error); 366258065Spjd return (NULL); 367258065Spjd } 368258065Spjd 369258065Spjd newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); 370258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 371258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 372258065Spjd newnvp = nvpair_clone(nvp); 373258065Spjd if (newnvp == NULL) 374258065Spjd break; 375258065Spjd nvlist_move_nvpair(newnvl, newnvp); 376258065Spjd } 377258065Spjd if (nvp != NULL) { 378258065Spjd nvlist_destroy(newnvl); 379258065Spjd return (NULL); 380258065Spjd } 381258065Spjd return (newnvl); 382258065Spjd} 383258065Spjd 384279438Srstone#ifndef _KERNEL 385271579Spjdstatic bool 386271579Spjdnvlist_dump_error_check(const nvlist_t *nvl, int fd, int level) 387271579Spjd{ 388271579Spjd 389271579Spjd if (nvlist_error(nvl) != 0) { 390271579Spjd dprintf(fd, "%*serror: %d\n", level * 4, "", 391271579Spjd nvlist_error(nvl)); 392271579Spjd return (true); 393271579Spjd } 394271579Spjd 395271579Spjd return (false); 396271579Spjd} 397271579Spjd 398258065Spjd/* 399258065Spjd * Dump content of nvlist. 400258065Spjd */ 401271579Spjdvoid 402271579Spjdnvlist_dump(const nvlist_t *nvl, int fd) 403258065Spjd{ 404277925Spjd const nvlist_t *tmpnvl; 405277925Spjd nvpair_t *nvp, *tmpnvp; 406277927Spjd void *cookie; 407271579Spjd int level; 408258065Spjd 409271579Spjd level = 0; 410271579Spjd if (nvlist_dump_error_check(nvl, fd, level)) 411258065Spjd return; 412258065Spjd 413271579Spjd nvp = nvlist_first_nvpair(nvl); 414271579Spjd while (nvp != NULL) { 415258065Spjd dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), 416258065Spjd nvpair_type_string(nvpair_type(nvp))); 417258065Spjd switch (nvpair_type(nvp)) { 418258065Spjd case NV_TYPE_NULL: 419258065Spjd dprintf(fd, " null\n"); 420258065Spjd break; 421258065Spjd case NV_TYPE_BOOL: 422258065Spjd dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? 423258065Spjd "TRUE" : "FALSE"); 424258065Spjd break; 425258065Spjd case NV_TYPE_NUMBER: 426258065Spjd dprintf(fd, " %ju (%jd) (0x%jx)\n", 427258065Spjd (uintmax_t)nvpair_get_number(nvp), 428258065Spjd (intmax_t)nvpair_get_number(nvp), 429258065Spjd (uintmax_t)nvpair_get_number(nvp)); 430258065Spjd break; 431258065Spjd case NV_TYPE_STRING: 432258065Spjd dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); 433258065Spjd break; 434258065Spjd case NV_TYPE_NVLIST: 435258065Spjd dprintf(fd, "\n"); 436277925Spjd tmpnvl = nvpair_get_nvlist(nvp); 437277925Spjd if (nvlist_dump_error_check(tmpnvl, fd, level + 1)) 438271579Spjd break; 439277925Spjd tmpnvp = nvlist_first_nvpair(tmpnvl); 440277925Spjd if (tmpnvp != NULL) { 441277925Spjd nvl = tmpnvl; 442277925Spjd nvp = tmpnvp; 443277925Spjd level++; 444277925Spjd continue; 445271579Spjd } 446277925Spjd break; 447258065Spjd case NV_TYPE_DESCRIPTOR: 448258065Spjd dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); 449258065Spjd break; 450258065Spjd case NV_TYPE_BINARY: 451258065Spjd { 452258065Spjd const unsigned char *binary; 453258065Spjd unsigned int ii; 454258065Spjd size_t size; 455258065Spjd 456258065Spjd binary = nvpair_get_binary(nvp, &size); 457258065Spjd dprintf(fd, " %zu ", size); 458258065Spjd for (ii = 0; ii < size; ii++) 459258065Spjd dprintf(fd, "%02hhx", binary[ii]); 460258065Spjd dprintf(fd, "\n"); 461258065Spjd break; 462258065Spjd } 463258065Spjd default: 464258065Spjd PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 465258065Spjd } 466271579Spjd 467271579Spjd while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 468277927Spjd cookie = NULL; 469277927Spjd nvl = nvlist_get_parent(nvl, &cookie); 470277921Spjd if (nvl == NULL) 471271579Spjd return; 472277927Spjd nvp = cookie; 473277921Spjd level--; 474271579Spjd } 475258065Spjd } 476258065Spjd} 477258065Spjd 478258065Spjdvoid 479258065Spjdnvlist_fdump(const nvlist_t *nvl, FILE *fp) 480258065Spjd{ 481258065Spjd 482258065Spjd fflush(fp); 483258065Spjd nvlist_dump(nvl, fileno(fp)); 484258065Spjd} 485279438Srstone#endif 486258065Spjd 487258065Spjd/* 488258065Spjd * The function obtains size of the nvlist after nvlist_pack(). 489258065Spjd */ 490271579Spjdsize_t 491271579Spjdnvlist_size(const nvlist_t *nvl) 492258065Spjd{ 493277925Spjd const nvlist_t *tmpnvl; 494277925Spjd const nvpair_t *nvp, *tmpnvp; 495277927Spjd void *cookie; 496258065Spjd size_t size; 497258065Spjd 498258065Spjd NVLIST_ASSERT(nvl); 499258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 500258065Spjd 501258065Spjd size = sizeof(struct nvlist_header); 502271579Spjd nvp = nvlist_first_nvpair(nvl); 503271579Spjd while (nvp != NULL) { 504258065Spjd size += nvpair_header_size(); 505258065Spjd size += strlen(nvpair_name(nvp)) + 1; 506271579Spjd if (nvpair_type(nvp) == NV_TYPE_NVLIST) { 507271579Spjd size += sizeof(struct nvlist_header); 508271579Spjd size += nvpair_header_size() + 1; 509277925Spjd tmpnvl = nvpair_get_nvlist(nvp); 510277925Spjd PJDLOG_ASSERT(tmpnvl->nvl_error == 0); 511277925Spjd tmpnvp = nvlist_first_nvpair(tmpnvl); 512277925Spjd if (tmpnvp != NULL) { 513277925Spjd nvl = tmpnvl; 514277925Spjd nvp = tmpnvp; 515277925Spjd continue; 516277925Spjd } 517271579Spjd } else { 518258065Spjd size += nvpair_size(nvp); 519271579Spjd } 520271579Spjd 521271579Spjd while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 522277927Spjd cookie = NULL; 523277927Spjd nvl = nvlist_get_parent(nvl, &cookie); 524277921Spjd if (nvl == NULL) 525271579Spjd goto out; 526277927Spjd nvp = cookie; 527271579Spjd } 528258065Spjd } 529258065Spjd 530271579Spjdout: 531258065Spjd return (size); 532258065Spjd} 533258065Spjd 534279438Srstone#ifndef _KERNEL 535258065Spjdstatic int * 536258065Spjdnvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level) 537258065Spjd{ 538258065Spjd const nvpair_t *nvp; 539258065Spjd 540258065Spjd NVLIST_ASSERT(nvl); 541258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 542258065Spjd PJDLOG_ASSERT(level < 3); 543258065Spjd 544258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 545258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 546258065Spjd switch (nvpair_type(nvp)) { 547258065Spjd case NV_TYPE_DESCRIPTOR: 548258065Spjd *descs = nvpair_get_descriptor(nvp); 549258065Spjd descs++; 550258065Spjd break; 551258065Spjd case NV_TYPE_NVLIST: 552258065Spjd descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp), 553258065Spjd descs, level + 1); 554258065Spjd break; 555258065Spjd } 556258065Spjd } 557258065Spjd 558258065Spjd return (descs); 559258065Spjd} 560279438Srstone#endif 561258065Spjd 562279438Srstone#ifndef _KERNEL 563258065Spjdint * 564258065Spjdnvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp) 565258065Spjd{ 566258065Spjd size_t nitems; 567258065Spjd int *fds; 568258065Spjd 569258065Spjd nitems = nvlist_ndescriptors(nvl); 570279438Srstone fds = nv_malloc(sizeof(fds[0]) * (nitems + 1)); 571258065Spjd if (fds == NULL) 572258065Spjd return (NULL); 573258065Spjd if (nitems > 0) 574258065Spjd nvlist_xdescriptors(nvl, fds, 0); 575258065Spjd fds[nitems] = -1; 576258065Spjd if (nitemsp != NULL) 577258065Spjd *nitemsp = nitems; 578258065Spjd return (fds); 579258065Spjd} 580279438Srstone#endif 581258065Spjd 582258065Spjdstatic size_t 583258065Spjdnvlist_xndescriptors(const nvlist_t *nvl, int level) 584258065Spjd{ 585279438Srstone#ifndef _KERNEL 586258065Spjd const nvpair_t *nvp; 587258065Spjd size_t ndescs; 588258065Spjd 589258065Spjd NVLIST_ASSERT(nvl); 590258065Spjd PJDLOG_ASSERT(nvl->nvl_error == 0); 591258065Spjd PJDLOG_ASSERT(level < 3); 592258065Spjd 593258065Spjd ndescs = 0; 594258065Spjd for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 595258065Spjd nvp = nvlist_next_nvpair(nvl, nvp)) { 596258065Spjd switch (nvpair_type(nvp)) { 597258065Spjd case NV_TYPE_DESCRIPTOR: 598258065Spjd ndescs++; 599258065Spjd break; 600258065Spjd case NV_TYPE_NVLIST: 601258065Spjd ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp), 602258065Spjd level + 1); 603258065Spjd break; 604258065Spjd } 605258065Spjd } 606258065Spjd 607258065Spjd return (ndescs); 608279438Srstone#else 609279438Srstone return (0); 610279438Srstone#endif 611258065Spjd} 612258065Spjd 613258065Spjdsize_t 614258065Spjdnvlist_ndescriptors(const nvlist_t *nvl) 615258065Spjd{ 616258065Spjd 617258065Spjd return (nvlist_xndescriptors(nvl, 0)); 618258065Spjd} 619258065Spjd 620258065Spjdstatic unsigned char * 621258065Spjdnvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp) 622258065Spjd{ 623258065Spjd struct nvlist_header nvlhdr; 624258065Spjd 625258065Spjd NVLIST_ASSERT(nvl); 626258065Spjd 627258065Spjd nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC; 628258065Spjd nvlhdr.nvlh_version = NVLIST_HEADER_VERSION; 629258065Spjd nvlhdr.nvlh_flags = nvl->nvl_flags; 630258065Spjd#if BYTE_ORDER == BIG_ENDIAN 631258065Spjd nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN; 632258065Spjd#endif 633258065Spjd nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl); 634258065Spjd nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr); 635258065Spjd PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr)); 636258065Spjd memcpy(ptr, &nvlhdr, sizeof(nvlhdr)); 637258065Spjd ptr += sizeof(nvlhdr); 638258065Spjd *leftp -= sizeof(nvlhdr); 639258065Spjd 640258065Spjd return (ptr); 641258065Spjd} 642258065Spjd 643258065Spjdvoid * 644258065Spjdnvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) 645258065Spjd{ 646258065Spjd unsigned char *buf, *ptr; 647258065Spjd size_t left, size; 648277925Spjd const nvlist_t *tmpnvl; 649277925Spjd nvpair_t *nvp, *tmpnvp; 650277927Spjd void *cookie; 651258065Spjd 652258065Spjd NVLIST_ASSERT(nvl); 653258065Spjd 654258065Spjd if (nvl->nvl_error != 0) { 655279438Srstone RESTORE_ERRNO(nvl->nvl_error); 656258065Spjd return (NULL); 657258065Spjd } 658258065Spjd 659258065Spjd size = nvlist_size(nvl); 660279438Srstone buf = nv_malloc(size); 661258065Spjd if (buf == NULL) 662258065Spjd return (NULL); 663258065Spjd 664258065Spjd ptr = buf; 665258065Spjd left = size; 666258065Spjd 667258065Spjd ptr = nvlist_pack_header(nvl, ptr, &left); 668258065Spjd 669271579Spjd nvp = nvlist_first_nvpair(nvl); 670271579Spjd while (nvp != NULL) { 671271579Spjd NVPAIR_ASSERT(nvp); 672271579Spjd 673271579Spjd nvpair_init_datasize(nvp); 674271579Spjd ptr = nvpair_pack_header(nvp, ptr, &left); 675258065Spjd if (ptr == NULL) { 676279438Srstone nv_free(buf); 677258065Spjd return (NULL); 678258065Spjd } 679271579Spjd switch (nvpair_type(nvp)) { 680271579Spjd case NV_TYPE_NULL: 681271579Spjd ptr = nvpair_pack_null(nvp, ptr, &left); 682271579Spjd break; 683271579Spjd case NV_TYPE_BOOL: 684271579Spjd ptr = nvpair_pack_bool(nvp, ptr, &left); 685271579Spjd break; 686271579Spjd case NV_TYPE_NUMBER: 687271579Spjd ptr = nvpair_pack_number(nvp, ptr, &left); 688271579Spjd break; 689271579Spjd case NV_TYPE_STRING: 690271579Spjd ptr = nvpair_pack_string(nvp, ptr, &left); 691271579Spjd break; 692271579Spjd case NV_TYPE_NVLIST: 693277925Spjd tmpnvl = nvpair_get_nvlist(nvp); 694277925Spjd ptr = nvlist_pack_header(tmpnvl, ptr, &left); 695277925Spjd if (ptr == NULL) 696277925Spjd goto out; 697277925Spjd tmpnvp = nvlist_first_nvpair(tmpnvl); 698277925Spjd if (tmpnvp != NULL) { 699277925Spjd nvl = tmpnvl; 700277925Spjd nvp = tmpnvp; 701277925Spjd continue; 702277925Spjd } 703277925Spjd ptr = nvpair_pack_nvlist_up(ptr, &left); 704277925Spjd break; 705279438Srstone#ifndef _KERNEL 706271579Spjd case NV_TYPE_DESCRIPTOR: 707271579Spjd ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left); 708271579Spjd break; 709279438Srstone#endif 710271579Spjd case NV_TYPE_BINARY: 711271579Spjd ptr = nvpair_pack_binary(nvp, ptr, &left); 712271579Spjd break; 713271579Spjd default: 714271579Spjd PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 715271579Spjd } 716271579Spjd if (ptr == NULL) { 717279438Srstone nv_free(buf); 718271579Spjd return (NULL); 719271579Spjd } 720271579Spjd while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 721277927Spjd cookie = NULL; 722277927Spjd nvl = nvlist_get_parent(nvl, &cookie); 723277921Spjd if (nvl == NULL) 724271579Spjd goto out; 725277927Spjd nvp = cookie; 726271579Spjd ptr = nvpair_pack_nvlist_up(ptr, &left); 727271579Spjd if (ptr == NULL) 728271579Spjd goto out; 729271579Spjd } 730258065Spjd } 731258065Spjd 732271579Spjdout: 733258065Spjd if (sizep != NULL) 734258065Spjd *sizep = size; 735258065Spjd return (buf); 736258065Spjd} 737258065Spjd 738258065Spjdvoid * 739258065Spjdnvlist_pack(const nvlist_t *nvl, size_t *sizep) 740258065Spjd{ 741258065Spjd 742258065Spjd NVLIST_ASSERT(nvl); 743258065Spjd 744258065Spjd if (nvl->nvl_error != 0) { 745279438Srstone RESTORE_ERRNO(nvl->nvl_error); 746258065Spjd return (NULL); 747258065Spjd } 748258065Spjd 749258065Spjd if (nvlist_ndescriptors(nvl) > 0) { 750279438Srstone RESTORE_ERRNO(EOPNOTSUPP); 751258065Spjd return (NULL); 752258065Spjd } 753258065Spjd 754258065Spjd return (nvlist_xpack(nvl, NULL, sizep)); 755258065Spjd} 756258065Spjd 757258065Spjdstatic bool 758258065Spjdnvlist_check_header(struct nvlist_header *nvlhdrp) 759258065Spjd{ 760258065Spjd 761258065Spjd if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { 762279438Srstone RESTORE_ERRNO(EINVAL); 763258065Spjd return (false); 764258065Spjd } 765264021Sjilles if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { 766279438Srstone RESTORE_ERRNO(EINVAL); 767258065Spjd return (false); 768258065Spjd } 769258065Spjd#if BYTE_ORDER == BIG_ENDIAN 770258065Spjd if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) { 771258065Spjd nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size); 772258065Spjd nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors); 773258065Spjd } 774258065Spjd#else 775258065Spjd if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) { 776258065Spjd nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size); 777258065Spjd nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); 778258065Spjd } 779258065Spjd#endif 780258065Spjd return (true); 781258065Spjd} 782258065Spjd 783271579Spjdconst unsigned char * 784258065Spjdnvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, 785272843Spjd bool *isbep, size_t *leftp) 786258065Spjd{ 787258065Spjd struct nvlist_header nvlhdr; 788258065Spjd 789258065Spjd if (*leftp < sizeof(nvlhdr)) 790258065Spjd goto failed; 791258065Spjd 792258065Spjd memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); 793258065Spjd 794258065Spjd if (!nvlist_check_header(&nvlhdr)) 795258065Spjd goto failed; 796258065Spjd 797258065Spjd if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) 798258065Spjd goto failed; 799258065Spjd 800258065Spjd /* 801258065Spjd * nvlh_descriptors might be smaller than nfds in embedded nvlists. 802258065Spjd */ 803258065Spjd if (nvlhdr.nvlh_descriptors > nfds) 804258065Spjd goto failed; 805258065Spjd 806258065Spjd if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) 807258065Spjd goto failed; 808258065Spjd 809258065Spjd nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK); 810258065Spjd 811258065Spjd ptr += sizeof(nvlhdr); 812272843Spjd if (isbep != NULL) 813272843Spjd *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0); 814258065Spjd *leftp -= sizeof(nvlhdr); 815258065Spjd 816258065Spjd return (ptr); 817258065Spjdfailed: 818279438Srstone RESTORE_ERRNO(EINVAL); 819258065Spjd return (NULL); 820258065Spjd} 821258065Spjd 822258065Spjdnvlist_t * 823258065Spjdnvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) 824258065Spjd{ 825258065Spjd const unsigned char *ptr; 826271579Spjd nvlist_t *nvl, *retnvl, *tmpnvl; 827258065Spjd nvpair_t *nvp; 828258065Spjd size_t left; 829272843Spjd bool isbe; 830258065Spjd 831258065Spjd left = size; 832258065Spjd ptr = buf; 833258065Spjd 834271579Spjd tmpnvl = NULL; 835271579Spjd nvl = retnvl = nvlist_create(0); 836258065Spjd if (nvl == NULL) 837258065Spjd goto failed; 838258065Spjd 839272843Spjd ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); 840258065Spjd if (ptr == NULL) 841258065Spjd goto failed; 842258065Spjd 843258065Spjd while (left > 0) { 844272843Spjd ptr = nvpair_unpack(isbe, ptr, &left, &nvp); 845258065Spjd if (ptr == NULL) 846258065Spjd goto failed; 847271579Spjd switch (nvpair_type(nvp)) { 848271579Spjd case NV_TYPE_NULL: 849272843Spjd ptr = nvpair_unpack_null(isbe, nvp, ptr, &left); 850271579Spjd break; 851271579Spjd case NV_TYPE_BOOL: 852272843Spjd ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left); 853271579Spjd break; 854271579Spjd case NV_TYPE_NUMBER: 855272843Spjd ptr = nvpair_unpack_number(isbe, nvp, ptr, &left); 856271579Spjd break; 857271579Spjd case NV_TYPE_STRING: 858272843Spjd ptr = nvpair_unpack_string(isbe, nvp, ptr, &left); 859271579Spjd break; 860271579Spjd case NV_TYPE_NVLIST: 861272843Spjd ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds, 862272843Spjd &tmpnvl); 863271579Spjd nvlist_set_parent(tmpnvl, nvp); 864271579Spjd break; 865279438Srstone#ifndef _KERNEL 866271579Spjd case NV_TYPE_DESCRIPTOR: 867272843Spjd ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left, 868271579Spjd fds, nfds); 869271579Spjd break; 870279438Srstone#endif 871271579Spjd case NV_TYPE_BINARY: 872272843Spjd ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left); 873271579Spjd break; 874271579Spjd case NV_TYPE_NVLIST_UP: 875271579Spjd if (nvl->nvl_parent == NULL) 876271579Spjd goto failed; 877271579Spjd nvl = nvpair_nvlist(nvl->nvl_parent); 878271579Spjd continue; 879271579Spjd default: 880271579Spjd PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 881271579Spjd } 882271579Spjd if (ptr == NULL) 883271579Spjd goto failed; 884258065Spjd nvlist_move_nvpair(nvl, nvp); 885271579Spjd if (tmpnvl != NULL) { 886271579Spjd nvl = tmpnvl; 887271579Spjd tmpnvl = NULL; 888271579Spjd } 889258065Spjd } 890258065Spjd 891271579Spjd return (retnvl); 892258065Spjdfailed: 893271579Spjd nvlist_destroy(retnvl); 894258065Spjd return (NULL); 895258065Spjd} 896258065Spjd 897258065Spjdnvlist_t * 898258065Spjdnvlist_unpack(const void *buf, size_t size) 899258065Spjd{ 900258065Spjd 901258065Spjd return (nvlist_xunpack(buf, size, NULL, 0)); 902258065Spjd} 903258065Spjd 904279438Srstone#ifndef _KERNEL 905258065Spjdint 906258065Spjdnvlist_send(int sock, const nvlist_t *nvl) 907258065Spjd{ 908258065Spjd size_t datasize, nfds; 909258065Spjd int *fds; 910258065Spjd void *data; 911258065Spjd int64_t fdidx; 912258065Spjd int serrno, ret; 913258065Spjd 914258065Spjd if (nvlist_error(nvl) != 0) { 915258065Spjd errno = nvlist_error(nvl); 916258065Spjd return (-1); 917258065Spjd } 918258065Spjd 919258065Spjd fds = nvlist_descriptors(nvl, &nfds); 920258065Spjd if (fds == NULL) 921258065Spjd return (-1); 922258065Spjd 923258065Spjd ret = -1; 924258065Spjd data = NULL; 925258065Spjd fdidx = 0; 926258065Spjd 927258065Spjd data = nvlist_xpack(nvl, &fdidx, &datasize); 928258065Spjd if (data == NULL) 929258065Spjd goto out; 930258065Spjd 931258065Spjd if (buf_send(sock, data, datasize) == -1) 932258065Spjd goto out; 933258065Spjd 934258065Spjd if (nfds > 0) { 935258065Spjd if (fd_send(sock, fds, nfds) == -1) 936258065Spjd goto out; 937258065Spjd } 938258065Spjd 939258065Spjd ret = 0; 940258065Spjdout: 941258065Spjd serrno = errno; 942258065Spjd free(fds); 943258065Spjd free(data); 944258065Spjd errno = serrno; 945258065Spjd return (ret); 946258065Spjd} 947258065Spjd 948258065Spjdnvlist_t * 949258065Spjdnvlist_recv(int sock) 950258065Spjd{ 951258065Spjd struct nvlist_header nvlhdr; 952258065Spjd nvlist_t *nvl, *ret; 953259430Spjd unsigned char *buf; 954271028Spjd size_t nfds, size, i; 955271028Spjd int serrno, *fds; 956258065Spjd 957259430Spjd if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1) 958258065Spjd return (NULL); 959258065Spjd 960258065Spjd if (!nvlist_check_header(&nvlhdr)) 961258065Spjd return (NULL); 962258065Spjd 963258065Spjd nfds = (size_t)nvlhdr.nvlh_descriptors; 964258065Spjd size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size; 965258065Spjd 966258065Spjd buf = malloc(size); 967258065Spjd if (buf == NULL) 968258065Spjd return (NULL); 969258065Spjd 970259430Spjd memcpy(buf, &nvlhdr, sizeof(nvlhdr)); 971259430Spjd 972258065Spjd ret = NULL; 973258065Spjd fds = NULL; 974258065Spjd 975259430Spjd if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1) 976258065Spjd goto out; 977258065Spjd 978258065Spjd if (nfds > 0) { 979258065Spjd fds = malloc(nfds * sizeof(fds[0])); 980258065Spjd if (fds == NULL) 981258065Spjd goto out; 982258065Spjd if (fd_recv(sock, fds, nfds) == -1) 983258065Spjd goto out; 984258065Spjd } 985258065Spjd 986258065Spjd nvl = nvlist_xunpack(buf, size, fds, nfds); 987271026Spjd if (nvl == NULL) { 988271026Spjd for (i = 0; i < nfds; i++) 989271026Spjd close(fds[i]); 990258065Spjd goto out; 991271026Spjd } 992258065Spjd 993258065Spjd ret = nvl; 994258065Spjdout: 995258065Spjd serrno = errno; 996258065Spjd free(buf); 997258065Spjd free(fds); 998258065Spjd errno = serrno; 999258065Spjd 1000258065Spjd return (ret); 1001258065Spjd} 1002258065Spjd 1003258065Spjdnvlist_t * 1004258065Spjdnvlist_xfer(int sock, nvlist_t *nvl) 1005258065Spjd{ 1006258065Spjd 1007258065Spjd if (nvlist_send(sock, nvl) < 0) { 1008258065Spjd nvlist_destroy(nvl); 1009258065Spjd return (NULL); 1010258065Spjd } 1011258065Spjd nvlist_destroy(nvl); 1012258065Spjd return (nvlist_recv(sock)); 1013258065Spjd} 1014279438Srstone#endif 1015258065Spjd 1016258065Spjdnvpair_t * 1017258065Spjdnvlist_first_nvpair(const nvlist_t *nvl) 1018258065Spjd{ 1019258065Spjd 1020258065Spjd NVLIST_ASSERT(nvl); 1021258065Spjd 1022258065Spjd return (TAILQ_FIRST(&nvl->nvl_head)); 1023258065Spjd} 1024258065Spjd 1025258065Spjdnvpair_t * 1026258065Spjdnvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 1027258065Spjd{ 1028258065Spjd nvpair_t *retnvp; 1029258065Spjd 1030258065Spjd NVLIST_ASSERT(nvl); 1031258065Spjd NVPAIR_ASSERT(nvp); 1032258065Spjd PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 1033258065Spjd 1034258065Spjd retnvp = nvpair_next(nvp); 1035258065Spjd PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl); 1036258065Spjd 1037258065Spjd return (retnvp); 1038258065Spjd 1039258065Spjd} 1040258065Spjd 1041258065Spjdnvpair_t * 1042258065Spjdnvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 1043258065Spjd{ 1044258065Spjd nvpair_t *retnvp; 1045258065Spjd 1046258065Spjd NVLIST_ASSERT(nvl); 1047258065Spjd NVPAIR_ASSERT(nvp); 1048258065Spjd PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 1049258065Spjd 1050258065Spjd retnvp = nvpair_prev(nvp); 1051258065Spjd PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl); 1052258065Spjd 1053258065Spjd return (retnvp); 1054258065Spjd} 1055258065Spjd 1056258065Spjdconst char * 1057258065Spjdnvlist_next(const nvlist_t *nvl, int *typep, void **cookiep) 1058258065Spjd{ 1059258065Spjd nvpair_t *nvp; 1060258065Spjd 1061258065Spjd NVLIST_ASSERT(nvl); 1062258065Spjd PJDLOG_ASSERT(cookiep != NULL); 1063258065Spjd 1064258065Spjd if (*cookiep == NULL) 1065258065Spjd nvp = nvlist_first_nvpair(nvl); 1066258065Spjd else 1067258065Spjd nvp = nvlist_next_nvpair(nvl, *cookiep); 1068258065Spjd if (nvp == NULL) 1069258065Spjd return (NULL); 1070258065Spjd if (typep != NULL) 1071258065Spjd *typep = nvpair_type(nvp); 1072258065Spjd *cookiep = nvp; 1073258065Spjd return (nvpair_name(nvp)); 1074258065Spjd} 1075258065Spjd 1076258065Spjdbool 1077258065Spjdnvlist_exists(const nvlist_t *nvl, const char *name) 1078258065Spjd{ 1079258065Spjd 1080279435Srstone return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL); 1081258065Spjd} 1082258065Spjd 1083279435Srstone#define NVLIST_EXISTS(type, TYPE) \ 1084258065Spjdbool \ 1085258065Spjdnvlist_exists_##type(const nvlist_t *nvl, const char *name) \ 1086258065Spjd{ \ 1087258065Spjd \ 1088279435Srstone return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \ 1089258065Spjd} 1090258065Spjd 1091279435SrstoneNVLIST_EXISTS(null, NULL) 1092279435SrstoneNVLIST_EXISTS(bool, BOOL) 1093279435SrstoneNVLIST_EXISTS(number, NUMBER) 1094279435SrstoneNVLIST_EXISTS(string, STRING) 1095279435SrstoneNVLIST_EXISTS(nvlist, NVLIST) 1096279438Srstone#ifndef _KERNEL 1097279435SrstoneNVLIST_EXISTS(descriptor, DESCRIPTOR) 1098279438Srstone#endif 1099279435SrstoneNVLIST_EXISTS(binary, BINARY) 1100258065Spjd 1101258065Spjd#undef NVLIST_EXISTS 1102258065Spjd 1103279438Srstone#ifndef _KERNEL 1104258065Spjdbool 1105258065Spjdnvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...) 1106258065Spjd{ 1107258065Spjd va_list nameap; 1108258065Spjd bool ret; 1109258065Spjd 1110258065Spjd va_start(nameap, namefmt); 1111258065Spjd ret = nvlist_existsv(nvl, namefmt, nameap); 1112258065Spjd va_end(nameap); 1113258065Spjd return (ret); 1114258065Spjd} 1115258065Spjd 1116258065Spjd#define NVLIST_EXISTSF(type) \ 1117258065Spjdbool \ 1118258065Spjdnvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...) \ 1119258065Spjd{ \ 1120258065Spjd va_list nameap; \ 1121258065Spjd bool ret; \ 1122258065Spjd \ 1123258065Spjd va_start(nameap, namefmt); \ 1124258065Spjd ret = nvlist_existsv_##type(nvl, namefmt, nameap); \ 1125258065Spjd va_end(nameap); \ 1126258065Spjd return (ret); \ 1127258065Spjd} 1128258065Spjd 1129258065SpjdNVLIST_EXISTSF(null) 1130258065SpjdNVLIST_EXISTSF(bool) 1131258065SpjdNVLIST_EXISTSF(number) 1132258065SpjdNVLIST_EXISTSF(string) 1133258065SpjdNVLIST_EXISTSF(nvlist) 1134279438Srstone#ifndef _KERNEL 1135258065SpjdNVLIST_EXISTSF(descriptor) 1136279438Srstone#endif 1137258065SpjdNVLIST_EXISTSF(binary) 1138258065Spjd 1139258065Spjd#undef NVLIST_EXISTSF 1140258065Spjd 1141258065Spjdbool 1142258065Spjdnvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap) 1143258065Spjd{ 1144279435Srstone char *name; 1145279435Srstone bool exists; 1146258065Spjd 1147279438Srstone nv_vasprintf(&name, namefmt, nameap); 1148279435Srstone if (name == NULL) 1149279435Srstone return (false); 1150279435Srstone 1151279435Srstone exists = nvlist_exists(nvl, name); 1152279438Srstone nv_free(name); 1153279435Srstone return (exists); 1154258065Spjd} 1155258065Spjd 1156279435Srstone#define NVLIST_EXISTSV(type) \ 1157258065Spjdbool \ 1158258065Spjdnvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \ 1159258065Spjd va_list nameap) \ 1160258065Spjd{ \ 1161279435Srstone char *name; \ 1162279435Srstone bool exists; \ 1163258065Spjd \ 1164279435Srstone vasprintf(&name, namefmt, nameap); \ 1165279435Srstone if (name == NULL) \ 1166279435Srstone return (false); \ 1167279435Srstone exists = nvlist_exists_##type(nvl, name); \ 1168279435Srstone free(name); \ 1169279435Srstone return (exists); \ 1170258065Spjd} 1171258065Spjd 1172279435SrstoneNVLIST_EXISTSV(null) 1173279435SrstoneNVLIST_EXISTSV(bool) 1174279435SrstoneNVLIST_EXISTSV(number) 1175279435SrstoneNVLIST_EXISTSV(string) 1176279435SrstoneNVLIST_EXISTSV(nvlist) 1177279435SrstoneNVLIST_EXISTSV(descriptor) 1178279435SrstoneNVLIST_EXISTSV(binary) 1179258065Spjd 1180258065Spjd#undef NVLIST_EXISTSV 1181279438Srstone#endif 1182258065Spjd 1183258065Spjdvoid 1184258065Spjdnvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) 1185258065Spjd{ 1186258065Spjd nvpair_t *newnvp; 1187258065Spjd 1188258065Spjd NVPAIR_ASSERT(nvp); 1189258065Spjd 1190258065Spjd if (nvlist_error(nvl) != 0) { 1191279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1192258065Spjd return; 1193258065Spjd } 1194258065Spjd if (nvlist_exists(nvl, nvpair_name(nvp))) { 1195279438Srstone nvl->nvl_error = EEXIST; 1196279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1197258065Spjd return; 1198258065Spjd } 1199258065Spjd 1200258065Spjd newnvp = nvpair_clone(nvp); 1201258065Spjd if (newnvp == NULL) { 1202279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1203279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1204258065Spjd return; 1205258065Spjd } 1206258065Spjd 1207258065Spjd nvpair_insert(&nvl->nvl_head, newnvp, nvl); 1208258065Spjd} 1209258065Spjd 1210258065Spjdvoid 1211258065Spjdnvlist_add_null(nvlist_t *nvl, const char *name) 1212258065Spjd{ 1213258065Spjd 1214258065Spjd nvlist_addf_null(nvl, "%s", name); 1215258065Spjd} 1216258065Spjd 1217258065Spjdvoid 1218258065Spjdnvlist_add_bool(nvlist_t *nvl, const char *name, bool value) 1219258065Spjd{ 1220258065Spjd 1221258065Spjd nvlist_addf_bool(nvl, value, "%s", name); 1222258065Spjd} 1223258065Spjd 1224258065Spjdvoid 1225258065Spjdnvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value) 1226258065Spjd{ 1227258065Spjd 1228258065Spjd nvlist_addf_number(nvl, value, "%s", name); 1229258065Spjd} 1230258065Spjd 1231258065Spjdvoid 1232258065Spjdnvlist_add_string(nvlist_t *nvl, const char *name, const char *value) 1233258065Spjd{ 1234258065Spjd 1235258065Spjd nvlist_addf_string(nvl, value, "%s", name); 1236258065Spjd} 1237258065Spjd 1238258065Spjdvoid 1239258065Spjdnvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) 1240258065Spjd{ 1241258065Spjd va_list valueap; 1242258065Spjd 1243258065Spjd va_start(valueap, valuefmt); 1244258065Spjd nvlist_add_stringv(nvl, name, valuefmt, valueap); 1245258065Spjd va_end(valueap); 1246258065Spjd} 1247258065Spjd 1248258065Spjdvoid 1249258065Spjdnvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, 1250258065Spjd va_list valueap) 1251258065Spjd{ 1252258065Spjd nvpair_t *nvp; 1253258065Spjd 1254258065Spjd if (nvlist_error(nvl) != 0) { 1255279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1256258065Spjd return; 1257258065Spjd } 1258258065Spjd 1259258065Spjd nvp = nvpair_create_stringv(name, valuefmt, valueap); 1260279438Srstone if (nvp == NULL) { 1261279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1262279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1263279438Srstone } else 1264258065Spjd nvlist_move_nvpair(nvl, nvp); 1265258065Spjd} 1266258065Spjd 1267258065Spjdvoid 1268258065Spjdnvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value) 1269258065Spjd{ 1270258065Spjd 1271258065Spjd nvlist_addf_nvlist(nvl, value, "%s", name); 1272258065Spjd} 1273258065Spjd 1274279438Srstone#ifndef _KERNEL 1275258065Spjdvoid 1276258065Spjdnvlist_add_descriptor(nvlist_t *nvl, const char *name, int value) 1277258065Spjd{ 1278258065Spjd 1279258065Spjd nvlist_addf_descriptor(nvl, value, "%s", name); 1280258065Spjd} 1281279438Srstone#endif 1282258065Spjd 1283258065Spjdvoid 1284258065Spjdnvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, 1285258065Spjd size_t size) 1286258065Spjd{ 1287258065Spjd 1288258065Spjd nvlist_addf_binary(nvl, value, size, "%s", name); 1289258065Spjd} 1290258065Spjd 1291258065Spjdvoid 1292258065Spjdnvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...) 1293258065Spjd{ 1294258065Spjd va_list nameap; 1295258065Spjd 1296258065Spjd va_start(nameap, namefmt); 1297258065Spjd nvlist_addv_null(nvl, namefmt, nameap); 1298258065Spjd va_end(nameap); 1299258065Spjd} 1300258065Spjd 1301258065Spjdvoid 1302258065Spjdnvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...) 1303258065Spjd{ 1304258065Spjd va_list nameap; 1305258065Spjd 1306258065Spjd va_start(nameap, namefmt); 1307258065Spjd nvlist_addv_bool(nvl, value, namefmt, nameap); 1308258065Spjd va_end(nameap); 1309258065Spjd} 1310258065Spjd 1311258065Spjdvoid 1312258065Spjdnvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...) 1313258065Spjd{ 1314258065Spjd va_list nameap; 1315258065Spjd 1316258065Spjd va_start(nameap, namefmt); 1317258065Spjd nvlist_addv_number(nvl, value, namefmt, nameap); 1318258065Spjd va_end(nameap); 1319258065Spjd} 1320258065Spjd 1321258065Spjdvoid 1322258065Spjdnvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...) 1323258065Spjd{ 1324258065Spjd va_list nameap; 1325258065Spjd 1326258065Spjd va_start(nameap, namefmt); 1327258065Spjd nvlist_addv_string(nvl, value, namefmt, nameap); 1328258065Spjd va_end(nameap); 1329258065Spjd} 1330258065Spjd 1331258065Spjdvoid 1332258065Spjdnvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, 1333258065Spjd ...) 1334258065Spjd{ 1335258065Spjd va_list nameap; 1336258065Spjd 1337258065Spjd va_start(nameap, namefmt); 1338258065Spjd nvlist_addv_nvlist(nvl, value, namefmt, nameap); 1339258065Spjd va_end(nameap); 1340258065Spjd} 1341258065Spjd 1342279438Srstone#ifndef _KERNEL 1343258065Spjdvoid 1344258065Spjdnvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...) 1345258065Spjd{ 1346258065Spjd va_list nameap; 1347258065Spjd 1348258065Spjd va_start(nameap, namefmt); 1349258065Spjd nvlist_addv_descriptor(nvl, value, namefmt, nameap); 1350258065Spjd va_end(nameap); 1351258065Spjd} 1352279438Srstone#endif 1353258065Spjd 1354258065Spjdvoid 1355258065Spjdnvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size, 1356258065Spjd const char *namefmt, ...) 1357258065Spjd{ 1358258065Spjd va_list nameap; 1359258065Spjd 1360258065Spjd va_start(nameap, namefmt); 1361258065Spjd nvlist_addv_binary(nvl, value, size, namefmt, nameap); 1362258065Spjd va_end(nameap); 1363258065Spjd} 1364258065Spjd 1365258065Spjdvoid 1366258065Spjdnvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap) 1367258065Spjd{ 1368258065Spjd nvpair_t *nvp; 1369258065Spjd 1370258065Spjd if (nvlist_error(nvl) != 0) { 1371279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1372258065Spjd return; 1373258065Spjd } 1374258065Spjd 1375258065Spjd nvp = nvpair_createv_null(namefmt, nameap); 1376279438Srstone if (nvp == NULL) { 1377279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1378279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1379279438Srstone } else 1380258065Spjd nvlist_move_nvpair(nvl, nvp); 1381258065Spjd} 1382258065Spjd 1383258065Spjdvoid 1384258065Spjdnvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap) 1385258065Spjd{ 1386258065Spjd nvpair_t *nvp; 1387258065Spjd 1388258065Spjd if (nvlist_error(nvl) != 0) { 1389279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1390258065Spjd return; 1391258065Spjd } 1392258065Spjd 1393258065Spjd nvp = nvpair_createv_bool(value, namefmt, nameap); 1394279438Srstone if (nvp == NULL) { 1395279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1396279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1397279438Srstone } else 1398258065Spjd nvlist_move_nvpair(nvl, nvp); 1399258065Spjd} 1400258065Spjd 1401258065Spjdvoid 1402258065Spjdnvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt, 1403258065Spjd va_list nameap) 1404258065Spjd{ 1405258065Spjd nvpair_t *nvp; 1406258065Spjd 1407258065Spjd if (nvlist_error(nvl) != 0) { 1408279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1409258065Spjd return; 1410258065Spjd } 1411258065Spjd 1412258065Spjd nvp = nvpair_createv_number(value, namefmt, nameap); 1413279438Srstone if (nvp == NULL) { 1414279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1415279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1416279438Srstone } else 1417258065Spjd nvlist_move_nvpair(nvl, nvp); 1418258065Spjd} 1419258065Spjd 1420258065Spjdvoid 1421258065Spjdnvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt, 1422258065Spjd va_list nameap) 1423258065Spjd{ 1424258065Spjd nvpair_t *nvp; 1425258065Spjd 1426258065Spjd if (nvlist_error(nvl) != 0) { 1427279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1428258065Spjd return; 1429258065Spjd } 1430258065Spjd 1431258065Spjd nvp = nvpair_createv_string(value, namefmt, nameap); 1432279438Srstone if (nvp == NULL) { 1433279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1434279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1435279438Srstone } else 1436258065Spjd nvlist_move_nvpair(nvl, nvp); 1437258065Spjd} 1438258065Spjd 1439258065Spjdvoid 1440258065Spjdnvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, 1441258065Spjd va_list nameap) 1442258065Spjd{ 1443258065Spjd nvpair_t *nvp; 1444258065Spjd 1445258065Spjd if (nvlist_error(nvl) != 0) { 1446279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1447258065Spjd return; 1448258065Spjd } 1449258065Spjd 1450258065Spjd nvp = nvpair_createv_nvlist(value, namefmt, nameap); 1451279438Srstone if (nvp == NULL) { 1452279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1453279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1454279438Srstone } else 1455258065Spjd nvlist_move_nvpair(nvl, nvp); 1456258065Spjd} 1457258065Spjd 1458279438Srstone#ifndef _KERNEL 1459258065Spjdvoid 1460258065Spjdnvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt, 1461258065Spjd va_list nameap) 1462258065Spjd{ 1463258065Spjd nvpair_t *nvp; 1464258065Spjd 1465258065Spjd if (nvlist_error(nvl) != 0) { 1466258065Spjd errno = nvlist_error(nvl); 1467258065Spjd return; 1468258065Spjd } 1469258065Spjd 1470258065Spjd nvp = nvpair_createv_descriptor(value, namefmt, nameap); 1471258065Spjd if (nvp == NULL) 1472258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1473258065Spjd else 1474258065Spjd nvlist_move_nvpair(nvl, nvp); 1475258065Spjd} 1476279438Srstone#endif 1477258065Spjd 1478258065Spjdvoid 1479258065Spjdnvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size, 1480258065Spjd const char *namefmt, va_list nameap) 1481258065Spjd{ 1482258065Spjd nvpair_t *nvp; 1483258065Spjd 1484258065Spjd if (nvlist_error(nvl) != 0) { 1485279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1486258065Spjd return; 1487258065Spjd } 1488258065Spjd 1489258065Spjd nvp = nvpair_createv_binary(value, size, namefmt, nameap); 1490279438Srstone if (nvp == NULL) { 1491279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1492279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1493279438Srstone } else 1494258065Spjd nvlist_move_nvpair(nvl, nvp); 1495258065Spjd} 1496258065Spjd 1497258065Spjdvoid 1498258065Spjdnvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1499258065Spjd{ 1500258065Spjd 1501258065Spjd NVPAIR_ASSERT(nvp); 1502258065Spjd PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); 1503258065Spjd 1504258065Spjd if (nvlist_error(nvl) != 0) { 1505258065Spjd nvpair_free(nvp); 1506279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1507258065Spjd return; 1508258065Spjd } 1509258065Spjd if (nvlist_exists(nvl, nvpair_name(nvp))) { 1510258065Spjd nvpair_free(nvp); 1511279438Srstone nvl->nvl_error = EEXIST; 1512279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1513258065Spjd return; 1514258065Spjd } 1515258065Spjd 1516258065Spjd nvpair_insert(&nvl->nvl_head, nvp, nvl); 1517258065Spjd} 1518258065Spjd 1519258065Spjd#define NVLIST_MOVE(vtype, type) \ 1520258065Spjdvoid \ 1521258065Spjdnvlist_move_##type(nvlist_t *nvl, const char *name, vtype value) \ 1522258065Spjd{ \ 1523258065Spjd \ 1524258065Spjd nvlist_movef_##type(nvl, value, "%s", name); \ 1525258065Spjd} 1526258065Spjd 1527258065SpjdNVLIST_MOVE(char *, string) 1528258065SpjdNVLIST_MOVE(nvlist_t *, nvlist) 1529279438Srstone#ifndef _KERNEL 1530258065SpjdNVLIST_MOVE(int, descriptor) 1531279438Srstone#endif 1532258065Spjd 1533258065Spjd#undef NVLIST_MOVE 1534258065Spjd 1535258065Spjdvoid 1536258065Spjdnvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size) 1537258065Spjd{ 1538258065Spjd 1539258065Spjd nvlist_movef_binary(nvl, value, size, "%s", name); 1540258065Spjd} 1541258065Spjd 1542258065Spjd#define NVLIST_MOVEF(vtype, type) \ 1543258065Spjdvoid \ 1544258065Spjdnvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt, \ 1545258065Spjd ...) \ 1546258065Spjd{ \ 1547258065Spjd va_list nameap; \ 1548258065Spjd \ 1549258065Spjd va_start(nameap, namefmt); \ 1550258065Spjd nvlist_movev_##type(nvl, value, namefmt, nameap); \ 1551258065Spjd va_end(nameap); \ 1552258065Spjd} 1553258065Spjd 1554258065SpjdNVLIST_MOVEF(char *, string) 1555258065SpjdNVLIST_MOVEF(nvlist_t *, nvlist) 1556279438Srstone#ifndef _KERNEL 1557258065SpjdNVLIST_MOVEF(int, descriptor) 1558279438Srstone#endif 1559258065Spjd 1560258065Spjd#undef NVLIST_MOVEF 1561258065Spjd 1562258065Spjdvoid 1563258065Spjdnvlist_movef_binary(nvlist_t *nvl, void *value, size_t size, 1564258065Spjd const char *namefmt, ...) 1565258065Spjd{ 1566258065Spjd va_list nameap; 1567258065Spjd 1568258065Spjd va_start(nameap, namefmt); 1569258065Spjd nvlist_movev_binary(nvl, value, size, namefmt, nameap); 1570258065Spjd va_end(nameap); 1571258065Spjd} 1572258065Spjd 1573258065Spjdvoid 1574258065Spjdnvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt, 1575258065Spjd va_list nameap) 1576258065Spjd{ 1577258065Spjd nvpair_t *nvp; 1578258065Spjd 1579258065Spjd if (nvlist_error(nvl) != 0) { 1580279438Srstone nv_free(value); 1581279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1582258065Spjd return; 1583258065Spjd } 1584258065Spjd 1585258065Spjd nvp = nvpair_movev_string(value, namefmt, nameap); 1586279438Srstone if (nvp == NULL) { 1587279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1588279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1589279438Srstone } else 1590258065Spjd nvlist_move_nvpair(nvl, nvp); 1591258065Spjd} 1592258065Spjd 1593258065Spjdvoid 1594258065Spjdnvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt, 1595258065Spjd va_list nameap) 1596258065Spjd{ 1597258065Spjd nvpair_t *nvp; 1598258065Spjd 1599258065Spjd if (nvlist_error(nvl) != 0) { 1600271579Spjd if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) 1601271579Spjd nvlist_destroy(value); 1602279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1603258065Spjd return; 1604258065Spjd } 1605258065Spjd 1606258065Spjd nvp = nvpair_movev_nvlist(value, namefmt, nameap); 1607279438Srstone if (nvp == NULL) { 1608279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1609279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1610279438Srstone } else 1611258065Spjd nvlist_move_nvpair(nvl, nvp); 1612258065Spjd} 1613258065Spjd 1614279438Srstone#ifndef _KERNEL 1615258065Spjdvoid 1616258065Spjdnvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt, 1617258065Spjd va_list nameap) 1618258065Spjd{ 1619258065Spjd nvpair_t *nvp; 1620258065Spjd 1621258065Spjd if (nvlist_error(nvl) != 0) { 1622258065Spjd close(value); 1623258065Spjd errno = nvlist_error(nvl); 1624258065Spjd return; 1625258065Spjd } 1626258065Spjd 1627258065Spjd nvp = nvpair_movev_descriptor(value, namefmt, nameap); 1628258065Spjd if (nvp == NULL) 1629258065Spjd nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); 1630258065Spjd else 1631258065Spjd nvlist_move_nvpair(nvl, nvp); 1632258065Spjd} 1633279438Srstone#endif 1634258065Spjd 1635258065Spjdvoid 1636258065Spjdnvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, 1637258065Spjd const char *namefmt, va_list nameap) 1638258065Spjd{ 1639258065Spjd nvpair_t *nvp; 1640258065Spjd 1641258065Spjd if (nvlist_error(nvl) != 0) { 1642279438Srstone nv_free(value); 1643279438Srstone RESTORE_ERRNO(nvlist_error(nvl)); 1644258065Spjd return; 1645258065Spjd } 1646258065Spjd 1647258065Spjd nvp = nvpair_movev_binary(value, size, namefmt, nameap); 1648279438Srstone if (nvp == NULL) { 1649279438Srstone nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1650279438Srstone RESTORE_ERRNO(nvl->nvl_error); 1651279438Srstone } else 1652258065Spjd nvlist_move_nvpair(nvl, nvp); 1653258065Spjd} 1654258065Spjd 1655279435Srstoneconst nvpair_t * 1656279435Srstonenvlist_get_nvpair(const nvlist_t *nvl, const char *name) 1657279435Srstone{ 1658279435Srstone 1659279435Srstone return (nvlist_find(nvl, NV_TYPE_NONE, name)); 1660279435Srstone} 1661279435Srstone 1662279435Srstone#define NVLIST_GET(ftype, type, TYPE) \ 1663258065Spjdftype \ 1664258065Spjdnvlist_get_##type(const nvlist_t *nvl, const char *name) \ 1665258065Spjd{ \ 1666279435Srstone const nvpair_t *nvp; \ 1667258065Spjd \ 1668279435Srstone nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 1669279435Srstone if (nvp == NULL) \ 1670279435Srstone nvlist_report_missing(NV_TYPE_##TYPE, name); \ 1671279435Srstone return (nvpair_get_##type(nvp)); \ 1672258065Spjd} 1673258065Spjd 1674279435SrstoneNVLIST_GET(bool, bool, BOOL) 1675279435SrstoneNVLIST_GET(uint64_t, number, NUMBER) 1676279435SrstoneNVLIST_GET(const char *, string, STRING) 1677279435SrstoneNVLIST_GET(const nvlist_t *, nvlist, NVLIST) 1678279438Srstone#ifndef _KERNEL 1679279435SrstoneNVLIST_GET(int, descriptor, DESCRIPTOR) 1680279438Srstone#endif 1681258065Spjd 1682258065Spjd#undef NVLIST_GET 1683258065Spjd 1684258065Spjdconst void * 1685258065Spjdnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) 1686258065Spjd{ 1687279435Srstone nvpair_t *nvp; 1688258065Spjd 1689279435Srstone nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 1690279435Srstone if (nvp == NULL) 1691279435Srstone nvlist_report_missing(NV_TYPE_BINARY, name); 1692279435Srstone 1693279435Srstone return (nvpair_get_binary(nvp, sizep)); 1694258065Spjd} 1695258065Spjd 1696258065Spjd#define NVLIST_GETF(ftype, type) \ 1697258065Spjdftype \ 1698258065Spjdnvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...) \ 1699258065Spjd{ \ 1700258065Spjd va_list nameap; \ 1701258065Spjd ftype value; \ 1702258065Spjd \ 1703258065Spjd va_start(nameap, namefmt); \ 1704258065Spjd value = nvlist_getv_##type(nvl, namefmt, nameap); \ 1705258065Spjd va_end(nameap); \ 1706258065Spjd \ 1707258065Spjd return (value); \ 1708258065Spjd} 1709258065Spjd 1710279438Srstone#ifndef _KERNEL 1711258065SpjdNVLIST_GETF(bool, bool) 1712258065SpjdNVLIST_GETF(uint64_t, number) 1713258065SpjdNVLIST_GETF(const char *, string) 1714258065SpjdNVLIST_GETF(const nvlist_t *, nvlist) 1715258065SpjdNVLIST_GETF(int, descriptor) 1716258065Spjd 1717258065Spjd#undef NVLIST_GETF 1718258065Spjd 1719258065Spjdconst void * 1720258065Spjdnvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) 1721258065Spjd{ 1722258065Spjd va_list nameap; 1723258065Spjd const void *value; 1724258065Spjd 1725258065Spjd va_start(nameap, namefmt); 1726258065Spjd value = nvlist_getv_binary(nvl, sizep, namefmt, nameap); 1727258065Spjd va_end(nameap); 1728258065Spjd 1729258065Spjd return (value); 1730258065Spjd} 1731258065Spjd 1732258065Spjd#define NVLIST_GETV(ftype, type, TYPE) \ 1733258065Spjdftype \ 1734258065Spjdnvlist_getv_##type(const nvlist_t *nvl, const char *namefmt, \ 1735258065Spjd va_list nameap) \ 1736258065Spjd{ \ 1737279435Srstone char *name; \ 1738279435Srstone ftype value; \ 1739258065Spjd \ 1740279435Srstone vasprintf(&name, namefmt, nameap); \ 1741279435Srstone if (name == NULL) \ 1742279435Srstone nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \ 1743279435Srstone value = nvlist_get_##type(nvl, name); \ 1744279435Srstone free(name); \ 1745279435Srstone \ 1746279435Srstone return (value); \ 1747258065Spjd} 1748258065Spjd 1749258065SpjdNVLIST_GETV(bool, bool, BOOL) 1750258065SpjdNVLIST_GETV(uint64_t, number, NUMBER) 1751258065SpjdNVLIST_GETV(const char *, string, STRING) 1752258065SpjdNVLIST_GETV(const nvlist_t *, nvlist, NVLIST) 1753258065SpjdNVLIST_GETV(int, descriptor, DESCRIPTOR) 1754258065Spjd 1755258065Spjd#undef NVLIST_GETV 1756258065Spjd 1757258065Spjdconst void * 1758258065Spjdnvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, 1759258065Spjd va_list nameap) 1760258065Spjd{ 1761279435Srstone char *name; 1762279435Srstone const void *binary; 1763258065Spjd 1764279438Srstone nv_vasprintf(&name, namefmt, nameap); 1765279435Srstone if (name == NULL) 1766279435Srstone nvlist_report_missing(NV_TYPE_BINARY, "<unknown>"); 1767258065Spjd 1768279435Srstone binary = nvlist_get_binary(nvl, name, sizep); 1769279438Srstone nv_free(name); 1770279435Srstone return (binary); 1771258065Spjd} 1772279438Srstone#endif 1773258065Spjd 1774279435Srstone#define NVLIST_TAKE(ftype, type, TYPE) \ 1775258065Spjdftype \ 1776258065Spjdnvlist_take_##type(nvlist_t *nvl, const char *name) \ 1777258065Spjd{ \ 1778279435Srstone nvpair_t *nvp; \ 1779279435Srstone ftype value; \ 1780258065Spjd \ 1781279435Srstone nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 1782279435Srstone if (nvp == NULL) \ 1783279435Srstone nvlist_report_missing(NV_TYPE_##TYPE, name); \ 1784279435Srstone value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ 1785279435Srstone nvlist_remove_nvpair(nvl, nvp); \ 1786279435Srstone nvpair_free_structure(nvp); \ 1787279435Srstone return (value); \ 1788258065Spjd} 1789258065Spjd 1790279435SrstoneNVLIST_TAKE(bool, bool, BOOL) 1791279435SrstoneNVLIST_TAKE(uint64_t, number, NUMBER) 1792279435SrstoneNVLIST_TAKE(char *, string, STRING) 1793279435SrstoneNVLIST_TAKE(nvlist_t *, nvlist, NVLIST) 1794279438Srstone#ifndef _KERNEL 1795279435SrstoneNVLIST_TAKE(int, descriptor, DESCRIPTOR) 1796279438Srstone#endif 1797258065Spjd 1798258065Spjd#undef NVLIST_TAKE 1799258065Spjd 1800258065Spjdvoid * 1801258065Spjdnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) 1802258065Spjd{ 1803279435Srstone nvpair_t *nvp; 1804279435Srstone void *value; 1805258065Spjd 1806279435Srstone nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 1807279435Srstone if (nvp == NULL) 1808279435Srstone nvlist_report_missing(NV_TYPE_BINARY, name); 1809279435Srstone 1810279435Srstone value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); 1811279435Srstone nvlist_remove_nvpair(nvl, nvp); 1812279435Srstone nvpair_free_structure(nvp); 1813279435Srstone return (value); 1814258065Spjd} 1815258065Spjd 1816258065Spjd#define NVLIST_TAKEF(ftype, type) \ 1817258065Spjdftype \ 1818258065Spjdnvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...) \ 1819258065Spjd{ \ 1820258065Spjd va_list nameap; \ 1821258065Spjd ftype value; \ 1822258065Spjd \ 1823258065Spjd va_start(nameap, namefmt); \ 1824258065Spjd value = nvlist_takev_##type(nvl, namefmt, nameap); \ 1825258065Spjd va_end(nameap); \ 1826258065Spjd \ 1827258065Spjd return (value); \ 1828258065Spjd} 1829258065Spjd 1830279438Srstone#ifndef _KERNEL 1831258065SpjdNVLIST_TAKEF(bool, bool) 1832258065SpjdNVLIST_TAKEF(uint64_t, number) 1833258065SpjdNVLIST_TAKEF(char *, string) 1834258065SpjdNVLIST_TAKEF(nvlist_t *, nvlist) 1835258065SpjdNVLIST_TAKEF(int, descriptor) 1836258065Spjd 1837258065Spjd#undef NVLIST_TAKEF 1838258065Spjd 1839258065Spjdvoid * 1840258065Spjdnvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) 1841258065Spjd{ 1842258065Spjd va_list nameap; 1843258065Spjd void *value; 1844258065Spjd 1845258065Spjd va_start(nameap, namefmt); 1846258065Spjd value = nvlist_takev_binary(nvl, sizep, namefmt, nameap); 1847258065Spjd va_end(nameap); 1848258065Spjd 1849258065Spjd return (value); 1850258065Spjd} 1851258065Spjd 1852258065Spjd#define NVLIST_TAKEV(ftype, type, TYPE) \ 1853258065Spjdftype \ 1854258065Spjdnvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \ 1855258065Spjd{ \ 1856279435Srstone char *name; \ 1857258065Spjd ftype value; \ 1858258065Spjd \ 1859279435Srstone vasprintf(&name, namefmt, nameap); \ 1860279435Srstone if (name == NULL) \ 1861279435Srstone nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \ 1862279435Srstone value = nvlist_take_##type(nvl, name); \ 1863279435Srstone free(name); \ 1864258065Spjd return (value); \ 1865258065Spjd} 1866258065Spjd 1867258065SpjdNVLIST_TAKEV(bool, bool, BOOL) 1868258065SpjdNVLIST_TAKEV(uint64_t, number, NUMBER) 1869258065SpjdNVLIST_TAKEV(char *, string, STRING) 1870258065SpjdNVLIST_TAKEV(nvlist_t *, nvlist, NVLIST) 1871258065SpjdNVLIST_TAKEV(int, descriptor, DESCRIPTOR) 1872258065Spjd 1873258065Spjd#undef NVLIST_TAKEV 1874258065Spjd 1875258065Spjdvoid * 1876258065Spjdnvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, 1877258065Spjd va_list nameap) 1878258065Spjd{ 1879279435Srstone char *name; 1880279435Srstone void *binary; 1881258065Spjd 1882279438Srstone nv_vasprintf(&name, namefmt, nameap); 1883279435Srstone if (name == NULL) 1884279435Srstone nvlist_report_missing(NV_TYPE_BINARY, "<unknown>"); 1885258065Spjd 1886279435Srstone binary = nvlist_take_binary(nvl, name, sizep); 1887279438Srstone nv_free(name); 1888279435Srstone return (binary); 1889258065Spjd} 1890279438Srstone#endif 1891258065Spjd 1892258065Spjdvoid 1893258065Spjdnvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1894258065Spjd{ 1895258065Spjd 1896258065Spjd NVLIST_ASSERT(nvl); 1897258065Spjd NVPAIR_ASSERT(nvp); 1898258065Spjd PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 1899258065Spjd 1900258065Spjd nvpair_remove(&nvl->nvl_head, nvp, nvl); 1901258065Spjd} 1902258065Spjd 1903258065Spjdvoid 1904258065Spjdnvlist_free(nvlist_t *nvl, const char *name) 1905258065Spjd{ 1906258065Spjd 1907279435Srstone nvlist_free_type(nvl, name, NV_TYPE_NONE); 1908258065Spjd} 1909258065Spjd 1910279435Srstone#define NVLIST_FREE(type, TYPE) \ 1911258065Spjdvoid \ 1912258065Spjdnvlist_free_##type(nvlist_t *nvl, const char *name) \ 1913258065Spjd{ \ 1914258065Spjd \ 1915279435Srstone nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ 1916258065Spjd} 1917258065Spjd 1918279435SrstoneNVLIST_FREE(null, NULL) 1919279435SrstoneNVLIST_FREE(bool, BOOL) 1920279435SrstoneNVLIST_FREE(number, NUMBER) 1921279435SrstoneNVLIST_FREE(string, STRING) 1922279435SrstoneNVLIST_FREE(nvlist, NVLIST) 1923279438Srstone#ifndef _KERNEL 1924279435SrstoneNVLIST_FREE(descriptor, DESCRIPTOR) 1925279438Srstone#endif 1926279435SrstoneNVLIST_FREE(binary, BINARY) 1927258065Spjd 1928258065Spjd#undef NVLIST_FREE 1929258065Spjd 1930279438Srstone#ifndef _KERNEL 1931258065Spjdvoid 1932258065Spjdnvlist_freef(nvlist_t *nvl, const char *namefmt, ...) 1933258065Spjd{ 1934258065Spjd va_list nameap; 1935258065Spjd 1936258065Spjd va_start(nameap, namefmt); 1937258065Spjd nvlist_freev(nvl, namefmt, nameap); 1938258065Spjd va_end(nameap); 1939258065Spjd} 1940258065Spjd 1941258065Spjd#define NVLIST_FREEF(type) \ 1942258065Spjdvoid \ 1943258065Spjdnvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...) \ 1944258065Spjd{ \ 1945258065Spjd va_list nameap; \ 1946258065Spjd \ 1947258065Spjd va_start(nameap, namefmt); \ 1948258065Spjd nvlist_freev_##type(nvl, namefmt, nameap); \ 1949258065Spjd va_end(nameap); \ 1950258065Spjd} 1951258065Spjd 1952258065SpjdNVLIST_FREEF(null) 1953258065SpjdNVLIST_FREEF(bool) 1954258065SpjdNVLIST_FREEF(number) 1955258065SpjdNVLIST_FREEF(string) 1956258065SpjdNVLIST_FREEF(nvlist) 1957258065SpjdNVLIST_FREEF(descriptor) 1958258065SpjdNVLIST_FREEF(binary) 1959258065Spjd 1960258065Spjd#undef NVLIST_FREEF 1961258065Spjd 1962258065Spjdvoid 1963258065Spjdnvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap) 1964258065Spjd{ 1965258065Spjd 1966258065Spjd nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap); 1967258065Spjd} 1968258065Spjd 1969258065Spjd#define NVLIST_FREEV(type, TYPE) \ 1970258065Spjdvoid \ 1971258065Spjdnvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \ 1972258065Spjd{ \ 1973279435Srstone char *name; \ 1974258065Spjd \ 1975279435Srstone vasprintf(&name, namefmt, nameap); \ 1976279435Srstone if (name == NULL) \ 1977279435Srstone nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \ 1978279435Srstone nvlist_free_##type(nvl, name); \ 1979279435Srstone free(name); \ 1980258065Spjd} 1981258065Spjd 1982258065SpjdNVLIST_FREEV(null, NULL) 1983258065SpjdNVLIST_FREEV(bool, BOOL) 1984258065SpjdNVLIST_FREEV(number, NUMBER) 1985258065SpjdNVLIST_FREEV(string, STRING) 1986258065SpjdNVLIST_FREEV(nvlist, NVLIST) 1987258065SpjdNVLIST_FREEV(descriptor, DESCRIPTOR) 1988258065SpjdNVLIST_FREEV(binary, BINARY) 1989258065Spjd#undef NVLIST_FREEV 1990279438Srstone#endif 1991258065Spjd 1992258065Spjdvoid 1993258065Spjdnvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1994258065Spjd{ 1995258065Spjd 1996258065Spjd NVLIST_ASSERT(nvl); 1997258065Spjd NVPAIR_ASSERT(nvp); 1998258065Spjd PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 1999258065Spjd 2000258065Spjd nvlist_remove_nvpair(nvl, nvp); 2001258065Spjd nvpair_free(nvp); 2002258065Spjd} 2003