154f98da9SMariusz Zaborski /*- 254f98da9SMariusz Zaborski * Copyright (c) 2009-2013 The FreeBSD Foundation 3347a39b4SMariusz Zaborski * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org> 454f98da9SMariusz Zaborski * All rights reserved. 554f98da9SMariusz Zaborski * 654f98da9SMariusz Zaborski * This software was developed by Pawel Jakub Dawidek under sponsorship from 754f98da9SMariusz Zaborski * the FreeBSD Foundation. 854f98da9SMariusz Zaborski * 954f98da9SMariusz Zaborski * Redistribution and use in source and binary forms, with or without 1054f98da9SMariusz Zaborski * modification, are permitted provided that the following conditions 1154f98da9SMariusz Zaborski * are met: 1254f98da9SMariusz Zaborski * 1. Redistributions of source code must retain the above copyright 1354f98da9SMariusz Zaborski * notice, this list of conditions and the following disclaimer. 1454f98da9SMariusz Zaborski * 2. Redistributions in binary form must reproduce the above copyright 1554f98da9SMariusz Zaborski * notice, this list of conditions and the following disclaimer in the 1654f98da9SMariusz Zaborski * documentation and/or other materials provided with the distribution. 1754f98da9SMariusz Zaborski * 1854f98da9SMariusz Zaborski * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1954f98da9SMariusz Zaborski * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2054f98da9SMariusz Zaborski * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2154f98da9SMariusz Zaborski * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2254f98da9SMariusz Zaborski * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2354f98da9SMariusz Zaborski * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2454f98da9SMariusz Zaborski * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2554f98da9SMariusz Zaborski * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2654f98da9SMariusz Zaborski * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2754f98da9SMariusz Zaborski * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2854f98da9SMariusz Zaborski * SUCH DAMAGE. 2954f98da9SMariusz Zaborski */ 3054f98da9SMariusz Zaborski 3154f98da9SMariusz Zaborski #include <sys/cdefs.h> 3254f98da9SMariusz Zaborski __FBSDID("$FreeBSD$"); 3354f98da9SMariusz Zaborski 3454f98da9SMariusz Zaborski #include <sys/param.h> 3554f98da9SMariusz Zaborski #include <sys/endian.h> 3654f98da9SMariusz Zaborski #include <sys/queue.h> 3754f98da9SMariusz Zaborski 3854f98da9SMariusz Zaborski #ifdef _KERNEL 3954f98da9SMariusz Zaborski 4054f98da9SMariusz Zaborski #include <sys/errno.h> 4154f98da9SMariusz Zaborski #include <sys/kernel.h> 4254f98da9SMariusz Zaborski #include <sys/lock.h> 4354f98da9SMariusz Zaborski #include <sys/malloc.h> 4454f98da9SMariusz Zaborski #include <sys/systm.h> 4554f98da9SMariusz Zaborski 4654f98da9SMariusz Zaborski #include <machine/stdarg.h> 4754f98da9SMariusz Zaborski 4854f98da9SMariusz Zaborski #else 4954f98da9SMariusz Zaborski #include <sys/socket.h> 5054f98da9SMariusz Zaborski 5154f98da9SMariusz Zaborski #include <errno.h> 5254f98da9SMariusz Zaborski #include <stdarg.h> 5354f98da9SMariusz Zaborski #include <stdbool.h> 5454f98da9SMariusz Zaborski #include <stdint.h> 5554f98da9SMariusz Zaborski #define _WITH_DPRINTF 5654f98da9SMariusz Zaborski #include <stdio.h> 5754f98da9SMariusz Zaborski #include <stdlib.h> 5854f98da9SMariusz Zaborski #include <string.h> 5954f98da9SMariusz Zaborski #include <unistd.h> 6054f98da9SMariusz Zaborski 6154f98da9SMariusz Zaborski #include "msgio.h" 6254f98da9SMariusz Zaborski #endif 6354f98da9SMariusz Zaborski 6454f98da9SMariusz Zaborski #ifdef HAVE_PJDLOG 6554f98da9SMariusz Zaborski #include <pjdlog.h> 6654f98da9SMariusz Zaborski #endif 6754f98da9SMariusz Zaborski 6854f98da9SMariusz Zaborski #include <sys/nv.h> 6954f98da9SMariusz Zaborski 7054f98da9SMariusz Zaborski #include "nv_impl.h" 7154f98da9SMariusz Zaborski #include "nvlist_impl.h" 7254f98da9SMariusz Zaborski #include "nvpair_impl.h" 7354f98da9SMariusz Zaborski 7454f98da9SMariusz Zaborski #ifndef HAVE_PJDLOG 7554f98da9SMariusz Zaborski #ifdef _KERNEL 7654f98da9SMariusz Zaborski #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) 7754f98da9SMariusz Zaborski #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) 7854f98da9SMariusz Zaborski #define PJDLOG_ABORT(...) panic(__VA_ARGS__) 7954f98da9SMariusz Zaborski #else 8054f98da9SMariusz Zaborski #include <assert.h> 8154f98da9SMariusz Zaborski #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 8254f98da9SMariusz Zaborski #define PJDLOG_RASSERT(expr, ...) assert(expr) 8354f98da9SMariusz Zaborski #define PJDLOG_ABORT(...) do { \ 8454f98da9SMariusz Zaborski fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \ 8554f98da9SMariusz Zaborski fprintf(stderr, __VA_ARGS__); \ 8654f98da9SMariusz Zaborski fprintf(stderr, "\n"); \ 8754f98da9SMariusz Zaborski abort(); \ 8854f98da9SMariusz Zaborski } while (0) 8954f98da9SMariusz Zaborski #endif 9054f98da9SMariusz Zaborski #endif 9154f98da9SMariusz Zaborski 92347a39b4SMariusz Zaborski #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN | NV_FLAG_IN_ARRAY) 9354f98da9SMariusz Zaborski #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE) 9454f98da9SMariusz Zaborski #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK) 9554f98da9SMariusz Zaborski 9654f98da9SMariusz Zaborski #define NVLIST_MAGIC 0x6e766c /* "nvl" */ 9754f98da9SMariusz Zaborski struct nvlist { 9854f98da9SMariusz Zaborski int nvl_magic; 9954f98da9SMariusz Zaborski int nvl_error; 10054f98da9SMariusz Zaborski int nvl_flags; 10154f98da9SMariusz Zaborski nvpair_t *nvl_parent; 102347a39b4SMariusz Zaborski nvpair_t *nvl_array_next; 10354f98da9SMariusz Zaborski struct nvl_head nvl_head; 10454f98da9SMariusz Zaborski }; 10554f98da9SMariusz Zaborski 10654f98da9SMariusz Zaborski #define NVLIST_ASSERT(nvl) do { \ 10754f98da9SMariusz Zaborski PJDLOG_ASSERT((nvl) != NULL); \ 10854f98da9SMariusz Zaborski PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \ 10954f98da9SMariusz Zaborski } while (0) 11054f98da9SMariusz Zaborski 11154f98da9SMariusz Zaborski #ifdef _KERNEL 11254f98da9SMariusz Zaborski MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist"); 11354f98da9SMariusz Zaborski #endif 11454f98da9SMariusz Zaborski 11554f98da9SMariusz Zaborski #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp) 11654f98da9SMariusz Zaborski 11754f98da9SMariusz Zaborski #define NVLIST_HEADER_MAGIC 0x6c 11854f98da9SMariusz Zaborski #define NVLIST_HEADER_VERSION 0x00 11954f98da9SMariusz Zaborski struct nvlist_header { 12054f98da9SMariusz Zaborski uint8_t nvlh_magic; 12154f98da9SMariusz Zaborski uint8_t nvlh_version; 12254f98da9SMariusz Zaborski uint8_t nvlh_flags; 12354f98da9SMariusz Zaborski uint64_t nvlh_descriptors; 12454f98da9SMariusz Zaborski uint64_t nvlh_size; 12554f98da9SMariusz Zaborski } __packed; 12654f98da9SMariusz Zaborski 12754f98da9SMariusz Zaborski nvlist_t * 12854f98da9SMariusz Zaborski nvlist_create(int flags) 12954f98da9SMariusz Zaborski { 13054f98da9SMariusz Zaborski nvlist_t *nvl; 13154f98da9SMariusz Zaborski 13254f98da9SMariusz Zaborski PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 13354f98da9SMariusz Zaborski 13454f98da9SMariusz Zaborski nvl = nv_malloc(sizeof(*nvl)); 13554f98da9SMariusz Zaborski if (nvl == NULL) 13654f98da9SMariusz Zaborski return (NULL); 13754f98da9SMariusz Zaborski nvl->nvl_error = 0; 13854f98da9SMariusz Zaborski nvl->nvl_flags = flags; 13954f98da9SMariusz Zaborski nvl->nvl_parent = NULL; 140347a39b4SMariusz Zaborski nvl->nvl_array_next = NULL; 14154f98da9SMariusz Zaborski TAILQ_INIT(&nvl->nvl_head); 14254f98da9SMariusz Zaborski nvl->nvl_magic = NVLIST_MAGIC; 14354f98da9SMariusz Zaborski 14454f98da9SMariusz Zaborski return (nvl); 14554f98da9SMariusz Zaborski } 14654f98da9SMariusz Zaborski 14754f98da9SMariusz Zaborski void 14854f98da9SMariusz Zaborski nvlist_destroy(nvlist_t *nvl) 14954f98da9SMariusz Zaborski { 15054f98da9SMariusz Zaborski nvpair_t *nvp; 15154f98da9SMariusz Zaborski 15254f98da9SMariusz Zaborski if (nvl == NULL) 15354f98da9SMariusz Zaborski return; 15454f98da9SMariusz Zaborski 15554f98da9SMariusz Zaborski ERRNO_SAVE(); 15654f98da9SMariusz Zaborski 15754f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 15854f98da9SMariusz Zaborski 15954f98da9SMariusz Zaborski while ((nvp = nvlist_first_nvpair(nvl)) != NULL) { 16054f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); 16154f98da9SMariusz Zaborski nvpair_free(nvp); 16254f98da9SMariusz Zaborski } 163347a39b4SMariusz Zaborski if (nvl->nvl_array_next != NULL) 164347a39b4SMariusz Zaborski nvpair_free_structure(nvl->nvl_array_next); 165347a39b4SMariusz Zaborski nvl->nvl_array_next = NULL; 166347a39b4SMariusz Zaborski nvl->nvl_parent = NULL; 16754f98da9SMariusz Zaborski nvl->nvl_magic = 0; 16854f98da9SMariusz Zaborski nv_free(nvl); 16954f98da9SMariusz Zaborski 17054f98da9SMariusz Zaborski ERRNO_RESTORE(); 17154f98da9SMariusz Zaborski } 17254f98da9SMariusz Zaborski 17354f98da9SMariusz Zaborski void 17454f98da9SMariusz Zaborski nvlist_set_error(nvlist_t *nvl, int error) 17554f98da9SMariusz Zaborski { 17654f98da9SMariusz Zaborski 17754f98da9SMariusz Zaborski PJDLOG_ASSERT(error != 0); 17854f98da9SMariusz Zaborski 17954f98da9SMariusz Zaborski /* 18054f98da9SMariusz Zaborski * Check for error != 0 so that we don't do the wrong thing if somebody 18154f98da9SMariusz Zaborski * tries to abuse this API when asserts are disabled. 18254f98da9SMariusz Zaborski */ 18354f98da9SMariusz Zaborski if (nvl != NULL && error != 0 && nvl->nvl_error == 0) 18454f98da9SMariusz Zaborski nvl->nvl_error = error; 18554f98da9SMariusz Zaborski } 18654f98da9SMariusz Zaborski 18754f98da9SMariusz Zaborski int 18854f98da9SMariusz Zaborski nvlist_error(const nvlist_t *nvl) 18954f98da9SMariusz Zaborski { 19054f98da9SMariusz Zaborski 19154f98da9SMariusz Zaborski if (nvl == NULL) 19254f98da9SMariusz Zaborski return (ENOMEM); 19354f98da9SMariusz Zaborski 19454f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 19554f98da9SMariusz Zaborski 19654f98da9SMariusz Zaborski return (nvl->nvl_error); 19754f98da9SMariusz Zaborski } 19854f98da9SMariusz Zaborski 19954f98da9SMariusz Zaborski nvpair_t * 20054f98da9SMariusz Zaborski nvlist_get_nvpair_parent(const nvlist_t *nvl) 20154f98da9SMariusz Zaborski { 20254f98da9SMariusz Zaborski 20354f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 20454f98da9SMariusz Zaborski 20554f98da9SMariusz Zaborski return (nvl->nvl_parent); 20654f98da9SMariusz Zaborski } 20754f98da9SMariusz Zaborski 20854f98da9SMariusz Zaborski const nvlist_t * 20954f98da9SMariusz Zaborski nvlist_get_parent(const nvlist_t *nvl, void **cookiep) 21054f98da9SMariusz Zaborski { 21154f98da9SMariusz Zaborski nvpair_t *nvp; 21254f98da9SMariusz Zaborski 21354f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 21454f98da9SMariusz Zaborski 21554f98da9SMariusz Zaborski nvp = nvl->nvl_parent; 21654f98da9SMariusz Zaborski if (cookiep != NULL) 21754f98da9SMariusz Zaborski *cookiep = nvp; 21854f98da9SMariusz Zaborski if (nvp == NULL) 21954f98da9SMariusz Zaborski return (NULL); 22054f98da9SMariusz Zaborski 22154f98da9SMariusz Zaborski return (nvpair_nvlist(nvp)); 22254f98da9SMariusz Zaborski } 22354f98da9SMariusz Zaborski 22454f98da9SMariusz Zaborski void 22554f98da9SMariusz Zaborski nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent) 22654f98da9SMariusz Zaborski { 22754f98da9SMariusz Zaborski 22854f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 22954f98da9SMariusz Zaborski 23054f98da9SMariusz Zaborski nvl->nvl_parent = parent; 23154f98da9SMariusz Zaborski } 23254f98da9SMariusz Zaborski 233347a39b4SMariusz Zaborski void 234347a39b4SMariusz Zaborski nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele) 235347a39b4SMariusz Zaborski { 236347a39b4SMariusz Zaborski 237347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 238347a39b4SMariusz Zaborski 2391b550329SMariusz Zaborski if (ele != NULL) { 240347a39b4SMariusz Zaborski nvl->nvl_flags |= NV_FLAG_IN_ARRAY; 2411b550329SMariusz Zaborski } else { 242347a39b4SMariusz Zaborski nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY; 2431b550329SMariusz Zaborski nv_free(nvl->nvl_array_next); 2441b550329SMariusz Zaborski } 245347a39b4SMariusz Zaborski 246347a39b4SMariusz Zaborski nvl->nvl_array_next = ele; 247347a39b4SMariusz Zaborski } 248347a39b4SMariusz Zaborski 249347a39b4SMariusz Zaborski bool 250347a39b4SMariusz Zaborski nvlist_in_array(const nvlist_t *nvl) 251347a39b4SMariusz Zaborski { 252347a39b4SMariusz Zaborski 253347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 254347a39b4SMariusz Zaborski 255347a39b4SMariusz Zaborski return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0); 256347a39b4SMariusz Zaborski } 257347a39b4SMariusz Zaborski 258347a39b4SMariusz Zaborski const nvlist_t * 259347a39b4SMariusz Zaborski nvlist_get_array_next(const nvlist_t *nvl) 260347a39b4SMariusz Zaborski { 261347a39b4SMariusz Zaborski nvpair_t *nvp; 262347a39b4SMariusz Zaborski 263347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 264347a39b4SMariusz Zaborski 265347a39b4SMariusz Zaborski nvp = nvl->nvl_array_next; 266347a39b4SMariusz Zaborski if (nvp == NULL) 267347a39b4SMariusz Zaborski return (NULL); 268347a39b4SMariusz Zaborski 269347a39b4SMariusz Zaborski return (nvpair_get_nvlist(nvp)); 270347a39b4SMariusz Zaborski } 271347a39b4SMariusz Zaborski 272347a39b4SMariusz Zaborski const nvlist_t * 273347a39b4SMariusz Zaborski nvlist_get_pararr(const nvlist_t *nvl, void **cookiep) 274347a39b4SMariusz Zaborski { 275347a39b4SMariusz Zaborski const nvlist_t *ret; 276347a39b4SMariusz Zaborski 277347a39b4SMariusz Zaborski ret = nvlist_get_array_next(nvl); 278347a39b4SMariusz Zaborski if (ret != NULL) { 279347a39b4SMariusz Zaborski if (cookiep != NULL) 280347a39b4SMariusz Zaborski *cookiep = NULL; 281347a39b4SMariusz Zaborski return (ret); 282347a39b4SMariusz Zaborski } 283347a39b4SMariusz Zaborski 284347a39b4SMariusz Zaborski ret = nvlist_get_parent(nvl, cookiep); 285347a39b4SMariusz Zaborski return (ret); 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 31854f98da9SMariusz Zaborski static 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 { 71254f98da9SMariusz Zaborski nvpair_t *nvp; 71354f98da9SMariusz Zaborski const char *name; 71454f98da9SMariusz Zaborski int type; 71554f98da9SMariusz Zaborski 71654f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 71754f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 71854f98da9SMariusz Zaborski 71954f98da9SMariusz Zaborski nvp = NULL; 72054f98da9SMariusz Zaborski do { 72154f98da9SMariusz Zaborski while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) { 72254f98da9SMariusz Zaborski switch (type) { 72354f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 72454f98da9SMariusz Zaborski *descs = nvpair_get_descriptor(nvp); 72554f98da9SMariusz Zaborski descs++; 72654f98da9SMariusz Zaborski break; 727347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 728347a39b4SMariusz Zaborski { 729347a39b4SMariusz Zaborski const int *value; 730347a39b4SMariusz Zaborski size_t nitems; 731347a39b4SMariusz Zaborski unsigned int ii; 732347a39b4SMariusz Zaborski 733347a39b4SMariusz Zaborski value = nvpair_get_descriptor_array(nvp, 734347a39b4SMariusz Zaborski &nitems); 735347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 736347a39b4SMariusz Zaborski *descs = value[ii]; 737347a39b4SMariusz Zaborski descs++; 738347a39b4SMariusz Zaborski } 739347a39b4SMariusz Zaborski break; 740347a39b4SMariusz Zaborski } 74154f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 74254f98da9SMariusz Zaborski nvl = nvpair_get_nvlist(nvp); 74354f98da9SMariusz Zaborski nvp = NULL; 74454f98da9SMariusz Zaborski break; 745347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 746347a39b4SMariusz Zaborski { 747347a39b4SMariusz Zaborski const nvlist_t * const *value; 748347a39b4SMariusz Zaborski size_t nitems; 749347a39b4SMariusz Zaborski 750347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 751347a39b4SMariusz Zaborski PJDLOG_ASSERT(value != NULL); 752347a39b4SMariusz Zaborski PJDLOG_ASSERT(nitems > 0); 753347a39b4SMariusz Zaborski 754347a39b4SMariusz Zaborski nvl = value[0]; 755347a39b4SMariusz Zaborski nvp = NULL; 756347a39b4SMariusz Zaborski break; 75754f98da9SMariusz Zaborski } 75854f98da9SMariusz Zaborski } 759347a39b4SMariusz Zaborski } 760347a39b4SMariusz Zaborski } while ((nvl = nvlist_get_pararr(nvl, (void**)&nvp)) != NULL); 76154f98da9SMariusz Zaborski 76254f98da9SMariusz Zaborski return (descs); 76354f98da9SMariusz Zaborski } 76454f98da9SMariusz Zaborski #endif 76554f98da9SMariusz Zaborski 76654f98da9SMariusz Zaborski #ifndef _KERNEL 76754f98da9SMariusz Zaborski int * 76854f98da9SMariusz Zaborski nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp) 76954f98da9SMariusz Zaborski { 77054f98da9SMariusz Zaborski size_t nitems; 77154f98da9SMariusz Zaborski int *fds; 77254f98da9SMariusz Zaborski 77354f98da9SMariusz Zaborski nitems = nvlist_ndescriptors(nvl); 77454f98da9SMariusz Zaborski fds = nv_malloc(sizeof(fds[0]) * (nitems + 1)); 77554f98da9SMariusz Zaborski if (fds == NULL) 77654f98da9SMariusz Zaborski return (NULL); 77754f98da9SMariusz Zaborski if (nitems > 0) 77854f98da9SMariusz Zaborski nvlist_xdescriptors(nvl, fds); 77954f98da9SMariusz Zaborski fds[nitems] = -1; 78054f98da9SMariusz Zaborski if (nitemsp != NULL) 78154f98da9SMariusz Zaborski *nitemsp = nitems; 78254f98da9SMariusz Zaborski return (fds); 78354f98da9SMariusz Zaborski } 78454f98da9SMariusz Zaborski #endif 78554f98da9SMariusz Zaborski 78654f98da9SMariusz Zaborski size_t 78754f98da9SMariusz Zaborski nvlist_ndescriptors(const nvlist_t *nvl) 78854f98da9SMariusz Zaborski { 78954f98da9SMariusz Zaborski #ifndef _KERNEL 79054f98da9SMariusz Zaborski nvpair_t *nvp; 79154f98da9SMariusz Zaborski const char *name; 79254f98da9SMariusz Zaborski size_t ndescs; 79354f98da9SMariusz Zaborski int type; 79454f98da9SMariusz Zaborski 79554f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 79654f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 79754f98da9SMariusz Zaborski 79854f98da9SMariusz Zaborski ndescs = 0; 79954f98da9SMariusz Zaborski nvp = NULL; 80054f98da9SMariusz Zaborski do { 80154f98da9SMariusz Zaborski while ((name = nvlist_next(nvl, &type, (void**)&nvp)) != NULL) { 80254f98da9SMariusz Zaborski switch (type) { 80354f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 80454f98da9SMariusz Zaborski ndescs++; 80554f98da9SMariusz Zaborski break; 80654f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 80754f98da9SMariusz Zaborski nvl = nvpair_get_nvlist(nvp); 80854f98da9SMariusz Zaborski nvp = NULL; 80954f98da9SMariusz Zaborski break; 810347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 811347a39b4SMariusz Zaborski { 812347a39b4SMariusz Zaborski const nvlist_t * const *value; 813347a39b4SMariusz Zaborski size_t nitems; 814347a39b4SMariusz Zaborski 815347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 816347a39b4SMariusz Zaborski PJDLOG_ASSERT(value != NULL); 817347a39b4SMariusz Zaborski PJDLOG_ASSERT(nitems > 0); 818347a39b4SMariusz Zaborski 819347a39b4SMariusz Zaborski nvl = value[0]; 820347a39b4SMariusz Zaborski nvp = NULL; 821347a39b4SMariusz Zaborski break; 822347a39b4SMariusz Zaborski } 823347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 824347a39b4SMariusz Zaborski { 825347a39b4SMariusz Zaborski size_t nitems; 826347a39b4SMariusz Zaborski 827347a39b4SMariusz Zaborski (void)nvpair_get_descriptor_array(nvp, 828347a39b4SMariusz Zaborski &nitems); 829347a39b4SMariusz Zaborski ndescs += nitems; 830347a39b4SMariusz Zaborski break; 83154f98da9SMariusz Zaborski } 83254f98da9SMariusz Zaborski } 833347a39b4SMariusz Zaborski } 834347a39b4SMariusz Zaborski } while ((nvl = nvlist_get_pararr(nvl, (void**)&nvp)) != NULL); 83554f98da9SMariusz Zaborski 83654f98da9SMariusz Zaborski return (ndescs); 83754f98da9SMariusz Zaborski #else 83854f98da9SMariusz Zaborski return (0); 83954f98da9SMariusz Zaborski #endif 84054f98da9SMariusz Zaborski } 84154f98da9SMariusz Zaborski 84254f98da9SMariusz Zaborski static unsigned char * 84354f98da9SMariusz Zaborski nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp) 84454f98da9SMariusz Zaborski { 84554f98da9SMariusz Zaborski struct nvlist_header nvlhdr; 84654f98da9SMariusz Zaborski 84754f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 84854f98da9SMariusz Zaborski 84954f98da9SMariusz Zaborski nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC; 85054f98da9SMariusz Zaborski nvlhdr.nvlh_version = NVLIST_HEADER_VERSION; 85154f98da9SMariusz Zaborski nvlhdr.nvlh_flags = nvl->nvl_flags; 85254f98da9SMariusz Zaborski #if BYTE_ORDER == BIG_ENDIAN 85354f98da9SMariusz Zaborski nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN; 85454f98da9SMariusz Zaborski #endif 85554f98da9SMariusz Zaborski nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl); 85654f98da9SMariusz Zaborski nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr); 85754f98da9SMariusz Zaborski PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr)); 85854f98da9SMariusz Zaborski memcpy(ptr, &nvlhdr, sizeof(nvlhdr)); 85954f98da9SMariusz Zaborski ptr += sizeof(nvlhdr); 86054f98da9SMariusz Zaborski *leftp -= sizeof(nvlhdr); 86154f98da9SMariusz Zaborski 86254f98da9SMariusz Zaborski return (ptr); 86354f98da9SMariusz Zaborski } 86454f98da9SMariusz Zaborski 86554f98da9SMariusz Zaborski static void * 86654f98da9SMariusz Zaborski nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) 86754f98da9SMariusz Zaborski { 86854f98da9SMariusz Zaborski unsigned char *buf, *ptr; 86954f98da9SMariusz Zaborski size_t left, size; 87054f98da9SMariusz Zaborski const nvlist_t *tmpnvl; 87154f98da9SMariusz Zaborski nvpair_t *nvp, *tmpnvp; 87254f98da9SMariusz Zaborski void *cookie; 87354f98da9SMariusz Zaborski 87454f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 87554f98da9SMariusz Zaborski 87654f98da9SMariusz Zaborski if (nvl->nvl_error != 0) { 87754f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 87854f98da9SMariusz Zaborski return (NULL); 87954f98da9SMariusz Zaborski } 88054f98da9SMariusz Zaborski 88154f98da9SMariusz Zaborski size = nvlist_size(nvl); 88254f98da9SMariusz Zaborski buf = nv_malloc(size); 88354f98da9SMariusz Zaborski if (buf == NULL) 88454f98da9SMariusz Zaborski return (NULL); 88554f98da9SMariusz Zaborski 88654f98da9SMariusz Zaborski ptr = buf; 88754f98da9SMariusz Zaborski left = size; 88854f98da9SMariusz Zaborski 88954f98da9SMariusz Zaborski ptr = nvlist_pack_header(nvl, ptr, &left); 89054f98da9SMariusz Zaborski 89154f98da9SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 89254f98da9SMariusz Zaborski while (nvp != NULL) { 89354f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 89454f98da9SMariusz Zaborski 89554f98da9SMariusz Zaborski nvpair_init_datasize(nvp); 89654f98da9SMariusz Zaborski ptr = nvpair_pack_header(nvp, ptr, &left); 897c68f8061SMariusz Zaborski if (ptr == NULL) 898c68f8061SMariusz Zaborski goto fail; 89954f98da9SMariusz Zaborski switch (nvpair_type(nvp)) { 90054f98da9SMariusz Zaborski case NV_TYPE_NULL: 90154f98da9SMariusz Zaborski ptr = nvpair_pack_null(nvp, ptr, &left); 90254f98da9SMariusz Zaborski break; 90354f98da9SMariusz Zaborski case NV_TYPE_BOOL: 90454f98da9SMariusz Zaborski ptr = nvpair_pack_bool(nvp, ptr, &left); 90554f98da9SMariusz Zaborski break; 90654f98da9SMariusz Zaborski case NV_TYPE_NUMBER: 90754f98da9SMariusz Zaborski ptr = nvpair_pack_number(nvp, ptr, &left); 90854f98da9SMariusz Zaborski break; 90954f98da9SMariusz Zaborski case NV_TYPE_STRING: 91054f98da9SMariusz Zaborski ptr = nvpair_pack_string(nvp, ptr, &left); 91154f98da9SMariusz Zaborski break; 91254f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 91354f98da9SMariusz Zaborski tmpnvl = nvpair_get_nvlist(nvp); 91454f98da9SMariusz Zaborski ptr = nvlist_pack_header(tmpnvl, ptr, &left); 91554f98da9SMariusz Zaborski if (ptr == NULL) 916c68f8061SMariusz Zaborski goto fail; 91754f98da9SMariusz Zaborski tmpnvp = nvlist_first_nvpair(tmpnvl); 91854f98da9SMariusz Zaborski if (tmpnvp != NULL) { 91954f98da9SMariusz Zaborski nvl = tmpnvl; 92054f98da9SMariusz Zaborski nvp = tmpnvp; 92154f98da9SMariusz Zaborski continue; 92254f98da9SMariusz Zaborski } 92354f98da9SMariusz Zaborski ptr = nvpair_pack_nvlist_up(ptr, &left); 92454f98da9SMariusz Zaborski break; 92554f98da9SMariusz Zaborski #ifndef _KERNEL 92654f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 92754f98da9SMariusz Zaborski ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left); 92854f98da9SMariusz Zaborski break; 929347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 930347a39b4SMariusz Zaborski ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp, 931347a39b4SMariusz Zaborski &left); 932347a39b4SMariusz Zaborski break; 93354f98da9SMariusz Zaborski #endif 93454f98da9SMariusz Zaborski case NV_TYPE_BINARY: 93554f98da9SMariusz Zaborski ptr = nvpair_pack_binary(nvp, ptr, &left); 93654f98da9SMariusz Zaborski break; 937347a39b4SMariusz Zaborski case NV_TYPE_BOOL_ARRAY: 938347a39b4SMariusz Zaborski ptr = nvpair_pack_bool_array(nvp, ptr, &left); 939347a39b4SMariusz Zaborski break; 940347a39b4SMariusz Zaborski case NV_TYPE_NUMBER_ARRAY: 941347a39b4SMariusz Zaborski ptr = nvpair_pack_number_array(nvp, ptr, &left); 942347a39b4SMariusz Zaborski break; 943347a39b4SMariusz Zaborski case NV_TYPE_STRING_ARRAY: 944347a39b4SMariusz Zaborski ptr = nvpair_pack_string_array(nvp, ptr, &left); 945347a39b4SMariusz Zaborski break; 946347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 947347a39b4SMariusz Zaborski { 948347a39b4SMariusz Zaborski const nvlist_t * const * value; 949347a39b4SMariusz Zaborski size_t nitems; 950347a39b4SMariusz Zaborski unsigned int ii; 951347a39b4SMariusz Zaborski 952347a39b4SMariusz Zaborski tmpnvl = NULL; 953347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 954347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 955347a39b4SMariusz Zaborski ptr = nvlist_pack_header(value[ii], ptr, &left); 956347a39b4SMariusz Zaborski if (ptr == NULL) 957347a39b4SMariusz Zaborski goto out; 958347a39b4SMariusz Zaborski tmpnvp = nvlist_first_nvpair(value[ii]); 959347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 960347a39b4SMariusz Zaborski tmpnvl = value[ii]; 961347a39b4SMariusz Zaborski break; 962347a39b4SMariusz Zaborski } 963347a39b4SMariusz Zaborski ptr = nvpair_pack_nvlist_array_next(ptr, &left); 964347a39b4SMariusz Zaborski if (ptr == NULL) 965347a39b4SMariusz Zaborski goto out; 966347a39b4SMariusz Zaborski } 967347a39b4SMariusz Zaborski if (tmpnvl != NULL) { 968347a39b4SMariusz Zaborski nvl = tmpnvl; 969347a39b4SMariusz Zaborski nvp = tmpnvp; 970347a39b4SMariusz Zaborski continue; 971347a39b4SMariusz Zaborski } 972347a39b4SMariusz Zaborski break; 973347a39b4SMariusz Zaborski } 97454f98da9SMariusz Zaborski default: 97554f98da9SMariusz Zaborski PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 97654f98da9SMariusz Zaborski } 977c68f8061SMariusz Zaborski if (ptr == NULL) 978c68f8061SMariusz Zaborski goto fail; 97954f98da9SMariusz Zaborski while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 980347a39b4SMariusz Zaborski do { 98154f98da9SMariusz Zaborski cookie = NULL; 982347a39b4SMariusz Zaborski if (nvlist_in_array(nvl)) { 983347a39b4SMariusz Zaborski ptr = nvpair_pack_nvlist_array_next(ptr, 984347a39b4SMariusz Zaborski &left); 985347a39b4SMariusz Zaborski if (ptr == NULL) 986347a39b4SMariusz Zaborski goto fail; 987347a39b4SMariusz Zaborski } 988347a39b4SMariusz Zaborski nvl = nvlist_get_pararr(nvl, &cookie); 98954f98da9SMariusz Zaborski if (nvl == NULL) 99054f98da9SMariusz Zaborski goto out; 991347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) { 992347a39b4SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 993347a39b4SMariusz Zaborski ptr = nvlist_pack_header(nvl, ptr, 994347a39b4SMariusz Zaborski &left); 995347a39b4SMariusz Zaborski if (ptr == NULL) 996347a39b4SMariusz Zaborski goto fail; 997347a39b4SMariusz Zaborski } else if (nvpair_type((nvpair_t *)cookie) != 998347a39b4SMariusz Zaborski NV_TYPE_NVLIST_ARRAY) { 99954f98da9SMariusz Zaborski ptr = nvpair_pack_nvlist_up(ptr, &left); 100054f98da9SMariusz Zaborski if (ptr == NULL) 1001c68f8061SMariusz Zaborski goto fail; 1002347a39b4SMariusz Zaborski nvp = cookie; 1003347a39b4SMariusz Zaborski } else { 1004347a39b4SMariusz Zaborski nvp = cookie; 1005347a39b4SMariusz Zaborski } 1006347a39b4SMariusz Zaborski } while (nvp == NULL); 1007347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) 1008347a39b4SMariusz Zaborski break; 100954f98da9SMariusz Zaborski } 101054f98da9SMariusz Zaborski } 101154f98da9SMariusz Zaborski 101254f98da9SMariusz Zaborski out: 101354f98da9SMariusz Zaborski if (sizep != NULL) 101454f98da9SMariusz Zaborski *sizep = size; 101554f98da9SMariusz Zaborski return (buf); 1016c68f8061SMariusz Zaborski fail: 1017c68f8061SMariusz Zaborski nv_free(buf); 1018c68f8061SMariusz Zaborski return (NULL); 101954f98da9SMariusz Zaborski } 102054f98da9SMariusz Zaborski 102154f98da9SMariusz Zaborski void * 102254f98da9SMariusz Zaborski nvlist_pack(const nvlist_t *nvl, size_t *sizep) 102354f98da9SMariusz Zaborski { 102454f98da9SMariusz Zaborski 102554f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 102654f98da9SMariusz Zaborski 102754f98da9SMariusz Zaborski if (nvl->nvl_error != 0) { 102854f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 102954f98da9SMariusz Zaborski return (NULL); 103054f98da9SMariusz Zaborski } 103154f98da9SMariusz Zaborski 103254f98da9SMariusz Zaborski if (nvlist_ndescriptors(nvl) > 0) { 103354f98da9SMariusz Zaborski ERRNO_SET(EOPNOTSUPP); 103454f98da9SMariusz Zaborski return (NULL); 103554f98da9SMariusz Zaborski } 103654f98da9SMariusz Zaborski 103754f98da9SMariusz Zaborski return (nvlist_xpack(nvl, NULL, sizep)); 103854f98da9SMariusz Zaborski } 103954f98da9SMariusz Zaborski 104054f98da9SMariusz Zaborski static bool 104154f98da9SMariusz Zaborski nvlist_check_header(struct nvlist_header *nvlhdrp) 104254f98da9SMariusz Zaborski { 104354f98da9SMariusz Zaborski 104454f98da9SMariusz Zaborski if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { 104554f98da9SMariusz Zaborski ERRNO_SET(EINVAL); 104654f98da9SMariusz Zaborski return (false); 104754f98da9SMariusz Zaborski } 104854f98da9SMariusz Zaborski if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { 104954f98da9SMariusz Zaborski ERRNO_SET(EINVAL); 105054f98da9SMariusz Zaborski return (false); 105154f98da9SMariusz Zaborski } 105254f98da9SMariusz Zaborski #if BYTE_ORDER == BIG_ENDIAN 105354f98da9SMariusz Zaborski if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) { 105454f98da9SMariusz Zaborski nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size); 105554f98da9SMariusz Zaborski nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors); 105654f98da9SMariusz Zaborski } 105754f98da9SMariusz Zaborski #else 105854f98da9SMariusz Zaborski if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) { 105954f98da9SMariusz Zaborski nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size); 106054f98da9SMariusz Zaborski nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); 106154f98da9SMariusz Zaborski } 106254f98da9SMariusz Zaborski #endif 106354f98da9SMariusz Zaborski return (true); 106454f98da9SMariusz Zaborski } 106554f98da9SMariusz Zaborski 106654f98da9SMariusz Zaborski const unsigned char * 106754f98da9SMariusz Zaborski nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, 106854f98da9SMariusz Zaborski bool *isbep, size_t *leftp) 106954f98da9SMariusz Zaborski { 107054f98da9SMariusz Zaborski struct nvlist_header nvlhdr; 1071347a39b4SMariusz Zaborski int inarrayf; 107254f98da9SMariusz Zaborski 107354f98da9SMariusz Zaborski if (*leftp < sizeof(nvlhdr)) 107454f98da9SMariusz Zaborski goto failed; 107554f98da9SMariusz Zaborski 107654f98da9SMariusz Zaborski memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); 107754f98da9SMariusz Zaborski 107854f98da9SMariusz Zaborski if (!nvlist_check_header(&nvlhdr)) 107954f98da9SMariusz Zaborski goto failed; 108054f98da9SMariusz Zaborski 108154f98da9SMariusz Zaborski if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) 108254f98da9SMariusz Zaborski goto failed; 108354f98da9SMariusz Zaborski 108454f98da9SMariusz Zaborski /* 108554f98da9SMariusz Zaborski * nvlh_descriptors might be smaller than nfds in embedded nvlists. 108654f98da9SMariusz Zaborski */ 108754f98da9SMariusz Zaborski if (nvlhdr.nvlh_descriptors > nfds) 108854f98da9SMariusz Zaborski goto failed; 108954f98da9SMariusz Zaborski 109054f98da9SMariusz Zaborski if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) 109154f98da9SMariusz Zaborski goto failed; 109254f98da9SMariusz Zaborski 1093347a39b4SMariusz Zaborski inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY); 1094347a39b4SMariusz Zaborski nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf; 109554f98da9SMariusz Zaborski 109654f98da9SMariusz Zaborski ptr += sizeof(nvlhdr); 109754f98da9SMariusz Zaborski if (isbep != NULL) 109854f98da9SMariusz Zaborski *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0); 109954f98da9SMariusz Zaborski *leftp -= sizeof(nvlhdr); 110054f98da9SMariusz Zaborski 110154f98da9SMariusz Zaborski return (ptr); 110254f98da9SMariusz Zaborski failed: 110354f98da9SMariusz Zaborski ERRNO_SET(EINVAL); 110454f98da9SMariusz Zaborski return (NULL); 110554f98da9SMariusz Zaborski } 110654f98da9SMariusz Zaborski 110754f98da9SMariusz Zaborski static nvlist_t * 110854f98da9SMariusz Zaborski nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds, 110954f98da9SMariusz Zaborski int flags) 111054f98da9SMariusz Zaborski { 111154f98da9SMariusz Zaborski const unsigned char *ptr; 1112347a39b4SMariusz Zaborski nvlist_t *nvl, *retnvl, *tmpnvl, *array; 111354f98da9SMariusz Zaborski nvpair_t *nvp; 111454f98da9SMariusz Zaborski size_t left; 111554f98da9SMariusz Zaborski bool isbe; 111654f98da9SMariusz Zaborski 111754f98da9SMariusz Zaborski PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 111854f98da9SMariusz Zaborski 111954f98da9SMariusz Zaborski left = size; 112054f98da9SMariusz Zaborski ptr = buf; 112154f98da9SMariusz Zaborski 1122347a39b4SMariusz Zaborski tmpnvl = array = NULL; 112354f98da9SMariusz Zaborski nvl = retnvl = nvlist_create(0); 112454f98da9SMariusz Zaborski if (nvl == NULL) 112554f98da9SMariusz Zaborski goto failed; 112654f98da9SMariusz Zaborski 112754f98da9SMariusz Zaborski ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); 112854f98da9SMariusz Zaborski if (ptr == NULL) 112954f98da9SMariusz Zaborski goto failed; 113054f98da9SMariusz Zaborski if (nvl->nvl_flags != flags) { 113154f98da9SMariusz Zaborski ERRNO_SET(EILSEQ); 113254f98da9SMariusz Zaborski goto failed; 113354f98da9SMariusz Zaborski } 113454f98da9SMariusz Zaborski 113554f98da9SMariusz Zaborski while (left > 0) { 113654f98da9SMariusz Zaborski ptr = nvpair_unpack(isbe, ptr, &left, &nvp); 113754f98da9SMariusz Zaborski if (ptr == NULL) 113854f98da9SMariusz Zaborski goto failed; 113954f98da9SMariusz Zaborski switch (nvpair_type(nvp)) { 114054f98da9SMariusz Zaborski case NV_TYPE_NULL: 114154f98da9SMariusz Zaborski ptr = nvpair_unpack_null(isbe, nvp, ptr, &left); 114254f98da9SMariusz Zaborski break; 114354f98da9SMariusz Zaborski case NV_TYPE_BOOL: 114454f98da9SMariusz Zaborski ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left); 114554f98da9SMariusz Zaborski break; 114654f98da9SMariusz Zaborski case NV_TYPE_NUMBER: 114754f98da9SMariusz Zaborski ptr = nvpair_unpack_number(isbe, nvp, ptr, &left); 114854f98da9SMariusz Zaborski break; 114954f98da9SMariusz Zaborski case NV_TYPE_STRING: 115054f98da9SMariusz Zaborski ptr = nvpair_unpack_string(isbe, nvp, ptr, &left); 115154f98da9SMariusz Zaborski break; 115254f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 115354f98da9SMariusz Zaborski ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds, 115454f98da9SMariusz Zaborski &tmpnvl); 115551dae13fSMariusz Zaborski if (tmpnvl == NULL || ptr == NULL) 115651dae13fSMariusz Zaborski goto failed; 115754f98da9SMariusz Zaborski nvlist_set_parent(tmpnvl, nvp); 115854f98da9SMariusz Zaborski break; 115954f98da9SMariusz Zaborski #ifndef _KERNEL 116054f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 116154f98da9SMariusz Zaborski ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left, 116254f98da9SMariusz Zaborski fds, nfds); 116354f98da9SMariusz Zaborski break; 1164347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 1165347a39b4SMariusz Zaborski ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr, 1166347a39b4SMariusz Zaborski &left, fds, nfds); 1167347a39b4SMariusz Zaborski break; 116854f98da9SMariusz Zaborski #endif 116954f98da9SMariusz Zaborski case NV_TYPE_BINARY: 117054f98da9SMariusz Zaborski ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left); 117154f98da9SMariusz Zaborski break; 117254f98da9SMariusz Zaborski case NV_TYPE_NVLIST_UP: 117354f98da9SMariusz Zaborski if (nvl->nvl_parent == NULL) 117454f98da9SMariusz Zaborski goto failed; 117554f98da9SMariusz Zaborski nvl = nvpair_nvlist(nvl->nvl_parent); 117654f98da9SMariusz Zaborski nvpair_free_structure(nvp); 117754f98da9SMariusz Zaborski continue; 1178347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY_NEXT: 1179347a39b4SMariusz Zaborski if (nvl->nvl_array_next == NULL) { 1180347a39b4SMariusz Zaborski if (nvl->nvl_parent == NULL) 1181347a39b4SMariusz Zaborski goto failed; 1182347a39b4SMariusz Zaborski nvl = nvpair_nvlist(nvl->nvl_parent); 1183347a39b4SMariusz Zaborski } else { 1184347a39b4SMariusz Zaborski nvl = __DECONST(nvlist_t *, 1185347a39b4SMariusz Zaborski nvlist_get_array_next(nvl)); 1186347a39b4SMariusz Zaborski ptr = nvlist_unpack_header(nvl, ptr, nfds, 1187347a39b4SMariusz Zaborski &isbe, &left); 1188347a39b4SMariusz Zaborski if (ptr == NULL) 1189347a39b4SMariusz Zaborski goto failed; 1190347a39b4SMariusz Zaborski } 1191347a39b4SMariusz Zaborski nvpair_free_structure(nvp); 1192347a39b4SMariusz Zaborski continue; 1193347a39b4SMariusz Zaborski case NV_TYPE_BOOL_ARRAY: 1194347a39b4SMariusz Zaborski ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left); 1195347a39b4SMariusz Zaborski break; 1196347a39b4SMariusz Zaborski case NV_TYPE_NUMBER_ARRAY: 1197347a39b4SMariusz Zaborski ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left); 1198347a39b4SMariusz Zaborski break; 1199347a39b4SMariusz Zaborski case NV_TYPE_STRING_ARRAY: 1200347a39b4SMariusz Zaborski ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left); 1201347a39b4SMariusz Zaborski break; 1202347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 1203347a39b4SMariusz Zaborski ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left, 1204347a39b4SMariusz Zaborski &array); 1205347a39b4SMariusz Zaborski if (ptr == NULL) 1206347a39b4SMariusz Zaborski goto failed; 1207347a39b4SMariusz Zaborski tmpnvl = array; 1208347a39b4SMariusz Zaborski while (array != NULL) { 1209347a39b4SMariusz Zaborski nvlist_set_parent(array, nvp); 1210347a39b4SMariusz Zaborski array = __DECONST(nvlist_t *, 1211347a39b4SMariusz Zaborski nvlist_get_array_next(array)); 1212347a39b4SMariusz Zaborski } 1213347a39b4SMariusz Zaborski ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe, 1214347a39b4SMariusz Zaborski &left); 1215347a39b4SMariusz Zaborski break; 121654f98da9SMariusz Zaborski default: 121754f98da9SMariusz Zaborski PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 121854f98da9SMariusz Zaborski } 121954f98da9SMariusz Zaborski if (ptr == NULL) 122054f98da9SMariusz Zaborski goto failed; 122130740f45SMariusz Zaborski if (!nvlist_move_nvpair(nvl, nvp)) 122230740f45SMariusz Zaborski goto failed; 122354f98da9SMariusz Zaborski if (tmpnvl != NULL) { 122454f98da9SMariusz Zaborski nvl = tmpnvl; 122554f98da9SMariusz Zaborski tmpnvl = NULL; 122654f98da9SMariusz Zaborski } 122754f98da9SMariusz Zaborski } 122854f98da9SMariusz Zaborski 122954f98da9SMariusz Zaborski return (retnvl); 123054f98da9SMariusz Zaborski failed: 123154f98da9SMariusz Zaborski nvlist_destroy(retnvl); 123254f98da9SMariusz Zaborski return (NULL); 123354f98da9SMariusz Zaborski } 123454f98da9SMariusz Zaborski 123554f98da9SMariusz Zaborski nvlist_t * 123654f98da9SMariusz Zaborski nvlist_unpack(const void *buf, size_t size, int flags) 123754f98da9SMariusz Zaborski { 123854f98da9SMariusz Zaborski 123954f98da9SMariusz Zaborski return (nvlist_xunpack(buf, size, NULL, 0, flags)); 124054f98da9SMariusz Zaborski } 124154f98da9SMariusz Zaborski 124254f98da9SMariusz Zaborski #ifndef _KERNEL 124354f98da9SMariusz Zaborski int 124454f98da9SMariusz Zaborski nvlist_send(int sock, const nvlist_t *nvl) 124554f98da9SMariusz Zaborski { 124654f98da9SMariusz Zaborski size_t datasize, nfds; 124754f98da9SMariusz Zaborski int *fds; 124854f98da9SMariusz Zaborski void *data; 124954f98da9SMariusz Zaborski int64_t fdidx; 125054f98da9SMariusz Zaborski int ret; 125154f98da9SMariusz Zaborski 125254f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 125354f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 125454f98da9SMariusz Zaborski return (-1); 125554f98da9SMariusz Zaborski } 125654f98da9SMariusz Zaborski 125754f98da9SMariusz Zaborski fds = nvlist_descriptors(nvl, &nfds); 125854f98da9SMariusz Zaborski if (fds == NULL) 125954f98da9SMariusz Zaborski return (-1); 126054f98da9SMariusz Zaborski 126154f98da9SMariusz Zaborski ret = -1; 126254f98da9SMariusz Zaborski data = NULL; 126354f98da9SMariusz Zaborski fdidx = 0; 126454f98da9SMariusz Zaborski 126554f98da9SMariusz Zaborski data = nvlist_xpack(nvl, &fdidx, &datasize); 126654f98da9SMariusz Zaborski if (data == NULL) 126754f98da9SMariusz Zaborski goto out; 126854f98da9SMariusz Zaborski 126954f98da9SMariusz Zaborski if (buf_send(sock, data, datasize) == -1) 127054f98da9SMariusz Zaborski goto out; 127154f98da9SMariusz Zaborski 127254f98da9SMariusz Zaborski if (nfds > 0) { 127354f98da9SMariusz Zaborski if (fd_send(sock, fds, nfds) == -1) 127454f98da9SMariusz Zaborski goto out; 127554f98da9SMariusz Zaborski } 127654f98da9SMariusz Zaborski 127754f98da9SMariusz Zaborski ret = 0; 127854f98da9SMariusz Zaborski out: 127954f98da9SMariusz Zaborski ERRNO_SAVE(); 128054f98da9SMariusz Zaborski nv_free(fds); 128154f98da9SMariusz Zaborski nv_free(data); 128254f98da9SMariusz Zaborski ERRNO_RESTORE(); 128354f98da9SMariusz Zaborski return (ret); 128454f98da9SMariusz Zaborski } 128554f98da9SMariusz Zaborski 128654f98da9SMariusz Zaborski nvlist_t * 128754f98da9SMariusz Zaborski nvlist_recv(int sock, int flags) 128854f98da9SMariusz Zaborski { 128954f98da9SMariusz Zaborski struct nvlist_header nvlhdr; 129054f98da9SMariusz Zaborski nvlist_t *nvl, *ret; 129154f98da9SMariusz Zaborski unsigned char *buf; 129254f98da9SMariusz Zaborski size_t nfds, size, i; 129354f98da9SMariusz Zaborski int *fds; 129454f98da9SMariusz Zaborski 129554f98da9SMariusz Zaborski if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1) 129654f98da9SMariusz Zaborski return (NULL); 129754f98da9SMariusz Zaborski 129854f98da9SMariusz Zaborski if (!nvlist_check_header(&nvlhdr)) 129954f98da9SMariusz Zaborski return (NULL); 130054f98da9SMariusz Zaborski 130154f98da9SMariusz Zaborski nfds = (size_t)nvlhdr.nvlh_descriptors; 130254f98da9SMariusz Zaborski size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size; 130354f98da9SMariusz Zaborski 130454f98da9SMariusz Zaborski buf = nv_malloc(size); 130554f98da9SMariusz Zaborski if (buf == NULL) 130654f98da9SMariusz Zaborski return (NULL); 130754f98da9SMariusz Zaborski 130854f98da9SMariusz Zaborski memcpy(buf, &nvlhdr, sizeof(nvlhdr)); 130954f98da9SMariusz Zaborski 131054f98da9SMariusz Zaborski ret = NULL; 131154f98da9SMariusz Zaborski fds = NULL; 131254f98da9SMariusz Zaborski 131354f98da9SMariusz Zaborski if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1) 131454f98da9SMariusz Zaborski goto out; 131554f98da9SMariusz Zaborski 131654f98da9SMariusz Zaborski if (nfds > 0) { 131754f98da9SMariusz Zaborski fds = nv_malloc(nfds * sizeof(fds[0])); 131854f98da9SMariusz Zaborski if (fds == NULL) 131954f98da9SMariusz Zaborski goto out; 132054f98da9SMariusz Zaborski if (fd_recv(sock, fds, nfds) == -1) 132154f98da9SMariusz Zaborski goto out; 132254f98da9SMariusz Zaborski } 132354f98da9SMariusz Zaborski 132454f98da9SMariusz Zaborski nvl = nvlist_xunpack(buf, size, fds, nfds, flags); 132554f98da9SMariusz Zaborski if (nvl == NULL) { 132654f98da9SMariusz Zaborski ERRNO_SAVE(); 132754f98da9SMariusz Zaborski for (i = 0; i < nfds; i++) 132854f98da9SMariusz Zaborski close(fds[i]); 132954f98da9SMariusz Zaborski ERRNO_RESTORE(); 133054f98da9SMariusz Zaborski goto out; 133154f98da9SMariusz Zaborski } 133254f98da9SMariusz Zaborski 133354f98da9SMariusz Zaborski ret = nvl; 133454f98da9SMariusz Zaborski out: 133554f98da9SMariusz Zaborski ERRNO_SAVE(); 133654f98da9SMariusz Zaborski nv_free(buf); 133754f98da9SMariusz Zaborski nv_free(fds); 133854f98da9SMariusz Zaborski ERRNO_RESTORE(); 133954f98da9SMariusz Zaborski 134054f98da9SMariusz Zaborski return (ret); 134154f98da9SMariusz Zaborski } 134254f98da9SMariusz Zaborski 134354f98da9SMariusz Zaborski nvlist_t * 134454f98da9SMariusz Zaborski nvlist_xfer(int sock, nvlist_t *nvl, int flags) 134554f98da9SMariusz Zaborski { 134654f98da9SMariusz Zaborski 134754f98da9SMariusz Zaborski if (nvlist_send(sock, nvl) < 0) { 134854f98da9SMariusz Zaborski nvlist_destroy(nvl); 134954f98da9SMariusz Zaborski return (NULL); 135054f98da9SMariusz Zaborski } 135154f98da9SMariusz Zaborski nvlist_destroy(nvl); 135254f98da9SMariusz Zaborski return (nvlist_recv(sock, flags)); 135354f98da9SMariusz Zaborski } 135454f98da9SMariusz Zaborski #endif 135554f98da9SMariusz Zaborski 135654f98da9SMariusz Zaborski nvpair_t * 135754f98da9SMariusz Zaborski nvlist_first_nvpair(const nvlist_t *nvl) 135854f98da9SMariusz Zaborski { 135954f98da9SMariusz Zaborski 136054f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 136154f98da9SMariusz Zaborski 136254f98da9SMariusz Zaborski return (TAILQ_FIRST(&nvl->nvl_head)); 136354f98da9SMariusz Zaborski } 136454f98da9SMariusz Zaborski 136554f98da9SMariusz Zaborski nvpair_t * 136654f98da9SMariusz Zaborski nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 136754f98da9SMariusz Zaborski { 136854f98da9SMariusz Zaborski nvpair_t *retnvp; 136954f98da9SMariusz Zaborski 137054f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 137154f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 137254f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 137354f98da9SMariusz Zaborski 137454f98da9SMariusz Zaborski retnvp = nvpair_next(nvp); 137554f98da9SMariusz Zaborski PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl); 137654f98da9SMariusz Zaborski 137754f98da9SMariusz Zaborski return (retnvp); 137854f98da9SMariusz Zaborski 137954f98da9SMariusz Zaborski } 138054f98da9SMariusz Zaborski 138154f98da9SMariusz Zaborski nvpair_t * 138254f98da9SMariusz Zaborski nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 138354f98da9SMariusz Zaborski { 138454f98da9SMariusz Zaborski nvpair_t *retnvp; 138554f98da9SMariusz Zaborski 138654f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 138754f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 138854f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 138954f98da9SMariusz Zaborski 139054f98da9SMariusz Zaborski retnvp = nvpair_prev(nvp); 139154f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl); 139254f98da9SMariusz Zaborski 139354f98da9SMariusz Zaborski return (retnvp); 139454f98da9SMariusz Zaborski } 139554f98da9SMariusz Zaborski 139654f98da9SMariusz Zaborski const char * 139754f98da9SMariusz Zaborski nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep) 139854f98da9SMariusz Zaborski { 139954f98da9SMariusz Zaborski nvpair_t *nvp; 140054f98da9SMariusz Zaborski 140154f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 140254f98da9SMariusz Zaborski 140389ca10c6SMariusz Zaborski if (cookiep == NULL || *cookiep == NULL) 140454f98da9SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 140554f98da9SMariusz Zaborski else 140654f98da9SMariusz Zaborski nvp = nvlist_next_nvpair(nvl, *cookiep); 140754f98da9SMariusz Zaborski if (nvp == NULL) 140854f98da9SMariusz Zaborski return (NULL); 140954f98da9SMariusz Zaborski if (typep != NULL) 141054f98da9SMariusz Zaborski *typep = nvpair_type(nvp); 141189ca10c6SMariusz Zaborski if (cookiep != NULL) 141254f98da9SMariusz Zaborski *cookiep = nvp; 141354f98da9SMariusz Zaborski return (nvpair_name(nvp)); 141454f98da9SMariusz Zaborski } 141554f98da9SMariusz Zaborski 141654f98da9SMariusz Zaborski bool 141754f98da9SMariusz Zaborski nvlist_exists(const nvlist_t *nvl, const char *name) 141854f98da9SMariusz Zaborski { 141954f98da9SMariusz Zaborski 142054f98da9SMariusz Zaborski return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL); 142154f98da9SMariusz Zaborski } 142254f98da9SMariusz Zaborski 142354f98da9SMariusz Zaborski #define NVLIST_EXISTS(type, TYPE) \ 142454f98da9SMariusz Zaborski bool \ 142554f98da9SMariusz Zaborski nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ 142654f98da9SMariusz Zaborski { \ 142754f98da9SMariusz Zaborski \ 142854f98da9SMariusz Zaborski return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \ 142954f98da9SMariusz Zaborski } 143054f98da9SMariusz Zaborski 143154f98da9SMariusz Zaborski NVLIST_EXISTS(null, NULL) 143254f98da9SMariusz Zaborski NVLIST_EXISTS(bool, BOOL) 143354f98da9SMariusz Zaborski NVLIST_EXISTS(number, NUMBER) 143454f98da9SMariusz Zaborski NVLIST_EXISTS(string, STRING) 143554f98da9SMariusz Zaborski NVLIST_EXISTS(nvlist, NVLIST) 1436347a39b4SMariusz Zaborski NVLIST_EXISTS(binary, BINARY) 1437347a39b4SMariusz Zaborski NVLIST_EXISTS(bool_array, BOOL_ARRAY) 1438347a39b4SMariusz Zaborski NVLIST_EXISTS(number_array, NUMBER_ARRAY) 1439347a39b4SMariusz Zaborski NVLIST_EXISTS(string_array, STRING_ARRAY) 1440347a39b4SMariusz Zaborski NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY) 144154f98da9SMariusz Zaborski #ifndef _KERNEL 144254f98da9SMariusz Zaborski NVLIST_EXISTS(descriptor, DESCRIPTOR) 1443347a39b4SMariusz Zaborski NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY) 144454f98da9SMariusz Zaborski #endif 144554f98da9SMariusz Zaborski 144654f98da9SMariusz Zaborski #undef NVLIST_EXISTS 144754f98da9SMariusz Zaborski 144854f98da9SMariusz Zaborski void 144954f98da9SMariusz Zaborski nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) 145054f98da9SMariusz Zaborski { 145154f98da9SMariusz Zaborski nvpair_t *newnvp; 145254f98da9SMariusz Zaborski 145354f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 145454f98da9SMariusz Zaborski 145554f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 145654f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 145754f98da9SMariusz Zaborski return; 145854f98da9SMariusz Zaborski } 145954f98da9SMariusz Zaborski if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { 146054f98da9SMariusz Zaborski if (nvlist_exists(nvl, nvpair_name(nvp))) { 146154f98da9SMariusz Zaborski nvl->nvl_error = EEXIST; 146254f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 146354f98da9SMariusz Zaborski return; 146454f98da9SMariusz Zaborski } 146554f98da9SMariusz Zaborski } 146654f98da9SMariusz Zaborski 146754f98da9SMariusz Zaborski newnvp = nvpair_clone(nvp); 146854f98da9SMariusz Zaborski if (newnvp == NULL) { 146954f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 147054f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 147154f98da9SMariusz Zaborski return; 147254f98da9SMariusz Zaborski } 147354f98da9SMariusz Zaborski 147454f98da9SMariusz Zaborski nvpair_insert(&nvl->nvl_head, newnvp, nvl); 147554f98da9SMariusz Zaborski } 147654f98da9SMariusz Zaborski 147754f98da9SMariusz Zaborski void 147854f98da9SMariusz Zaborski nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) 147954f98da9SMariusz Zaborski { 148054f98da9SMariusz Zaborski va_list valueap; 148154f98da9SMariusz Zaborski 148254f98da9SMariusz Zaborski va_start(valueap, valuefmt); 148354f98da9SMariusz Zaborski nvlist_add_stringv(nvl, name, valuefmt, valueap); 148454f98da9SMariusz Zaborski va_end(valueap); 148554f98da9SMariusz Zaborski } 148654f98da9SMariusz Zaborski 148754f98da9SMariusz Zaborski void 148854f98da9SMariusz Zaborski nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, 148954f98da9SMariusz Zaborski va_list valueap) 149054f98da9SMariusz Zaborski { 149154f98da9SMariusz Zaborski nvpair_t *nvp; 149254f98da9SMariusz Zaborski 149354f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 149454f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 149554f98da9SMariusz Zaborski return; 149654f98da9SMariusz Zaborski } 149754f98da9SMariusz Zaborski 149854f98da9SMariusz Zaborski nvp = nvpair_create_stringv(name, valuefmt, valueap); 149954f98da9SMariusz Zaborski if (nvp == NULL) { 150054f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 150154f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 150254f98da9SMariusz Zaborski } else { 150330740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 150454f98da9SMariusz Zaborski } 150554f98da9SMariusz Zaborski } 150654f98da9SMariusz Zaborski 150754f98da9SMariusz Zaborski void 150854f98da9SMariusz Zaborski nvlist_add_null(nvlist_t *nvl, const char *name) 150954f98da9SMariusz Zaborski { 151054f98da9SMariusz Zaborski nvpair_t *nvp; 151154f98da9SMariusz Zaborski 151254f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 151354f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 151454f98da9SMariusz Zaborski return; 151554f98da9SMariusz Zaborski } 151654f98da9SMariusz Zaborski 151754f98da9SMariusz Zaborski nvp = nvpair_create_null(name); 151854f98da9SMariusz Zaborski if (nvp == NULL) { 151954f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 152054f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 152154f98da9SMariusz Zaborski } else { 152230740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 152354f98da9SMariusz Zaborski } 152454f98da9SMariusz Zaborski } 152554f98da9SMariusz Zaborski 152654f98da9SMariusz Zaborski void 152754f98da9SMariusz Zaborski nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, 152854f98da9SMariusz Zaborski size_t size) 152954f98da9SMariusz Zaborski { 153054f98da9SMariusz Zaborski nvpair_t *nvp; 153154f98da9SMariusz Zaborski 153254f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 153354f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 153454f98da9SMariusz Zaborski return; 153554f98da9SMariusz Zaborski } 153654f98da9SMariusz Zaborski 153754f98da9SMariusz Zaborski nvp = nvpair_create_binary(name, value, size); 153854f98da9SMariusz Zaborski if (nvp == NULL) { 153954f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 154054f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 154154f98da9SMariusz Zaborski } else { 154230740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 154354f98da9SMariusz Zaborski } 154454f98da9SMariusz Zaborski } 154554f98da9SMariusz Zaborski 154654f98da9SMariusz Zaborski 154754f98da9SMariusz Zaborski #define NVLIST_ADD(vtype, type) \ 154854f98da9SMariusz Zaborski void \ 154954f98da9SMariusz Zaborski nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \ 155054f98da9SMariusz Zaborski { \ 155154f98da9SMariusz Zaborski nvpair_t *nvp; \ 155254f98da9SMariusz Zaborski \ 155354f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { \ 155454f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); \ 155554f98da9SMariusz Zaborski return; \ 155654f98da9SMariusz Zaborski } \ 155754f98da9SMariusz Zaborski \ 155854f98da9SMariusz Zaborski nvp = nvpair_create_##type(name, value); \ 155954f98da9SMariusz Zaborski if (nvp == NULL) { \ 156054f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 156154f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); \ 156254f98da9SMariusz Zaborski } else { \ 156330740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); \ 156454f98da9SMariusz Zaborski } \ 156554f98da9SMariusz Zaborski } 156654f98da9SMariusz Zaborski 156754f98da9SMariusz Zaborski NVLIST_ADD(bool, bool) 156854f98da9SMariusz Zaborski NVLIST_ADD(uint64_t, number) 156954f98da9SMariusz Zaborski NVLIST_ADD(const char *, string) 157054f98da9SMariusz Zaborski NVLIST_ADD(const nvlist_t *, nvlist) 157154f98da9SMariusz Zaborski #ifndef _KERNEL 157254f98da9SMariusz Zaborski NVLIST_ADD(int, descriptor); 157354f98da9SMariusz Zaborski #endif 157454f98da9SMariusz Zaborski 157554f98da9SMariusz Zaborski #undef NVLIST_ADD 157654f98da9SMariusz Zaborski 1577347a39b4SMariusz Zaborski #define NVLIST_ADD_ARRAY(vtype, type) \ 1578347a39b4SMariusz Zaborski void \ 1579347a39b4SMariusz Zaborski nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value, \ 1580347a39b4SMariusz Zaborski size_t nitems) \ 1581347a39b4SMariusz Zaborski { \ 1582347a39b4SMariusz Zaborski nvpair_t *nvp; \ 1583347a39b4SMariusz Zaborski \ 1584347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { \ 1585347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); \ 1586347a39b4SMariusz Zaborski return; \ 1587347a39b4SMariusz Zaborski } \ 1588347a39b4SMariusz Zaborski \ 1589347a39b4SMariusz Zaborski nvp = nvpair_create_##type##_array(name, value, nitems); \ 1590347a39b4SMariusz Zaborski if (nvp == NULL) { \ 1591347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 1592347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); \ 1593347a39b4SMariusz Zaborski } else { \ 1594347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); \ 1595347a39b4SMariusz Zaborski } \ 1596347a39b4SMariusz Zaborski } 1597347a39b4SMariusz Zaborski 1598347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const bool *, bool) 1599347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const uint64_t *, number) 1600347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const char * const *, string) 1601347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist) 1602347a39b4SMariusz Zaborski #ifndef _KERNEL 1603347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const int *, descriptor) 1604347a39b4SMariusz Zaborski #endif 1605347a39b4SMariusz Zaborski 1606347a39b4SMariusz Zaborski #undef NVLIST_ADD_ARRAY 1607347a39b4SMariusz Zaborski 160830740f45SMariusz Zaborski bool 160954f98da9SMariusz Zaborski nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) 161054f98da9SMariusz Zaborski { 161154f98da9SMariusz Zaborski 161254f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 161354f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); 161454f98da9SMariusz Zaborski 161554f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 161654f98da9SMariusz Zaborski nvpair_free(nvp); 161754f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 161830740f45SMariusz Zaborski return (false); 161954f98da9SMariusz Zaborski } 162054f98da9SMariusz Zaborski if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { 162154f98da9SMariusz Zaborski if (nvlist_exists(nvl, nvpair_name(nvp))) { 162254f98da9SMariusz Zaborski nvpair_free(nvp); 162354f98da9SMariusz Zaborski nvl->nvl_error = EEXIST; 162454f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 162530740f45SMariusz Zaborski return (false); 162654f98da9SMariusz Zaborski } 162754f98da9SMariusz Zaborski } 162854f98da9SMariusz Zaborski 162954f98da9SMariusz Zaborski nvpair_insert(&nvl->nvl_head, nvp, nvl); 163030740f45SMariusz Zaborski return (true); 163154f98da9SMariusz Zaborski } 163254f98da9SMariusz Zaborski 163354f98da9SMariusz Zaborski void 163454f98da9SMariusz Zaborski nvlist_move_string(nvlist_t *nvl, const char *name, char *value) 163554f98da9SMariusz Zaborski { 163654f98da9SMariusz Zaborski nvpair_t *nvp; 163754f98da9SMariusz Zaborski 163854f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 163954f98da9SMariusz Zaborski nv_free(value); 164054f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 164154f98da9SMariusz Zaborski return; 164254f98da9SMariusz Zaborski } 164354f98da9SMariusz Zaborski 164454f98da9SMariusz Zaborski nvp = nvpair_move_string(name, value); 164554f98da9SMariusz Zaborski if (nvp == NULL) { 164654f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 164754f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 164854f98da9SMariusz Zaborski } else { 164930740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 165054f98da9SMariusz Zaborski } 165154f98da9SMariusz Zaborski } 165254f98da9SMariusz Zaborski 165354f98da9SMariusz Zaborski void 165454f98da9SMariusz Zaborski nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value) 165554f98da9SMariusz Zaborski { 165654f98da9SMariusz Zaborski nvpair_t *nvp; 165754f98da9SMariusz Zaborski 165854f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 165954f98da9SMariusz Zaborski if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) 166054f98da9SMariusz Zaborski nvlist_destroy(value); 166154f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 166254f98da9SMariusz Zaborski return; 166354f98da9SMariusz Zaborski } 166454f98da9SMariusz Zaborski 166554f98da9SMariusz Zaborski nvp = nvpair_move_nvlist(name, value); 166654f98da9SMariusz Zaborski if (nvp == NULL) { 166754f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 166854f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 166954f98da9SMariusz Zaborski } else { 167030740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 167154f98da9SMariusz Zaborski } 167254f98da9SMariusz Zaborski } 167354f98da9SMariusz Zaborski 167454f98da9SMariusz Zaborski #ifndef _KERNEL 167554f98da9SMariusz Zaborski void 167654f98da9SMariusz Zaborski nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value) 167754f98da9SMariusz Zaborski { 167854f98da9SMariusz Zaborski nvpair_t *nvp; 167954f98da9SMariusz Zaborski 168054f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 168154f98da9SMariusz Zaborski close(value); 168254f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 168354f98da9SMariusz Zaborski return; 168454f98da9SMariusz Zaborski } 168554f98da9SMariusz Zaborski 168654f98da9SMariusz Zaborski nvp = nvpair_move_descriptor(name, value); 168754f98da9SMariusz Zaborski if (nvp == NULL) { 168854f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 168954f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 169054f98da9SMariusz Zaborski } else { 169130740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 169254f98da9SMariusz Zaborski } 169354f98da9SMariusz Zaborski } 169454f98da9SMariusz Zaborski #endif 169554f98da9SMariusz Zaborski 169654f98da9SMariusz Zaborski void 169754f98da9SMariusz Zaborski nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size) 169854f98da9SMariusz Zaborski { 169954f98da9SMariusz Zaborski nvpair_t *nvp; 170054f98da9SMariusz Zaborski 170154f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 170254f98da9SMariusz Zaborski nv_free(value); 170354f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 170454f98da9SMariusz Zaborski return; 170554f98da9SMariusz Zaborski } 170654f98da9SMariusz Zaborski 170754f98da9SMariusz Zaborski nvp = nvpair_move_binary(name, value, size); 170854f98da9SMariusz Zaborski if (nvp == NULL) { 170954f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 171054f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 171154f98da9SMariusz Zaborski } else { 171230740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 171354f98da9SMariusz Zaborski } 171454f98da9SMariusz Zaborski } 171554f98da9SMariusz Zaborski 1716347a39b4SMariusz Zaborski void 1717347a39b4SMariusz Zaborski nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value, 1718347a39b4SMariusz Zaborski size_t nitems) 1719347a39b4SMariusz Zaborski { 1720347a39b4SMariusz Zaborski nvpair_t *nvp; 1721347a39b4SMariusz Zaborski 1722347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1723347a39b4SMariusz Zaborski nv_free(value); 1724347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1725347a39b4SMariusz Zaborski return; 1726347a39b4SMariusz Zaborski } 1727347a39b4SMariusz Zaborski 1728347a39b4SMariusz Zaborski nvp = nvpair_move_bool_array(name, value, nitems); 1729347a39b4SMariusz Zaborski if (nvp == NULL) { 1730347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1731347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1732347a39b4SMariusz Zaborski } else { 1733347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1734347a39b4SMariusz Zaborski } 1735347a39b4SMariusz Zaborski } 1736347a39b4SMariusz Zaborski 1737347a39b4SMariusz Zaborski void 1738347a39b4SMariusz Zaborski nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value, 1739347a39b4SMariusz Zaborski size_t nitems) 1740347a39b4SMariusz Zaborski { 1741347a39b4SMariusz Zaborski nvpair_t *nvp; 1742347a39b4SMariusz Zaborski size_t i; 1743347a39b4SMariusz Zaborski 1744347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1745347a39b4SMariusz Zaborski if (value != NULL) { 1746347a39b4SMariusz Zaborski for (i = 0; i < nitems; i++) 1747347a39b4SMariusz Zaborski nv_free(value[i]); 1748347a39b4SMariusz Zaborski nv_free(value); 1749347a39b4SMariusz Zaborski } 1750347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1751347a39b4SMariusz Zaborski return; 1752347a39b4SMariusz Zaborski } 1753347a39b4SMariusz Zaborski 1754347a39b4SMariusz Zaborski nvp = nvpair_move_string_array(name, value, nitems); 1755347a39b4SMariusz Zaborski if (nvp == NULL) { 1756347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1757347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1758347a39b4SMariusz Zaborski } else { 1759347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1760347a39b4SMariusz Zaborski } 1761347a39b4SMariusz Zaborski } 1762347a39b4SMariusz Zaborski 1763347a39b4SMariusz Zaborski void 1764347a39b4SMariusz Zaborski nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value, 1765347a39b4SMariusz Zaborski size_t nitems) 1766347a39b4SMariusz Zaborski { 1767347a39b4SMariusz Zaborski nvpair_t *nvp; 1768347a39b4SMariusz Zaborski size_t i; 1769347a39b4SMariusz Zaborski 1770347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1771347a39b4SMariusz Zaborski if (value != NULL) { 1772347a39b4SMariusz Zaborski for (i = 0; i < nitems; i++) { 1773347a39b4SMariusz Zaborski if (nvlist_get_pararr(value[i], NULL) == NULL) 1774347a39b4SMariusz Zaborski nvlist_destroy(value[i]); 1775347a39b4SMariusz Zaborski } 1776347a39b4SMariusz Zaborski } 1777347a39b4SMariusz Zaborski nv_free(value); 1778347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1779347a39b4SMariusz Zaborski return; 1780347a39b4SMariusz Zaborski } 1781347a39b4SMariusz Zaborski 1782347a39b4SMariusz Zaborski nvp = nvpair_move_nvlist_array(name, value, nitems); 1783347a39b4SMariusz Zaborski if (nvp == NULL) { 1784347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1785347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1786347a39b4SMariusz Zaborski } else { 1787347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1788347a39b4SMariusz Zaborski } 1789347a39b4SMariusz Zaborski } 1790347a39b4SMariusz Zaborski 1791347a39b4SMariusz Zaborski void 1792347a39b4SMariusz Zaborski nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value, 1793347a39b4SMariusz Zaborski size_t nitems) 1794347a39b4SMariusz Zaborski { 1795347a39b4SMariusz Zaborski nvpair_t *nvp; 1796347a39b4SMariusz Zaborski 1797347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1798347a39b4SMariusz Zaborski nv_free(value); 1799347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1800347a39b4SMariusz Zaborski return; 1801347a39b4SMariusz Zaborski } 1802347a39b4SMariusz Zaborski 1803347a39b4SMariusz Zaborski nvp = nvpair_move_number_array(name, value, nitems); 1804347a39b4SMariusz Zaborski if (nvp == NULL) { 1805347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1806347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1807347a39b4SMariusz Zaborski } else { 1808347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1809347a39b4SMariusz Zaborski } 1810347a39b4SMariusz Zaborski } 1811347a39b4SMariusz Zaborski 1812347a39b4SMariusz Zaborski #ifndef _KERNEL 1813347a39b4SMariusz Zaborski void 1814347a39b4SMariusz Zaborski nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value, 1815347a39b4SMariusz Zaborski size_t nitems) 1816347a39b4SMariusz Zaborski { 1817347a39b4SMariusz Zaborski nvpair_t *nvp; 1818347a39b4SMariusz Zaborski size_t i; 1819347a39b4SMariusz Zaborski 1820347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1821347a39b4SMariusz Zaborski if (value != 0) { 1822347a39b4SMariusz Zaborski for (i = 0; i < nitems; i++) 1823347a39b4SMariusz Zaborski close(value[i]); 1824347a39b4SMariusz Zaborski nv_free(value); 1825347a39b4SMariusz Zaborski } 1826347a39b4SMariusz Zaborski 1827347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1828347a39b4SMariusz Zaborski return; 1829347a39b4SMariusz Zaborski } 1830347a39b4SMariusz Zaborski 1831347a39b4SMariusz Zaborski nvp = nvpair_move_descriptor_array(name, value, nitems); 1832347a39b4SMariusz Zaborski if (nvp == NULL) { 1833347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1834347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1835347a39b4SMariusz Zaborski } else { 1836347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1837347a39b4SMariusz Zaborski } 1838347a39b4SMariusz Zaborski } 1839347a39b4SMariusz Zaborski #endif 1840347a39b4SMariusz Zaborski 184154f98da9SMariusz Zaborski const nvpair_t * 184254f98da9SMariusz Zaborski nvlist_get_nvpair(const nvlist_t *nvl, const char *name) 184354f98da9SMariusz Zaborski { 184454f98da9SMariusz Zaborski 184554f98da9SMariusz Zaborski return (nvlist_find(nvl, NV_TYPE_NONE, name)); 184654f98da9SMariusz Zaborski } 184754f98da9SMariusz Zaborski 184854f98da9SMariusz Zaborski #define NVLIST_GET(ftype, type, TYPE) \ 184954f98da9SMariusz Zaborski ftype \ 185054f98da9SMariusz Zaborski nvlist_get_##type(const nvlist_t *nvl, const char *name) \ 185154f98da9SMariusz Zaborski { \ 185254f98da9SMariusz Zaborski const nvpair_t *nvp; \ 185354f98da9SMariusz Zaborski \ 185454f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 185554f98da9SMariusz Zaborski if (nvp == NULL) \ 185654f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE, name); \ 185754f98da9SMariusz Zaborski return (nvpair_get_##type(nvp)); \ 185854f98da9SMariusz Zaborski } 185954f98da9SMariusz Zaborski 186054f98da9SMariusz Zaborski NVLIST_GET(bool, bool, BOOL) 186154f98da9SMariusz Zaborski NVLIST_GET(uint64_t, number, NUMBER) 186254f98da9SMariusz Zaborski NVLIST_GET(const char *, string, STRING) 186354f98da9SMariusz Zaborski NVLIST_GET(const nvlist_t *, nvlist, NVLIST) 186454f98da9SMariusz Zaborski #ifndef _KERNEL 186554f98da9SMariusz Zaborski NVLIST_GET(int, descriptor, DESCRIPTOR) 186654f98da9SMariusz Zaborski #endif 186754f98da9SMariusz Zaborski 186854f98da9SMariusz Zaborski #undef NVLIST_GET 186954f98da9SMariusz Zaborski 187054f98da9SMariusz Zaborski const void * 187154f98da9SMariusz Zaborski nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) 187254f98da9SMariusz Zaborski { 187354f98da9SMariusz Zaborski nvpair_t *nvp; 187454f98da9SMariusz Zaborski 187554f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 187654f98da9SMariusz Zaborski if (nvp == NULL) 187754f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_BINARY, name); 187854f98da9SMariusz Zaborski 187954f98da9SMariusz Zaborski return (nvpair_get_binary(nvp, sizep)); 188054f98da9SMariusz Zaborski } 188154f98da9SMariusz Zaborski 1882347a39b4SMariusz Zaborski #define NVLIST_GET_ARRAY(ftype, type, TYPE) \ 1883347a39b4SMariusz Zaborski ftype \ 1884347a39b4SMariusz Zaborski nvlist_get_##type##_array(const nvlist_t *nvl, const char *name, \ 1885347a39b4SMariusz Zaborski size_t *nitems) \ 1886347a39b4SMariusz Zaborski { \ 1887347a39b4SMariusz Zaborski const nvpair_t *nvp; \ 1888347a39b4SMariusz Zaborski \ 1889347a39b4SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 1890347a39b4SMariusz Zaborski if (nvp == NULL) \ 1891347a39b4SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ 1892347a39b4SMariusz Zaborski return (nvpair_get_##type##_array(nvp, nitems)); \ 1893347a39b4SMariusz Zaborski } 1894347a39b4SMariusz Zaborski 1895347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const bool *, bool, BOOL) 1896347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER) 1897347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const char * const *, string, STRING) 1898347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST) 1899347a39b4SMariusz Zaborski #ifndef _KERNEL 1900347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR) 1901347a39b4SMariusz Zaborski #endif 1902347a39b4SMariusz Zaborski 1903347a39b4SMariusz Zaborski #undef NVLIST_GET_ARRAY 1904347a39b4SMariusz Zaborski 190554f98da9SMariusz Zaborski #define NVLIST_TAKE(ftype, type, TYPE) \ 190654f98da9SMariusz Zaborski ftype \ 190754f98da9SMariusz Zaborski nvlist_take_##type(nvlist_t *nvl, const char *name) \ 190854f98da9SMariusz Zaborski { \ 190954f98da9SMariusz Zaborski nvpair_t *nvp; \ 191054f98da9SMariusz Zaborski ftype value; \ 191154f98da9SMariusz Zaborski \ 191254f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 191354f98da9SMariusz Zaborski if (nvp == NULL) \ 191454f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE, name); \ 191554f98da9SMariusz Zaborski value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ 191654f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); \ 191754f98da9SMariusz Zaborski nvpair_free_structure(nvp); \ 191854f98da9SMariusz Zaborski return (value); \ 191954f98da9SMariusz Zaborski } 192054f98da9SMariusz Zaborski 192154f98da9SMariusz Zaborski NVLIST_TAKE(bool, bool, BOOL) 192254f98da9SMariusz Zaborski NVLIST_TAKE(uint64_t, number, NUMBER) 192354f98da9SMariusz Zaborski NVLIST_TAKE(char *, string, STRING) 192454f98da9SMariusz Zaborski NVLIST_TAKE(nvlist_t *, nvlist, NVLIST) 192554f98da9SMariusz Zaborski #ifndef _KERNEL 192654f98da9SMariusz Zaborski NVLIST_TAKE(int, descriptor, DESCRIPTOR) 192754f98da9SMariusz Zaborski #endif 192854f98da9SMariusz Zaborski 192954f98da9SMariusz Zaborski #undef NVLIST_TAKE 193054f98da9SMariusz Zaborski 193154f98da9SMariusz Zaborski void * 193254f98da9SMariusz Zaborski nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) 193354f98da9SMariusz Zaborski { 193454f98da9SMariusz Zaborski nvpair_t *nvp; 193554f98da9SMariusz Zaborski void *value; 193654f98da9SMariusz Zaborski 193754f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 193854f98da9SMariusz Zaborski if (nvp == NULL) 193954f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_BINARY, name); 194054f98da9SMariusz Zaborski 194154f98da9SMariusz Zaborski value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); 194254f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); 194354f98da9SMariusz Zaborski nvpair_free_structure(nvp); 194454f98da9SMariusz Zaborski return (value); 194554f98da9SMariusz Zaborski } 194654f98da9SMariusz Zaborski 1947347a39b4SMariusz Zaborski #define NVLIST_TAKE_ARRAY(ftype, type, TYPE) \ 1948347a39b4SMariusz Zaborski ftype \ 1949347a39b4SMariusz Zaborski nvlist_take_##type##_array(nvlist_t *nvl, const char *name, \ 1950347a39b4SMariusz Zaborski size_t *nitems) \ 1951347a39b4SMariusz Zaborski { \ 1952347a39b4SMariusz Zaborski nvpair_t *nvp; \ 1953347a39b4SMariusz Zaborski ftype value; \ 1954347a39b4SMariusz Zaborski \ 1955347a39b4SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 1956347a39b4SMariusz Zaborski if (nvp == NULL) \ 1957347a39b4SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ 1958347a39b4SMariusz Zaborski value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\ 1959347a39b4SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); \ 1960347a39b4SMariusz Zaborski nvpair_free_structure(nvp); \ 1961347a39b4SMariusz Zaborski return (value); \ 1962347a39b4SMariusz Zaborski } 1963347a39b4SMariusz Zaborski 1964347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(bool *, bool, BOOL) 1965347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER) 1966347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(char **, string, STRING) 1967347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST) 1968347a39b4SMariusz Zaborski #ifndef _KERNEL 1969347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR) 1970347a39b4SMariusz Zaborski #endif 1971347a39b4SMariusz Zaborski 197254f98da9SMariusz Zaborski void 197354f98da9SMariusz Zaborski nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) 197454f98da9SMariusz Zaborski { 197554f98da9SMariusz Zaborski 197654f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 197754f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 197854f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 197954f98da9SMariusz Zaborski 198054f98da9SMariusz Zaborski nvpair_remove(&nvl->nvl_head, nvp, nvl); 198154f98da9SMariusz Zaborski } 198254f98da9SMariusz Zaborski 198354f98da9SMariusz Zaborski void 198454f98da9SMariusz Zaborski nvlist_free(nvlist_t *nvl, const char *name) 198554f98da9SMariusz Zaborski { 198654f98da9SMariusz Zaborski 198754f98da9SMariusz Zaborski nvlist_free_type(nvl, name, NV_TYPE_NONE); 198854f98da9SMariusz Zaborski } 198954f98da9SMariusz Zaborski 199054f98da9SMariusz Zaborski #define NVLIST_FREE(type, TYPE) \ 199154f98da9SMariusz Zaborski void \ 199254f98da9SMariusz Zaborski nvlist_free_##type(nvlist_t *nvl, const char *name) \ 199354f98da9SMariusz Zaborski { \ 199454f98da9SMariusz Zaborski \ 199554f98da9SMariusz Zaborski nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ 199654f98da9SMariusz Zaborski } 199754f98da9SMariusz Zaborski 199854f98da9SMariusz Zaborski NVLIST_FREE(null, NULL) 199954f98da9SMariusz Zaborski NVLIST_FREE(bool, BOOL) 200054f98da9SMariusz Zaborski NVLIST_FREE(number, NUMBER) 200154f98da9SMariusz Zaborski NVLIST_FREE(string, STRING) 200254f98da9SMariusz Zaborski NVLIST_FREE(nvlist, NVLIST) 2003347a39b4SMariusz Zaborski NVLIST_FREE(binary, BINARY) 2004347a39b4SMariusz Zaborski NVLIST_FREE(bool_array, BOOL_ARRAY) 2005347a39b4SMariusz Zaborski NVLIST_FREE(number_array, NUMBER_ARRAY) 2006347a39b4SMariusz Zaborski NVLIST_FREE(string_array, STRING_ARRAY) 2007347a39b4SMariusz Zaborski NVLIST_FREE(nvlist_array, NVLIST_ARRAY) 200854f98da9SMariusz Zaborski #ifndef _KERNEL 200954f98da9SMariusz Zaborski NVLIST_FREE(descriptor, DESCRIPTOR) 2010347a39b4SMariusz Zaborski NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY) 201154f98da9SMariusz Zaborski #endif 201254f98da9SMariusz Zaborski 201354f98da9SMariusz Zaborski #undef NVLIST_FREE 201454f98da9SMariusz Zaborski 201554f98da9SMariusz Zaborski void 201654f98da9SMariusz Zaborski nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) 201754f98da9SMariusz Zaborski { 201854f98da9SMariusz Zaborski 201954f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 202054f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 202154f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 202254f98da9SMariusz Zaborski 202354f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); 202454f98da9SMariusz Zaborski nvpair_free(nvp); 202554f98da9SMariusz Zaborski } 202654f98da9SMariusz Zaborski 2027