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 #include <stdio.h> 5654f98da9SMariusz Zaborski #include <stdlib.h> 5754f98da9SMariusz Zaborski #include <string.h> 5854f98da9SMariusz Zaborski #include <unistd.h> 5954f98da9SMariusz Zaborski 6054f98da9SMariusz Zaborski #include "msgio.h" 6154f98da9SMariusz Zaborski #endif 6254f98da9SMariusz Zaborski 6354f98da9SMariusz Zaborski #ifdef HAVE_PJDLOG 6454f98da9SMariusz Zaborski #include <pjdlog.h> 6554f98da9SMariusz Zaborski #endif 6654f98da9SMariusz Zaborski 6754f98da9SMariusz Zaborski #include <sys/nv.h> 6854f98da9SMariusz Zaborski 6954f98da9SMariusz Zaborski #include "nv_impl.h" 7054f98da9SMariusz Zaborski #include "nvlist_impl.h" 7154f98da9SMariusz Zaborski #include "nvpair_impl.h" 7254f98da9SMariusz Zaborski 7354f98da9SMariusz Zaborski #ifndef HAVE_PJDLOG 7454f98da9SMariusz Zaborski #ifdef _KERNEL 7554f98da9SMariusz Zaborski #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) 7654f98da9SMariusz Zaborski #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) 7754f98da9SMariusz Zaborski #define PJDLOG_ABORT(...) panic(__VA_ARGS__) 7854f98da9SMariusz Zaborski #else 7954f98da9SMariusz Zaborski #include <assert.h> 8054f98da9SMariusz Zaborski #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 8154f98da9SMariusz Zaborski #define PJDLOG_RASSERT(expr, ...) assert(expr) 8254f98da9SMariusz Zaborski #define PJDLOG_ABORT(...) do { \ 8354f98da9SMariusz Zaborski fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \ 8454f98da9SMariusz Zaborski fprintf(stderr, __VA_ARGS__); \ 8554f98da9SMariusz Zaborski fprintf(stderr, "\n"); \ 8654f98da9SMariusz Zaborski abort(); \ 8754f98da9SMariusz Zaborski } while (0) 8854f98da9SMariusz Zaborski #endif 8954f98da9SMariusz Zaborski #endif 9054f98da9SMariusz Zaborski 91347a39b4SMariusz Zaborski #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN | NV_FLAG_IN_ARRAY) 9254f98da9SMariusz Zaborski #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE) 9354f98da9SMariusz Zaborski #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK) 9454f98da9SMariusz Zaborski 9554f98da9SMariusz Zaborski #define NVLIST_MAGIC 0x6e766c /* "nvl" */ 9654f98da9SMariusz Zaborski struct nvlist { 9754f98da9SMariusz Zaborski int nvl_magic; 9854f98da9SMariusz Zaborski int nvl_error; 9954f98da9SMariusz Zaborski int nvl_flags; 10054f98da9SMariusz Zaborski nvpair_t *nvl_parent; 101347a39b4SMariusz Zaborski nvpair_t *nvl_array_next; 10254f98da9SMariusz Zaborski struct nvl_head nvl_head; 10354f98da9SMariusz Zaborski }; 10454f98da9SMariusz Zaborski 10554f98da9SMariusz Zaborski #define NVLIST_ASSERT(nvl) do { \ 10654f98da9SMariusz Zaborski PJDLOG_ASSERT((nvl) != NULL); \ 10754f98da9SMariusz Zaborski PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \ 10854f98da9SMariusz Zaborski } while (0) 10954f98da9SMariusz Zaborski 11054f98da9SMariusz Zaborski #ifdef _KERNEL 11154f98da9SMariusz Zaborski MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist"); 11254f98da9SMariusz Zaborski #endif 11354f98da9SMariusz Zaborski 11454f98da9SMariusz Zaborski #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp) 11554f98da9SMariusz Zaborski 11654f98da9SMariusz Zaborski #define NVLIST_HEADER_MAGIC 0x6c 11754f98da9SMariusz Zaborski #define NVLIST_HEADER_VERSION 0x00 11854f98da9SMariusz Zaborski struct nvlist_header { 11954f98da9SMariusz Zaborski uint8_t nvlh_magic; 12054f98da9SMariusz Zaborski uint8_t nvlh_version; 12154f98da9SMariusz Zaborski uint8_t nvlh_flags; 12254f98da9SMariusz Zaborski uint64_t nvlh_descriptors; 12354f98da9SMariusz Zaborski uint64_t nvlh_size; 12454f98da9SMariusz Zaborski } __packed; 12554f98da9SMariusz Zaborski 12654f98da9SMariusz Zaborski nvlist_t * 12754f98da9SMariusz Zaborski nvlist_create(int flags) 12854f98da9SMariusz Zaborski { 12954f98da9SMariusz Zaborski nvlist_t *nvl; 13054f98da9SMariusz Zaborski 13154f98da9SMariusz Zaborski PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 13254f98da9SMariusz Zaborski 13354f98da9SMariusz Zaborski nvl = nv_malloc(sizeof(*nvl)); 13454f98da9SMariusz Zaborski if (nvl == NULL) 13554f98da9SMariusz Zaborski return (NULL); 13654f98da9SMariusz Zaborski nvl->nvl_error = 0; 13754f98da9SMariusz Zaborski nvl->nvl_flags = flags; 13854f98da9SMariusz Zaborski nvl->nvl_parent = NULL; 139347a39b4SMariusz Zaborski nvl->nvl_array_next = NULL; 14054f98da9SMariusz Zaborski TAILQ_INIT(&nvl->nvl_head); 14154f98da9SMariusz Zaborski nvl->nvl_magic = NVLIST_MAGIC; 14254f98da9SMariusz Zaborski 14354f98da9SMariusz Zaborski return (nvl); 14454f98da9SMariusz Zaborski } 14554f98da9SMariusz Zaborski 14654f98da9SMariusz Zaborski void 14754f98da9SMariusz Zaborski nvlist_destroy(nvlist_t *nvl) 14854f98da9SMariusz Zaborski { 14954f98da9SMariusz Zaborski nvpair_t *nvp; 15054f98da9SMariusz Zaborski 15154f98da9SMariusz Zaborski if (nvl == NULL) 15254f98da9SMariusz Zaborski return; 15354f98da9SMariusz Zaborski 15454f98da9SMariusz Zaborski ERRNO_SAVE(); 15554f98da9SMariusz Zaborski 15654f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 15754f98da9SMariusz Zaborski 15854f98da9SMariusz Zaborski while ((nvp = nvlist_first_nvpair(nvl)) != NULL) { 15954f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); 16054f98da9SMariusz Zaborski nvpair_free(nvp); 16154f98da9SMariusz Zaborski } 162347a39b4SMariusz Zaborski if (nvl->nvl_array_next != NULL) 163347a39b4SMariusz Zaborski nvpair_free_structure(nvl->nvl_array_next); 164347a39b4SMariusz Zaborski nvl->nvl_array_next = NULL; 165347a39b4SMariusz Zaborski nvl->nvl_parent = NULL; 16654f98da9SMariusz Zaborski nvl->nvl_magic = 0; 16754f98da9SMariusz Zaborski nv_free(nvl); 16854f98da9SMariusz Zaborski 16954f98da9SMariusz Zaborski ERRNO_RESTORE(); 17054f98da9SMariusz Zaborski } 17154f98da9SMariusz Zaborski 17254f98da9SMariusz Zaborski void 17354f98da9SMariusz Zaborski nvlist_set_error(nvlist_t *nvl, int error) 17454f98da9SMariusz Zaborski { 17554f98da9SMariusz Zaborski 17654f98da9SMariusz Zaborski PJDLOG_ASSERT(error != 0); 17754f98da9SMariusz Zaborski 17854f98da9SMariusz Zaborski /* 17954f98da9SMariusz Zaborski * Check for error != 0 so that we don't do the wrong thing if somebody 18054f98da9SMariusz Zaborski * tries to abuse this API when asserts are disabled. 18154f98da9SMariusz Zaborski */ 18254f98da9SMariusz Zaborski if (nvl != NULL && error != 0 && nvl->nvl_error == 0) 18354f98da9SMariusz Zaborski nvl->nvl_error = error; 18454f98da9SMariusz Zaborski } 18554f98da9SMariusz Zaborski 18654f98da9SMariusz Zaborski int 18754f98da9SMariusz Zaborski nvlist_error(const nvlist_t *nvl) 18854f98da9SMariusz Zaborski { 18954f98da9SMariusz Zaborski 19054f98da9SMariusz Zaborski if (nvl == NULL) 19154f98da9SMariusz Zaborski return (ENOMEM); 19254f98da9SMariusz Zaborski 19354f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 19454f98da9SMariusz Zaborski 19554f98da9SMariusz Zaborski return (nvl->nvl_error); 19654f98da9SMariusz Zaborski } 19754f98da9SMariusz Zaborski 19854f98da9SMariusz Zaborski nvpair_t * 19954f98da9SMariusz Zaborski nvlist_get_nvpair_parent(const nvlist_t *nvl) 20054f98da9SMariusz Zaborski { 20154f98da9SMariusz Zaborski 20254f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 20354f98da9SMariusz Zaborski 20454f98da9SMariusz Zaborski return (nvl->nvl_parent); 20554f98da9SMariusz Zaborski } 20654f98da9SMariusz Zaborski 20754f98da9SMariusz Zaborski const nvlist_t * 20854f98da9SMariusz Zaborski nvlist_get_parent(const nvlist_t *nvl, void **cookiep) 20954f98da9SMariusz Zaborski { 21054f98da9SMariusz Zaborski nvpair_t *nvp; 21154f98da9SMariusz Zaborski 21254f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 21354f98da9SMariusz Zaborski 21454f98da9SMariusz Zaborski nvp = nvl->nvl_parent; 21554f98da9SMariusz Zaborski if (cookiep != NULL) 21654f98da9SMariusz Zaborski *cookiep = nvp; 21754f98da9SMariusz Zaborski if (nvp == NULL) 21854f98da9SMariusz Zaborski return (NULL); 21954f98da9SMariusz Zaborski 22054f98da9SMariusz Zaborski return (nvpair_nvlist(nvp)); 22154f98da9SMariusz Zaborski } 22254f98da9SMariusz Zaborski 22354f98da9SMariusz Zaborski void 22454f98da9SMariusz Zaborski nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent) 22554f98da9SMariusz Zaborski { 22654f98da9SMariusz Zaborski 22754f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 22854f98da9SMariusz Zaborski 22954f98da9SMariusz Zaborski nvl->nvl_parent = parent; 23054f98da9SMariusz Zaborski } 23154f98da9SMariusz Zaborski 232347a39b4SMariusz Zaborski void 233347a39b4SMariusz Zaborski nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele) 234347a39b4SMariusz Zaborski { 235347a39b4SMariusz Zaborski 236347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 237347a39b4SMariusz Zaborski 2381b550329SMariusz Zaborski if (ele != NULL) { 239347a39b4SMariusz Zaborski nvl->nvl_flags |= NV_FLAG_IN_ARRAY; 2401b550329SMariusz Zaborski } else { 241347a39b4SMariusz Zaborski nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY; 2421b550329SMariusz Zaborski nv_free(nvl->nvl_array_next); 2431b550329SMariusz Zaborski } 244347a39b4SMariusz Zaborski 245347a39b4SMariusz Zaborski nvl->nvl_array_next = ele; 246347a39b4SMariusz Zaborski } 247347a39b4SMariusz Zaborski 248347a39b4SMariusz Zaborski bool 249347a39b4SMariusz Zaborski nvlist_in_array(const nvlist_t *nvl) 250347a39b4SMariusz Zaborski { 251347a39b4SMariusz Zaborski 252347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 253347a39b4SMariusz Zaborski 254347a39b4SMariusz Zaborski return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0); 255347a39b4SMariusz Zaborski } 256347a39b4SMariusz Zaborski 257347a39b4SMariusz Zaborski const nvlist_t * 258347a39b4SMariusz Zaborski nvlist_get_array_next(const nvlist_t *nvl) 259347a39b4SMariusz Zaborski { 260347a39b4SMariusz Zaborski nvpair_t *nvp; 261347a39b4SMariusz Zaborski 262347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 263347a39b4SMariusz Zaborski 264347a39b4SMariusz Zaborski nvp = nvl->nvl_array_next; 265347a39b4SMariusz Zaborski if (nvp == NULL) 266347a39b4SMariusz Zaborski return (NULL); 267347a39b4SMariusz Zaborski 268347a39b4SMariusz Zaborski return (nvpair_get_nvlist(nvp)); 269347a39b4SMariusz Zaborski } 270347a39b4SMariusz Zaborski 271347a39b4SMariusz Zaborski const nvlist_t * 272347a39b4SMariusz Zaborski nvlist_get_pararr(const nvlist_t *nvl, void **cookiep) 273347a39b4SMariusz Zaborski { 274347a39b4SMariusz Zaborski const nvlist_t *ret; 275347a39b4SMariusz Zaborski 276347a39b4SMariusz Zaborski ret = nvlist_get_array_next(nvl); 277347a39b4SMariusz Zaborski if (ret != NULL) { 278347a39b4SMariusz Zaborski if (cookiep != NULL) 279347a39b4SMariusz Zaborski *cookiep = NULL; 280347a39b4SMariusz Zaborski return (ret); 281347a39b4SMariusz Zaborski } 282347a39b4SMariusz Zaborski 28308016b31SMariusz Zaborski return (nvlist_get_parent(nvl, cookiep)); 284347a39b4SMariusz Zaborski } 285347a39b4SMariusz Zaborski 28654f98da9SMariusz Zaborski bool 28754f98da9SMariusz Zaborski nvlist_empty(const nvlist_t *nvl) 28854f98da9SMariusz Zaborski { 28954f98da9SMariusz Zaborski 29054f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 29154f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 29254f98da9SMariusz Zaborski 29354f98da9SMariusz Zaborski return (nvlist_first_nvpair(nvl) == NULL); 29454f98da9SMariusz Zaborski } 29554f98da9SMariusz Zaborski 29654f98da9SMariusz Zaborski int 29754f98da9SMariusz Zaborski nvlist_flags(const nvlist_t *nvl) 29854f98da9SMariusz Zaborski { 29954f98da9SMariusz Zaborski 30054f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 30154f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 30254f98da9SMariusz Zaborski 303347a39b4SMariusz Zaborski return (nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); 304347a39b4SMariusz Zaborski } 305347a39b4SMariusz Zaborski 306347a39b4SMariusz Zaborski void 307347a39b4SMariusz Zaborski nvlist_set_flags(nvlist_t *nvl, int flags) 308347a39b4SMariusz Zaborski { 309347a39b4SMariusz Zaborski 310347a39b4SMariusz Zaborski NVLIST_ASSERT(nvl); 311347a39b4SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 312347a39b4SMariusz Zaborski 313347a39b4SMariusz Zaborski nvl->nvl_flags = flags; 31454f98da9SMariusz Zaborski } 31554f98da9SMariusz Zaborski 3165ef231f6SMariusz Zaborski void 31754f98da9SMariusz Zaborski nvlist_report_missing(int type, const char *name) 31854f98da9SMariusz Zaborski { 31954f98da9SMariusz Zaborski 32054f98da9SMariusz Zaborski PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", 32154f98da9SMariusz Zaborski name, nvpair_type_string(type)); 32254f98da9SMariusz Zaborski } 32354f98da9SMariusz Zaborski 32454f98da9SMariusz Zaborski static nvpair_t * 32554f98da9SMariusz Zaborski nvlist_find(const nvlist_t *nvl, int type, const char *name) 32654f98da9SMariusz Zaborski { 32754f98da9SMariusz Zaborski nvpair_t *nvp; 32854f98da9SMariusz Zaborski 32954f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 33054f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 33154f98da9SMariusz Zaborski PJDLOG_ASSERT(type == NV_TYPE_NONE || 33254f98da9SMariusz Zaborski (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 33354f98da9SMariusz Zaborski 33454f98da9SMariusz Zaborski for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 33554f98da9SMariusz Zaborski nvp = nvlist_next_nvpair(nvl, nvp)) { 33654f98da9SMariusz Zaborski if (type != NV_TYPE_NONE && nvpair_type(nvp) != type) 33754f98da9SMariusz Zaborski continue; 33854f98da9SMariusz Zaborski if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) { 33954f98da9SMariusz Zaborski if (strcasecmp(nvpair_name(nvp), name) != 0) 34054f98da9SMariusz Zaborski continue; 34154f98da9SMariusz Zaborski } else { 34254f98da9SMariusz Zaborski if (strcmp(nvpair_name(nvp), name) != 0) 34354f98da9SMariusz Zaborski continue; 34454f98da9SMariusz Zaborski } 34554f98da9SMariusz Zaborski break; 34654f98da9SMariusz Zaborski } 34754f98da9SMariusz Zaborski 34854f98da9SMariusz Zaborski if (nvp == NULL) 34954f98da9SMariusz Zaborski ERRNO_SET(ENOENT); 35054f98da9SMariusz Zaborski 35154f98da9SMariusz Zaborski return (nvp); 35254f98da9SMariusz Zaborski } 35354f98da9SMariusz Zaborski 35454f98da9SMariusz Zaborski bool 35554f98da9SMariusz Zaborski nvlist_exists_type(const nvlist_t *nvl, const char *name, int type) 35654f98da9SMariusz Zaborski { 35754f98da9SMariusz Zaborski 35854f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 35954f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 36054f98da9SMariusz Zaborski PJDLOG_ASSERT(type == NV_TYPE_NONE || 36154f98da9SMariusz Zaborski (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 36254f98da9SMariusz Zaborski 36354f98da9SMariusz Zaborski return (nvlist_find(nvl, type, name) != NULL); 36454f98da9SMariusz Zaborski } 36554f98da9SMariusz Zaborski 36654f98da9SMariusz Zaborski void 36754f98da9SMariusz Zaborski nvlist_free_type(nvlist_t *nvl, const char *name, int type) 36854f98da9SMariusz Zaborski { 36954f98da9SMariusz Zaborski nvpair_t *nvp; 37054f98da9SMariusz Zaborski 37154f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 37254f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 37354f98da9SMariusz Zaborski PJDLOG_ASSERT(type == NV_TYPE_NONE || 37454f98da9SMariusz Zaborski (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 37554f98da9SMariusz Zaborski 37654f98da9SMariusz Zaborski nvp = nvlist_find(nvl, type, name); 37754f98da9SMariusz Zaborski if (nvp != NULL) 37854f98da9SMariusz Zaborski nvlist_free_nvpair(nvl, nvp); 37954f98da9SMariusz Zaborski else 38054f98da9SMariusz Zaborski nvlist_report_missing(type, name); 38154f98da9SMariusz Zaborski } 38254f98da9SMariusz Zaborski 38354f98da9SMariusz Zaborski nvlist_t * 38454f98da9SMariusz Zaborski nvlist_clone(const nvlist_t *nvl) 38554f98da9SMariusz Zaborski { 38654f98da9SMariusz Zaborski nvlist_t *newnvl; 38754f98da9SMariusz Zaborski nvpair_t *nvp, *newnvp; 38854f98da9SMariusz Zaborski 38954f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 39054f98da9SMariusz Zaborski 39154f98da9SMariusz Zaborski if (nvl->nvl_error != 0) { 39254f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 39354f98da9SMariusz Zaborski return (NULL); 39454f98da9SMariusz Zaborski } 39554f98da9SMariusz Zaborski 39654f98da9SMariusz Zaborski newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); 39754f98da9SMariusz Zaborski for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 39854f98da9SMariusz Zaborski nvp = nvlist_next_nvpair(nvl, nvp)) { 39954f98da9SMariusz Zaborski newnvp = nvpair_clone(nvp); 40054f98da9SMariusz Zaborski if (newnvp == NULL) 40154f98da9SMariusz Zaborski break; 40230740f45SMariusz Zaborski (void)nvlist_move_nvpair(newnvl, newnvp); 40354f98da9SMariusz Zaborski } 40454f98da9SMariusz Zaborski if (nvp != NULL) { 40554f98da9SMariusz Zaborski nvlist_destroy(newnvl); 40654f98da9SMariusz Zaborski return (NULL); 40754f98da9SMariusz Zaborski } 40854f98da9SMariusz Zaborski return (newnvl); 40954f98da9SMariusz Zaborski } 41054f98da9SMariusz Zaborski 41154f98da9SMariusz Zaborski #ifndef _KERNEL 41254f98da9SMariusz Zaborski static bool 41354f98da9SMariusz Zaborski nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level) 41454f98da9SMariusz Zaborski { 41554f98da9SMariusz Zaborski 41654f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 41754f98da9SMariusz Zaborski dprintf(fd, "%*serror: %d\n", level * 4, "", 41854f98da9SMariusz Zaborski nvlist_error(nvl)); 41954f98da9SMariusz Zaborski return (true); 42054f98da9SMariusz Zaborski } 42154f98da9SMariusz Zaborski 42254f98da9SMariusz Zaborski return (false); 42354f98da9SMariusz Zaborski } 42454f98da9SMariusz Zaborski 42554f98da9SMariusz Zaborski /* 42654f98da9SMariusz Zaborski * Dump content of nvlist. 42754f98da9SMariusz Zaborski */ 42854f98da9SMariusz Zaborski void 42954f98da9SMariusz Zaborski nvlist_dump(const nvlist_t *nvl, int fd) 43054f98da9SMariusz Zaborski { 43154f98da9SMariusz Zaborski const nvlist_t *tmpnvl; 43254f98da9SMariusz Zaborski nvpair_t *nvp, *tmpnvp; 43354f98da9SMariusz Zaborski void *cookie; 43454f98da9SMariusz Zaborski int level; 43554f98da9SMariusz Zaborski 43654f98da9SMariusz Zaborski level = 0; 43754f98da9SMariusz Zaborski if (nvlist_dump_error_check(nvl, fd, level)) 43854f98da9SMariusz Zaborski return; 43954f98da9SMariusz Zaborski 44054f98da9SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 44154f98da9SMariusz Zaborski while (nvp != NULL) { 44254f98da9SMariusz Zaborski dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), 44354f98da9SMariusz Zaborski nvpair_type_string(nvpair_type(nvp))); 44454f98da9SMariusz Zaborski switch (nvpair_type(nvp)) { 44554f98da9SMariusz Zaborski case NV_TYPE_NULL: 44654f98da9SMariusz Zaborski dprintf(fd, " null\n"); 44754f98da9SMariusz Zaborski break; 44854f98da9SMariusz Zaborski case NV_TYPE_BOOL: 44954f98da9SMariusz Zaborski dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? 45054f98da9SMariusz Zaborski "TRUE" : "FALSE"); 45154f98da9SMariusz Zaborski break; 45254f98da9SMariusz Zaborski case NV_TYPE_NUMBER: 45354f98da9SMariusz Zaborski dprintf(fd, " %ju (%jd) (0x%jx)\n", 45454f98da9SMariusz Zaborski (uintmax_t)nvpair_get_number(nvp), 45554f98da9SMariusz Zaborski (intmax_t)nvpair_get_number(nvp), 45654f98da9SMariusz Zaborski (uintmax_t)nvpair_get_number(nvp)); 45754f98da9SMariusz Zaborski break; 45854f98da9SMariusz Zaborski case NV_TYPE_STRING: 45954f98da9SMariusz Zaborski dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); 46054f98da9SMariusz Zaborski break; 46154f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 46254f98da9SMariusz Zaborski dprintf(fd, "\n"); 46354f98da9SMariusz Zaborski tmpnvl = nvpair_get_nvlist(nvp); 46454f98da9SMariusz Zaborski if (nvlist_dump_error_check(tmpnvl, fd, level + 1)) 46554f98da9SMariusz Zaborski break; 46654f98da9SMariusz Zaborski tmpnvp = nvlist_first_nvpair(tmpnvl); 46754f98da9SMariusz Zaborski if (tmpnvp != NULL) { 46854f98da9SMariusz Zaborski nvl = tmpnvl; 46954f98da9SMariusz Zaborski nvp = tmpnvp; 47054f98da9SMariusz Zaborski level++; 47154f98da9SMariusz Zaborski continue; 47254f98da9SMariusz Zaborski } 47354f98da9SMariusz Zaborski break; 47454f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 47554f98da9SMariusz Zaborski dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); 47654f98da9SMariusz Zaborski break; 47754f98da9SMariusz Zaborski case NV_TYPE_BINARY: 47854f98da9SMariusz Zaborski { 47954f98da9SMariusz Zaborski const unsigned char *binary; 48054f98da9SMariusz Zaborski unsigned int ii; 48154f98da9SMariusz Zaborski size_t size; 48254f98da9SMariusz Zaborski 48354f98da9SMariusz Zaborski binary = nvpair_get_binary(nvp, &size); 48454f98da9SMariusz Zaborski dprintf(fd, " %zu ", size); 48554f98da9SMariusz Zaborski for (ii = 0; ii < size; ii++) 48654f98da9SMariusz Zaborski dprintf(fd, "%02hhx", binary[ii]); 48754f98da9SMariusz Zaborski dprintf(fd, "\n"); 48854f98da9SMariusz Zaborski break; 48954f98da9SMariusz Zaborski } 490347a39b4SMariusz Zaborski case NV_TYPE_BOOL_ARRAY: 491347a39b4SMariusz Zaborski { 492347a39b4SMariusz Zaborski const bool *value; 493347a39b4SMariusz Zaborski unsigned int ii; 494347a39b4SMariusz Zaborski size_t nitems; 495347a39b4SMariusz Zaborski 496347a39b4SMariusz Zaborski value = nvpair_get_bool_array(nvp, &nitems); 497347a39b4SMariusz Zaborski dprintf(fd, " [ "); 498347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 499347a39b4SMariusz Zaborski dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE"); 500347a39b4SMariusz Zaborski if (ii != nitems - 1) 501347a39b4SMariusz Zaborski dprintf(fd, ", "); 502347a39b4SMariusz Zaborski } 503347a39b4SMariusz Zaborski dprintf(fd, " ]\n"); 504347a39b4SMariusz Zaborski break; 505347a39b4SMariusz Zaborski } 506347a39b4SMariusz Zaborski case NV_TYPE_STRING_ARRAY: 507347a39b4SMariusz Zaborski { 508347a39b4SMariusz Zaborski const char * const *value; 509347a39b4SMariusz Zaborski unsigned int ii; 510347a39b4SMariusz Zaborski size_t nitems; 511347a39b4SMariusz Zaborski 512347a39b4SMariusz Zaborski value = nvpair_get_string_array(nvp, &nitems); 513347a39b4SMariusz Zaborski dprintf(fd, " [ "); 514347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 515347a39b4SMariusz Zaborski if (value[ii] == NULL) 516347a39b4SMariusz Zaborski dprintf(fd, "NULL"); 517347a39b4SMariusz Zaborski else 518347a39b4SMariusz Zaborski dprintf(fd, "\"%s\"", value[ii]); 519347a39b4SMariusz Zaborski if (ii != nitems - 1) 520347a39b4SMariusz Zaborski dprintf(fd, ", "); 521347a39b4SMariusz Zaborski } 522347a39b4SMariusz Zaborski dprintf(fd, " ]\n"); 523347a39b4SMariusz Zaborski break; 524347a39b4SMariusz Zaborski } 525347a39b4SMariusz Zaborski case NV_TYPE_NUMBER_ARRAY: 526347a39b4SMariusz Zaborski { 527347a39b4SMariusz Zaborski const uint64_t *value; 528347a39b4SMariusz Zaborski unsigned int ii; 529347a39b4SMariusz Zaborski size_t nitems; 530347a39b4SMariusz Zaborski 531347a39b4SMariusz Zaborski value = nvpair_get_number_array(nvp, &nitems); 532347a39b4SMariusz Zaborski dprintf(fd, " [ "); 533347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 534347a39b4SMariusz Zaborski dprintf(fd, "%ju (%jd) (0x%jx)", 535347a39b4SMariusz Zaborski value[ii], value[ii], value[ii]); 536347a39b4SMariusz Zaborski if (ii != nitems - 1) 537347a39b4SMariusz Zaborski dprintf(fd, ", "); 538347a39b4SMariusz Zaborski } 539347a39b4SMariusz Zaborski dprintf(fd, " ]\n"); 540347a39b4SMariusz Zaborski break; 541347a39b4SMariusz Zaborski } 542347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 543347a39b4SMariusz Zaborski { 544347a39b4SMariusz Zaborski const int *value; 545347a39b4SMariusz Zaborski unsigned int ii; 546347a39b4SMariusz Zaborski size_t nitems; 547347a39b4SMariusz Zaborski 548347a39b4SMariusz Zaborski value = nvpair_get_descriptor_array(nvp, &nitems); 549347a39b4SMariusz Zaborski dprintf(fd, " [ "); 550347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 551347a39b4SMariusz Zaborski dprintf(fd, "%d", value[ii]); 552347a39b4SMariusz Zaborski if (ii != nitems - 1) 553347a39b4SMariusz Zaborski dprintf(fd, ", "); 554347a39b4SMariusz Zaborski } 555347a39b4SMariusz Zaborski dprintf(fd, " ]\n"); 556347a39b4SMariusz Zaborski break; 557347a39b4SMariusz Zaborski } 558347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 559347a39b4SMariusz Zaborski { 560347a39b4SMariusz Zaborski const nvlist_t * const *value; 561347a39b4SMariusz Zaborski unsigned int ii; 562347a39b4SMariusz Zaborski size_t nitems; 563347a39b4SMariusz Zaborski 564347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 565347a39b4SMariusz Zaborski dprintf(fd, " %zu\n", nitems); 566347a39b4SMariusz Zaborski tmpnvl = NULL; 567347a39b4SMariusz Zaborski tmpnvp = NULL; 568347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 569347a39b4SMariusz Zaborski if (nvlist_dump_error_check(value[ii], fd, 570347a39b4SMariusz Zaborski level + 1)) { 571347a39b4SMariusz Zaborski break; 572347a39b4SMariusz Zaborski } 573347a39b4SMariusz Zaborski 574347a39b4SMariusz Zaborski if (tmpnvl == NULL) { 575347a39b4SMariusz Zaborski tmpnvp = nvlist_first_nvpair(value[ii]); 576347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 577347a39b4SMariusz Zaborski tmpnvl = value[ii]; 578347a39b4SMariusz Zaborski } else { 579347a39b4SMariusz Zaborski dprintf(fd, "%*s,\n", 580347a39b4SMariusz Zaborski (level + 1) * 4, ""); 581347a39b4SMariusz Zaborski } 582347a39b4SMariusz Zaborski } 583347a39b4SMariusz Zaborski } 584347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 585347a39b4SMariusz Zaborski nvl = tmpnvl; 586347a39b4SMariusz Zaborski nvp = tmpnvp; 587347a39b4SMariusz Zaborski level++; 588347a39b4SMariusz Zaborski continue; 589347a39b4SMariusz Zaborski } 590347a39b4SMariusz Zaborski break; 591347a39b4SMariusz Zaborski } 59254f98da9SMariusz Zaborski default: 59354f98da9SMariusz Zaborski PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 59454f98da9SMariusz Zaborski } 59554f98da9SMariusz Zaborski 59654f98da9SMariusz Zaborski while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 597347a39b4SMariusz Zaborski do { 59854f98da9SMariusz Zaborski cookie = NULL; 599347a39b4SMariusz Zaborski if (nvlist_in_array(nvl)) 600347a39b4SMariusz Zaborski dprintf(fd, "%*s,\n", level * 4, ""); 601347a39b4SMariusz Zaborski nvl = nvlist_get_pararr(nvl, &cookie); 60254f98da9SMariusz Zaborski if (nvl == NULL) 60354f98da9SMariusz Zaborski return; 604347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) { 605347a39b4SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 606347a39b4SMariusz Zaborski } else { 60754f98da9SMariusz Zaborski nvp = cookie; 60854f98da9SMariusz Zaborski level--; 60954f98da9SMariusz Zaborski } 610347a39b4SMariusz Zaborski } while (nvp == NULL); 611347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) 612347a39b4SMariusz Zaborski break; 613347a39b4SMariusz Zaborski } 61454f98da9SMariusz Zaborski } 61554f98da9SMariusz Zaborski } 61654f98da9SMariusz Zaborski 61754f98da9SMariusz Zaborski void 61854f98da9SMariusz Zaborski nvlist_fdump(const nvlist_t *nvl, FILE *fp) 61954f98da9SMariusz Zaborski { 62054f98da9SMariusz Zaborski 62154f98da9SMariusz Zaborski fflush(fp); 62254f98da9SMariusz Zaborski nvlist_dump(nvl, fileno(fp)); 62354f98da9SMariusz Zaborski } 62454f98da9SMariusz Zaborski #endif 62554f98da9SMariusz Zaborski 62654f98da9SMariusz Zaborski /* 62754f98da9SMariusz Zaborski * The function obtains size of the nvlist after nvlist_pack(). 62854f98da9SMariusz Zaborski */ 62954f98da9SMariusz Zaborski size_t 63054f98da9SMariusz Zaborski nvlist_size(const nvlist_t *nvl) 63154f98da9SMariusz Zaborski { 63254f98da9SMariusz Zaborski const nvlist_t *tmpnvl; 633347a39b4SMariusz Zaborski const nvlist_t * const *nvlarray; 63454f98da9SMariusz Zaborski const nvpair_t *nvp, *tmpnvp; 63554f98da9SMariusz Zaborski void *cookie; 636347a39b4SMariusz Zaborski size_t size, nitems; 637347a39b4SMariusz Zaborski unsigned int ii; 63854f98da9SMariusz Zaborski 63954f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 64054f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 64154f98da9SMariusz Zaborski 64254f98da9SMariusz Zaborski size = sizeof(struct nvlist_header); 64354f98da9SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 64454f98da9SMariusz Zaborski while (nvp != NULL) { 64554f98da9SMariusz Zaborski size += nvpair_header_size(); 64654f98da9SMariusz Zaborski size += strlen(nvpair_name(nvp)) + 1; 64754f98da9SMariusz Zaborski if (nvpair_type(nvp) == NV_TYPE_NVLIST) { 64854f98da9SMariusz Zaborski size += sizeof(struct nvlist_header); 64954f98da9SMariusz Zaborski size += nvpair_header_size() + 1; 65054f98da9SMariusz Zaborski tmpnvl = nvpair_get_nvlist(nvp); 65154f98da9SMariusz Zaborski PJDLOG_ASSERT(tmpnvl->nvl_error == 0); 65254f98da9SMariusz Zaborski tmpnvp = nvlist_first_nvpair(tmpnvl); 65354f98da9SMariusz Zaborski if (tmpnvp != NULL) { 65454f98da9SMariusz Zaborski nvl = tmpnvl; 65554f98da9SMariusz Zaborski nvp = tmpnvp; 65654f98da9SMariusz Zaborski continue; 65754f98da9SMariusz Zaborski } 658347a39b4SMariusz Zaborski } else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) { 659347a39b4SMariusz Zaborski nvlarray = nvpair_get_nvlist_array(nvp, &nitems); 660347a39b4SMariusz Zaborski PJDLOG_ASSERT(nitems > 0); 661347a39b4SMariusz Zaborski 662347a39b4SMariusz Zaborski size += (nvpair_header_size() + 1) * nitems; 663347a39b4SMariusz Zaborski size += sizeof(struct nvlist_header) * nitems; 664347a39b4SMariusz Zaborski 665347a39b4SMariusz Zaborski tmpnvl = NULL; 666347a39b4SMariusz Zaborski tmpnvp = NULL; 667347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 668347a39b4SMariusz Zaborski PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0); 669347a39b4SMariusz Zaborski tmpnvp = nvlist_first_nvpair(nvlarray[ii]); 670347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 671347a39b4SMariusz Zaborski tmpnvl = nvlarray[ii]; 672347a39b4SMariusz Zaborski break; 673347a39b4SMariusz Zaborski } 674347a39b4SMariusz Zaborski } 675347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 676347a39b4SMariusz Zaborski nvp = tmpnvp; 677347a39b4SMariusz Zaborski nvl = tmpnvl; 678347a39b4SMariusz Zaborski continue; 679347a39b4SMariusz Zaborski } 680347a39b4SMariusz Zaborski 68154f98da9SMariusz Zaborski } else { 68254f98da9SMariusz Zaborski size += nvpair_size(nvp); 68354f98da9SMariusz Zaborski } 68454f98da9SMariusz Zaborski 68554f98da9SMariusz Zaborski while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 686347a39b4SMariusz Zaborski do { 68754f98da9SMariusz Zaborski cookie = NULL; 688347a39b4SMariusz Zaborski nvl = nvlist_get_pararr(nvl, &cookie); 68954f98da9SMariusz Zaborski if (nvl == NULL) 69054f98da9SMariusz Zaborski goto out; 691347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) { 692347a39b4SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 693347a39b4SMariusz Zaborski } else { 69454f98da9SMariusz Zaborski nvp = cookie; 69554f98da9SMariusz Zaborski } 696347a39b4SMariusz Zaborski } while (nvp == NULL); 697347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) 698347a39b4SMariusz Zaborski break; 699347a39b4SMariusz Zaborski } 70054f98da9SMariusz Zaborski } 70154f98da9SMariusz Zaborski 70254f98da9SMariusz Zaborski out: 70354f98da9SMariusz Zaborski return (size); 70454f98da9SMariusz Zaborski } 70554f98da9SMariusz Zaborski 70654f98da9SMariusz Zaborski #ifndef _KERNEL 70754f98da9SMariusz Zaborski static int * 70854f98da9SMariusz Zaborski nvlist_xdescriptors(const nvlist_t *nvl, int *descs) 70954f98da9SMariusz Zaborski { 71054f98da9SMariusz Zaborski nvpair_t *nvp; 71154f98da9SMariusz Zaborski int type; 71254f98da9SMariusz Zaborski 71354f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 71454f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 71554f98da9SMariusz Zaborski 71654f98da9SMariusz Zaborski nvp = NULL; 71754f98da9SMariusz Zaborski do { 71808016b31SMariusz Zaborski while (nvlist_next(nvl, &type, (void *)&nvp) != NULL) { 71954f98da9SMariusz Zaborski switch (type) { 72054f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 72154f98da9SMariusz Zaborski *descs = nvpair_get_descriptor(nvp); 72254f98da9SMariusz Zaborski descs++; 72354f98da9SMariusz Zaborski break; 724347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 725347a39b4SMariusz Zaborski { 726347a39b4SMariusz Zaborski const int *value; 727347a39b4SMariusz Zaborski size_t nitems; 728347a39b4SMariusz Zaborski unsigned int ii; 729347a39b4SMariusz Zaborski 730347a39b4SMariusz Zaborski value = nvpair_get_descriptor_array(nvp, 731347a39b4SMariusz Zaborski &nitems); 732347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 733347a39b4SMariusz Zaborski *descs = value[ii]; 734347a39b4SMariusz Zaborski descs++; 735347a39b4SMariusz Zaborski } 736347a39b4SMariusz Zaborski break; 737347a39b4SMariusz Zaborski } 73854f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 73954f98da9SMariusz Zaborski nvl = nvpair_get_nvlist(nvp); 74054f98da9SMariusz Zaborski nvp = NULL; 74154f98da9SMariusz Zaborski break; 742347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 743347a39b4SMariusz Zaborski { 744347a39b4SMariusz Zaborski const nvlist_t * const *value; 745347a39b4SMariusz Zaborski size_t nitems; 746347a39b4SMariusz Zaborski 747347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 748347a39b4SMariusz Zaborski PJDLOG_ASSERT(value != NULL); 749347a39b4SMariusz Zaborski PJDLOG_ASSERT(nitems > 0); 750347a39b4SMariusz Zaborski 751347a39b4SMariusz Zaborski nvl = value[0]; 752347a39b4SMariusz Zaborski nvp = NULL; 753347a39b4SMariusz Zaborski break; 75454f98da9SMariusz Zaborski } 75554f98da9SMariusz Zaborski } 756347a39b4SMariusz Zaborski } 75708016b31SMariusz Zaborski } while ((nvl = nvlist_get_pararr(nvl, (void *)&nvp)) != NULL); 75854f98da9SMariusz Zaborski 75954f98da9SMariusz Zaborski return (descs); 76054f98da9SMariusz Zaborski } 76154f98da9SMariusz Zaborski #endif 76254f98da9SMariusz Zaborski 76354f98da9SMariusz Zaborski #ifndef _KERNEL 76454f98da9SMariusz Zaborski int * 76554f98da9SMariusz Zaborski nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp) 76654f98da9SMariusz Zaborski { 76754f98da9SMariusz Zaborski size_t nitems; 76854f98da9SMariusz Zaborski int *fds; 76954f98da9SMariusz Zaborski 77054f98da9SMariusz Zaborski nitems = nvlist_ndescriptors(nvl); 77154f98da9SMariusz Zaborski fds = nv_malloc(sizeof(fds[0]) * (nitems + 1)); 77254f98da9SMariusz Zaborski if (fds == NULL) 77354f98da9SMariusz Zaborski return (NULL); 77454f98da9SMariusz Zaborski if (nitems > 0) 77554f98da9SMariusz Zaborski nvlist_xdescriptors(nvl, fds); 77654f98da9SMariusz Zaborski fds[nitems] = -1; 77754f98da9SMariusz Zaborski if (nitemsp != NULL) 77854f98da9SMariusz Zaborski *nitemsp = nitems; 77954f98da9SMariusz Zaborski return (fds); 78054f98da9SMariusz Zaborski } 78154f98da9SMariusz Zaborski #endif 78254f98da9SMariusz Zaborski 78354f98da9SMariusz Zaborski size_t 78454f98da9SMariusz Zaborski nvlist_ndescriptors(const nvlist_t *nvl) 78554f98da9SMariusz Zaborski { 78654f98da9SMariusz Zaborski #ifndef _KERNEL 78754f98da9SMariusz Zaborski nvpair_t *nvp; 78854f98da9SMariusz Zaborski size_t ndescs; 78954f98da9SMariusz Zaborski int type; 79054f98da9SMariusz Zaborski 79154f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 79254f98da9SMariusz Zaborski PJDLOG_ASSERT(nvl->nvl_error == 0); 79354f98da9SMariusz Zaborski 79454f98da9SMariusz Zaborski ndescs = 0; 79554f98da9SMariusz Zaborski nvp = NULL; 79654f98da9SMariusz Zaborski do { 79708016b31SMariusz Zaborski while (nvlist_next(nvl, &type, (void *)&nvp) != NULL) { 79854f98da9SMariusz Zaborski switch (type) { 79954f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 80054f98da9SMariusz Zaborski ndescs++; 80154f98da9SMariusz Zaborski break; 80254f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 80354f98da9SMariusz Zaborski nvl = nvpair_get_nvlist(nvp); 80454f98da9SMariusz Zaborski nvp = NULL; 80554f98da9SMariusz Zaborski break; 806347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 807347a39b4SMariusz Zaborski { 808347a39b4SMariusz Zaborski const nvlist_t * const *value; 809347a39b4SMariusz Zaborski size_t nitems; 810347a39b4SMariusz Zaborski 811347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 812347a39b4SMariusz Zaborski PJDLOG_ASSERT(value != NULL); 813347a39b4SMariusz Zaborski PJDLOG_ASSERT(nitems > 0); 814347a39b4SMariusz Zaborski 815347a39b4SMariusz Zaborski nvl = value[0]; 816347a39b4SMariusz Zaborski nvp = NULL; 817347a39b4SMariusz Zaborski break; 818347a39b4SMariusz Zaborski } 819347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 820347a39b4SMariusz Zaborski { 821347a39b4SMariusz Zaborski size_t nitems; 822347a39b4SMariusz Zaborski 823347a39b4SMariusz Zaborski (void)nvpair_get_descriptor_array(nvp, 824347a39b4SMariusz Zaborski &nitems); 825347a39b4SMariusz Zaborski ndescs += nitems; 826347a39b4SMariusz Zaborski break; 82754f98da9SMariusz Zaborski } 82854f98da9SMariusz Zaborski } 829347a39b4SMariusz Zaborski } 83008016b31SMariusz Zaborski } while ((nvl = nvlist_get_pararr(nvl, (void *)&nvp)) != NULL); 83154f98da9SMariusz Zaborski 83254f98da9SMariusz Zaborski return (ndescs); 83354f98da9SMariusz Zaborski #else 83454f98da9SMariusz Zaborski return (0); 83554f98da9SMariusz Zaborski #endif 83654f98da9SMariusz Zaborski } 83754f98da9SMariusz Zaborski 83854f98da9SMariusz Zaborski static unsigned char * 83954f98da9SMariusz Zaborski nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp) 84054f98da9SMariusz Zaborski { 84154f98da9SMariusz Zaborski struct nvlist_header nvlhdr; 84254f98da9SMariusz Zaborski 84354f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 84454f98da9SMariusz Zaborski 84554f98da9SMariusz Zaborski nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC; 84654f98da9SMariusz Zaborski nvlhdr.nvlh_version = NVLIST_HEADER_VERSION; 84754f98da9SMariusz Zaborski nvlhdr.nvlh_flags = nvl->nvl_flags; 84854f98da9SMariusz Zaborski #if BYTE_ORDER == BIG_ENDIAN 84954f98da9SMariusz Zaborski nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN; 85054f98da9SMariusz Zaborski #endif 85154f98da9SMariusz Zaborski nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl); 85254f98da9SMariusz Zaborski nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr); 85354f98da9SMariusz Zaborski PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr)); 85454f98da9SMariusz Zaborski memcpy(ptr, &nvlhdr, sizeof(nvlhdr)); 85554f98da9SMariusz Zaborski ptr += sizeof(nvlhdr); 85654f98da9SMariusz Zaborski *leftp -= sizeof(nvlhdr); 85754f98da9SMariusz Zaborski 85854f98da9SMariusz Zaborski return (ptr); 85954f98da9SMariusz Zaborski } 86054f98da9SMariusz Zaborski 86154f98da9SMariusz Zaborski static void * 86254f98da9SMariusz Zaborski nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) 86354f98da9SMariusz Zaborski { 86454f98da9SMariusz Zaborski unsigned char *buf, *ptr; 86554f98da9SMariusz Zaborski size_t left, size; 86654f98da9SMariusz Zaborski const nvlist_t *tmpnvl; 86754f98da9SMariusz Zaborski nvpair_t *nvp, *tmpnvp; 86854f98da9SMariusz Zaborski void *cookie; 86954f98da9SMariusz Zaborski 87054f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 87154f98da9SMariusz Zaborski 87254f98da9SMariusz Zaborski if (nvl->nvl_error != 0) { 87354f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 87454f98da9SMariusz Zaborski return (NULL); 87554f98da9SMariusz Zaborski } 87654f98da9SMariusz Zaborski 87754f98da9SMariusz Zaborski size = nvlist_size(nvl); 87854f98da9SMariusz Zaborski buf = nv_malloc(size); 87954f98da9SMariusz Zaborski if (buf == NULL) 88054f98da9SMariusz Zaborski return (NULL); 88154f98da9SMariusz Zaborski 88254f98da9SMariusz Zaborski ptr = buf; 88354f98da9SMariusz Zaborski left = size; 88454f98da9SMariusz Zaborski 88554f98da9SMariusz Zaborski ptr = nvlist_pack_header(nvl, ptr, &left); 88654f98da9SMariusz Zaborski 88754f98da9SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 88854f98da9SMariusz Zaborski while (nvp != NULL) { 88954f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 89054f98da9SMariusz Zaborski 89154f98da9SMariusz Zaborski nvpair_init_datasize(nvp); 89254f98da9SMariusz Zaborski ptr = nvpair_pack_header(nvp, ptr, &left); 893c68f8061SMariusz Zaborski if (ptr == NULL) 894c68f8061SMariusz Zaborski goto fail; 89554f98da9SMariusz Zaborski switch (nvpair_type(nvp)) { 89654f98da9SMariusz Zaborski case NV_TYPE_NULL: 89754f98da9SMariusz Zaborski ptr = nvpair_pack_null(nvp, ptr, &left); 89854f98da9SMariusz Zaborski break; 89954f98da9SMariusz Zaborski case NV_TYPE_BOOL: 90054f98da9SMariusz Zaborski ptr = nvpair_pack_bool(nvp, ptr, &left); 90154f98da9SMariusz Zaborski break; 90254f98da9SMariusz Zaborski case NV_TYPE_NUMBER: 90354f98da9SMariusz Zaborski ptr = nvpair_pack_number(nvp, ptr, &left); 90454f98da9SMariusz Zaborski break; 90554f98da9SMariusz Zaborski case NV_TYPE_STRING: 90654f98da9SMariusz Zaborski ptr = nvpair_pack_string(nvp, ptr, &left); 90754f98da9SMariusz Zaborski break; 90854f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 90954f98da9SMariusz Zaborski tmpnvl = nvpair_get_nvlist(nvp); 91054f98da9SMariusz Zaborski ptr = nvlist_pack_header(tmpnvl, ptr, &left); 91154f98da9SMariusz Zaborski if (ptr == NULL) 912c68f8061SMariusz Zaborski goto fail; 91354f98da9SMariusz Zaborski tmpnvp = nvlist_first_nvpair(tmpnvl); 91454f98da9SMariusz Zaborski if (tmpnvp != NULL) { 91554f98da9SMariusz Zaborski nvl = tmpnvl; 91654f98da9SMariusz Zaborski nvp = tmpnvp; 91754f98da9SMariusz Zaborski continue; 91854f98da9SMariusz Zaborski } 91954f98da9SMariusz Zaborski ptr = nvpair_pack_nvlist_up(ptr, &left); 92054f98da9SMariusz Zaborski break; 92154f98da9SMariusz Zaborski #ifndef _KERNEL 92254f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 92354f98da9SMariusz Zaborski ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left); 92454f98da9SMariusz Zaborski break; 925347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 926347a39b4SMariusz Zaborski ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp, 927347a39b4SMariusz Zaborski &left); 928347a39b4SMariusz Zaborski break; 92954f98da9SMariusz Zaborski #endif 93054f98da9SMariusz Zaborski case NV_TYPE_BINARY: 93154f98da9SMariusz Zaborski ptr = nvpair_pack_binary(nvp, ptr, &left); 93254f98da9SMariusz Zaborski break; 933347a39b4SMariusz Zaborski case NV_TYPE_BOOL_ARRAY: 934347a39b4SMariusz Zaborski ptr = nvpair_pack_bool_array(nvp, ptr, &left); 935347a39b4SMariusz Zaborski break; 936347a39b4SMariusz Zaborski case NV_TYPE_NUMBER_ARRAY: 937347a39b4SMariusz Zaborski ptr = nvpair_pack_number_array(nvp, ptr, &left); 938347a39b4SMariusz Zaborski break; 939347a39b4SMariusz Zaborski case NV_TYPE_STRING_ARRAY: 940347a39b4SMariusz Zaborski ptr = nvpair_pack_string_array(nvp, ptr, &left); 941347a39b4SMariusz Zaborski break; 942347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 943347a39b4SMariusz Zaborski { 944347a39b4SMariusz Zaborski const nvlist_t * const * value; 945347a39b4SMariusz Zaborski size_t nitems; 946347a39b4SMariusz Zaborski unsigned int ii; 947347a39b4SMariusz Zaborski 948347a39b4SMariusz Zaborski tmpnvl = NULL; 949347a39b4SMariusz Zaborski value = nvpair_get_nvlist_array(nvp, &nitems); 950347a39b4SMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 951347a39b4SMariusz Zaborski ptr = nvlist_pack_header(value[ii], ptr, &left); 952347a39b4SMariusz Zaborski if (ptr == NULL) 953347a39b4SMariusz Zaborski goto out; 954347a39b4SMariusz Zaborski tmpnvp = nvlist_first_nvpair(value[ii]); 955347a39b4SMariusz Zaborski if (tmpnvp != NULL) { 956347a39b4SMariusz Zaborski tmpnvl = value[ii]; 957347a39b4SMariusz Zaborski break; 958347a39b4SMariusz Zaborski } 959347a39b4SMariusz Zaborski ptr = nvpair_pack_nvlist_array_next(ptr, &left); 960347a39b4SMariusz Zaborski if (ptr == NULL) 961347a39b4SMariusz Zaborski goto out; 962347a39b4SMariusz Zaborski } 963347a39b4SMariusz Zaborski if (tmpnvl != NULL) { 964347a39b4SMariusz Zaborski nvl = tmpnvl; 965347a39b4SMariusz Zaborski nvp = tmpnvp; 966347a39b4SMariusz Zaborski continue; 967347a39b4SMariusz Zaborski } 968347a39b4SMariusz Zaborski break; 969347a39b4SMariusz Zaborski } 97054f98da9SMariusz Zaborski default: 97154f98da9SMariusz Zaborski PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 97254f98da9SMariusz Zaborski } 973c68f8061SMariusz Zaborski if (ptr == NULL) 974c68f8061SMariusz Zaborski goto fail; 97554f98da9SMariusz Zaborski while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 976347a39b4SMariusz Zaborski do { 97754f98da9SMariusz Zaborski cookie = NULL; 978347a39b4SMariusz Zaborski if (nvlist_in_array(nvl)) { 979347a39b4SMariusz Zaborski ptr = nvpair_pack_nvlist_array_next(ptr, 980347a39b4SMariusz Zaborski &left); 981347a39b4SMariusz Zaborski if (ptr == NULL) 982347a39b4SMariusz Zaborski goto fail; 983347a39b4SMariusz Zaborski } 984347a39b4SMariusz Zaborski nvl = nvlist_get_pararr(nvl, &cookie); 98554f98da9SMariusz Zaborski if (nvl == NULL) 98654f98da9SMariusz Zaborski goto out; 987347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) { 988347a39b4SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 989347a39b4SMariusz Zaborski ptr = nvlist_pack_header(nvl, ptr, 990347a39b4SMariusz Zaborski &left); 991347a39b4SMariusz Zaborski if (ptr == NULL) 992347a39b4SMariusz Zaborski goto fail; 993347a39b4SMariusz Zaborski } else if (nvpair_type((nvpair_t *)cookie) != 994347a39b4SMariusz Zaborski NV_TYPE_NVLIST_ARRAY) { 99554f98da9SMariusz Zaborski ptr = nvpair_pack_nvlist_up(ptr, &left); 99654f98da9SMariusz Zaborski if (ptr == NULL) 997c68f8061SMariusz Zaborski goto fail; 998347a39b4SMariusz Zaborski nvp = cookie; 999347a39b4SMariusz Zaborski } else { 1000347a39b4SMariusz Zaborski nvp = cookie; 1001347a39b4SMariusz Zaborski } 1002347a39b4SMariusz Zaborski } while (nvp == NULL); 1003347a39b4SMariusz Zaborski if (nvlist_in_array(nvl) && cookie == NULL) 1004347a39b4SMariusz Zaborski break; 100554f98da9SMariusz Zaborski } 100654f98da9SMariusz Zaborski } 100754f98da9SMariusz Zaborski 100854f98da9SMariusz Zaborski out: 100954f98da9SMariusz Zaborski if (sizep != NULL) 101054f98da9SMariusz Zaborski *sizep = size; 101154f98da9SMariusz Zaborski return (buf); 1012c68f8061SMariusz Zaborski fail: 1013c68f8061SMariusz Zaborski nv_free(buf); 1014c68f8061SMariusz Zaborski return (NULL); 101554f98da9SMariusz Zaborski } 101654f98da9SMariusz Zaborski 101754f98da9SMariusz Zaborski void * 101854f98da9SMariusz Zaborski nvlist_pack(const nvlist_t *nvl, size_t *sizep) 101954f98da9SMariusz Zaborski { 102054f98da9SMariusz Zaborski 102154f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 102254f98da9SMariusz Zaborski 102354f98da9SMariusz Zaborski if (nvl->nvl_error != 0) { 102454f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 102554f98da9SMariusz Zaborski return (NULL); 102654f98da9SMariusz Zaborski } 102754f98da9SMariusz Zaborski 102854f98da9SMariusz Zaborski if (nvlist_ndescriptors(nvl) > 0) { 102954f98da9SMariusz Zaborski ERRNO_SET(EOPNOTSUPP); 103054f98da9SMariusz Zaborski return (NULL); 103154f98da9SMariusz Zaborski } 103254f98da9SMariusz Zaborski 103354f98da9SMariusz Zaborski return (nvlist_xpack(nvl, NULL, sizep)); 103454f98da9SMariusz Zaborski } 103554f98da9SMariusz Zaborski 103654f98da9SMariusz Zaborski static bool 103754f98da9SMariusz Zaborski nvlist_check_header(struct nvlist_header *nvlhdrp) 103854f98da9SMariusz Zaborski { 103954f98da9SMariusz Zaborski 104054f98da9SMariusz Zaborski if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { 104154f98da9SMariusz Zaborski ERRNO_SET(EINVAL); 104254f98da9SMariusz Zaborski return (false); 104354f98da9SMariusz Zaborski } 104454f98da9SMariusz Zaborski if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { 104554f98da9SMariusz Zaborski ERRNO_SET(EINVAL); 104654f98da9SMariusz Zaborski return (false); 104754f98da9SMariusz Zaborski } 104854f98da9SMariusz Zaborski #if BYTE_ORDER == BIG_ENDIAN 104954f98da9SMariusz Zaborski if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) { 105054f98da9SMariusz Zaborski nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size); 105154f98da9SMariusz Zaborski nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors); 105254f98da9SMariusz Zaborski } 105354f98da9SMariusz Zaborski #else 105454f98da9SMariusz Zaborski if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) { 105554f98da9SMariusz Zaborski nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size); 105654f98da9SMariusz Zaborski nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); 105754f98da9SMariusz Zaborski } 105854f98da9SMariusz Zaborski #endif 105954f98da9SMariusz Zaborski return (true); 106054f98da9SMariusz Zaborski } 106154f98da9SMariusz Zaborski 106254f98da9SMariusz Zaborski const unsigned char * 106354f98da9SMariusz Zaborski nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, 106454f98da9SMariusz Zaborski bool *isbep, size_t *leftp) 106554f98da9SMariusz Zaborski { 106654f98da9SMariusz Zaborski struct nvlist_header nvlhdr; 1067347a39b4SMariusz Zaborski int inarrayf; 106854f98da9SMariusz Zaborski 106954f98da9SMariusz Zaborski if (*leftp < sizeof(nvlhdr)) 107054f98da9SMariusz Zaborski goto failed; 107154f98da9SMariusz Zaborski 107254f98da9SMariusz Zaborski memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); 107354f98da9SMariusz Zaborski 107454f98da9SMariusz Zaborski if (!nvlist_check_header(&nvlhdr)) 107554f98da9SMariusz Zaborski goto failed; 107654f98da9SMariusz Zaborski 107754f98da9SMariusz Zaborski if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) 107854f98da9SMariusz Zaborski goto failed; 107954f98da9SMariusz Zaborski 108054f98da9SMariusz Zaborski /* 108154f98da9SMariusz Zaborski * nvlh_descriptors might be smaller than nfds in embedded nvlists. 108254f98da9SMariusz Zaborski */ 108354f98da9SMariusz Zaborski if (nvlhdr.nvlh_descriptors > nfds) 108454f98da9SMariusz Zaborski goto failed; 108554f98da9SMariusz Zaborski 108654f98da9SMariusz Zaborski if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) 108754f98da9SMariusz Zaborski goto failed; 108854f98da9SMariusz Zaborski 1089347a39b4SMariusz Zaborski inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY); 1090347a39b4SMariusz Zaborski nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf; 109154f98da9SMariusz Zaborski 109254f98da9SMariusz Zaborski ptr += sizeof(nvlhdr); 109354f98da9SMariusz Zaborski if (isbep != NULL) 109454f98da9SMariusz Zaborski *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0); 109554f98da9SMariusz Zaborski *leftp -= sizeof(nvlhdr); 109654f98da9SMariusz Zaborski 109754f98da9SMariusz Zaborski return (ptr); 109854f98da9SMariusz Zaborski failed: 109954f98da9SMariusz Zaborski ERRNO_SET(EINVAL); 110054f98da9SMariusz Zaborski return (NULL); 110154f98da9SMariusz Zaborski } 110254f98da9SMariusz Zaborski 110354f98da9SMariusz Zaborski static nvlist_t * 110454f98da9SMariusz Zaborski nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds, 110554f98da9SMariusz Zaborski int flags) 110654f98da9SMariusz Zaborski { 110754f98da9SMariusz Zaborski const unsigned char *ptr; 1108347a39b4SMariusz Zaborski nvlist_t *nvl, *retnvl, *tmpnvl, *array; 110954f98da9SMariusz Zaborski nvpair_t *nvp; 111054f98da9SMariusz Zaborski size_t left; 111154f98da9SMariusz Zaborski bool isbe; 111254f98da9SMariusz Zaborski 111354f98da9SMariusz Zaborski PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 111454f98da9SMariusz Zaborski 111554f98da9SMariusz Zaborski left = size; 111654f98da9SMariusz Zaborski ptr = buf; 111754f98da9SMariusz Zaborski 1118347a39b4SMariusz Zaborski tmpnvl = array = NULL; 111954f98da9SMariusz Zaborski nvl = retnvl = nvlist_create(0); 112054f98da9SMariusz Zaborski if (nvl == NULL) 112154f98da9SMariusz Zaborski goto failed; 112254f98da9SMariusz Zaborski 112354f98da9SMariusz Zaborski ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); 112454f98da9SMariusz Zaborski if (ptr == NULL) 112554f98da9SMariusz Zaborski goto failed; 112654f98da9SMariusz Zaborski if (nvl->nvl_flags != flags) { 112754f98da9SMariusz Zaborski ERRNO_SET(EILSEQ); 112854f98da9SMariusz Zaborski goto failed; 112954f98da9SMariusz Zaborski } 113054f98da9SMariusz Zaborski 113154f98da9SMariusz Zaborski while (left > 0) { 113254f98da9SMariusz Zaborski ptr = nvpair_unpack(isbe, ptr, &left, &nvp); 113354f98da9SMariusz Zaborski if (ptr == NULL) 113454f98da9SMariusz Zaborski goto failed; 113554f98da9SMariusz Zaborski switch (nvpair_type(nvp)) { 113654f98da9SMariusz Zaborski case NV_TYPE_NULL: 113754f98da9SMariusz Zaborski ptr = nvpair_unpack_null(isbe, nvp, ptr, &left); 113854f98da9SMariusz Zaborski break; 113954f98da9SMariusz Zaborski case NV_TYPE_BOOL: 114054f98da9SMariusz Zaborski ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left); 114154f98da9SMariusz Zaborski break; 114254f98da9SMariusz Zaborski case NV_TYPE_NUMBER: 114354f98da9SMariusz Zaborski ptr = nvpair_unpack_number(isbe, nvp, ptr, &left); 114454f98da9SMariusz Zaborski break; 114554f98da9SMariusz Zaborski case NV_TYPE_STRING: 114654f98da9SMariusz Zaborski ptr = nvpair_unpack_string(isbe, nvp, ptr, &left); 114754f98da9SMariusz Zaborski break; 114854f98da9SMariusz Zaborski case NV_TYPE_NVLIST: 114954f98da9SMariusz Zaborski ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds, 115054f98da9SMariusz Zaborski &tmpnvl); 115151dae13fSMariusz Zaborski if (tmpnvl == NULL || ptr == NULL) 115251dae13fSMariusz Zaborski goto failed; 115354f98da9SMariusz Zaborski nvlist_set_parent(tmpnvl, nvp); 115454f98da9SMariusz Zaborski break; 115554f98da9SMariusz Zaborski #ifndef _KERNEL 115654f98da9SMariusz Zaborski case NV_TYPE_DESCRIPTOR: 115754f98da9SMariusz Zaborski ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left, 115854f98da9SMariusz Zaborski fds, nfds); 115954f98da9SMariusz Zaborski break; 1160347a39b4SMariusz Zaborski case NV_TYPE_DESCRIPTOR_ARRAY: 1161347a39b4SMariusz Zaborski ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr, 1162347a39b4SMariusz Zaborski &left, fds, nfds); 1163347a39b4SMariusz Zaborski break; 116454f98da9SMariusz Zaborski #endif 116554f98da9SMariusz Zaborski case NV_TYPE_BINARY: 116654f98da9SMariusz Zaborski ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left); 116754f98da9SMariusz Zaborski break; 116854f98da9SMariusz Zaborski case NV_TYPE_NVLIST_UP: 116954f98da9SMariusz Zaborski if (nvl->nvl_parent == NULL) 117054f98da9SMariusz Zaborski goto failed; 117154f98da9SMariusz Zaborski nvl = nvpair_nvlist(nvl->nvl_parent); 117254f98da9SMariusz Zaborski nvpair_free_structure(nvp); 117354f98da9SMariusz Zaborski continue; 1174347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY_NEXT: 1175347a39b4SMariusz Zaborski if (nvl->nvl_array_next == NULL) { 1176347a39b4SMariusz Zaborski if (nvl->nvl_parent == NULL) 1177347a39b4SMariusz Zaborski goto failed; 1178347a39b4SMariusz Zaborski nvl = nvpair_nvlist(nvl->nvl_parent); 1179347a39b4SMariusz Zaborski } else { 1180347a39b4SMariusz Zaborski nvl = __DECONST(nvlist_t *, 1181347a39b4SMariusz Zaborski nvlist_get_array_next(nvl)); 1182347a39b4SMariusz Zaborski ptr = nvlist_unpack_header(nvl, ptr, nfds, 1183347a39b4SMariusz Zaborski &isbe, &left); 1184347a39b4SMariusz Zaborski if (ptr == NULL) 1185347a39b4SMariusz Zaborski goto failed; 1186347a39b4SMariusz Zaborski } 1187347a39b4SMariusz Zaborski nvpair_free_structure(nvp); 1188347a39b4SMariusz Zaborski continue; 1189347a39b4SMariusz Zaborski case NV_TYPE_BOOL_ARRAY: 1190347a39b4SMariusz Zaborski ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left); 1191347a39b4SMariusz Zaborski break; 1192347a39b4SMariusz Zaborski case NV_TYPE_NUMBER_ARRAY: 1193347a39b4SMariusz Zaborski ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left); 1194347a39b4SMariusz Zaborski break; 1195347a39b4SMariusz Zaborski case NV_TYPE_STRING_ARRAY: 1196347a39b4SMariusz Zaborski ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left); 1197347a39b4SMariusz Zaborski break; 1198347a39b4SMariusz Zaborski case NV_TYPE_NVLIST_ARRAY: 1199347a39b4SMariusz Zaborski ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left, 1200347a39b4SMariusz Zaborski &array); 1201347a39b4SMariusz Zaborski if (ptr == NULL) 1202347a39b4SMariusz Zaborski goto failed; 12031dacabe1SMariusz Zaborski PJDLOG_ASSERT(array != NULL); 1204347a39b4SMariusz Zaborski tmpnvl = array; 12051dacabe1SMariusz Zaborski do { 1206347a39b4SMariusz Zaborski nvlist_set_parent(array, nvp); 1207347a39b4SMariusz Zaborski array = __DECONST(nvlist_t *, 1208347a39b4SMariusz Zaborski nvlist_get_array_next(array)); 12091dacabe1SMariusz Zaborski } while (array != NULL); 1210347a39b4SMariusz Zaborski ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe, 1211347a39b4SMariusz Zaborski &left); 1212347a39b4SMariusz Zaborski break; 121354f98da9SMariusz Zaborski default: 121454f98da9SMariusz Zaborski PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 121554f98da9SMariusz Zaborski } 121654f98da9SMariusz Zaborski if (ptr == NULL) 121754f98da9SMariusz Zaborski goto failed; 121830740f45SMariusz Zaborski if (!nvlist_move_nvpair(nvl, nvp)) 121930740f45SMariusz Zaborski goto failed; 122054f98da9SMariusz Zaborski if (tmpnvl != NULL) { 122154f98da9SMariusz Zaborski nvl = tmpnvl; 122254f98da9SMariusz Zaborski tmpnvl = NULL; 122354f98da9SMariusz Zaborski } 122454f98da9SMariusz Zaborski } 122554f98da9SMariusz Zaborski 122654f98da9SMariusz Zaborski return (retnvl); 122754f98da9SMariusz Zaborski failed: 122854f98da9SMariusz Zaborski nvlist_destroy(retnvl); 122954f98da9SMariusz Zaborski return (NULL); 123054f98da9SMariusz Zaborski } 123154f98da9SMariusz Zaborski 123254f98da9SMariusz Zaborski nvlist_t * 123354f98da9SMariusz Zaborski nvlist_unpack(const void *buf, size_t size, int flags) 123454f98da9SMariusz Zaborski { 123554f98da9SMariusz Zaborski 123654f98da9SMariusz Zaborski return (nvlist_xunpack(buf, size, NULL, 0, flags)); 123754f98da9SMariusz Zaborski } 123854f98da9SMariusz Zaborski 123954f98da9SMariusz Zaborski #ifndef _KERNEL 124054f98da9SMariusz Zaborski int 124154f98da9SMariusz Zaborski nvlist_send(int sock, const nvlist_t *nvl) 124254f98da9SMariusz Zaborski { 124354f98da9SMariusz Zaborski size_t datasize, nfds; 124454f98da9SMariusz Zaborski int *fds; 124554f98da9SMariusz Zaborski void *data; 124654f98da9SMariusz Zaborski int64_t fdidx; 124754f98da9SMariusz Zaborski int ret; 124854f98da9SMariusz Zaborski 124954f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 125054f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 125154f98da9SMariusz Zaborski return (-1); 125254f98da9SMariusz Zaborski } 125354f98da9SMariusz Zaborski 125454f98da9SMariusz Zaborski fds = nvlist_descriptors(nvl, &nfds); 125554f98da9SMariusz Zaborski if (fds == NULL) 125654f98da9SMariusz Zaborski return (-1); 125754f98da9SMariusz Zaborski 125854f98da9SMariusz Zaborski ret = -1; 125954f98da9SMariusz Zaborski fdidx = 0; 126054f98da9SMariusz Zaborski 126154f98da9SMariusz Zaborski data = nvlist_xpack(nvl, &fdidx, &datasize); 126254f98da9SMariusz Zaborski if (data == NULL) 126354f98da9SMariusz Zaborski goto out; 126454f98da9SMariusz Zaborski 126554f98da9SMariusz Zaborski if (buf_send(sock, data, datasize) == -1) 126654f98da9SMariusz Zaborski goto out; 126754f98da9SMariusz Zaborski 126854f98da9SMariusz Zaborski if (nfds > 0) { 126954f98da9SMariusz Zaborski if (fd_send(sock, fds, nfds) == -1) 127054f98da9SMariusz Zaborski goto out; 127154f98da9SMariusz Zaborski } 127254f98da9SMariusz Zaborski 127354f98da9SMariusz Zaborski ret = 0; 127454f98da9SMariusz Zaborski out: 127554f98da9SMariusz Zaborski ERRNO_SAVE(); 127654f98da9SMariusz Zaborski nv_free(fds); 127754f98da9SMariusz Zaborski nv_free(data); 127854f98da9SMariusz Zaborski ERRNO_RESTORE(); 127954f98da9SMariusz Zaborski return (ret); 128054f98da9SMariusz Zaborski } 128154f98da9SMariusz Zaborski 128254f98da9SMariusz Zaborski nvlist_t * 128354f98da9SMariusz Zaborski nvlist_recv(int sock, int flags) 128454f98da9SMariusz Zaborski { 128554f98da9SMariusz Zaborski struct nvlist_header nvlhdr; 128654f98da9SMariusz Zaborski nvlist_t *nvl, *ret; 128754f98da9SMariusz Zaborski unsigned char *buf; 128854f98da9SMariusz Zaborski size_t nfds, size, i; 128954f98da9SMariusz Zaborski int *fds; 129054f98da9SMariusz Zaborski 129154f98da9SMariusz Zaborski if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1) 129254f98da9SMariusz Zaborski return (NULL); 129354f98da9SMariusz Zaborski 129454f98da9SMariusz Zaborski if (!nvlist_check_header(&nvlhdr)) 129554f98da9SMariusz Zaborski return (NULL); 129654f98da9SMariusz Zaborski 129754f98da9SMariusz Zaborski nfds = (size_t)nvlhdr.nvlh_descriptors; 129854f98da9SMariusz Zaborski size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size; 129954f98da9SMariusz Zaborski 130054f98da9SMariusz Zaborski buf = nv_malloc(size); 130154f98da9SMariusz Zaborski if (buf == NULL) 130254f98da9SMariusz Zaborski return (NULL); 130354f98da9SMariusz Zaborski 130454f98da9SMariusz Zaborski memcpy(buf, &nvlhdr, sizeof(nvlhdr)); 130554f98da9SMariusz Zaborski 130654f98da9SMariusz Zaborski ret = NULL; 130754f98da9SMariusz Zaborski fds = NULL; 130854f98da9SMariusz Zaborski 130954f98da9SMariusz Zaborski if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1) 131054f98da9SMariusz Zaborski goto out; 131154f98da9SMariusz Zaborski 131254f98da9SMariusz Zaborski if (nfds > 0) { 131354f98da9SMariusz Zaborski fds = nv_malloc(nfds * sizeof(fds[0])); 131454f98da9SMariusz Zaborski if (fds == NULL) 131554f98da9SMariusz Zaborski goto out; 131654f98da9SMariusz Zaborski if (fd_recv(sock, fds, nfds) == -1) 131754f98da9SMariusz Zaborski goto out; 131854f98da9SMariusz Zaborski } 131954f98da9SMariusz Zaborski 132054f98da9SMariusz Zaborski nvl = nvlist_xunpack(buf, size, fds, nfds, flags); 132154f98da9SMariusz Zaborski if (nvl == NULL) { 132254f98da9SMariusz Zaborski ERRNO_SAVE(); 132354f98da9SMariusz Zaborski for (i = 0; i < nfds; i++) 132454f98da9SMariusz Zaborski close(fds[i]); 132554f98da9SMariusz Zaborski ERRNO_RESTORE(); 132654f98da9SMariusz Zaborski goto out; 132754f98da9SMariusz Zaborski } 132854f98da9SMariusz Zaborski 132954f98da9SMariusz Zaborski ret = nvl; 133054f98da9SMariusz Zaborski out: 133154f98da9SMariusz Zaborski ERRNO_SAVE(); 133254f98da9SMariusz Zaborski nv_free(buf); 133354f98da9SMariusz Zaborski nv_free(fds); 133454f98da9SMariusz Zaborski ERRNO_RESTORE(); 133554f98da9SMariusz Zaborski 133654f98da9SMariusz Zaborski return (ret); 133754f98da9SMariusz Zaborski } 133854f98da9SMariusz Zaborski 133954f98da9SMariusz Zaborski nvlist_t * 134054f98da9SMariusz Zaborski nvlist_xfer(int sock, nvlist_t *nvl, int flags) 134154f98da9SMariusz Zaborski { 134254f98da9SMariusz Zaborski 134354f98da9SMariusz Zaborski if (nvlist_send(sock, nvl) < 0) { 134454f98da9SMariusz Zaborski nvlist_destroy(nvl); 134554f98da9SMariusz Zaborski return (NULL); 134654f98da9SMariusz Zaborski } 134754f98da9SMariusz Zaborski nvlist_destroy(nvl); 134854f98da9SMariusz Zaborski return (nvlist_recv(sock, flags)); 134954f98da9SMariusz Zaborski } 135054f98da9SMariusz Zaborski #endif 135154f98da9SMariusz Zaborski 135254f98da9SMariusz Zaborski nvpair_t * 135354f98da9SMariusz Zaborski nvlist_first_nvpair(const nvlist_t *nvl) 135454f98da9SMariusz Zaborski { 135554f98da9SMariusz Zaborski 135654f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 135754f98da9SMariusz Zaborski 135854f98da9SMariusz Zaborski return (TAILQ_FIRST(&nvl->nvl_head)); 135954f98da9SMariusz Zaborski } 136054f98da9SMariusz Zaborski 136154f98da9SMariusz Zaborski nvpair_t * 136254f98da9SMariusz Zaborski nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 136354f98da9SMariusz Zaborski { 136454f98da9SMariusz Zaborski nvpair_t *retnvp; 136554f98da9SMariusz Zaborski 136654f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 136754f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 136854f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 136954f98da9SMariusz Zaborski 137054f98da9SMariusz Zaborski retnvp = nvpair_next(nvp); 137154f98da9SMariusz Zaborski PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl); 137254f98da9SMariusz Zaborski 137354f98da9SMariusz Zaborski return (retnvp); 137454f98da9SMariusz Zaborski 137554f98da9SMariusz Zaborski } 137654f98da9SMariusz Zaborski 137754f98da9SMariusz Zaborski nvpair_t * 137854f98da9SMariusz Zaborski nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 137954f98da9SMariusz Zaborski { 138054f98da9SMariusz Zaborski nvpair_t *retnvp; 138154f98da9SMariusz Zaborski 138254f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 138354f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 138454f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 138554f98da9SMariusz Zaborski 138654f98da9SMariusz Zaborski retnvp = nvpair_prev(nvp); 138754f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl); 138854f98da9SMariusz Zaborski 138954f98da9SMariusz Zaborski return (retnvp); 139054f98da9SMariusz Zaborski } 139154f98da9SMariusz Zaborski 139254f98da9SMariusz Zaborski const char * 139354f98da9SMariusz Zaborski nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep) 139454f98da9SMariusz Zaborski { 139554f98da9SMariusz Zaborski nvpair_t *nvp; 139654f98da9SMariusz Zaborski 139754f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 139854f98da9SMariusz Zaborski 139989ca10c6SMariusz Zaborski if (cookiep == NULL || *cookiep == NULL) 140054f98da9SMariusz Zaborski nvp = nvlist_first_nvpair(nvl); 140154f98da9SMariusz Zaborski else 140254f98da9SMariusz Zaborski nvp = nvlist_next_nvpair(nvl, *cookiep); 140354f98da9SMariusz Zaborski if (nvp == NULL) 140454f98da9SMariusz Zaborski return (NULL); 140554f98da9SMariusz Zaborski if (typep != NULL) 140654f98da9SMariusz Zaborski *typep = nvpair_type(nvp); 140789ca10c6SMariusz Zaborski if (cookiep != NULL) 140854f98da9SMariusz Zaborski *cookiep = nvp; 140954f98da9SMariusz Zaborski return (nvpair_name(nvp)); 141054f98da9SMariusz Zaborski } 141154f98da9SMariusz Zaborski 141254f98da9SMariusz Zaborski bool 141354f98da9SMariusz Zaborski nvlist_exists(const nvlist_t *nvl, const char *name) 141454f98da9SMariusz Zaborski { 141554f98da9SMariusz Zaborski 141654f98da9SMariusz Zaborski return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL); 141754f98da9SMariusz Zaborski } 141854f98da9SMariusz Zaborski 141954f98da9SMariusz Zaborski #define NVLIST_EXISTS(type, TYPE) \ 142054f98da9SMariusz Zaborski bool \ 142154f98da9SMariusz Zaborski nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ 142254f98da9SMariusz Zaborski { \ 142354f98da9SMariusz Zaborski \ 142454f98da9SMariusz Zaborski return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \ 142554f98da9SMariusz Zaborski } 142654f98da9SMariusz Zaborski 142754f98da9SMariusz Zaborski NVLIST_EXISTS(null, NULL) 142854f98da9SMariusz Zaborski NVLIST_EXISTS(bool, BOOL) 142954f98da9SMariusz Zaborski NVLIST_EXISTS(number, NUMBER) 143054f98da9SMariusz Zaborski NVLIST_EXISTS(string, STRING) 143154f98da9SMariusz Zaborski NVLIST_EXISTS(nvlist, NVLIST) 1432347a39b4SMariusz Zaborski NVLIST_EXISTS(binary, BINARY) 1433347a39b4SMariusz Zaborski NVLIST_EXISTS(bool_array, BOOL_ARRAY) 1434347a39b4SMariusz Zaborski NVLIST_EXISTS(number_array, NUMBER_ARRAY) 1435347a39b4SMariusz Zaborski NVLIST_EXISTS(string_array, STRING_ARRAY) 1436347a39b4SMariusz Zaborski NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY) 143754f98da9SMariusz Zaborski #ifndef _KERNEL 143854f98da9SMariusz Zaborski NVLIST_EXISTS(descriptor, DESCRIPTOR) 1439347a39b4SMariusz Zaborski NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY) 144054f98da9SMariusz Zaborski #endif 144154f98da9SMariusz Zaborski 144254f98da9SMariusz Zaborski #undef NVLIST_EXISTS 144354f98da9SMariusz Zaborski 144454f98da9SMariusz Zaborski void 144554f98da9SMariusz Zaborski nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) 144654f98da9SMariusz Zaborski { 144754f98da9SMariusz Zaborski nvpair_t *newnvp; 144854f98da9SMariusz Zaborski 144954f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 145054f98da9SMariusz Zaborski 145154f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 145254f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 145354f98da9SMariusz Zaborski return; 145454f98da9SMariusz Zaborski } 145554f98da9SMariusz Zaborski if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { 145654f98da9SMariusz Zaborski if (nvlist_exists(nvl, nvpair_name(nvp))) { 145754f98da9SMariusz Zaborski nvl->nvl_error = EEXIST; 145854f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 145954f98da9SMariusz Zaborski return; 146054f98da9SMariusz Zaborski } 146154f98da9SMariusz Zaborski } 146254f98da9SMariusz Zaborski 146354f98da9SMariusz Zaborski newnvp = nvpair_clone(nvp); 146454f98da9SMariusz Zaborski if (newnvp == NULL) { 146554f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 146654f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 146754f98da9SMariusz Zaborski return; 146854f98da9SMariusz Zaborski } 146954f98da9SMariusz Zaborski 147054f98da9SMariusz Zaborski nvpair_insert(&nvl->nvl_head, newnvp, nvl); 147154f98da9SMariusz Zaborski } 147254f98da9SMariusz Zaborski 147354f98da9SMariusz Zaborski void 147454f98da9SMariusz Zaborski nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) 147554f98da9SMariusz Zaborski { 147654f98da9SMariusz Zaborski va_list valueap; 147754f98da9SMariusz Zaborski 147854f98da9SMariusz Zaborski va_start(valueap, valuefmt); 147954f98da9SMariusz Zaborski nvlist_add_stringv(nvl, name, valuefmt, valueap); 148054f98da9SMariusz Zaborski va_end(valueap); 148154f98da9SMariusz Zaborski } 148254f98da9SMariusz Zaborski 148354f98da9SMariusz Zaborski void 148454f98da9SMariusz Zaborski nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, 148554f98da9SMariusz Zaborski va_list valueap) 148654f98da9SMariusz Zaborski { 148754f98da9SMariusz Zaborski nvpair_t *nvp; 148854f98da9SMariusz Zaborski 148954f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 149054f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 149154f98da9SMariusz Zaborski return; 149254f98da9SMariusz Zaborski } 149354f98da9SMariusz Zaborski 149454f98da9SMariusz Zaborski nvp = nvpair_create_stringv(name, valuefmt, valueap); 149554f98da9SMariusz Zaborski if (nvp == NULL) { 149654f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 149754f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 149854f98da9SMariusz Zaborski } else { 149930740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 150054f98da9SMariusz Zaborski } 150154f98da9SMariusz Zaborski } 150254f98da9SMariusz Zaborski 150354f98da9SMariusz Zaborski void 150454f98da9SMariusz Zaborski nvlist_add_null(nvlist_t *nvl, const char *name) 150554f98da9SMariusz Zaborski { 150654f98da9SMariusz Zaborski nvpair_t *nvp; 150754f98da9SMariusz Zaborski 150854f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 150954f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 151054f98da9SMariusz Zaborski return; 151154f98da9SMariusz Zaborski } 151254f98da9SMariusz Zaborski 151354f98da9SMariusz Zaborski nvp = nvpair_create_null(name); 151454f98da9SMariusz Zaborski if (nvp == NULL) { 151554f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 151654f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 151754f98da9SMariusz Zaborski } else { 151830740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 151954f98da9SMariusz Zaborski } 152054f98da9SMariusz Zaborski } 152154f98da9SMariusz Zaborski 152254f98da9SMariusz Zaborski void 152354f98da9SMariusz Zaborski nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, 152454f98da9SMariusz Zaborski size_t size) 152554f98da9SMariusz Zaborski { 152654f98da9SMariusz Zaborski nvpair_t *nvp; 152754f98da9SMariusz Zaborski 152854f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 152954f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 153054f98da9SMariusz Zaborski return; 153154f98da9SMariusz Zaborski } 153254f98da9SMariusz Zaborski 153354f98da9SMariusz Zaborski nvp = nvpair_create_binary(name, value, size); 153454f98da9SMariusz Zaborski if (nvp == NULL) { 153554f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 153654f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 153754f98da9SMariusz Zaborski } else { 153830740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 153954f98da9SMariusz Zaborski } 154054f98da9SMariusz Zaborski } 154154f98da9SMariusz Zaborski 154254f98da9SMariusz Zaborski 154354f98da9SMariusz Zaborski #define NVLIST_ADD(vtype, type) \ 154454f98da9SMariusz Zaborski void \ 154554f98da9SMariusz Zaborski nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \ 154654f98da9SMariusz Zaborski { \ 154754f98da9SMariusz Zaborski nvpair_t *nvp; \ 154854f98da9SMariusz Zaborski \ 154954f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { \ 155054f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); \ 155154f98da9SMariusz Zaborski return; \ 155254f98da9SMariusz Zaborski } \ 155354f98da9SMariusz Zaborski \ 155454f98da9SMariusz Zaborski nvp = nvpair_create_##type(name, value); \ 155554f98da9SMariusz Zaborski if (nvp == NULL) { \ 155654f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 155754f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); \ 155854f98da9SMariusz Zaborski } else { \ 155930740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); \ 156054f98da9SMariusz Zaborski } \ 156154f98da9SMariusz Zaborski } 156254f98da9SMariusz Zaborski 156354f98da9SMariusz Zaborski NVLIST_ADD(bool, bool) 156454f98da9SMariusz Zaborski NVLIST_ADD(uint64_t, number) 156554f98da9SMariusz Zaborski NVLIST_ADD(const char *, string) 156654f98da9SMariusz Zaborski NVLIST_ADD(const nvlist_t *, nvlist) 156754f98da9SMariusz Zaborski #ifndef _KERNEL 156854f98da9SMariusz Zaborski NVLIST_ADD(int, descriptor); 156954f98da9SMariusz Zaborski #endif 157054f98da9SMariusz Zaborski 157154f98da9SMariusz Zaborski #undef NVLIST_ADD 157254f98da9SMariusz Zaborski 1573347a39b4SMariusz Zaborski #define NVLIST_ADD_ARRAY(vtype, type) \ 1574347a39b4SMariusz Zaborski void \ 1575347a39b4SMariusz Zaborski nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value, \ 1576347a39b4SMariusz Zaborski size_t nitems) \ 1577347a39b4SMariusz Zaborski { \ 1578347a39b4SMariusz Zaborski nvpair_t *nvp; \ 1579347a39b4SMariusz Zaborski \ 1580347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { \ 1581347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); \ 1582347a39b4SMariusz Zaborski return; \ 1583347a39b4SMariusz Zaborski } \ 1584347a39b4SMariusz Zaborski \ 1585347a39b4SMariusz Zaborski nvp = nvpair_create_##type##_array(name, value, nitems); \ 1586347a39b4SMariusz Zaborski if (nvp == NULL) { \ 1587347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 1588347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); \ 1589347a39b4SMariusz Zaborski } else { \ 1590347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); \ 1591347a39b4SMariusz Zaborski } \ 1592347a39b4SMariusz Zaborski } 1593347a39b4SMariusz Zaborski 1594347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const bool *, bool) 1595347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const uint64_t *, number) 1596347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const char * const *, string) 1597347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist) 1598347a39b4SMariusz Zaborski #ifndef _KERNEL 1599347a39b4SMariusz Zaborski NVLIST_ADD_ARRAY(const int *, descriptor) 1600347a39b4SMariusz Zaborski #endif 1601347a39b4SMariusz Zaborski 1602347a39b4SMariusz Zaborski #undef NVLIST_ADD_ARRAY 1603347a39b4SMariusz Zaborski 160430740f45SMariusz Zaborski bool 160554f98da9SMariusz Zaborski nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) 160654f98da9SMariusz Zaborski { 160754f98da9SMariusz Zaborski 160854f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 160954f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); 161054f98da9SMariusz Zaborski 161154f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 161254f98da9SMariusz Zaborski nvpair_free(nvp); 161354f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 161430740f45SMariusz Zaborski return (false); 161554f98da9SMariusz Zaborski } 161654f98da9SMariusz Zaborski if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { 161754f98da9SMariusz Zaborski if (nvlist_exists(nvl, nvpair_name(nvp))) { 161854f98da9SMariusz Zaborski nvpair_free(nvp); 161954f98da9SMariusz Zaborski nvl->nvl_error = EEXIST; 162054f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 162130740f45SMariusz Zaborski return (false); 162254f98da9SMariusz Zaborski } 162354f98da9SMariusz Zaborski } 162454f98da9SMariusz Zaborski 162554f98da9SMariusz Zaborski nvpair_insert(&nvl->nvl_head, nvp, nvl); 162630740f45SMariusz Zaborski return (true); 162754f98da9SMariusz Zaborski } 162854f98da9SMariusz Zaborski 162954f98da9SMariusz Zaborski void 163054f98da9SMariusz Zaborski nvlist_move_string(nvlist_t *nvl, const char *name, char *value) 163154f98da9SMariusz Zaborski { 163254f98da9SMariusz Zaborski nvpair_t *nvp; 163354f98da9SMariusz Zaborski 163454f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 163554f98da9SMariusz Zaborski nv_free(value); 163654f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 163754f98da9SMariusz Zaborski return; 163854f98da9SMariusz Zaborski } 163954f98da9SMariusz Zaborski 164054f98da9SMariusz Zaborski nvp = nvpair_move_string(name, value); 164154f98da9SMariusz Zaborski if (nvp == NULL) { 164254f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 164354f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 164454f98da9SMariusz Zaborski } else { 164530740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 164654f98da9SMariusz Zaborski } 164754f98da9SMariusz Zaborski } 164854f98da9SMariusz Zaborski 164954f98da9SMariusz Zaborski void 165054f98da9SMariusz Zaborski nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value) 165154f98da9SMariusz Zaborski { 165254f98da9SMariusz Zaborski nvpair_t *nvp; 165354f98da9SMariusz Zaborski 165454f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 165554f98da9SMariusz Zaborski if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) 165654f98da9SMariusz Zaborski nvlist_destroy(value); 165754f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 165854f98da9SMariusz Zaborski return; 165954f98da9SMariusz Zaborski } 166054f98da9SMariusz Zaborski 166154f98da9SMariusz Zaborski nvp = nvpair_move_nvlist(name, value); 166254f98da9SMariusz Zaborski if (nvp == NULL) { 166354f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 166454f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 166554f98da9SMariusz Zaborski } else { 166630740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 166754f98da9SMariusz Zaborski } 166854f98da9SMariusz Zaborski } 166954f98da9SMariusz Zaborski 167054f98da9SMariusz Zaborski #ifndef _KERNEL 167154f98da9SMariusz Zaborski void 167254f98da9SMariusz Zaborski nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value) 167354f98da9SMariusz Zaborski { 167454f98da9SMariusz Zaborski nvpair_t *nvp; 167554f98da9SMariusz Zaborski 167654f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 167754f98da9SMariusz Zaborski close(value); 167854f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 167954f98da9SMariusz Zaborski return; 168054f98da9SMariusz Zaborski } 168154f98da9SMariusz Zaborski 168254f98da9SMariusz Zaborski nvp = nvpair_move_descriptor(name, value); 168354f98da9SMariusz Zaborski if (nvp == NULL) { 168454f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 168554f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 168654f98da9SMariusz Zaborski } else { 168730740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 168854f98da9SMariusz Zaborski } 168954f98da9SMariusz Zaborski } 169054f98da9SMariusz Zaborski #endif 169154f98da9SMariusz Zaborski 169254f98da9SMariusz Zaborski void 169354f98da9SMariusz Zaborski nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size) 169454f98da9SMariusz Zaborski { 169554f98da9SMariusz Zaborski nvpair_t *nvp; 169654f98da9SMariusz Zaborski 169754f98da9SMariusz Zaborski if (nvlist_error(nvl) != 0) { 169854f98da9SMariusz Zaborski nv_free(value); 169954f98da9SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 170054f98da9SMariusz Zaborski return; 170154f98da9SMariusz Zaborski } 170254f98da9SMariusz Zaborski 170354f98da9SMariusz Zaborski nvp = nvpair_move_binary(name, value, size); 170454f98da9SMariusz Zaborski if (nvp == NULL) { 170554f98da9SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 170654f98da9SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 170754f98da9SMariusz Zaborski } else { 170830740f45SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 170954f98da9SMariusz Zaborski } 171054f98da9SMariusz Zaborski } 171154f98da9SMariusz Zaborski 1712347a39b4SMariusz Zaborski void 1713347a39b4SMariusz Zaborski nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value, 1714347a39b4SMariusz Zaborski size_t nitems) 1715347a39b4SMariusz Zaborski { 1716347a39b4SMariusz Zaborski nvpair_t *nvp; 1717347a39b4SMariusz Zaborski 1718347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1719347a39b4SMariusz Zaborski nv_free(value); 1720347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1721347a39b4SMariusz Zaborski return; 1722347a39b4SMariusz Zaborski } 1723347a39b4SMariusz Zaborski 1724347a39b4SMariusz Zaborski nvp = nvpair_move_bool_array(name, value, nitems); 1725347a39b4SMariusz Zaborski if (nvp == NULL) { 1726347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1727347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1728347a39b4SMariusz Zaborski } else { 1729347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1730347a39b4SMariusz Zaborski } 1731347a39b4SMariusz Zaborski } 1732347a39b4SMariusz Zaborski 1733347a39b4SMariusz Zaborski void 1734347a39b4SMariusz Zaborski nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value, 1735347a39b4SMariusz Zaborski size_t nitems) 1736347a39b4SMariusz Zaborski { 1737347a39b4SMariusz Zaborski nvpair_t *nvp; 1738347a39b4SMariusz Zaborski size_t i; 1739347a39b4SMariusz Zaborski 1740347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1741347a39b4SMariusz Zaborski if (value != NULL) { 1742347a39b4SMariusz Zaborski for (i = 0; i < nitems; i++) 1743347a39b4SMariusz Zaborski nv_free(value[i]); 1744347a39b4SMariusz Zaborski nv_free(value); 1745347a39b4SMariusz Zaborski } 1746347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1747347a39b4SMariusz Zaborski return; 1748347a39b4SMariusz Zaborski } 1749347a39b4SMariusz Zaborski 1750347a39b4SMariusz Zaborski nvp = nvpair_move_string_array(name, value, nitems); 1751347a39b4SMariusz Zaborski if (nvp == NULL) { 1752347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1753347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1754347a39b4SMariusz Zaborski } else { 1755347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1756347a39b4SMariusz Zaborski } 1757347a39b4SMariusz Zaborski } 1758347a39b4SMariusz Zaborski 1759347a39b4SMariusz Zaborski void 1760347a39b4SMariusz Zaborski nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value, 1761347a39b4SMariusz Zaborski size_t nitems) 1762347a39b4SMariusz Zaborski { 1763347a39b4SMariusz Zaborski nvpair_t *nvp; 1764347a39b4SMariusz Zaborski size_t i; 1765347a39b4SMariusz Zaborski 1766347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1767347a39b4SMariusz Zaborski if (value != NULL) { 1768347a39b4SMariusz Zaborski for (i = 0; i < nitems; i++) { 1769347a39b4SMariusz Zaborski if (nvlist_get_pararr(value[i], NULL) == NULL) 1770347a39b4SMariusz Zaborski nvlist_destroy(value[i]); 1771347a39b4SMariusz Zaborski } 1772347a39b4SMariusz Zaborski } 1773347a39b4SMariusz Zaborski nv_free(value); 1774347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1775347a39b4SMariusz Zaborski return; 1776347a39b4SMariusz Zaborski } 1777347a39b4SMariusz Zaborski 1778347a39b4SMariusz Zaborski nvp = nvpair_move_nvlist_array(name, value, nitems); 1779347a39b4SMariusz Zaborski if (nvp == NULL) { 1780347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1781347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1782347a39b4SMariusz Zaborski } else { 1783347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1784347a39b4SMariusz Zaborski } 1785347a39b4SMariusz Zaborski } 1786347a39b4SMariusz Zaborski 1787347a39b4SMariusz Zaborski void 1788347a39b4SMariusz Zaborski nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value, 1789347a39b4SMariusz Zaborski size_t nitems) 1790347a39b4SMariusz Zaborski { 1791347a39b4SMariusz Zaborski nvpair_t *nvp; 1792347a39b4SMariusz Zaborski 1793347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1794347a39b4SMariusz Zaborski nv_free(value); 1795347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1796347a39b4SMariusz Zaborski return; 1797347a39b4SMariusz Zaborski } 1798347a39b4SMariusz Zaborski 1799347a39b4SMariusz Zaborski nvp = nvpair_move_number_array(name, value, nitems); 1800347a39b4SMariusz Zaborski if (nvp == NULL) { 1801347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1802347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1803347a39b4SMariusz Zaborski } else { 1804347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1805347a39b4SMariusz Zaborski } 1806347a39b4SMariusz Zaborski } 1807347a39b4SMariusz Zaborski 1808347a39b4SMariusz Zaborski #ifndef _KERNEL 1809347a39b4SMariusz Zaborski void 1810347a39b4SMariusz Zaborski nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value, 1811347a39b4SMariusz Zaborski size_t nitems) 1812347a39b4SMariusz Zaborski { 1813347a39b4SMariusz Zaborski nvpair_t *nvp; 1814347a39b4SMariusz Zaborski size_t i; 1815347a39b4SMariusz Zaborski 1816347a39b4SMariusz Zaborski if (nvlist_error(nvl) != 0) { 1817347a39b4SMariusz Zaborski if (value != 0) { 1818347a39b4SMariusz Zaborski for (i = 0; i < nitems; i++) 1819347a39b4SMariusz Zaborski close(value[i]); 1820347a39b4SMariusz Zaborski nv_free(value); 1821347a39b4SMariusz Zaborski } 1822347a39b4SMariusz Zaborski 1823347a39b4SMariusz Zaborski ERRNO_SET(nvlist_error(nvl)); 1824347a39b4SMariusz Zaborski return; 1825347a39b4SMariusz Zaborski } 1826347a39b4SMariusz Zaborski 1827347a39b4SMariusz Zaborski nvp = nvpair_move_descriptor_array(name, value, nitems); 1828347a39b4SMariusz Zaborski if (nvp == NULL) { 1829347a39b4SMariusz Zaborski nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1830347a39b4SMariusz Zaborski ERRNO_SET(nvl->nvl_error); 1831347a39b4SMariusz Zaborski } else { 1832347a39b4SMariusz Zaborski (void)nvlist_move_nvpair(nvl, nvp); 1833347a39b4SMariusz Zaborski } 1834347a39b4SMariusz Zaborski } 1835347a39b4SMariusz Zaborski #endif 1836347a39b4SMariusz Zaborski 183754f98da9SMariusz Zaborski const nvpair_t * 183854f98da9SMariusz Zaborski nvlist_get_nvpair(const nvlist_t *nvl, const char *name) 183954f98da9SMariusz Zaborski { 184054f98da9SMariusz Zaborski 184154f98da9SMariusz Zaborski return (nvlist_find(nvl, NV_TYPE_NONE, name)); 184254f98da9SMariusz Zaborski } 184354f98da9SMariusz Zaborski 184454f98da9SMariusz Zaborski #define NVLIST_GET(ftype, type, TYPE) \ 184554f98da9SMariusz Zaborski ftype \ 184654f98da9SMariusz Zaborski nvlist_get_##type(const nvlist_t *nvl, const char *name) \ 184754f98da9SMariusz Zaborski { \ 184854f98da9SMariusz Zaborski const nvpair_t *nvp; \ 184954f98da9SMariusz Zaborski \ 185054f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 185154f98da9SMariusz Zaborski if (nvp == NULL) \ 185254f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE, name); \ 185354f98da9SMariusz Zaborski return (nvpair_get_##type(nvp)); \ 185454f98da9SMariusz Zaborski } 185554f98da9SMariusz Zaborski 185654f98da9SMariusz Zaborski NVLIST_GET(bool, bool, BOOL) 185754f98da9SMariusz Zaborski NVLIST_GET(uint64_t, number, NUMBER) 185854f98da9SMariusz Zaborski NVLIST_GET(const char *, string, STRING) 185954f98da9SMariusz Zaborski NVLIST_GET(const nvlist_t *, nvlist, NVLIST) 186054f98da9SMariusz Zaborski #ifndef _KERNEL 186154f98da9SMariusz Zaborski NVLIST_GET(int, descriptor, DESCRIPTOR) 186254f98da9SMariusz Zaborski #endif 186354f98da9SMariusz Zaborski 186454f98da9SMariusz Zaborski #undef NVLIST_GET 186554f98da9SMariusz Zaborski 186654f98da9SMariusz Zaborski const void * 186754f98da9SMariusz Zaborski nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) 186854f98da9SMariusz Zaborski { 186954f98da9SMariusz Zaborski nvpair_t *nvp; 187054f98da9SMariusz Zaborski 187154f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 187254f98da9SMariusz Zaborski if (nvp == NULL) 187354f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_BINARY, name); 187454f98da9SMariusz Zaborski 187554f98da9SMariusz Zaborski return (nvpair_get_binary(nvp, sizep)); 187654f98da9SMariusz Zaborski } 187754f98da9SMariusz Zaborski 1878347a39b4SMariusz Zaborski #define NVLIST_GET_ARRAY(ftype, type, TYPE) \ 1879347a39b4SMariusz Zaborski ftype \ 1880347a39b4SMariusz Zaborski nvlist_get_##type##_array(const nvlist_t *nvl, const char *name, \ 1881347a39b4SMariusz Zaborski size_t *nitems) \ 1882347a39b4SMariusz Zaborski { \ 1883347a39b4SMariusz Zaborski const nvpair_t *nvp; \ 1884347a39b4SMariusz Zaborski \ 1885347a39b4SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 1886347a39b4SMariusz Zaborski if (nvp == NULL) \ 1887347a39b4SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ 1888347a39b4SMariusz Zaborski return (nvpair_get_##type##_array(nvp, nitems)); \ 1889347a39b4SMariusz Zaborski } 1890347a39b4SMariusz Zaborski 1891347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const bool *, bool, BOOL) 1892347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER) 1893347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const char * const *, string, STRING) 1894347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST) 1895347a39b4SMariusz Zaborski #ifndef _KERNEL 1896347a39b4SMariusz Zaborski NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR) 1897347a39b4SMariusz Zaborski #endif 1898347a39b4SMariusz Zaborski 1899347a39b4SMariusz Zaborski #undef NVLIST_GET_ARRAY 1900347a39b4SMariusz Zaborski 190154f98da9SMariusz Zaborski #define NVLIST_TAKE(ftype, type, TYPE) \ 190254f98da9SMariusz Zaborski ftype \ 190354f98da9SMariusz Zaborski nvlist_take_##type(nvlist_t *nvl, const char *name) \ 190454f98da9SMariusz Zaborski { \ 190554f98da9SMariusz Zaborski nvpair_t *nvp; \ 190654f98da9SMariusz Zaborski ftype value; \ 190754f98da9SMariusz Zaborski \ 190854f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 190954f98da9SMariusz Zaborski if (nvp == NULL) \ 191054f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE, name); \ 191154f98da9SMariusz Zaborski value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ 191254f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); \ 191354f98da9SMariusz Zaborski nvpair_free_structure(nvp); \ 191454f98da9SMariusz Zaborski return (value); \ 191554f98da9SMariusz Zaborski } 191654f98da9SMariusz Zaborski 191754f98da9SMariusz Zaborski NVLIST_TAKE(bool, bool, BOOL) 191854f98da9SMariusz Zaborski NVLIST_TAKE(uint64_t, number, NUMBER) 191954f98da9SMariusz Zaborski NVLIST_TAKE(char *, string, STRING) 192054f98da9SMariusz Zaborski NVLIST_TAKE(nvlist_t *, nvlist, NVLIST) 192154f98da9SMariusz Zaborski #ifndef _KERNEL 192254f98da9SMariusz Zaborski NVLIST_TAKE(int, descriptor, DESCRIPTOR) 192354f98da9SMariusz Zaborski #endif 192454f98da9SMariusz Zaborski 192554f98da9SMariusz Zaborski #undef NVLIST_TAKE 192654f98da9SMariusz Zaborski 192754f98da9SMariusz Zaborski void * 192854f98da9SMariusz Zaborski nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) 192954f98da9SMariusz Zaborski { 193054f98da9SMariusz Zaborski nvpair_t *nvp; 193154f98da9SMariusz Zaborski void *value; 193254f98da9SMariusz Zaborski 193354f98da9SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 193454f98da9SMariusz Zaborski if (nvp == NULL) 193554f98da9SMariusz Zaborski nvlist_report_missing(NV_TYPE_BINARY, name); 193654f98da9SMariusz Zaborski 193754f98da9SMariusz Zaborski value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); 193854f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); 193954f98da9SMariusz Zaborski nvpair_free_structure(nvp); 194054f98da9SMariusz Zaborski return (value); 194154f98da9SMariusz Zaborski } 194254f98da9SMariusz Zaborski 1943347a39b4SMariusz Zaborski #define NVLIST_TAKE_ARRAY(ftype, type, TYPE) \ 1944347a39b4SMariusz Zaborski ftype \ 1945347a39b4SMariusz Zaborski nvlist_take_##type##_array(nvlist_t *nvl, const char *name, \ 1946347a39b4SMariusz Zaborski size_t *nitems) \ 1947347a39b4SMariusz Zaborski { \ 1948347a39b4SMariusz Zaborski nvpair_t *nvp; \ 1949347a39b4SMariusz Zaborski ftype value; \ 1950347a39b4SMariusz Zaborski \ 1951347a39b4SMariusz Zaborski nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 1952347a39b4SMariusz Zaborski if (nvp == NULL) \ 1953347a39b4SMariusz Zaborski nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ 1954347a39b4SMariusz Zaborski value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\ 1955347a39b4SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); \ 1956347a39b4SMariusz Zaborski nvpair_free_structure(nvp); \ 1957347a39b4SMariusz Zaborski return (value); \ 1958347a39b4SMariusz Zaborski } 1959347a39b4SMariusz Zaborski 1960347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(bool *, bool, BOOL) 1961347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER) 1962347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(char **, string, STRING) 1963347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST) 1964347a39b4SMariusz Zaborski #ifndef _KERNEL 1965347a39b4SMariusz Zaborski NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR) 1966347a39b4SMariusz Zaborski #endif 1967347a39b4SMariusz Zaborski 196854f98da9SMariusz Zaborski void 196954f98da9SMariusz Zaborski nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) 197054f98da9SMariusz Zaborski { 197154f98da9SMariusz Zaborski 197254f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 197354f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 197454f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 197554f98da9SMariusz Zaborski 197654f98da9SMariusz Zaborski nvpair_remove(&nvl->nvl_head, nvp, nvl); 197754f98da9SMariusz Zaborski } 197854f98da9SMariusz Zaborski 197954f98da9SMariusz Zaborski void 198054f98da9SMariusz Zaborski nvlist_free(nvlist_t *nvl, const char *name) 198154f98da9SMariusz Zaborski { 198254f98da9SMariusz Zaborski 198354f98da9SMariusz Zaborski nvlist_free_type(nvl, name, NV_TYPE_NONE); 198454f98da9SMariusz Zaborski } 198554f98da9SMariusz Zaborski 198654f98da9SMariusz Zaborski #define NVLIST_FREE(type, TYPE) \ 198754f98da9SMariusz Zaborski void \ 198854f98da9SMariusz Zaborski nvlist_free_##type(nvlist_t *nvl, const char *name) \ 198954f98da9SMariusz Zaborski { \ 199054f98da9SMariusz Zaborski \ 199154f98da9SMariusz Zaborski nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ 199254f98da9SMariusz Zaborski } 199354f98da9SMariusz Zaborski 199454f98da9SMariusz Zaborski NVLIST_FREE(null, NULL) 199554f98da9SMariusz Zaborski NVLIST_FREE(bool, BOOL) 199654f98da9SMariusz Zaborski NVLIST_FREE(number, NUMBER) 199754f98da9SMariusz Zaborski NVLIST_FREE(string, STRING) 199854f98da9SMariusz Zaborski NVLIST_FREE(nvlist, NVLIST) 1999347a39b4SMariusz Zaborski NVLIST_FREE(binary, BINARY) 2000347a39b4SMariusz Zaborski NVLIST_FREE(bool_array, BOOL_ARRAY) 2001347a39b4SMariusz Zaborski NVLIST_FREE(number_array, NUMBER_ARRAY) 2002347a39b4SMariusz Zaborski NVLIST_FREE(string_array, STRING_ARRAY) 2003347a39b4SMariusz Zaborski NVLIST_FREE(nvlist_array, NVLIST_ARRAY) 200454f98da9SMariusz Zaborski #ifndef _KERNEL 200554f98da9SMariusz Zaborski NVLIST_FREE(descriptor, DESCRIPTOR) 2006347a39b4SMariusz Zaborski NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY) 200754f98da9SMariusz Zaborski #endif 200854f98da9SMariusz Zaborski 200954f98da9SMariusz Zaborski #undef NVLIST_FREE 201054f98da9SMariusz Zaborski 201154f98da9SMariusz Zaborski void 201254f98da9SMariusz Zaborski nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) 201354f98da9SMariusz Zaborski { 201454f98da9SMariusz Zaborski 201554f98da9SMariusz Zaborski NVLIST_ASSERT(nvl); 201654f98da9SMariusz Zaborski NVPAIR_ASSERT(nvp); 201754f98da9SMariusz Zaborski PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 201854f98da9SMariusz Zaborski 201954f98da9SMariusz Zaborski nvlist_remove_nvpair(nvl, nvp); 202054f98da9SMariusz Zaborski nvpair_free(nvp); 202154f98da9SMariusz Zaborski } 202254f98da9SMariusz Zaborski 2023