154f98da9SMariusz Zaborski /*- 21acf3485SMariusz Zaborski * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 31acf3485SMariusz Zaborski * 454f98da9SMariusz Zaborski * Copyright (c) 2009-2013 The FreeBSD Foundation 5347a39b4SMariusz Zaborski * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org> 654f98da9SMariusz Zaborski * All rights reserved. 754f98da9SMariusz Zaborski * 854f98da9SMariusz Zaborski * This software was developed by Pawel Jakub Dawidek under sponsorship from 954f98da9SMariusz Zaborski * the FreeBSD Foundation. 1054f98da9SMariusz Zaborski * 1154f98da9SMariusz Zaborski * Redistribution and use in source and binary forms, with or without 1254f98da9SMariusz Zaborski * modification, are permitted provided that the following conditions 1354f98da9SMariusz Zaborski * are met: 1454f98da9SMariusz Zaborski * 1. Redistributions of source code must retain the above copyright 1554f98da9SMariusz Zaborski * notice, this list of conditions and the following disclaimer. 1654f98da9SMariusz Zaborski * 2. Redistributions in binary form must reproduce the above copyright 1754f98da9SMariusz Zaborski * notice, this list of conditions and the following disclaimer in the 1854f98da9SMariusz Zaborski * documentation and/or other materials provided with the distribution. 1954f98da9SMariusz Zaborski * 2054f98da9SMariusz Zaborski * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 2154f98da9SMariusz Zaborski * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2254f98da9SMariusz Zaborski * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2354f98da9SMariusz Zaborski * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2454f98da9SMariusz Zaborski * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2554f98da9SMariusz Zaborski * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2654f98da9SMariusz Zaborski * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2754f98da9SMariusz Zaborski * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2854f98da9SMariusz Zaborski * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2954f98da9SMariusz Zaborski * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3054f98da9SMariusz Zaborski * SUCH DAMAGE. 3154f98da9SMariusz Zaborski */ 3254f98da9SMariusz Zaborski 3354f98da9SMariusz Zaborski #include <sys/cdefs.h> 3454f98da9SMariusz Zaborski __FBSDID("$FreeBSD$"); 3554f98da9SMariusz Zaborski 3654f98da9SMariusz Zaborski #include <sys/param.h> 3754f98da9SMariusz Zaborski #include <sys/endian.h> 3854f98da9SMariusz Zaborski #include <sys/queue.h> 3954f98da9SMariusz Zaborski 4054f98da9SMariusz Zaborski #ifdef _KERNEL 4154f98da9SMariusz Zaborski 4254f98da9SMariusz Zaborski #include <sys/errno.h> 4354f98da9SMariusz Zaborski #include <sys/kernel.h> 4454f98da9SMariusz Zaborski #include <sys/lock.h> 4554f98da9SMariusz Zaborski #include <sys/malloc.h> 4654f98da9SMariusz Zaborski #include <sys/systm.h> 4754f98da9SMariusz Zaborski 4854f98da9SMariusz Zaborski #include <machine/stdarg.h> 4954f98da9SMariusz Zaborski 5054f98da9SMariusz Zaborski #else 5154f98da9SMariusz Zaborski #include <sys/socket.h> 5254f98da9SMariusz Zaborski 5354f98da9SMariusz Zaborski #include <errno.h> 5454f98da9SMariusz Zaborski #include <stdarg.h> 5554f98da9SMariusz Zaborski #include <stdbool.h> 5654f98da9SMariusz Zaborski #include <stdint.h> 5754f98da9SMariusz Zaborski #include <stdio.h> 5854f98da9SMariusz Zaborski #include <stdlib.h> 5954f98da9SMariusz Zaborski #include <string.h> 6054f98da9SMariusz Zaborski #include <unistd.h> 6154f98da9SMariusz Zaborski 6254f98da9SMariusz Zaborski #include "msgio.h" 6354f98da9SMariusz Zaborski #endif 6454f98da9SMariusz Zaborski 6554f98da9SMariusz Zaborski #ifdef HAVE_PJDLOG 6654f98da9SMariusz Zaborski #include <pjdlog.h> 6754f98da9SMariusz Zaborski #endif 6854f98da9SMariusz Zaborski 6954f98da9SMariusz Zaborski #include <sys/nv.h> 7054f98da9SMariusz Zaborski 7154f98da9SMariusz Zaborski #include "nv_impl.h" 7254f98da9SMariusz Zaborski #include "nvlist_impl.h" 7354f98da9SMariusz Zaborski #include "nvpair_impl.h" 7454f98da9SMariusz Zaborski 7554f98da9SMariusz Zaborski #ifndef HAVE_PJDLOG 7654f98da9SMariusz Zaborski #ifdef _KERNEL 7754f98da9SMariusz Zaborski #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) 7854f98da9SMariusz Zaborski #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) 7954f98da9SMariusz Zaborski #define PJDLOG_ABORT(...) panic(__VA_ARGS__) 8054f98da9SMariusz Zaborski #else 8154f98da9SMariusz Zaborski #include <assert.h> 8254f98da9SMariusz Zaborski #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 8354f98da9SMariusz Zaborski #define PJDLOG_RASSERT(expr, ...) assert(expr) 8454f98da9SMariusz Zaborski #define PJDLOG_ABORT(...) do { \ 8554f98da9SMariusz Zaborski fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \ 8654f98da9SMariusz Zaborski fprintf(stderr, __VA_ARGS__); \ 8754f98da9SMariusz Zaborski fprintf(stderr, "\n"); \ 8854f98da9SMariusz Zaborski abort(); \ 8954f98da9SMariusz Zaborski } while (0) 9054f98da9SMariusz Zaborski #endif 9154f98da9SMariusz Zaborski #endif 9254f98da9SMariusz Zaborski 93347a39b4SMariusz Zaborski #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN | NV_FLAG_IN_ARRAY) 9454f98da9SMariusz Zaborski #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE) 9554f98da9SMariusz Zaborski #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK) 9654f98da9SMariusz Zaborski 9754f98da9SMariusz Zaborski #define NVLIST_MAGIC 0x6e766c /* "nvl" */ 9854f98da9SMariusz Zaborski struct nvlist { 9954f98da9SMariusz Zaborski int nvl_magic; 10054f98da9SMariusz Zaborski int nvl_error; 10154f98da9SMariusz Zaborski int nvl_flags; 10254f98da9SMariusz Zaborski nvpair_t *nvl_parent; 103347a39b4SMariusz Zaborski nvpair_t *nvl_array_next; 10454f98da9SMariusz Zaborski struct nvl_head nvl_head; 10554f98da9SMariusz Zaborski }; 10654f98da9SMariusz Zaborski 10754f98da9SMariusz Zaborski #define NVLIST_ASSERT(nvl) do { \ 10854f98da9SMariusz Zaborski PJDLOG_ASSERT((nvl) != NULL); \ 10954f98da9SMariusz Zaborski PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \ 11054f98da9SMariusz Zaborski } while (0) 11154f98da9SMariusz Zaborski 11254f98da9SMariusz Zaborski #ifdef _KERNEL 11354f98da9SMariusz Zaborski MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist"); 11454f98da9SMariusz Zaborski #endif 11554f98da9SMariusz Zaborski 11654f98da9SMariusz Zaborski #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp) 11754f98da9SMariusz Zaborski 11854f98da9SMariusz Zaborski #define NVLIST_HEADER_MAGIC 0x6c 11954f98da9SMariusz Zaborski #define NVLIST_HEADER_VERSION 0x00 12054f98da9SMariusz Zaborski struct nvlist_header { 12154f98da9SMariusz Zaborski uint8_t nvlh_magic; 12254f98da9SMariusz Zaborski uint8_t nvlh_version; 12354f98da9SMariusz Zaborski uint8_t nvlh_flags; 12454f98da9SMariusz Zaborski uint64_t nvlh_descriptors; 12554f98da9SMariusz Zaborski uint64_t nvlh_size; 12654f98da9SMariusz Zaborski } __packed; 12754f98da9SMariusz Zaborski 12854f98da9SMariusz Zaborski nvlist_t * 12954f98da9SMariusz Zaborski nvlist_create(int flags) 13054f98da9SMariusz Zaborski { 13154f98da9SMariusz Zaborski nvlist_t *nvl; 13254f98da9SMariusz Zaborski 13354f98da9SMariusz Zaborski PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 13454f98da9SMariusz Zaborski 13554f98da9SMariusz Zaborski nvl = nv_malloc(sizeof(*nvl)); 13654f98da9SMariusz Zaborski if (nvl == NULL) 13754f98da9SMariusz Zaborski return (NULL); 13854f98da9SMariusz Zaborski nvl->nvl_error = 0; 13954f98da9SMariusz Zaborski nvl->nvl_flags = flags; 14054f98da9SMariusz Zaborski nvl->nvl_parent = NULL; 141347a39b4SMariusz Zaborski nvl->nvl_array_next = NULL; 14254f98da9SMariusz Zaborski TAILQ_INIT(&nvl->nvl_head); 14354f98da9SMariusz Zaborski nvl->nvl_magic = NVLIST_MAGIC; 14454f98da9SMariusz Zaborski 14554f98da9SMariusz Zaborski return (nvl); 14654f98da9SMariusz Zaborski } 14754f98da9SMariusz Zaborski 14854f98da9SMariusz Zaborski void 14954f98da9SMariusz Zaborski nvlist_destroy(nvlist_t *nvl) 15054f98da9SMariusz Zaborski { 15154f98da9SMariusz Zaborski nvpair_t *nvp; 15254f98da9SMariusz Zaborski 15354f98da9SMariusz Zaborski if (nvl == NULL) 15454f98da9SMariusz Zaborski return; 15554f98da9SMariusz Zaborski 15654f98da9SMariusz Zaborski ERRNO_SAVE(); 15754f98da9SMariusz Zaborski 15854f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 15954f98da9SMariusz Zaborski 16054f98da9SMariusz Zaborski while ((nvp = nvlist_first_nvpair(nvl)) != NULL) { 16154f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); 16254f98da9SMariusz Zaborski nvpair_free(nvp); 16354f98da9SMariusz Zaborski } 164347a39b4SMariusz Zaborski if (nvl->nvl_array_next != NULL) 165347a39b4SMariusz Zaborski nvpair_free_structure(nvl->nvl_array_next); 166347a39b4SMariusz Zaborski nvl->nvl_array_next = NULL; 167347a39b4SMariusz Zaborski nvl->nvl_parent = NULL; 16854f98da9SMariusz Zaborski nvl->nvl_magic = 0; 16954f98da9SMariusz Zaborski nv_free(nvl); 17054f98da9SMariusz Zaborski 17154f98da9SMariusz Zaborski ERRNO_RESTORE(); 17254f98da9SMariusz Zaborski } 17354f98da9SMariusz Zaborski 17454f98da9SMariusz Zaborski void 17554f98da9SMariusz Zaborski nvlist_set_error(nvlist_t *nvl, int error) 17654f98da9SMariusz Zaborski { 17754f98da9SMariusz Zaborski 17854f98da9SMariusz Zaborski PJDLOG_ASSERT(error != 0); 17954f98da9SMariusz Zaborski 18054f98da9SMariusz Zaborski /* 18154f98da9SMariusz Zaborski * Check for error != 0 so that we don't do the wrong thing if somebody 18254f98da9SMariusz Zaborski * tries to abuse this API when asserts are disabled. 18354f98da9SMariusz Zaborski */ 18454f98da9SMariusz Zaborski if (nvl != NULL && error != 0 && nvl->nvl_error == 0) 18554f98da9SMariusz Zaborski nvl->nvl_error = error; 18654f98da9SMariusz Zaborski } 18754f98da9SMariusz Zaborski 18854f98da9SMariusz Zaborski int 18954f98da9SMariusz Zaborski nvlist_error(const nvlist_t *nvl) 19054f98da9SMariusz Zaborski { 19154f98da9SMariusz Zaborski 19254f98da9SMariusz Zaborski if (nvl == NULL) 19354f98da9SMariusz Zaborski return (ENOMEM); 19454f98da9SMariusz Zaborski 19554f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 19654f98da9SMariusz Zaborski 19754f98da9SMariusz Zaborski return (nvl->nvl_error); 19854f98da9SMariusz Zaborski } 19954f98da9SMariusz Zaborski 20054f98da9SMariusz Zaborski nvpair_t * 20154f98da9SMariusz Zaborski nvlist_get_nvpair_parent(const nvlist_t *nvl) 20254f98da9SMariusz Zaborski { 20354f98da9SMariusz Zaborski 20454f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 20554f98da9SMariusz Zaborski 20654f98da9SMariusz Zaborski return (nvl->nvl_parent); 20754f98da9SMariusz Zaborski } 20854f98da9SMariusz Zaborski 20954f98da9SMariusz Zaborski const nvlist_t * 21054f98da9SMariusz Zaborski nvlist_get_parent(const nvlist_t *nvl, void **cookiep) 21154f98da9SMariusz Zaborski { 21254f98da9SMariusz Zaborski nvpair_t *nvp; 21354f98da9SMariusz Zaborski 21454f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 21554f98da9SMariusz Zaborski 21654f98da9SMariusz Zaborski nvp = nvl->nvl_parent; 21754f98da9SMariusz Zaborski if (cookiep != NULL) 21854f98da9SMariusz Zaborski *cookiep = nvp; 21954f98da9SMariusz Zaborski if (nvp == NULL) 22054f98da9SMariusz Zaborski return (NULL); 22154f98da9SMariusz Zaborski 22254f98da9SMariusz Zaborski return (nvpair_nvlist(nvp)); 22354f98da9SMariusz Zaborski } 22454f98da9SMariusz Zaborski 22554f98da9SMariusz Zaborski void 22654f98da9SMariusz Zaborski nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent) 22754f98da9SMariusz Zaborski { 22854f98da9SMariusz Zaborski 22954f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 23054f98da9SMariusz Zaborski 23154f98da9SMariusz Zaborski nvl->nvl_parent = parent; 23254f98da9SMariusz Zaborski } 23354f98da9SMariusz Zaborski 234347a39b4SMariusz Zaborski void 235347a39b4SMariusz Zaborski nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele) 236347a39b4SMariusz Zaborski { 237347a39b4SMariusz Zaborski 238347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 239347a39b4SMariusz Zaborski 2401b550329SMariusz Zaborski if (ele != NULL) { 241347a39b4SMariusz Zaborski nvl->nvl_flags |= NV_FLAG_IN_ARRAY; 2421b550329SMariusz Zaborski } else { 243347a39b4SMariusz Zaborski nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY; 2441b550329SMariusz Zaborski nv_free(nvl->nvl_array_next); 2451b550329SMariusz Zaborski } 246347a39b4SMariusz Zaborski 247347a39b4SMariusz Zaborski nvl->nvl_array_next = ele; 248347a39b4SMariusz Zaborski } 249347a39b4SMariusz Zaborski 250347a39b4SMariusz Zaborski bool 251347a39b4SMariusz Zaborski nvlist_in_array(const nvlist_t *nvl) 252347a39b4SMariusz Zaborski { 253347a39b4SMariusz Zaborski 254347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 255347a39b4SMariusz Zaborski 256347a39b4SMariusz Zaborski return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0); 257347a39b4SMariusz Zaborski } 258347a39b4SMariusz Zaborski 259347a39b4SMariusz Zaborski const nvlist_t * 260347a39b4SMariusz Zaborski nvlist_get_array_next(const nvlist_t *nvl) 261347a39b4SMariusz Zaborski { 262347a39b4SMariusz Zaborski nvpair_t *nvp; 263347a39b4SMariusz Zaborski 264347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 265347a39b4SMariusz Zaborski 266347a39b4SMariusz Zaborski nvp = nvl->nvl_array_next; 267347a39b4SMariusz Zaborski if (nvp == NULL) 268347a39b4SMariusz Zaborski return (NULL); 269347a39b4SMariusz Zaborski 270347a39b4SMariusz Zaborski return (nvpair_get_nvlist(nvp)); 271347a39b4SMariusz Zaborski } 272347a39b4SMariusz Zaborski 273347a39b4SMariusz Zaborski const nvlist_t * 274347a39b4SMariusz Zaborski nvlist_get_pararr(const nvlist_t *nvl, void **cookiep) 275347a39b4SMariusz Zaborski { 276347a39b4SMariusz Zaborski const nvlist_t *ret; 277347a39b4SMariusz Zaborski 278347a39b4SMariusz Zaborski ret = nvlist_get_array_next(nvl); 279347a39b4SMariusz Zaborski if (ret != NULL) { 280347a39b4SMariusz Zaborski if (cookiep != NULL) 281347a39b4SMariusz Zaborski *cookiep = NULL; 282347a39b4SMariusz Zaborski return (ret); 283347a39b4SMariusz Zaborski } 284347a39b4SMariusz Zaborski 28508016b31SMariusz Zaborski return (nvlist_get_parent(nvl, cookiep)); 286347a39b4SMariusz Zaborski } 287347a39b4SMariusz Zaborski 28854f98da9SMariusz Zaborski bool 28954f98da9SMariusz Zaborski nvlist_empty(const nvlist_t *nvl) 29054f98da9SMariusz Zaborski { 29154f98da9SMariusz Zaborski 29254f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 29354f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 29454f98da9SMariusz Zaborski 29554f98da9SMariusz Zaborski return (nvlist_first_nvpair(nvl) == NULL); 29654f98da9SMariusz Zaborski } 29754f98da9SMariusz Zaborski 29854f98da9SMariusz Zaborski int 29954f98da9SMariusz Zaborski nvlist_flags(const nvlist_t *nvl) 30054f98da9SMariusz Zaborski { 30154f98da9SMariusz Zaborski 30254f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 30354f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 30454f98da9SMariusz Zaborski 305347a39b4SMariusz Zaborski return (nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); 306347a39b4SMariusz Zaborski } 307347a39b4SMariusz Zaborski 308347a39b4SMariusz Zaborski void 309347a39b4SMariusz Zaborski nvlist_set_flags(nvlist_t *nvl, int flags) 310347a39b4SMariusz Zaborski { 311347a39b4SMariusz Zaborski 312347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 313347a39b4SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 314347a39b4SMariusz Zaborski 315347a39b4SMariusz Zaborski nvl->nvl_flags = flags; 31654f98da9SMariusz Zaborski } 31754f98da9SMariusz Zaborski 3185ef231f6SMariusz Zaborski void 31954f98da9SMariusz Zaborski nvlist_report_missing(int type, const char *name) 32054f98da9SMariusz Zaborski { 32154f98da9SMariusz Zaborski 32254f98da9SMariusz Zaborski PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", 32354f98da9SMariusz Zaborski name, nvpair_type_string(type)); 32454f98da9SMariusz Zaborski } 32554f98da9SMariusz Zaborski 32654f98da9SMariusz Zaborski static nvpair_t * 32754f98da9SMariusz Zaborski nvlist_find(const nvlist_t *nvl, int type, const char *name) 32854f98da9SMariusz Zaborski { 32954f98da9SMariusz Zaborski nvpair_t *nvp; 33054f98da9SMariusz Zaborski 33154f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 33254f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 33354f98da9SMariusz Zaborski PJDLOG_ASSERT(type == NV_TYPE_NONE || 33454f98da9SMariusz Zaborski (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 33554f98da9SMariusz Zaborski 33654f98da9SMariusz Zaborski for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 33754f98da9SMariusz Zaborski nvp = nvlist_next_nvpair(nvl, nvp)) { 33854f98da9SMariusz Zaborski if (type != NV_TYPE_NONE && nvpair_type(nvp) != type) 33954f98da9SMariusz Zaborski continue; 34054f98da9SMariusz Zaborski if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) { 34154f98da9SMariusz Zaborski if (strcasecmp(nvpair_name(nvp), name) != 0) 34254f98da9SMariusz Zaborski continue; 34354f98da9SMariusz Zaborski } else { 34454f98da9SMariusz Zaborski if (strcmp(nvpair_name(nvp), name) != 0) 34554f98da9SMariusz Zaborski continue; 34654f98da9SMariusz Zaborski } 34754f98da9SMariusz Zaborski break; 34854f98da9SMariusz Zaborski } 34954f98da9SMariusz Zaborski 35054f98da9SMariusz Zaborski if (nvp == NULL) 35154f98da9SMariusz Zaborski ERRNO_SET(ENOENT); 35254f98da9SMariusz Zaborski 35354f98da9SMariusz Zaborski return (nvp); 35454f98da9SMariusz Zaborski } 35554f98da9SMariusz Zaborski 35654f98da9SMariusz Zaborski bool 35754f98da9SMariusz Zaborski nvlist_exists_type(const nvlist_t *nvl, const char *name, int type) 35854f98da9SMariusz Zaborski { 35954f98da9SMariusz Zaborski 36054f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 36154f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 36254f98da9SMariusz Zaborski PJDLOG_ASSERT(type == NV_TYPE_NONE || 36354f98da9SMariusz Zaborski (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 36454f98da9SMariusz Zaborski 36554f98da9SMariusz Zaborski return (nvlist_find(nvl, type, name) != NULL); 36654f98da9SMariusz Zaborski } 36754f98da9SMariusz Zaborski 36854f98da9SMariusz Zaborski void 36954f98da9SMariusz Zaborski nvlist_free_type(nvlist_t *nvl, const char *name, int type) 37054f98da9SMariusz Zaborski { 37154f98da9SMariusz Zaborski nvpair_t *nvp; 37254f98da9SMariusz Zaborski 37354f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 37454f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 37554f98da9SMariusz Zaborski PJDLOG_ASSERT(type == NV_TYPE_NONE || 37654f98da9SMariusz Zaborski (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 37754f98da9SMariusz Zaborski 37854f98da9SMariusz Zaborski nvp = nvlist_find(nvl, type, name); 37954f98da9SMariusz Zaborski if (nvp != NULL) 38054f98da9SMariusz Zaborski nvlist_free_nvpair(nvl, nvp); 38154f98da9SMariusz Zaborski else 38254f98da9SMariusz Zaborski nvlist_report_missing(type, name); 38354f98da9SMariusz Zaborski } 38454f98da9SMariusz Zaborski 38554f98da9SMariusz Zaborski nvlist_t * 38654f98da9SMariusz Zaborski nvlist_clone(const nvlist_t *nvl) 38754f98da9SMariusz Zaborski { 38854f98da9SMariusz Zaborski nvlist_t *newnvl; 38954f98da9SMariusz Zaborski nvpair_t *nvp, *newnvp; 39054f98da9SMariusz Zaborski 39154f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 39254f98da9SMariusz Zaborski 39354f98da9SMariusz Zaborski if (nvl->nvl_error != 0) { 39454f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 39554f98da9SMariusz Zaborski return (NULL); 39654f98da9SMariusz Zaborski } 39754f98da9SMariusz Zaborski 39854f98da9SMariusz Zaborski newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); 39954f98da9SMariusz Zaborski for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 40054f98da9SMariusz Zaborski nvp = nvlist_next_nvpair(nvl, nvp)) { 40154f98da9SMariusz Zaborski newnvp = nvpair_clone(nvp); 40254f98da9SMariusz Zaborski if (newnvp == NULL) 40354f98da9SMariusz Zaborski break; 40430740f45SMariusz Zaborski (void)nvlist_move_nvpair(newnvl, newnvp); 40554f98da9SMariusz Zaborski } 40654f98da9SMariusz Zaborski if (nvp != NULL) { 40754f98da9SMariusz Zaborski nvlist_destroy(newnvl); 40854f98da9SMariusz Zaborski return (NULL); 40954f98da9SMariusz Zaborski } 41054f98da9SMariusz Zaborski return (newnvl); 41154f98da9SMariusz Zaborski } 41254f98da9SMariusz Zaborski 41354f98da9SMariusz Zaborski #ifndef _KERNEL 41454f98da9SMariusz Zaborski static bool 41554f98da9SMariusz Zaborski nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level) 41654f98da9SMariusz Zaborski { 41754f98da9SMariusz Zaborski 41854f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 41954f98da9SMariusz Zaborski dprintf(fd, "%*serror: %d\n", level * 4, "", 42054f98da9SMariusz Zaborski nvlist_error(nvl)); 42154f98da9SMariusz Zaborski return (true); 42254f98da9SMariusz Zaborski } 42354f98da9SMariusz Zaborski 42454f98da9SMariusz Zaborski return (false); 42554f98da9SMariusz Zaborski } 42654f98da9SMariusz Zaborski 42754f98da9SMariusz Zaborski /* 42854f98da9SMariusz Zaborski * Dump content of nvlist. 42954f98da9SMariusz Zaborski */ 43054f98da9SMariusz Zaborski void 43154f98da9SMariusz Zaborski nvlist_dump(const nvlist_t *nvl, int fd) 43254f98da9SMariusz Zaborski { 43354f98da9SMariusz Zaborski const nvlist_t *tmpnvl; 43454f98da9SMariusz Zaborski nvpair_t *nvp, *tmpnvp; 43554f98da9SMariusz Zaborski void *cookie; 43654f98da9SMariusz Zaborski int level; 43754f98da9SMariusz Zaborski 43854f98da9SMariusz Zaborski level = 0; 43954f98da9SMariusz Zaborski if (nvlist_dump_error_check(nvl, fd, level)) 44054f98da9SMariusz Zaborski return; 44154f98da9SMariusz Zaborski 44254f98da9SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 44354f98da9SMariusz Zaborski while (nvp != NULL) { 44454f98da9SMariusz Zaborski dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), 44554f98da9SMariusz Zaborski nvpair_type_string(nvpair_type(nvp))); 44654f98da9SMariusz Zaborski switch (nvpair_type(nvp)) { 44754f98da9SMariusz Zaborski case NV_TYPE_NULL: 44854f98da9SMariusz Zaborski dprintf(fd, " null\n"); 44954f98da9SMariusz Zaborski break; 45054f98da9SMariusz Zaborski case NV_TYPE_BOOL: 45154f98da9SMariusz Zaborski dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? 45254f98da9SMariusz Zaborski "TRUE" : "FALSE"); 45354f98da9SMariusz Zaborski break; 45454f98da9SMariusz Zaborski case NV_TYPE_NUMBER: 45554f98da9SMariusz Zaborski dprintf(fd, " %ju (%jd) (0x%jx)\n", 45654f98da9SMariusz Zaborski (uintmax_t)nvpair_get_number(nvp), 45754f98da9SMariusz Zaborski (intmax_t)nvpair_get_number(nvp), 45854f98da9SMariusz Zaborski (uintmax_t)nvpair_get_number(nvp)); 45954f98da9SMariusz Zaborski break; 46054f98da9SMariusz Zaborski case NV_TYPE_STRING: 46154f98da9SMariusz Zaborski dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); 46254f98da9SMariusz Zaborski break; 46354f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 46454f98da9SMariusz Zaborski dprintf(fd, "\n"); 46554f98da9SMariusz Zaborski tmpnvl = nvpair_get_nvlist(nvp); 46654f98da9SMariusz Zaborski if (nvlist_dump_error_check(tmpnvl, fd, level + 1)) 46754f98da9SMariusz Zaborski break; 46854f98da9SMariusz Zaborski tmpnvp = nvlist_first_nvpair(tmpnvl); 46954f98da9SMariusz Zaborski if (tmpnvp != NULL) { 47054f98da9SMariusz Zaborski nvl = tmpnvl; 47154f98da9SMariusz Zaborski nvp = tmpnvp; 47254f98da9SMariusz Zaborski level++; 47354f98da9SMariusz Zaborski continue; 47454f98da9SMariusz Zaborski } 47554f98da9SMariusz Zaborski break; 47654f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 47754f98da9SMariusz Zaborski dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); 47854f98da9SMariusz Zaborski break; 47954f98da9SMariusz Zaborski case NV_TYPE_BINARY: 48054f98da9SMariusz Zaborski { 48154f98da9SMariusz Zaborski const unsigned char *binary; 48254f98da9SMariusz Zaborski unsigned int ii; 48354f98da9SMariusz Zaborski size_t size; 48454f98da9SMariusz Zaborski 48554f98da9SMariusz Zaborski binary = nvpair_get_binary(nvp, &size); 48654f98da9SMariusz Zaborski dprintf(fd, " %zu ", size); 48754f98da9SMariusz Zaborski for (ii = 0; ii < size; ii++) 48854f98da9SMariusz Zaborski dprintf(fd, "%02hhx", binary[ii]); 48954f98da9SMariusz Zaborski dprintf(fd, "\n"); 49054f98da9SMariusz Zaborski break; 49154f98da9SMariusz Zaborski } 492347a39b4SMariusz Zaborski case NV_TYPE_BOOL_ARRAY: 493347a39b4SMariusz Zaborski { 494347a39b4SMariusz Zaborski const bool *value; 495347a39b4SMariusz Zaborski unsigned int ii; 496347a39b4SMariusz Zaborski size_t nitems; 497347a39b4SMariusz Zaborski 498347a39b4SMariusz Zaborski value = nvpair_get_bool_array(nvp, &nitems); 499347a39b4SMariusz Zaborski dprintf(fd, " [ "); 500347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 501347a39b4SMariusz Zaborski dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE"); 502347a39b4SMariusz Zaborski if (ii != nitems - 1) 503347a39b4SMariusz Zaborski dprintf(fd, ", "); 504347a39b4SMariusz Zaborski } 505347a39b4SMariusz Zaborski dprintf(fd, " ]\n"); 506347a39b4SMariusz Zaborski break; 507347a39b4SMariusz Zaborski } 508347a39b4SMariusz Zaborski case NV_TYPE_STRING_ARRAY: 509347a39b4SMariusz Zaborski { 510347a39b4SMariusz Zaborski const char * const *value; 511347a39b4SMariusz Zaborski unsigned int ii; 512347a39b4SMariusz Zaborski size_t nitems; 513347a39b4SMariusz Zaborski 514347a39b4SMariusz Zaborski value = nvpair_get_string_array(nvp, &nitems); 515347a39b4SMariusz Zaborski dprintf(fd, " [ "); 516347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 517347a39b4SMariusz Zaborski if (value[ii] == NULL) 518347a39b4SMariusz Zaborski dprintf(fd, "NULL"); 519347a39b4SMariusz Zaborski else 520347a39b4SMariusz Zaborski dprintf(fd, "\"%s\"", value[ii]); 521347a39b4SMariusz Zaborski if (ii != nitems - 1) 522347a39b4SMariusz Zaborski dprintf(fd, ", "); 523347a39b4SMariusz Zaborski } 524347a39b4SMariusz Zaborski dprintf(fd, " ]\n"); 525347a39b4SMariusz Zaborski break; 526347a39b4SMariusz Zaborski } 527347a39b4SMariusz Zaborski case NV_TYPE_NUMBER_ARRAY: 528347a39b4SMariusz Zaborski { 529347a39b4SMariusz Zaborski const uint64_t *value; 530347a39b4SMariusz Zaborski unsigned int ii; 531347a39b4SMariusz Zaborski size_t nitems; 532347a39b4SMariusz Zaborski 533347a39b4SMariusz Zaborski value = nvpair_get_number_array(nvp, &nitems); 534347a39b4SMariusz Zaborski dprintf(fd, " [ "); 535347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 536347a39b4SMariusz Zaborski dprintf(fd, "%ju (%jd) (0x%jx)", 537347a39b4SMariusz Zaborski value[ii], value[ii], value[ii]); 538347a39b4SMariusz Zaborski if (ii != nitems - 1) 539347a39b4SMariusz Zaborski dprintf(fd, ", "); 540347a39b4SMariusz Zaborski } 541347a39b4SMariusz Zaborski dprintf(fd, " ]\n"); 542347a39b4SMariusz Zaborski break; 543347a39b4SMariusz Zaborski } 544347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 545347a39b4SMariusz Zaborski { 546347a39b4SMariusz Zaborski const int *value; 547347a39b4SMariusz Zaborski unsigned int ii; 548347a39b4SMariusz Zaborski size_t nitems; 549347a39b4SMariusz Zaborski 550347a39b4SMariusz Zaborski value = nvpair_get_descriptor_array(nvp, &nitems); 551347a39b4SMariusz Zaborski dprintf(fd, " [ "); 552347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 553347a39b4SMariusz Zaborski dprintf(fd, "%d", value[ii]); 554347a39b4SMariusz Zaborski if (ii != nitems - 1) 555347a39b4SMariusz Zaborski dprintf(fd, ", "); 556347a39b4SMariusz Zaborski } 557347a39b4SMariusz Zaborski dprintf(fd, " ]\n"); 558347a39b4SMariusz Zaborski break; 559347a39b4SMariusz Zaborski } 560347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 561347a39b4SMariusz Zaborski { 562347a39b4SMariusz Zaborski const nvlist_t * const *value; 563347a39b4SMariusz Zaborski unsigned int ii; 564347a39b4SMariusz Zaborski size_t nitems; 565347a39b4SMariusz Zaborski 566347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 567347a39b4SMariusz Zaborski dprintf(fd, " %zu\n", nitems); 568347a39b4SMariusz Zaborski tmpnvl = NULL; 569347a39b4SMariusz Zaborski tmpnvp = NULL; 570347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 571347a39b4SMariusz Zaborski if (nvlist_dump_error_check(value[ii], fd, 572347a39b4SMariusz Zaborski level + 1)) { 573347a39b4SMariusz Zaborski break; 574347a39b4SMariusz Zaborski } 575347a39b4SMariusz Zaborski 576347a39b4SMariusz Zaborski if (tmpnvl == NULL) { 577347a39b4SMariusz Zaborski tmpnvp = nvlist_first_nvpair(value[ii]); 578347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 579347a39b4SMariusz Zaborski tmpnvl = value[ii]; 580347a39b4SMariusz Zaborski } else { 581347a39b4SMariusz Zaborski dprintf(fd, "%*s,\n", 582347a39b4SMariusz Zaborski (level + 1) * 4, ""); 583347a39b4SMariusz Zaborski } 584347a39b4SMariusz Zaborski } 585347a39b4SMariusz Zaborski } 586347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 587347a39b4SMariusz Zaborski nvl = tmpnvl; 588347a39b4SMariusz Zaborski nvp = tmpnvp; 589347a39b4SMariusz Zaborski level++; 590347a39b4SMariusz Zaborski continue; 591347a39b4SMariusz Zaborski } 592347a39b4SMariusz Zaborski break; 593347a39b4SMariusz Zaborski } 59454f98da9SMariusz Zaborski default: 59554f98da9SMariusz Zaborski PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 59654f98da9SMariusz Zaborski } 59754f98da9SMariusz Zaborski 59854f98da9SMariusz Zaborski while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 599347a39b4SMariusz Zaborski do { 60054f98da9SMariusz Zaborski cookie = NULL; 601347a39b4SMariusz Zaborski if (nvlist_in_array(nvl)) 602347a39b4SMariusz Zaborski dprintf(fd, "%*s,\n", level * 4, ""); 603347a39b4SMariusz Zaborski nvl = nvlist_get_pararr(nvl, &cookie); 60454f98da9SMariusz Zaborski if (nvl == NULL) 60554f98da9SMariusz Zaborski return; 606347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) { 607347a39b4SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 608347a39b4SMariusz Zaborski } else { 60954f98da9SMariusz Zaborski nvp = cookie; 61054f98da9SMariusz Zaborski level--; 61154f98da9SMariusz Zaborski } 612347a39b4SMariusz Zaborski } while (nvp == NULL); 613347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) 614347a39b4SMariusz Zaborski break; 615347a39b4SMariusz Zaborski } 61654f98da9SMariusz Zaborski } 61754f98da9SMariusz Zaborski } 61854f98da9SMariusz Zaborski 61954f98da9SMariusz Zaborski void 62054f98da9SMariusz Zaborski nvlist_fdump(const nvlist_t *nvl, FILE *fp) 62154f98da9SMariusz Zaborski { 62254f98da9SMariusz Zaborski 62354f98da9SMariusz Zaborski fflush(fp); 62454f98da9SMariusz Zaborski nvlist_dump(nvl, fileno(fp)); 62554f98da9SMariusz Zaborski } 62654f98da9SMariusz Zaborski #endif 62754f98da9SMariusz Zaborski 62854f98da9SMariusz Zaborski /* 62954f98da9SMariusz Zaborski * The function obtains size of the nvlist after nvlist_pack(). 63054f98da9SMariusz Zaborski */ 63154f98da9SMariusz Zaborski size_t 63254f98da9SMariusz Zaborski nvlist_size(const nvlist_t *nvl) 63354f98da9SMariusz Zaborski { 63454f98da9SMariusz Zaborski const nvlist_t *tmpnvl; 635347a39b4SMariusz Zaborski const nvlist_t * const *nvlarray; 63654f98da9SMariusz Zaborski const nvpair_t *nvp, *tmpnvp; 63754f98da9SMariusz Zaborski void *cookie; 638347a39b4SMariusz Zaborski size_t size, nitems; 639347a39b4SMariusz Zaborski unsigned int ii; 64054f98da9SMariusz Zaborski 64154f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 64254f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 64354f98da9SMariusz Zaborski 64454f98da9SMariusz Zaborski size = sizeof(struct nvlist_header); 64554f98da9SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 64654f98da9SMariusz Zaborski while (nvp != NULL) { 64754f98da9SMariusz Zaborski size += nvpair_header_size(); 64854f98da9SMariusz Zaborski size += strlen(nvpair_name(nvp)) + 1; 64954f98da9SMariusz Zaborski if (nvpair_type(nvp) == NV_TYPE_NVLIST) { 65054f98da9SMariusz Zaborski size += sizeof(struct nvlist_header); 65154f98da9SMariusz Zaborski size += nvpair_header_size() + 1; 65254f98da9SMariusz Zaborski tmpnvl = nvpair_get_nvlist(nvp); 65354f98da9SMariusz Zaborski PJDLOG_ASSERT(tmpnvl->nvl_error == 0); 65454f98da9SMariusz Zaborski tmpnvp = nvlist_first_nvpair(tmpnvl); 65554f98da9SMariusz Zaborski if (tmpnvp != NULL) { 65654f98da9SMariusz Zaborski nvl = tmpnvl; 65754f98da9SMariusz Zaborski nvp = tmpnvp; 65854f98da9SMariusz Zaborski continue; 65954f98da9SMariusz Zaborski } 660347a39b4SMariusz Zaborski } else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) { 661347a39b4SMariusz Zaborski nvlarray = nvpair_get_nvlist_array(nvp, &nitems); 662347a39b4SMariusz Zaborski PJDLOG_ASSERT(nitems > 0); 663347a39b4SMariusz Zaborski 664347a39b4SMariusz Zaborski size += (nvpair_header_size() + 1) * nitems; 665347a39b4SMariusz Zaborski size += sizeof(struct nvlist_header) * nitems; 666347a39b4SMariusz Zaborski 667347a39b4SMariusz Zaborski tmpnvl = NULL; 668347a39b4SMariusz Zaborski tmpnvp = NULL; 669347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 670347a39b4SMariusz Zaborski PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0); 671347a39b4SMariusz Zaborski tmpnvp = nvlist_first_nvpair(nvlarray[ii]); 672347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 673347a39b4SMariusz Zaborski tmpnvl = nvlarray[ii]; 674347a39b4SMariusz Zaborski break; 675347a39b4SMariusz Zaborski } 676347a39b4SMariusz Zaborski } 677347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 678347a39b4SMariusz Zaborski nvp = tmpnvp; 679347a39b4SMariusz Zaborski nvl = tmpnvl; 680347a39b4SMariusz Zaborski continue; 681347a39b4SMariusz Zaborski } 682347a39b4SMariusz Zaborski 68354f98da9SMariusz Zaborski } else { 68454f98da9SMariusz Zaborski size += nvpair_size(nvp); 68554f98da9SMariusz Zaborski } 68654f98da9SMariusz Zaborski 68754f98da9SMariusz Zaborski while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 688347a39b4SMariusz Zaborski do { 68954f98da9SMariusz Zaborski cookie = NULL; 690347a39b4SMariusz Zaborski nvl = nvlist_get_pararr(nvl, &cookie); 69154f98da9SMariusz Zaborski if (nvl == NULL) 69254f98da9SMariusz Zaborski goto out; 693347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) { 694347a39b4SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 695347a39b4SMariusz Zaborski } else { 69654f98da9SMariusz Zaborski nvp = cookie; 69754f98da9SMariusz Zaborski } 698347a39b4SMariusz Zaborski } while (nvp == NULL); 699347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) 700347a39b4SMariusz Zaborski break; 701347a39b4SMariusz Zaborski } 70254f98da9SMariusz Zaborski } 70354f98da9SMariusz Zaborski 70454f98da9SMariusz Zaborski out: 70554f98da9SMariusz Zaborski return (size); 70654f98da9SMariusz Zaborski } 70754f98da9SMariusz Zaborski 70854f98da9SMariusz Zaborski #ifndef _KERNEL 70954f98da9SMariusz Zaborski static int * 71054f98da9SMariusz Zaborski nvlist_xdescriptors(const nvlist_t *nvl, int *descs) 71154f98da9SMariusz Zaborski { 7129a8ce256SJilles Tjoelker void *cookie; 71354f98da9SMariusz Zaborski nvpair_t *nvp; 71454f98da9SMariusz Zaborski int type; 71554f98da9SMariusz Zaborski 71654f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 71754f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 71854f98da9SMariusz Zaborski 7199a8ce256SJilles Tjoelker cookie = NULL; 72054f98da9SMariusz Zaborski do { 7219a8ce256SJilles Tjoelker while (nvlist_next(nvl, &type, &cookie) != NULL) { 7229a8ce256SJilles Tjoelker nvp = cookie; 72354f98da9SMariusz Zaborski switch (type) { 72454f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 72554f98da9SMariusz Zaborski *descs = nvpair_get_descriptor(nvp); 72654f98da9SMariusz Zaborski descs++; 72754f98da9SMariusz Zaborski break; 728347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 729347a39b4SMariusz Zaborski { 730347a39b4SMariusz Zaborski const int *value; 731347a39b4SMariusz Zaborski size_t nitems; 732347a39b4SMariusz Zaborski unsigned int ii; 733347a39b4SMariusz Zaborski 734347a39b4SMariusz Zaborski value = nvpair_get_descriptor_array(nvp, 735347a39b4SMariusz Zaborski &nitems); 736347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 737347a39b4SMariusz Zaborski *descs = value[ii]; 738347a39b4SMariusz Zaborski descs++; 739347a39b4SMariusz Zaborski } 740347a39b4SMariusz Zaborski break; 741347a39b4SMariusz Zaborski } 74254f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 74354f98da9SMariusz Zaborski nvl = nvpair_get_nvlist(nvp); 7449a8ce256SJilles Tjoelker cookie = NULL; 74554f98da9SMariusz Zaborski break; 746347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 747347a39b4SMariusz Zaborski { 748347a39b4SMariusz Zaborski const nvlist_t * const *value; 749347a39b4SMariusz Zaborski size_t nitems; 750347a39b4SMariusz Zaborski 751347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 752347a39b4SMariusz Zaborski PJDLOG_ASSERT(value != NULL); 753347a39b4SMariusz Zaborski PJDLOG_ASSERT(nitems > 0); 754347a39b4SMariusz Zaborski 755347a39b4SMariusz Zaborski nvl = value[0]; 7569a8ce256SJilles Tjoelker cookie = NULL; 757347a39b4SMariusz Zaborski break; 75854f98da9SMariusz Zaborski } 75954f98da9SMariusz Zaborski } 760347a39b4SMariusz Zaborski } 7619a8ce256SJilles Tjoelker } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL); 76254f98da9SMariusz Zaborski 76354f98da9SMariusz Zaborski return (descs); 76454f98da9SMariusz Zaborski } 76554f98da9SMariusz Zaborski #endif 76654f98da9SMariusz Zaborski 76754f98da9SMariusz Zaborski #ifndef _KERNEL 76854f98da9SMariusz Zaborski int * 76954f98da9SMariusz Zaborski nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp) 77054f98da9SMariusz Zaborski { 77154f98da9SMariusz Zaborski size_t nitems; 77254f98da9SMariusz Zaborski int *fds; 77354f98da9SMariusz Zaborski 77454f98da9SMariusz Zaborski nitems = nvlist_ndescriptors(nvl); 77554f98da9SMariusz Zaborski fds = nv_malloc(sizeof(fds[0]) * (nitems + 1)); 77654f98da9SMariusz Zaborski if (fds == NULL) 77754f98da9SMariusz Zaborski return (NULL); 77854f98da9SMariusz Zaborski if (nitems > 0) 77954f98da9SMariusz Zaborski nvlist_xdescriptors(nvl, fds); 78054f98da9SMariusz Zaborski fds[nitems] = -1; 78154f98da9SMariusz Zaborski if (nitemsp != NULL) 78254f98da9SMariusz Zaborski *nitemsp = nitems; 78354f98da9SMariusz Zaborski return (fds); 78454f98da9SMariusz Zaborski } 78554f98da9SMariusz Zaborski #endif 78654f98da9SMariusz Zaborski 78754f98da9SMariusz Zaborski size_t 78854f98da9SMariusz Zaborski nvlist_ndescriptors(const nvlist_t *nvl) 78954f98da9SMariusz Zaborski { 79054f98da9SMariusz Zaborski #ifndef _KERNEL 7919a8ce256SJilles Tjoelker void *cookie; 79254f98da9SMariusz Zaborski nvpair_t *nvp; 79354f98da9SMariusz Zaborski size_t ndescs; 79454f98da9SMariusz Zaborski int type; 79554f98da9SMariusz Zaborski 79654f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 79754f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 79854f98da9SMariusz Zaborski 79954f98da9SMariusz Zaborski ndescs = 0; 8009a8ce256SJilles Tjoelker cookie = NULL; 80154f98da9SMariusz Zaborski do { 8029a8ce256SJilles Tjoelker while (nvlist_next(nvl, &type, &cookie) != NULL) { 8039a8ce256SJilles Tjoelker nvp = cookie; 80454f98da9SMariusz Zaborski switch (type) { 80554f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 80654f98da9SMariusz Zaborski ndescs++; 80754f98da9SMariusz Zaborski break; 80854f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 80954f98da9SMariusz Zaborski nvl = nvpair_get_nvlist(nvp); 8109a8ce256SJilles Tjoelker cookie = NULL; 81154f98da9SMariusz Zaborski break; 812347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 813347a39b4SMariusz Zaborski { 814347a39b4SMariusz Zaborski const nvlist_t * const *value; 815347a39b4SMariusz Zaborski size_t nitems; 816347a39b4SMariusz Zaborski 817347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 818347a39b4SMariusz Zaborski PJDLOG_ASSERT(value != NULL); 819347a39b4SMariusz Zaborski PJDLOG_ASSERT(nitems > 0); 820347a39b4SMariusz Zaborski 821347a39b4SMariusz Zaborski nvl = value[0]; 8229a8ce256SJilles Tjoelker cookie = NULL; 823347a39b4SMariusz Zaborski break; 824347a39b4SMariusz Zaborski } 825347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 826347a39b4SMariusz Zaborski { 827347a39b4SMariusz Zaborski size_t nitems; 828347a39b4SMariusz Zaborski 829347a39b4SMariusz Zaborski (void)nvpair_get_descriptor_array(nvp, 830347a39b4SMariusz Zaborski &nitems); 831347a39b4SMariusz Zaborski ndescs += nitems; 832347a39b4SMariusz Zaborski break; 83354f98da9SMariusz Zaborski } 83454f98da9SMariusz Zaborski } 835347a39b4SMariusz Zaborski } 8369a8ce256SJilles Tjoelker } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL); 83754f98da9SMariusz Zaborski 83854f98da9SMariusz Zaborski return (ndescs); 83954f98da9SMariusz Zaborski #else 84054f98da9SMariusz Zaborski return (0); 84154f98da9SMariusz Zaborski #endif 84254f98da9SMariusz Zaborski } 84354f98da9SMariusz Zaborski 84454f98da9SMariusz Zaborski static unsigned char * 84554f98da9SMariusz Zaborski nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp) 84654f98da9SMariusz Zaborski { 84754f98da9SMariusz Zaborski struct nvlist_header nvlhdr; 84854f98da9SMariusz Zaborski 84954f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 85054f98da9SMariusz Zaborski 85154f98da9SMariusz Zaborski nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC; 85254f98da9SMariusz Zaborski nvlhdr.nvlh_version = NVLIST_HEADER_VERSION; 85354f98da9SMariusz Zaborski nvlhdr.nvlh_flags = nvl->nvl_flags; 85454f98da9SMariusz Zaborski #if BYTE_ORDER == BIG_ENDIAN 85554f98da9SMariusz Zaborski nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN; 85654f98da9SMariusz Zaborski #endif 85754f98da9SMariusz Zaborski nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl); 85854f98da9SMariusz Zaborski nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr); 85954f98da9SMariusz Zaborski PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr)); 86054f98da9SMariusz Zaborski memcpy(ptr, &nvlhdr, sizeof(nvlhdr)); 86154f98da9SMariusz Zaborski ptr += sizeof(nvlhdr); 86254f98da9SMariusz Zaborski *leftp -= sizeof(nvlhdr); 86354f98da9SMariusz Zaborski 86454f98da9SMariusz Zaborski return (ptr); 86554f98da9SMariusz Zaborski } 86654f98da9SMariusz Zaborski 86754f98da9SMariusz Zaborski static void * 86854f98da9SMariusz Zaborski nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) 86954f98da9SMariusz Zaborski { 87054f98da9SMariusz Zaborski unsigned char *buf, *ptr; 87154f98da9SMariusz Zaborski size_t left, size; 87254f98da9SMariusz Zaborski const nvlist_t *tmpnvl; 87354f98da9SMariusz Zaborski nvpair_t *nvp, *tmpnvp; 87454f98da9SMariusz Zaborski void *cookie; 87554f98da9SMariusz Zaborski 87654f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 87754f98da9SMariusz Zaborski 87854f98da9SMariusz Zaborski if (nvl->nvl_error != 0) { 87954f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 88054f98da9SMariusz Zaborski return (NULL); 88154f98da9SMariusz Zaborski } 88254f98da9SMariusz Zaborski 88354f98da9SMariusz Zaborski size = nvlist_size(nvl); 88454f98da9SMariusz Zaborski buf = nv_malloc(size); 88554f98da9SMariusz Zaborski if (buf == NULL) 88654f98da9SMariusz Zaborski return (NULL); 88754f98da9SMariusz Zaborski 88854f98da9SMariusz Zaborski ptr = buf; 88954f98da9SMariusz Zaborski left = size; 89054f98da9SMariusz Zaborski 89154f98da9SMariusz Zaborski ptr = nvlist_pack_header(nvl, ptr, &left); 89254f98da9SMariusz Zaborski 89354f98da9SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 89454f98da9SMariusz Zaborski while (nvp != NULL) { 89554f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 89654f98da9SMariusz Zaborski 89754f98da9SMariusz Zaborski nvpair_init_datasize(nvp); 89854f98da9SMariusz Zaborski ptr = nvpair_pack_header(nvp, ptr, &left); 899c68f8061SMariusz Zaborski if (ptr == NULL) 900c68f8061SMariusz Zaborski goto fail; 90154f98da9SMariusz Zaborski switch (nvpair_type(nvp)) { 90254f98da9SMariusz Zaborski case NV_TYPE_NULL: 90354f98da9SMariusz Zaborski ptr = nvpair_pack_null(nvp, ptr, &left); 90454f98da9SMariusz Zaborski break; 90554f98da9SMariusz Zaborski case NV_TYPE_BOOL: 90654f98da9SMariusz Zaborski ptr = nvpair_pack_bool(nvp, ptr, &left); 90754f98da9SMariusz Zaborski break; 90854f98da9SMariusz Zaborski case NV_TYPE_NUMBER: 90954f98da9SMariusz Zaborski ptr = nvpair_pack_number(nvp, ptr, &left); 91054f98da9SMariusz Zaborski break; 91154f98da9SMariusz Zaborski case NV_TYPE_STRING: 91254f98da9SMariusz Zaborski ptr = nvpair_pack_string(nvp, ptr, &left); 91354f98da9SMariusz Zaborski break; 91454f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 91554f98da9SMariusz Zaborski tmpnvl = nvpair_get_nvlist(nvp); 91654f98da9SMariusz Zaborski ptr = nvlist_pack_header(tmpnvl, ptr, &left); 91754f98da9SMariusz Zaborski if (ptr == NULL) 918c68f8061SMariusz Zaborski goto fail; 91954f98da9SMariusz Zaborski tmpnvp = nvlist_first_nvpair(tmpnvl); 92054f98da9SMariusz Zaborski if (tmpnvp != NULL) { 92154f98da9SMariusz Zaborski nvl = tmpnvl; 92254f98da9SMariusz Zaborski nvp = tmpnvp; 92354f98da9SMariusz Zaborski continue; 92454f98da9SMariusz Zaborski } 92554f98da9SMariusz Zaborski ptr = nvpair_pack_nvlist_up(ptr, &left); 92654f98da9SMariusz Zaborski break; 92754f98da9SMariusz Zaborski #ifndef _KERNEL 92854f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 92954f98da9SMariusz Zaborski ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left); 93054f98da9SMariusz Zaborski break; 931347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 932347a39b4SMariusz Zaborski ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp, 933347a39b4SMariusz Zaborski &left); 934347a39b4SMariusz Zaborski break; 93554f98da9SMariusz Zaborski #endif 93654f98da9SMariusz Zaborski case NV_TYPE_BINARY: 93754f98da9SMariusz Zaborski ptr = nvpair_pack_binary(nvp, ptr, &left); 93854f98da9SMariusz Zaborski break; 939347a39b4SMariusz Zaborski case NV_TYPE_BOOL_ARRAY: 940347a39b4SMariusz Zaborski ptr = nvpair_pack_bool_array(nvp, ptr, &left); 941347a39b4SMariusz Zaborski break; 942347a39b4SMariusz Zaborski case NV_TYPE_NUMBER_ARRAY: 943347a39b4SMariusz Zaborski ptr = nvpair_pack_number_array(nvp, ptr, &left); 944347a39b4SMariusz Zaborski break; 945347a39b4SMariusz Zaborski case NV_TYPE_STRING_ARRAY: 946347a39b4SMariusz Zaborski ptr = nvpair_pack_string_array(nvp, ptr, &left); 947347a39b4SMariusz Zaborski break; 948347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 949347a39b4SMariusz Zaborski { 950347a39b4SMariusz Zaborski const nvlist_t * const * value; 951347a39b4SMariusz Zaborski size_t nitems; 952347a39b4SMariusz Zaborski unsigned int ii; 953347a39b4SMariusz Zaborski 954347a39b4SMariusz Zaborski tmpnvl = NULL; 955347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 956347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 957347a39b4SMariusz Zaborski ptr = nvlist_pack_header(value[ii], ptr, &left); 958347a39b4SMariusz Zaborski if (ptr == NULL) 959347a39b4SMariusz Zaborski goto out; 960347a39b4SMariusz Zaborski tmpnvp = nvlist_first_nvpair(value[ii]); 961347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 962347a39b4SMariusz Zaborski tmpnvl = value[ii]; 963347a39b4SMariusz Zaborski break; 964347a39b4SMariusz Zaborski } 965347a39b4SMariusz Zaborski ptr = nvpair_pack_nvlist_array_next(ptr, &left); 966347a39b4SMariusz Zaborski if (ptr == NULL) 967347a39b4SMariusz Zaborski goto out; 968347a39b4SMariusz Zaborski } 969347a39b4SMariusz Zaborski if (tmpnvl != NULL) { 970347a39b4SMariusz Zaborski nvl = tmpnvl; 971347a39b4SMariusz Zaborski nvp = tmpnvp; 972347a39b4SMariusz Zaborski continue; 973347a39b4SMariusz Zaborski } 974347a39b4SMariusz Zaborski break; 975347a39b4SMariusz Zaborski } 97654f98da9SMariusz Zaborski default: 97754f98da9SMariusz Zaborski PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 97854f98da9SMariusz Zaborski } 979c68f8061SMariusz Zaborski if (ptr == NULL) 980c68f8061SMariusz Zaborski goto fail; 98154f98da9SMariusz Zaborski while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 982347a39b4SMariusz Zaborski do { 98354f98da9SMariusz Zaborski cookie = NULL; 984347a39b4SMariusz Zaborski if (nvlist_in_array(nvl)) { 985347a39b4SMariusz Zaborski ptr = nvpair_pack_nvlist_array_next(ptr, 986347a39b4SMariusz Zaborski &left); 987347a39b4SMariusz Zaborski if (ptr == NULL) 988347a39b4SMariusz Zaborski goto fail; 989347a39b4SMariusz Zaborski } 990347a39b4SMariusz Zaborski nvl = nvlist_get_pararr(nvl, &cookie); 99154f98da9SMariusz Zaborski if (nvl == NULL) 99254f98da9SMariusz Zaborski goto out; 993347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) { 994347a39b4SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 995347a39b4SMariusz Zaborski ptr = nvlist_pack_header(nvl, ptr, 996347a39b4SMariusz Zaborski &left); 997347a39b4SMariusz Zaborski if (ptr == NULL) 998347a39b4SMariusz Zaborski goto fail; 999347a39b4SMariusz Zaborski } else if (nvpair_type((nvpair_t *)cookie) != 1000347a39b4SMariusz Zaborski NV_TYPE_NVLIST_ARRAY) { 100154f98da9SMariusz Zaborski ptr = nvpair_pack_nvlist_up(ptr, &left); 100254f98da9SMariusz Zaborski if (ptr == NULL) 1003c68f8061SMariusz Zaborski goto fail; 1004347a39b4SMariusz Zaborski nvp = cookie; 1005347a39b4SMariusz Zaborski } else { 1006347a39b4SMariusz Zaborski nvp = cookie; 1007347a39b4SMariusz Zaborski } 1008347a39b4SMariusz Zaborski } while (nvp == NULL); 1009347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) 1010347a39b4SMariusz Zaborski break; 101154f98da9SMariusz Zaborski } 101254f98da9SMariusz Zaborski } 101354f98da9SMariusz Zaborski 101454f98da9SMariusz Zaborski out: 101554f98da9SMariusz Zaborski if (sizep != NULL) 101654f98da9SMariusz Zaborski *sizep = size; 101754f98da9SMariusz Zaborski return (buf); 1018c68f8061SMariusz Zaborski fail: 1019c68f8061SMariusz Zaborski nv_free(buf); 1020c68f8061SMariusz Zaborski return (NULL); 102154f98da9SMariusz Zaborski } 102254f98da9SMariusz Zaborski 102354f98da9SMariusz Zaborski void * 102454f98da9SMariusz Zaborski nvlist_pack(const nvlist_t *nvl, size_t *sizep) 102554f98da9SMariusz Zaborski { 102654f98da9SMariusz Zaborski 102754f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 102854f98da9SMariusz Zaborski 102954f98da9SMariusz Zaborski if (nvl->nvl_error != 0) { 103054f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 103154f98da9SMariusz Zaborski return (NULL); 103254f98da9SMariusz Zaborski } 103354f98da9SMariusz Zaborski 103454f98da9SMariusz Zaborski if (nvlist_ndescriptors(nvl) > 0) { 103554f98da9SMariusz Zaborski ERRNO_SET(EOPNOTSUPP); 103654f98da9SMariusz Zaborski return (NULL); 103754f98da9SMariusz Zaborski } 103854f98da9SMariusz Zaborski 103954f98da9SMariusz Zaborski return (nvlist_xpack(nvl, NULL, sizep)); 104054f98da9SMariusz Zaborski } 104154f98da9SMariusz Zaborski 104254f98da9SMariusz Zaborski static bool 104354f98da9SMariusz Zaborski nvlist_check_header(struct nvlist_header *nvlhdrp) 104454f98da9SMariusz Zaborski { 104554f98da9SMariusz Zaborski 104654f98da9SMariusz Zaborski if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { 104754f98da9SMariusz Zaborski ERRNO_SET(EINVAL); 104854f98da9SMariusz Zaborski return (false); 104954f98da9SMariusz Zaborski } 105054f98da9SMariusz Zaborski if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { 105154f98da9SMariusz Zaborski ERRNO_SET(EINVAL); 105254f98da9SMariusz Zaborski return (false); 105354f98da9SMariusz Zaborski } 105454f98da9SMariusz Zaborski #if BYTE_ORDER == BIG_ENDIAN 105554f98da9SMariusz Zaborski if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) { 105654f98da9SMariusz Zaborski nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size); 105754f98da9SMariusz Zaborski nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors); 105854f98da9SMariusz Zaborski } 105954f98da9SMariusz Zaborski #else 106054f98da9SMariusz Zaborski if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) { 106154f98da9SMariusz Zaborski nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size); 106254f98da9SMariusz Zaborski nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); 106354f98da9SMariusz Zaborski } 106454f98da9SMariusz Zaborski #endif 106554f98da9SMariusz Zaborski return (true); 106654f98da9SMariusz Zaborski } 106754f98da9SMariusz Zaborski 106854f98da9SMariusz Zaborski const unsigned char * 106954f98da9SMariusz Zaborski nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, 107054f98da9SMariusz Zaborski bool *isbep, size_t *leftp) 107154f98da9SMariusz Zaborski { 107254f98da9SMariusz Zaborski struct nvlist_header nvlhdr; 1073347a39b4SMariusz Zaborski int inarrayf; 107454f98da9SMariusz Zaborski 107554f98da9SMariusz Zaborski if (*leftp < sizeof(nvlhdr)) 1076a3c485d3SMariusz Zaborski goto fail; 107754f98da9SMariusz Zaborski 107854f98da9SMariusz Zaborski memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); 107954f98da9SMariusz Zaborski 108054f98da9SMariusz Zaborski if (!nvlist_check_header(&nvlhdr)) 1081a3c485d3SMariusz Zaborski goto fail; 108254f98da9SMariusz Zaborski 108354f98da9SMariusz Zaborski if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) 1084a3c485d3SMariusz Zaborski goto fail; 108554f98da9SMariusz Zaborski 108654f98da9SMariusz Zaborski /* 108754f98da9SMariusz Zaborski * nvlh_descriptors might be smaller than nfds in embedded nvlists. 108854f98da9SMariusz Zaborski */ 108954f98da9SMariusz Zaborski if (nvlhdr.nvlh_descriptors > nfds) 1090a3c485d3SMariusz Zaborski goto fail; 109154f98da9SMariusz Zaborski 109254f98da9SMariusz Zaborski if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) 1093a3c485d3SMariusz Zaborski goto fail; 109454f98da9SMariusz Zaborski 1095347a39b4SMariusz Zaborski inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY); 1096347a39b4SMariusz Zaborski nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf; 109754f98da9SMariusz Zaborski 109854f98da9SMariusz Zaborski ptr += sizeof(nvlhdr); 109954f98da9SMariusz Zaborski if (isbep != NULL) 110054f98da9SMariusz Zaborski *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0); 110154f98da9SMariusz Zaborski *leftp -= sizeof(nvlhdr); 110254f98da9SMariusz Zaborski 110354f98da9SMariusz Zaborski return (ptr); 1104a3c485d3SMariusz Zaborski fail: 110554f98da9SMariusz Zaborski ERRNO_SET(EINVAL); 110654f98da9SMariusz Zaborski return (NULL); 110754f98da9SMariusz Zaborski } 110854f98da9SMariusz Zaborski 110954f98da9SMariusz Zaborski static nvlist_t * 111054f98da9SMariusz Zaborski nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds, 111154f98da9SMariusz Zaborski int flags) 111254f98da9SMariusz Zaborski { 111354f98da9SMariusz Zaborski const unsigned char *ptr; 1114347a39b4SMariusz Zaborski nvlist_t *nvl, *retnvl, *tmpnvl, *array; 111554f98da9SMariusz Zaborski nvpair_t *nvp; 111654f98da9SMariusz Zaborski size_t left; 111754f98da9SMariusz Zaborski bool isbe; 111854f98da9SMariusz Zaborski 111954f98da9SMariusz Zaborski PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 112054f98da9SMariusz Zaborski 112154f98da9SMariusz Zaborski left = size; 112254f98da9SMariusz Zaborski ptr = buf; 112354f98da9SMariusz Zaborski 1124347a39b4SMariusz Zaborski tmpnvl = array = NULL; 112554f98da9SMariusz Zaborski nvl = retnvl = nvlist_create(0); 112654f98da9SMariusz Zaborski if (nvl == NULL) 1127a3c485d3SMariusz Zaborski goto fail; 112854f98da9SMariusz Zaborski 112954f98da9SMariusz Zaborski ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); 113054f98da9SMariusz Zaborski if (ptr == NULL) 1131a3c485d3SMariusz Zaborski goto fail; 113254f98da9SMariusz Zaborski if (nvl->nvl_flags != flags) { 113354f98da9SMariusz Zaborski ERRNO_SET(EILSEQ); 1134a3c485d3SMariusz Zaborski goto fail; 113554f98da9SMariusz Zaborski } 113654f98da9SMariusz Zaborski 113754f98da9SMariusz Zaborski while (left > 0) { 113854f98da9SMariusz Zaborski ptr = nvpair_unpack(isbe, ptr, &left, &nvp); 113954f98da9SMariusz Zaborski if (ptr == NULL) 1140a3c485d3SMariusz Zaborski goto fail; 114154f98da9SMariusz Zaborski switch (nvpair_type(nvp)) { 114254f98da9SMariusz Zaborski case NV_TYPE_NULL: 114354f98da9SMariusz Zaborski ptr = nvpair_unpack_null(isbe, nvp, ptr, &left); 114454f98da9SMariusz Zaborski break; 114554f98da9SMariusz Zaborski case NV_TYPE_BOOL: 114654f98da9SMariusz Zaborski ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left); 114754f98da9SMariusz Zaborski break; 114854f98da9SMariusz Zaborski case NV_TYPE_NUMBER: 114954f98da9SMariusz Zaborski ptr = nvpair_unpack_number(isbe, nvp, ptr, &left); 115054f98da9SMariusz Zaborski break; 115154f98da9SMariusz Zaborski case NV_TYPE_STRING: 115254f98da9SMariusz Zaborski ptr = nvpair_unpack_string(isbe, nvp, ptr, &left); 115354f98da9SMariusz Zaborski break; 115454f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 115554f98da9SMariusz Zaborski ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds, 115654f98da9SMariusz Zaborski &tmpnvl); 115751dae13fSMariusz Zaborski if (tmpnvl == NULL || ptr == NULL) 1158a3c485d3SMariusz Zaborski goto fail; 115954f98da9SMariusz Zaborski nvlist_set_parent(tmpnvl, nvp); 116054f98da9SMariusz Zaborski break; 116154f98da9SMariusz Zaborski #ifndef _KERNEL 116254f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 116354f98da9SMariusz Zaborski ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left, 116454f98da9SMariusz Zaborski fds, nfds); 116554f98da9SMariusz Zaborski break; 1166347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 1167347a39b4SMariusz Zaborski ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr, 1168347a39b4SMariusz Zaborski &left, fds, nfds); 1169347a39b4SMariusz Zaborski break; 117054f98da9SMariusz Zaborski #endif 117154f98da9SMariusz Zaborski case NV_TYPE_BINARY: 117254f98da9SMariusz Zaborski ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left); 117354f98da9SMariusz Zaborski break; 117454f98da9SMariusz Zaborski case NV_TYPE_NVLIST_UP: 117554f98da9SMariusz Zaborski if (nvl->nvl_parent == NULL) 1176a3c485d3SMariusz Zaborski goto fail; 117754f98da9SMariusz Zaborski nvl = nvpair_nvlist(nvl->nvl_parent); 117854f98da9SMariusz Zaborski nvpair_free_structure(nvp); 117954f98da9SMariusz Zaborski continue; 1180347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY_NEXT: 1181347a39b4SMariusz Zaborski if (nvl->nvl_array_next == NULL) { 1182347a39b4SMariusz Zaborski if (nvl->nvl_parent == NULL) 1183a3c485d3SMariusz Zaborski goto fail; 1184347a39b4SMariusz Zaborski nvl = nvpair_nvlist(nvl->nvl_parent); 1185347a39b4SMariusz Zaborski } else { 1186347a39b4SMariusz Zaborski nvl = __DECONST(nvlist_t *, 1187347a39b4SMariusz Zaborski nvlist_get_array_next(nvl)); 1188347a39b4SMariusz Zaborski ptr = nvlist_unpack_header(nvl, ptr, nfds, 1189347a39b4SMariusz Zaborski &isbe, &left); 1190347a39b4SMariusz Zaborski if (ptr == NULL) 1191a3c485d3SMariusz Zaborski goto fail; 1192347a39b4SMariusz Zaborski } 1193347a39b4SMariusz Zaborski nvpair_free_structure(nvp); 1194347a39b4SMariusz Zaborski continue; 1195347a39b4SMariusz Zaborski case NV_TYPE_BOOL_ARRAY: 1196347a39b4SMariusz Zaborski ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left); 1197347a39b4SMariusz Zaborski break; 1198347a39b4SMariusz Zaborski case NV_TYPE_NUMBER_ARRAY: 1199347a39b4SMariusz Zaborski ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left); 1200347a39b4SMariusz Zaborski break; 1201347a39b4SMariusz Zaborski case NV_TYPE_STRING_ARRAY: 1202347a39b4SMariusz Zaborski ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left); 1203347a39b4SMariusz Zaborski break; 1204347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 1205347a39b4SMariusz Zaborski ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left, 1206347a39b4SMariusz Zaborski &array); 1207347a39b4SMariusz Zaborski if (ptr == NULL) 1208a3c485d3SMariusz Zaborski goto fail; 12091dacabe1SMariusz Zaborski PJDLOG_ASSERT(array != NULL); 1210347a39b4SMariusz Zaborski tmpnvl = array; 12111dacabe1SMariusz Zaborski do { 1212347a39b4SMariusz Zaborski nvlist_set_parent(array, nvp); 1213347a39b4SMariusz Zaborski array = __DECONST(nvlist_t *, 1214347a39b4SMariusz Zaborski nvlist_get_array_next(array)); 12151dacabe1SMariusz Zaborski } while (array != NULL); 1216347a39b4SMariusz Zaborski ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe, 1217347a39b4SMariusz Zaborski &left); 1218347a39b4SMariusz Zaborski break; 121954f98da9SMariusz Zaborski default: 122054f98da9SMariusz Zaborski PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 122154f98da9SMariusz Zaborski } 122254f98da9SMariusz Zaborski if (ptr == NULL) 1223a3c485d3SMariusz Zaborski goto fail; 122430740f45SMariusz Zaborski if (!nvlist_move_nvpair(nvl, nvp)) 1225a3c485d3SMariusz Zaborski goto fail; 122654f98da9SMariusz Zaborski if (tmpnvl != NULL) { 122754f98da9SMariusz Zaborski nvl = tmpnvl; 122854f98da9SMariusz Zaborski tmpnvl = NULL; 122954f98da9SMariusz Zaborski } 123054f98da9SMariusz Zaborski } 123154f98da9SMariusz Zaborski 123254f98da9SMariusz Zaborski return (retnvl); 1233a3c485d3SMariusz Zaborski fail: 123454f98da9SMariusz Zaborski nvlist_destroy(retnvl); 123554f98da9SMariusz Zaborski return (NULL); 123654f98da9SMariusz Zaborski } 123754f98da9SMariusz Zaborski 123854f98da9SMariusz Zaborski nvlist_t * 123954f98da9SMariusz Zaborski nvlist_unpack(const void *buf, size_t size, int flags) 124054f98da9SMariusz Zaborski { 124154f98da9SMariusz Zaborski 124254f98da9SMariusz Zaborski return (nvlist_xunpack(buf, size, NULL, 0, flags)); 124354f98da9SMariusz Zaborski } 124454f98da9SMariusz Zaborski 124554f98da9SMariusz Zaborski #ifndef _KERNEL 124654f98da9SMariusz Zaborski int 124754f98da9SMariusz Zaborski nvlist_send(int sock, const nvlist_t *nvl) 124854f98da9SMariusz Zaborski { 124954f98da9SMariusz Zaborski size_t datasize, nfds; 125054f98da9SMariusz Zaborski int *fds; 125154f98da9SMariusz Zaborski void *data; 125254f98da9SMariusz Zaborski int64_t fdidx; 125354f98da9SMariusz Zaborski int ret; 125454f98da9SMariusz Zaborski 125554f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 125654f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 125754f98da9SMariusz Zaborski return (-1); 125854f98da9SMariusz Zaborski } 125954f98da9SMariusz Zaborski 126054f98da9SMariusz Zaborski fds = nvlist_descriptors(nvl, &nfds); 126154f98da9SMariusz Zaborski if (fds == NULL) 126254f98da9SMariusz Zaborski return (-1); 126354f98da9SMariusz Zaborski 126454f98da9SMariusz Zaborski ret = -1; 126554f98da9SMariusz Zaborski fdidx = 0; 126654f98da9SMariusz Zaborski 126754f98da9SMariusz Zaborski data = nvlist_xpack(nvl, &fdidx, &datasize); 126854f98da9SMariusz Zaborski if (data == NULL) 126954f98da9SMariusz Zaborski goto out; 127054f98da9SMariusz Zaborski 127154f98da9SMariusz Zaborski if (buf_send(sock, data, datasize) == -1) 127254f98da9SMariusz Zaborski goto out; 127354f98da9SMariusz Zaborski 127454f98da9SMariusz Zaborski if (nfds > 0) { 127554f98da9SMariusz Zaborski if (fd_send(sock, fds, nfds) == -1) 127654f98da9SMariusz Zaborski goto out; 127754f98da9SMariusz Zaborski } 127854f98da9SMariusz Zaborski 127954f98da9SMariusz Zaborski ret = 0; 128054f98da9SMariusz Zaborski out: 128154f98da9SMariusz Zaborski ERRNO_SAVE(); 128254f98da9SMariusz Zaborski nv_free(fds); 128354f98da9SMariusz Zaborski nv_free(data); 128454f98da9SMariusz Zaborski ERRNO_RESTORE(); 128554f98da9SMariusz Zaborski return (ret); 128654f98da9SMariusz Zaborski } 128754f98da9SMariusz Zaborski 128854f98da9SMariusz Zaborski nvlist_t * 128954f98da9SMariusz Zaborski nvlist_recv(int sock, int flags) 129054f98da9SMariusz Zaborski { 129154f98da9SMariusz Zaborski struct nvlist_header nvlhdr; 129254f98da9SMariusz Zaborski nvlist_t *nvl, *ret; 129354f98da9SMariusz Zaborski unsigned char *buf; 129454f98da9SMariusz Zaborski size_t nfds, size, i; 129554f98da9SMariusz Zaborski int *fds; 129654f98da9SMariusz Zaborski 129754f98da9SMariusz Zaborski if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1) 129854f98da9SMariusz Zaborski return (NULL); 129954f98da9SMariusz Zaborski 130054f98da9SMariusz Zaborski if (!nvlist_check_header(&nvlhdr)) 130154f98da9SMariusz Zaborski return (NULL); 130254f98da9SMariusz Zaborski 130354f98da9SMariusz Zaborski nfds = (size_t)nvlhdr.nvlh_descriptors; 130454f98da9SMariusz Zaborski size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size; 130554f98da9SMariusz Zaborski 130654f98da9SMariusz Zaborski buf = nv_malloc(size); 130754f98da9SMariusz Zaborski if (buf == NULL) 130854f98da9SMariusz Zaborski return (NULL); 130954f98da9SMariusz Zaborski 131054f98da9SMariusz Zaborski memcpy(buf, &nvlhdr, sizeof(nvlhdr)); 131154f98da9SMariusz Zaborski 131254f98da9SMariusz Zaborski ret = NULL; 131354f98da9SMariusz Zaborski fds = NULL; 131454f98da9SMariusz Zaborski 131554f98da9SMariusz Zaborski if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1) 131654f98da9SMariusz Zaborski goto out; 131754f98da9SMariusz Zaborski 131854f98da9SMariusz Zaborski if (nfds > 0) { 131954f98da9SMariusz Zaborski fds = nv_malloc(nfds * sizeof(fds[0])); 132054f98da9SMariusz Zaborski if (fds == NULL) 132154f98da9SMariusz Zaborski goto out; 132254f98da9SMariusz Zaborski if (fd_recv(sock, fds, nfds) == -1) 132354f98da9SMariusz Zaborski goto out; 132454f98da9SMariusz Zaborski } 132554f98da9SMariusz Zaborski 132654f98da9SMariusz Zaborski nvl = nvlist_xunpack(buf, size, fds, nfds, flags); 132754f98da9SMariusz Zaborski if (nvl == NULL) { 132854f98da9SMariusz Zaborski ERRNO_SAVE(); 132954f98da9SMariusz Zaborski for (i = 0; i < nfds; i++) 133054f98da9SMariusz Zaborski close(fds[i]); 133154f98da9SMariusz Zaborski ERRNO_RESTORE(); 133254f98da9SMariusz Zaborski goto out; 133354f98da9SMariusz Zaborski } 133454f98da9SMariusz Zaborski 133554f98da9SMariusz Zaborski ret = nvl; 133654f98da9SMariusz Zaborski out: 133754f98da9SMariusz Zaborski ERRNO_SAVE(); 133854f98da9SMariusz Zaborski nv_free(buf); 133954f98da9SMariusz Zaborski nv_free(fds); 134054f98da9SMariusz Zaborski ERRNO_RESTORE(); 134154f98da9SMariusz Zaborski 134254f98da9SMariusz Zaborski return (ret); 134354f98da9SMariusz Zaborski } 134454f98da9SMariusz Zaborski 134554f98da9SMariusz Zaborski nvlist_t * 134654f98da9SMariusz Zaborski nvlist_xfer(int sock, nvlist_t *nvl, int flags) 134754f98da9SMariusz Zaborski { 134854f98da9SMariusz Zaborski 134954f98da9SMariusz Zaborski if (nvlist_send(sock, nvl) < 0) { 135054f98da9SMariusz Zaborski nvlist_destroy(nvl); 135154f98da9SMariusz Zaborski return (NULL); 135254f98da9SMariusz Zaborski } 135354f98da9SMariusz Zaborski nvlist_destroy(nvl); 135454f98da9SMariusz Zaborski return (nvlist_recv(sock, flags)); 135554f98da9SMariusz Zaborski } 135654f98da9SMariusz Zaborski #endif 135754f98da9SMariusz Zaborski 135854f98da9SMariusz Zaborski nvpair_t * 135954f98da9SMariusz Zaborski nvlist_first_nvpair(const nvlist_t *nvl) 136054f98da9SMariusz Zaborski { 136154f98da9SMariusz Zaborski 136254f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 136354f98da9SMariusz Zaborski 136454f98da9SMariusz Zaborski return (TAILQ_FIRST(&nvl->nvl_head)); 136554f98da9SMariusz Zaborski } 136654f98da9SMariusz Zaborski 136754f98da9SMariusz Zaborski nvpair_t * 136854f98da9SMariusz Zaborski nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 136954f98da9SMariusz Zaborski { 137054f98da9SMariusz Zaborski nvpair_t *retnvp; 137154f98da9SMariusz Zaborski 137254f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 137354f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 137454f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 137554f98da9SMariusz Zaborski 137654f98da9SMariusz Zaborski retnvp = nvpair_next(nvp); 137754f98da9SMariusz Zaborski PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl); 137854f98da9SMariusz Zaborski 137954f98da9SMariusz Zaborski return (retnvp); 138054f98da9SMariusz Zaborski 138154f98da9SMariusz Zaborski } 138254f98da9SMariusz Zaborski 138354f98da9SMariusz Zaborski nvpair_t * 138454f98da9SMariusz Zaborski nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 138554f98da9SMariusz Zaborski { 138654f98da9SMariusz Zaborski nvpair_t *retnvp; 138754f98da9SMariusz Zaborski 138854f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 138954f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 139054f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 139154f98da9SMariusz Zaborski 139254f98da9SMariusz Zaborski retnvp = nvpair_prev(nvp); 139354f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl); 139454f98da9SMariusz Zaborski 139554f98da9SMariusz Zaborski return (retnvp); 139654f98da9SMariusz Zaborski } 139754f98da9SMariusz Zaborski 139854f98da9SMariusz Zaborski const char * 139954f98da9SMariusz Zaborski nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep) 140054f98da9SMariusz Zaborski { 140154f98da9SMariusz Zaborski nvpair_t *nvp; 140254f98da9SMariusz Zaborski 140354f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 140454f98da9SMariusz Zaborski 140589ca10c6SMariusz Zaborski if (cookiep == NULL || *cookiep == NULL) 140654f98da9SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 140754f98da9SMariusz Zaborski else 140854f98da9SMariusz Zaborski nvp = nvlist_next_nvpair(nvl, *cookiep); 140954f98da9SMariusz Zaborski if (nvp == NULL) 141054f98da9SMariusz Zaborski return (NULL); 141154f98da9SMariusz Zaborski if (typep != NULL) 141254f98da9SMariusz Zaborski *typep = nvpair_type(nvp); 141389ca10c6SMariusz Zaborski if (cookiep != NULL) 141454f98da9SMariusz Zaborski *cookiep = nvp; 141554f98da9SMariusz Zaborski return (nvpair_name(nvp)); 141654f98da9SMariusz Zaborski } 141754f98da9SMariusz Zaborski 141854f98da9SMariusz Zaborski bool 141954f98da9SMariusz Zaborski nvlist_exists(const nvlist_t *nvl, const char *name) 142054f98da9SMariusz Zaborski { 142154f98da9SMariusz Zaborski 142254f98da9SMariusz Zaborski return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL); 142354f98da9SMariusz Zaborski } 142454f98da9SMariusz Zaborski 142554f98da9SMariusz Zaborski #define NVLIST_EXISTS(type, TYPE) \ 142654f98da9SMariusz Zaborski bool \ 142754f98da9SMariusz Zaborski nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ 142854f98da9SMariusz Zaborski { \ 142954f98da9SMariusz Zaborski \ 143054f98da9SMariusz Zaborski return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \ 143154f98da9SMariusz Zaborski } 143254f98da9SMariusz Zaborski 143354f98da9SMariusz Zaborski NVLIST_EXISTS(null, NULL) 143454f98da9SMariusz Zaborski NVLIST_EXISTS(bool, BOOL) 143554f98da9SMariusz Zaborski NVLIST_EXISTS(number, NUMBER) 143654f98da9SMariusz Zaborski NVLIST_EXISTS(string, STRING) 143754f98da9SMariusz Zaborski NVLIST_EXISTS(nvlist, NVLIST) 1438347a39b4SMariusz Zaborski NVLIST_EXISTS(binary, BINARY) 1439347a39b4SMariusz Zaborski NVLIST_EXISTS(bool_array, BOOL_ARRAY) 1440347a39b4SMariusz Zaborski NVLIST_EXISTS(number_array, NUMBER_ARRAY) 1441347a39b4SMariusz Zaborski NVLIST_EXISTS(string_array, STRING_ARRAY) 1442347a39b4SMariusz Zaborski NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY) 144354f98da9SMariusz Zaborski #ifndef _KERNEL 144454f98da9SMariusz Zaborski NVLIST_EXISTS(descriptor, DESCRIPTOR) 1445347a39b4SMariusz Zaborski NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY) 144654f98da9SMariusz Zaborski #endif 144754f98da9SMariusz Zaborski 144854f98da9SMariusz Zaborski #undef NVLIST_EXISTS 144954f98da9SMariusz Zaborski 145054f98da9SMariusz Zaborski void 145154f98da9SMariusz Zaborski nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) 145254f98da9SMariusz Zaborski { 145354f98da9SMariusz Zaborski nvpair_t *newnvp; 145454f98da9SMariusz Zaborski 145554f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 145654f98da9SMariusz Zaborski 145754f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 145854f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 145954f98da9SMariusz Zaborski return; 146054f98da9SMariusz Zaborski } 146154f98da9SMariusz Zaborski if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { 146254f98da9SMariusz Zaborski if (nvlist_exists(nvl, nvpair_name(nvp))) { 146354f98da9SMariusz Zaborski nvl->nvl_error = EEXIST; 146454f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 146554f98da9SMariusz Zaborski return; 146654f98da9SMariusz Zaborski } 146754f98da9SMariusz Zaborski } 146854f98da9SMariusz Zaborski 146954f98da9SMariusz Zaborski newnvp = nvpair_clone(nvp); 147054f98da9SMariusz Zaborski if (newnvp == NULL) { 147154f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 147254f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 147354f98da9SMariusz Zaborski return; 147454f98da9SMariusz Zaborski } 147554f98da9SMariusz Zaborski 147654f98da9SMariusz Zaborski nvpair_insert(&nvl->nvl_head, newnvp, nvl); 147754f98da9SMariusz Zaborski } 147854f98da9SMariusz Zaborski 147954f98da9SMariusz Zaborski void 148054f98da9SMariusz Zaborski nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) 148154f98da9SMariusz Zaborski { 148254f98da9SMariusz Zaborski va_list valueap; 148354f98da9SMariusz Zaborski 148454f98da9SMariusz Zaborski va_start(valueap, valuefmt); 148554f98da9SMariusz Zaborski nvlist_add_stringv(nvl, name, valuefmt, valueap); 148654f98da9SMariusz Zaborski va_end(valueap); 148754f98da9SMariusz Zaborski } 148854f98da9SMariusz Zaborski 148954f98da9SMariusz Zaborski void 149054f98da9SMariusz Zaborski nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, 149154f98da9SMariusz Zaborski va_list valueap) 149254f98da9SMariusz Zaborski { 149354f98da9SMariusz Zaborski nvpair_t *nvp; 149454f98da9SMariusz Zaborski 149554f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 149654f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 149754f98da9SMariusz Zaborski return; 149854f98da9SMariusz Zaborski } 149954f98da9SMariusz Zaborski 150054f98da9SMariusz Zaborski nvp = nvpair_create_stringv(name, valuefmt, valueap); 150154f98da9SMariusz Zaborski if (nvp == NULL) { 150254f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 150354f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 150454f98da9SMariusz Zaborski } else { 150530740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 150654f98da9SMariusz Zaborski } 150754f98da9SMariusz Zaborski } 150854f98da9SMariusz Zaborski 150954f98da9SMariusz Zaborski void 151054f98da9SMariusz Zaborski nvlist_add_null(nvlist_t *nvl, const char *name) 151154f98da9SMariusz Zaborski { 151254f98da9SMariusz Zaborski nvpair_t *nvp; 151354f98da9SMariusz Zaborski 151454f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 151554f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 151654f98da9SMariusz Zaborski return; 151754f98da9SMariusz Zaborski } 151854f98da9SMariusz Zaborski 151954f98da9SMariusz Zaborski nvp = nvpair_create_null(name); 152054f98da9SMariusz Zaborski if (nvp == NULL) { 152154f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 152254f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 152354f98da9SMariusz Zaborski } else { 152430740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 152554f98da9SMariusz Zaborski } 152654f98da9SMariusz Zaborski } 152754f98da9SMariusz Zaborski 152854f98da9SMariusz Zaborski void 152954f98da9SMariusz Zaborski nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, 153054f98da9SMariusz Zaborski size_t size) 153154f98da9SMariusz Zaborski { 153254f98da9SMariusz Zaborski nvpair_t *nvp; 153354f98da9SMariusz Zaborski 153454f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 153554f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 153654f98da9SMariusz Zaborski return; 153754f98da9SMariusz Zaborski } 153854f98da9SMariusz Zaborski 153954f98da9SMariusz Zaborski nvp = nvpair_create_binary(name, value, size); 154054f98da9SMariusz Zaborski if (nvp == NULL) { 154154f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 154254f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 154354f98da9SMariusz Zaborski } else { 154430740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 154554f98da9SMariusz Zaborski } 154654f98da9SMariusz Zaborski } 154754f98da9SMariusz Zaborski 154854f98da9SMariusz Zaborski 154954f98da9SMariusz Zaborski #define NVLIST_ADD(vtype, type) \ 155054f98da9SMariusz Zaborski void \ 155154f98da9SMariusz Zaborski nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \ 155254f98da9SMariusz Zaborski { \ 155354f98da9SMariusz Zaborski nvpair_t *nvp; \ 155454f98da9SMariusz Zaborski \ 155554f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { \ 155654f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); \ 155754f98da9SMariusz Zaborski return; \ 155854f98da9SMariusz Zaborski } \ 155954f98da9SMariusz Zaborski \ 156054f98da9SMariusz Zaborski nvp = nvpair_create_##type(name, value); \ 156154f98da9SMariusz Zaborski if (nvp == NULL) { \ 156254f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 156354f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); \ 156454f98da9SMariusz Zaborski } else { \ 156530740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); \ 156654f98da9SMariusz Zaborski } \ 156754f98da9SMariusz Zaborski } 156854f98da9SMariusz Zaborski 156954f98da9SMariusz Zaborski NVLIST_ADD(bool, bool) 157054f98da9SMariusz Zaborski NVLIST_ADD(uint64_t, number) 157154f98da9SMariusz Zaborski NVLIST_ADD(const char *, string) 157254f98da9SMariusz Zaborski NVLIST_ADD(const nvlist_t *, nvlist) 157354f98da9SMariusz Zaborski #ifndef _KERNEL 157454f98da9SMariusz Zaborski NVLIST_ADD(int, descriptor); 157554f98da9SMariusz Zaborski #endif 157654f98da9SMariusz Zaborski 157754f98da9SMariusz Zaborski #undef NVLIST_ADD 157854f98da9SMariusz Zaborski 1579347a39b4SMariusz Zaborski #define NVLIST_ADD_ARRAY(vtype, type) \ 1580347a39b4SMariusz Zaborski void \ 1581347a39b4SMariusz Zaborski nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value, \ 1582347a39b4SMariusz Zaborski size_t nitems) \ 1583347a39b4SMariusz Zaborski { \ 1584347a39b4SMariusz Zaborski nvpair_t *nvp; \ 1585347a39b4SMariusz Zaborski \ 1586347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { \ 1587347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); \ 1588347a39b4SMariusz Zaborski return; \ 1589347a39b4SMariusz Zaborski } \ 1590347a39b4SMariusz Zaborski \ 1591347a39b4SMariusz Zaborski nvp = nvpair_create_##type##_array(name, value, nitems); \ 1592347a39b4SMariusz Zaborski if (nvp == NULL) { \ 1593347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 1594347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); \ 1595347a39b4SMariusz Zaborski } else { \ 1596347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); \ 1597347a39b4SMariusz Zaborski } \ 1598347a39b4SMariusz Zaborski } 1599347a39b4SMariusz Zaborski 1600347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const bool *, bool) 1601347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const uint64_t *, number) 1602347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const char * const *, string) 1603347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist) 1604347a39b4SMariusz Zaborski #ifndef _KERNEL 1605347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const int *, descriptor) 1606347a39b4SMariusz Zaborski #endif 1607347a39b4SMariusz Zaborski 1608347a39b4SMariusz Zaborski #undef NVLIST_ADD_ARRAY 1609347a39b4SMariusz Zaborski 161030740f45SMariusz Zaborski bool 161154f98da9SMariusz Zaborski nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) 161254f98da9SMariusz Zaborski { 161354f98da9SMariusz Zaborski 161454f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 161554f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); 161654f98da9SMariusz Zaborski 161754f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 161854f98da9SMariusz Zaborski nvpair_free(nvp); 161954f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 162030740f45SMariusz Zaborski return (false); 162154f98da9SMariusz Zaborski } 162254f98da9SMariusz Zaborski if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { 162354f98da9SMariusz Zaborski if (nvlist_exists(nvl, nvpair_name(nvp))) { 162454f98da9SMariusz Zaborski nvpair_free(nvp); 162554f98da9SMariusz Zaborski nvl->nvl_error = EEXIST; 162654f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 162730740f45SMariusz Zaborski return (false); 162854f98da9SMariusz Zaborski } 162954f98da9SMariusz Zaborski } 163054f98da9SMariusz Zaborski 163154f98da9SMariusz Zaborski nvpair_insert(&nvl->nvl_head, nvp, nvl); 163230740f45SMariusz Zaborski return (true); 163354f98da9SMariusz Zaborski } 163454f98da9SMariusz Zaborski 163554f98da9SMariusz Zaborski void 163654f98da9SMariusz Zaborski nvlist_move_string(nvlist_t *nvl, const char *name, char *value) 163754f98da9SMariusz Zaborski { 163854f98da9SMariusz Zaborski nvpair_t *nvp; 163954f98da9SMariusz Zaborski 164054f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 164154f98da9SMariusz Zaborski nv_free(value); 164254f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 164354f98da9SMariusz Zaborski return; 164454f98da9SMariusz Zaborski } 164554f98da9SMariusz Zaborski 164654f98da9SMariusz Zaborski nvp = nvpair_move_string(name, value); 164754f98da9SMariusz Zaborski if (nvp == NULL) { 164854f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 164954f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 165054f98da9SMariusz Zaborski } else { 165130740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 165254f98da9SMariusz Zaborski } 165354f98da9SMariusz Zaborski } 165454f98da9SMariusz Zaborski 165554f98da9SMariusz Zaborski void 165654f98da9SMariusz Zaborski nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value) 165754f98da9SMariusz Zaborski { 165854f98da9SMariusz Zaborski nvpair_t *nvp; 165954f98da9SMariusz Zaborski 166054f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 166154f98da9SMariusz Zaborski if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) 166254f98da9SMariusz Zaborski nvlist_destroy(value); 166354f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 166454f98da9SMariusz Zaborski return; 166554f98da9SMariusz Zaborski } 166654f98da9SMariusz Zaborski 166754f98da9SMariusz Zaborski nvp = nvpair_move_nvlist(name, value); 166854f98da9SMariusz Zaborski if (nvp == NULL) { 166954f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 167054f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 167154f98da9SMariusz Zaborski } else { 167230740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 167354f98da9SMariusz Zaborski } 167454f98da9SMariusz Zaborski } 167554f98da9SMariusz Zaborski 167654f98da9SMariusz Zaborski #ifndef _KERNEL 167754f98da9SMariusz Zaborski void 167854f98da9SMariusz Zaborski nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value) 167954f98da9SMariusz Zaborski { 168054f98da9SMariusz Zaborski nvpair_t *nvp; 168154f98da9SMariusz Zaborski 168254f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 168354f98da9SMariusz Zaborski close(value); 168454f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 168554f98da9SMariusz Zaborski return; 168654f98da9SMariusz Zaborski } 168754f98da9SMariusz Zaborski 168854f98da9SMariusz Zaborski nvp = nvpair_move_descriptor(name, value); 168954f98da9SMariusz Zaborski if (nvp == NULL) { 169054f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 169154f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 169254f98da9SMariusz Zaborski } else { 169330740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 169454f98da9SMariusz Zaborski } 169554f98da9SMariusz Zaborski } 169654f98da9SMariusz Zaborski #endif 169754f98da9SMariusz Zaborski 169854f98da9SMariusz Zaborski void 169954f98da9SMariusz Zaborski nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size) 170054f98da9SMariusz Zaborski { 170154f98da9SMariusz Zaborski nvpair_t *nvp; 170254f98da9SMariusz Zaborski 170354f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 170454f98da9SMariusz Zaborski nv_free(value); 170554f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 170654f98da9SMariusz Zaborski return; 170754f98da9SMariusz Zaborski } 170854f98da9SMariusz Zaborski 170954f98da9SMariusz Zaborski nvp = nvpair_move_binary(name, value, size); 171054f98da9SMariusz Zaborski if (nvp == NULL) { 171154f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 171254f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 171354f98da9SMariusz Zaborski } else { 171430740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 171554f98da9SMariusz Zaborski } 171654f98da9SMariusz Zaborski } 171754f98da9SMariusz Zaborski 1718347a39b4SMariusz Zaborski void 1719347a39b4SMariusz Zaborski nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value, 1720347a39b4SMariusz Zaborski size_t nitems) 1721347a39b4SMariusz Zaborski { 1722347a39b4SMariusz Zaborski nvpair_t *nvp; 1723347a39b4SMariusz Zaborski 1724347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1725347a39b4SMariusz Zaborski nv_free(value); 1726347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1727347a39b4SMariusz Zaborski return; 1728347a39b4SMariusz Zaborski } 1729347a39b4SMariusz Zaborski 1730347a39b4SMariusz Zaborski nvp = nvpair_move_bool_array(name, value, nitems); 1731347a39b4SMariusz Zaborski if (nvp == NULL) { 1732347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1733347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1734347a39b4SMariusz Zaborski } else { 1735347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1736347a39b4SMariusz Zaborski } 1737347a39b4SMariusz Zaborski } 1738347a39b4SMariusz Zaborski 1739347a39b4SMariusz Zaborski void 1740347a39b4SMariusz Zaborski nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value, 1741347a39b4SMariusz Zaborski size_t nitems) 1742347a39b4SMariusz Zaborski { 1743347a39b4SMariusz Zaborski nvpair_t *nvp; 1744347a39b4SMariusz Zaborski size_t i; 1745347a39b4SMariusz Zaborski 1746347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1747347a39b4SMariusz Zaborski if (value != NULL) { 1748347a39b4SMariusz Zaborski for (i = 0; i < nitems; i++) 1749347a39b4SMariusz Zaborski nv_free(value[i]); 1750347a39b4SMariusz Zaborski nv_free(value); 1751347a39b4SMariusz Zaborski } 1752347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1753347a39b4SMariusz Zaborski return; 1754347a39b4SMariusz Zaborski } 1755347a39b4SMariusz Zaborski 1756347a39b4SMariusz Zaborski nvp = nvpair_move_string_array(name, value, nitems); 1757347a39b4SMariusz Zaborski if (nvp == NULL) { 1758347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1759347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1760347a39b4SMariusz Zaborski } else { 1761347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1762347a39b4SMariusz Zaborski } 1763347a39b4SMariusz Zaborski } 1764347a39b4SMariusz Zaborski 1765347a39b4SMariusz Zaborski void 1766347a39b4SMariusz Zaborski nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value, 1767347a39b4SMariusz Zaborski size_t nitems) 1768347a39b4SMariusz Zaborski { 1769347a39b4SMariusz Zaborski nvpair_t *nvp; 1770347a39b4SMariusz Zaborski size_t i; 1771347a39b4SMariusz Zaborski 1772347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1773347a39b4SMariusz Zaborski if (value != NULL) { 1774347a39b4SMariusz Zaborski for (i = 0; i < nitems; i++) { 1775347a39b4SMariusz Zaborski if (nvlist_get_pararr(value[i], NULL) == NULL) 1776347a39b4SMariusz Zaborski nvlist_destroy(value[i]); 1777347a39b4SMariusz Zaborski } 1778347a39b4SMariusz Zaborski } 1779347a39b4SMariusz Zaborski nv_free(value); 1780347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1781347a39b4SMariusz Zaborski return; 1782347a39b4SMariusz Zaborski } 1783347a39b4SMariusz Zaborski 1784347a39b4SMariusz Zaborski nvp = nvpair_move_nvlist_array(name, value, nitems); 1785347a39b4SMariusz Zaborski if (nvp == NULL) { 1786347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1787347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1788347a39b4SMariusz Zaborski } else { 1789347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1790347a39b4SMariusz Zaborski } 1791347a39b4SMariusz Zaborski } 1792347a39b4SMariusz Zaborski 1793347a39b4SMariusz Zaborski void 1794347a39b4SMariusz Zaborski nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value, 1795347a39b4SMariusz Zaborski size_t nitems) 1796347a39b4SMariusz Zaborski { 1797347a39b4SMariusz Zaborski nvpair_t *nvp; 1798347a39b4SMariusz Zaborski 1799347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1800347a39b4SMariusz Zaborski nv_free(value); 1801347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1802347a39b4SMariusz Zaborski return; 1803347a39b4SMariusz Zaborski } 1804347a39b4SMariusz Zaborski 1805347a39b4SMariusz Zaborski nvp = nvpair_move_number_array(name, value, nitems); 1806347a39b4SMariusz Zaborski if (nvp == NULL) { 1807347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1808347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1809347a39b4SMariusz Zaborski } else { 1810347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1811347a39b4SMariusz Zaborski } 1812347a39b4SMariusz Zaborski } 1813347a39b4SMariusz Zaborski 1814347a39b4SMariusz Zaborski #ifndef _KERNEL 1815347a39b4SMariusz Zaborski void 1816347a39b4SMariusz Zaborski nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value, 1817347a39b4SMariusz Zaborski size_t nitems) 1818347a39b4SMariusz Zaborski { 1819347a39b4SMariusz Zaborski nvpair_t *nvp; 1820347a39b4SMariusz Zaborski size_t i; 1821347a39b4SMariusz Zaborski 1822347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1823347a39b4SMariusz Zaborski if (value != 0) { 1824347a39b4SMariusz Zaborski for (i = 0; i < nitems; i++) 1825347a39b4SMariusz Zaborski close(value[i]); 1826347a39b4SMariusz Zaborski nv_free(value); 1827347a39b4SMariusz Zaborski } 1828347a39b4SMariusz Zaborski 1829347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1830347a39b4SMariusz Zaborski return; 1831347a39b4SMariusz Zaborski } 1832347a39b4SMariusz Zaborski 1833347a39b4SMariusz Zaborski nvp = nvpair_move_descriptor_array(name, value, nitems); 1834347a39b4SMariusz Zaborski if (nvp == NULL) { 1835347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1836347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1837347a39b4SMariusz Zaborski } else { 1838347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1839347a39b4SMariusz Zaborski } 1840347a39b4SMariusz Zaborski } 1841347a39b4SMariusz Zaborski #endif 1842347a39b4SMariusz Zaborski 184354f98da9SMariusz Zaborski const nvpair_t * 184454f98da9SMariusz Zaborski nvlist_get_nvpair(const nvlist_t *nvl, const char *name) 184554f98da9SMariusz Zaborski { 184654f98da9SMariusz Zaborski 184754f98da9SMariusz Zaborski return (nvlist_find(nvl, NV_TYPE_NONE, name)); 184854f98da9SMariusz Zaborski } 184954f98da9SMariusz Zaborski 185054f98da9SMariusz Zaborski #define NVLIST_GET(ftype, type, TYPE) \ 185154f98da9SMariusz Zaborski ftype \ 185254f98da9SMariusz Zaborski nvlist_get_##type(const nvlist_t *nvl, const char *name) \ 185354f98da9SMariusz Zaborski { \ 185454f98da9SMariusz Zaborski const nvpair_t *nvp; \ 185554f98da9SMariusz Zaborski \ 185654f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 185754f98da9SMariusz Zaborski if (nvp == NULL) \ 185854f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE, name); \ 185954f98da9SMariusz Zaborski return (nvpair_get_##type(nvp)); \ 186054f98da9SMariusz Zaborski } 186154f98da9SMariusz Zaborski 186254f98da9SMariusz Zaborski NVLIST_GET(bool, bool, BOOL) 186354f98da9SMariusz Zaborski NVLIST_GET(uint64_t, number, NUMBER) 186454f98da9SMariusz Zaborski NVLIST_GET(const char *, string, STRING) 186554f98da9SMariusz Zaborski NVLIST_GET(const nvlist_t *, nvlist, NVLIST) 186654f98da9SMariusz Zaborski #ifndef _KERNEL 186754f98da9SMariusz Zaborski NVLIST_GET(int, descriptor, DESCRIPTOR) 186854f98da9SMariusz Zaborski #endif 186954f98da9SMariusz Zaborski 187054f98da9SMariusz Zaborski #undef NVLIST_GET 187154f98da9SMariusz Zaborski 187254f98da9SMariusz Zaborski const void * 187354f98da9SMariusz Zaborski nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) 187454f98da9SMariusz Zaborski { 187554f98da9SMariusz Zaborski nvpair_t *nvp; 187654f98da9SMariusz Zaborski 187754f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 187854f98da9SMariusz Zaborski if (nvp == NULL) 187954f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_BINARY, name); 188054f98da9SMariusz Zaborski 188154f98da9SMariusz Zaborski return (nvpair_get_binary(nvp, sizep)); 188254f98da9SMariusz Zaborski } 188354f98da9SMariusz Zaborski 1884347a39b4SMariusz Zaborski #define NVLIST_GET_ARRAY(ftype, type, TYPE) \ 1885347a39b4SMariusz Zaborski ftype \ 1886347a39b4SMariusz Zaborski nvlist_get_##type##_array(const nvlist_t *nvl, const char *name, \ 1887347a39b4SMariusz Zaborski size_t *nitems) \ 1888347a39b4SMariusz Zaborski { \ 1889347a39b4SMariusz Zaborski const nvpair_t *nvp; \ 1890347a39b4SMariusz Zaborski \ 1891347a39b4SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 1892347a39b4SMariusz Zaborski if (nvp == NULL) \ 1893347a39b4SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ 1894347a39b4SMariusz Zaborski return (nvpair_get_##type##_array(nvp, nitems)); \ 1895347a39b4SMariusz Zaborski } 1896347a39b4SMariusz Zaborski 1897347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const bool *, bool, BOOL) 1898347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER) 1899347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const char * const *, string, STRING) 1900347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST) 1901347a39b4SMariusz Zaborski #ifndef _KERNEL 1902347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR) 1903347a39b4SMariusz Zaborski #endif 1904347a39b4SMariusz Zaborski 1905347a39b4SMariusz Zaborski #undef NVLIST_GET_ARRAY 1906347a39b4SMariusz Zaborski 190754f98da9SMariusz Zaborski #define NVLIST_TAKE(ftype, type, TYPE) \ 190854f98da9SMariusz Zaborski ftype \ 190954f98da9SMariusz Zaborski nvlist_take_##type(nvlist_t *nvl, const char *name) \ 191054f98da9SMariusz Zaborski { \ 191154f98da9SMariusz Zaborski nvpair_t *nvp; \ 191254f98da9SMariusz Zaborski ftype value; \ 191354f98da9SMariusz Zaborski \ 191454f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 191554f98da9SMariusz Zaborski if (nvp == NULL) \ 191654f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE, name); \ 191754f98da9SMariusz Zaborski value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ 191854f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); \ 191954f98da9SMariusz Zaborski nvpair_free_structure(nvp); \ 192054f98da9SMariusz Zaborski return (value); \ 192154f98da9SMariusz Zaborski } 192254f98da9SMariusz Zaborski 192354f98da9SMariusz Zaborski NVLIST_TAKE(bool, bool, BOOL) 192454f98da9SMariusz Zaborski NVLIST_TAKE(uint64_t, number, NUMBER) 192554f98da9SMariusz Zaborski NVLIST_TAKE(char *, string, STRING) 192654f98da9SMariusz Zaborski NVLIST_TAKE(nvlist_t *, nvlist, NVLIST) 192754f98da9SMariusz Zaborski #ifndef _KERNEL 192854f98da9SMariusz Zaborski NVLIST_TAKE(int, descriptor, DESCRIPTOR) 192954f98da9SMariusz Zaborski #endif 193054f98da9SMariusz Zaborski 193154f98da9SMariusz Zaborski #undef NVLIST_TAKE 193254f98da9SMariusz Zaborski 193354f98da9SMariusz Zaborski void * 193454f98da9SMariusz Zaborski nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) 193554f98da9SMariusz Zaborski { 193654f98da9SMariusz Zaborski nvpair_t *nvp; 193754f98da9SMariusz Zaborski void *value; 193854f98da9SMariusz Zaborski 193954f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 194054f98da9SMariusz Zaborski if (nvp == NULL) 194154f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_BINARY, name); 194254f98da9SMariusz Zaborski 194354f98da9SMariusz Zaborski value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); 194454f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); 194554f98da9SMariusz Zaborski nvpair_free_structure(nvp); 194654f98da9SMariusz Zaborski return (value); 194754f98da9SMariusz Zaborski } 194854f98da9SMariusz Zaborski 1949347a39b4SMariusz Zaborski #define NVLIST_TAKE_ARRAY(ftype, type, TYPE) \ 1950347a39b4SMariusz Zaborski ftype \ 1951347a39b4SMariusz Zaborski nvlist_take_##type##_array(nvlist_t *nvl, const char *name, \ 1952347a39b4SMariusz Zaborski size_t *nitems) \ 1953347a39b4SMariusz Zaborski { \ 1954347a39b4SMariusz Zaborski nvpair_t *nvp; \ 1955347a39b4SMariusz Zaborski ftype value; \ 1956347a39b4SMariusz Zaborski \ 1957347a39b4SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 1958347a39b4SMariusz Zaborski if (nvp == NULL) \ 1959347a39b4SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ 1960347a39b4SMariusz Zaborski value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\ 1961347a39b4SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); \ 1962347a39b4SMariusz Zaborski nvpair_free_structure(nvp); \ 1963347a39b4SMariusz Zaborski return (value); \ 1964347a39b4SMariusz Zaborski } 1965347a39b4SMariusz Zaborski 1966347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(bool *, bool, BOOL) 1967347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER) 1968347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(char **, string, STRING) 1969347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST) 1970347a39b4SMariusz Zaborski #ifndef _KERNEL 1971347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR) 1972347a39b4SMariusz Zaborski #endif 1973347a39b4SMariusz Zaborski 197454f98da9SMariusz Zaborski void 197554f98da9SMariusz Zaborski nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) 197654f98da9SMariusz Zaborski { 197754f98da9SMariusz Zaborski 197854f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 197954f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 198054f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 198154f98da9SMariusz Zaborski 198254f98da9SMariusz Zaborski nvpair_remove(&nvl->nvl_head, nvp, nvl); 198354f98da9SMariusz Zaborski } 198454f98da9SMariusz Zaborski 198554f98da9SMariusz Zaborski void 198654f98da9SMariusz Zaborski nvlist_free(nvlist_t *nvl, const char *name) 198754f98da9SMariusz Zaborski { 198854f98da9SMariusz Zaborski 198954f98da9SMariusz Zaborski nvlist_free_type(nvl, name, NV_TYPE_NONE); 199054f98da9SMariusz Zaborski } 199154f98da9SMariusz Zaborski 199254f98da9SMariusz Zaborski #define NVLIST_FREE(type, TYPE) \ 199354f98da9SMariusz Zaborski void \ 199454f98da9SMariusz Zaborski nvlist_free_##type(nvlist_t *nvl, const char *name) \ 199554f98da9SMariusz Zaborski { \ 199654f98da9SMariusz Zaborski \ 199754f98da9SMariusz Zaborski nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ 199854f98da9SMariusz Zaborski } 199954f98da9SMariusz Zaborski 200054f98da9SMariusz Zaborski NVLIST_FREE(null, NULL) 200154f98da9SMariusz Zaborski NVLIST_FREE(bool, BOOL) 200254f98da9SMariusz Zaborski NVLIST_FREE(number, NUMBER) 200354f98da9SMariusz Zaborski NVLIST_FREE(string, STRING) 200454f98da9SMariusz Zaborski NVLIST_FREE(nvlist, NVLIST) 2005347a39b4SMariusz Zaborski NVLIST_FREE(binary, BINARY) 2006347a39b4SMariusz Zaborski NVLIST_FREE(bool_array, BOOL_ARRAY) 2007347a39b4SMariusz Zaborski NVLIST_FREE(number_array, NUMBER_ARRAY) 2008347a39b4SMariusz Zaborski NVLIST_FREE(string_array, STRING_ARRAY) 2009347a39b4SMariusz Zaborski NVLIST_FREE(nvlist_array, NVLIST_ARRAY) 201054f98da9SMariusz Zaborski #ifndef _KERNEL 201154f98da9SMariusz Zaborski NVLIST_FREE(descriptor, DESCRIPTOR) 2012347a39b4SMariusz Zaborski NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY) 201354f98da9SMariusz Zaborski #endif 201454f98da9SMariusz Zaborski 201554f98da9SMariusz Zaborski #undef NVLIST_FREE 201654f98da9SMariusz Zaborski 201754f98da9SMariusz Zaborski void 201854f98da9SMariusz Zaborski nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) 201954f98da9SMariusz Zaborski { 202054f98da9SMariusz Zaborski 202154f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 202254f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 202354f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 202454f98da9SMariusz Zaborski 202554f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); 202654f98da9SMariusz Zaborski nvpair_free(nvp); 202754f98da9SMariusz Zaborski } 202854f98da9SMariusz Zaborski 2029