156e5ad5fSMatt Macy /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 356e5ad5fSMatt Macy * 456e5ad5fSMatt Macy * Copyright (c) 2009-2013 The FreeBSD Foundation 556e5ad5fSMatt Macy * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org> 656e5ad5fSMatt Macy * All rights reserved. 756e5ad5fSMatt Macy * 856e5ad5fSMatt Macy * This software was developed by Pawel Jakub Dawidek under sponsorship from 956e5ad5fSMatt Macy * the FreeBSD Foundation. 1056e5ad5fSMatt Macy * 1156e5ad5fSMatt Macy * Redistribution and use in source and binary forms, with or without 1256e5ad5fSMatt Macy * modification, are permitted provided that the following conditions 1356e5ad5fSMatt Macy * are met: 1456e5ad5fSMatt Macy * 1. Redistributions of source code must retain the above copyright 1556e5ad5fSMatt Macy * notice, this list of conditions and the following disclaimer. 1656e5ad5fSMatt Macy * 2. Redistributions in binary form must reproduce the above copyright 1756e5ad5fSMatt Macy * notice, this list of conditions and the following disclaimer in the 1856e5ad5fSMatt Macy * documentation and/or other materials provided with the distribution. 1956e5ad5fSMatt Macy * 2056e5ad5fSMatt Macy * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 2156e5ad5fSMatt Macy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2256e5ad5fSMatt Macy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2356e5ad5fSMatt Macy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2456e5ad5fSMatt Macy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2556e5ad5fSMatt Macy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2656e5ad5fSMatt Macy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2756e5ad5fSMatt Macy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2856e5ad5fSMatt Macy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2956e5ad5fSMatt Macy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3056e5ad5fSMatt Macy * SUCH DAMAGE. 3156e5ad5fSMatt Macy */ 3256e5ad5fSMatt Macy 3356e5ad5fSMatt Macy #include <sys/cdefs.h> 3456e5ad5fSMatt Macy __FBSDID("$FreeBSD$"); 3556e5ad5fSMatt Macy 3656e5ad5fSMatt Macy #include <sys/param.h> 3756e5ad5fSMatt Macy #include <sys/endian.h> 3856e5ad5fSMatt Macy #include <sys/queue.h> 3956e5ad5fSMatt Macy 4056e5ad5fSMatt Macy #ifdef _KERNEL 4156e5ad5fSMatt Macy 4256e5ad5fSMatt Macy #include <sys/errno.h> 4356e5ad5fSMatt Macy #include <sys/lock.h> 4456e5ad5fSMatt Macy #include <sys/malloc.h> 4556e5ad5fSMatt Macy #include <sys/systm.h> 4656e5ad5fSMatt Macy 4756e5ad5fSMatt Macy #include <machine/stdarg.h> 4856e5ad5fSMatt Macy 4956e5ad5fSMatt Macy #else 5056e5ad5fSMatt Macy #include <errno.h> 5156e5ad5fSMatt Macy #include <fcntl.h> 5256e5ad5fSMatt Macy #include <stdarg.h> 5356e5ad5fSMatt Macy #include <stdbool.h> 5456e5ad5fSMatt Macy #include <stdint.h> 5556e5ad5fSMatt Macy #include <stdlib.h> 5656e5ad5fSMatt Macy #include <string.h> 5756e5ad5fSMatt Macy #include <unistd.h> 5856e5ad5fSMatt Macy 5956e5ad5fSMatt Macy #include "common_impl.h" 6056e5ad5fSMatt Macy #endif 6156e5ad5fSMatt Macy 6256e5ad5fSMatt Macy #ifdef HAVE_PJDLOG 6356e5ad5fSMatt Macy #include <pjdlog.h> 6456e5ad5fSMatt Macy #endif 6556e5ad5fSMatt Macy 6656e5ad5fSMatt Macy #include <sys/nv.h> 6756e5ad5fSMatt Macy 6856e5ad5fSMatt Macy #include "nv_impl.h" 6956e5ad5fSMatt Macy #include "nvlist_impl.h" 7056e5ad5fSMatt Macy #include "nvpair_impl.h" 7156e5ad5fSMatt Macy 7256e5ad5fSMatt Macy #ifndef HAVE_PJDLOG 7356e5ad5fSMatt Macy #ifdef _KERNEL 7456e5ad5fSMatt Macy #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) 7556e5ad5fSMatt Macy #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) 7656e5ad5fSMatt Macy #define PJDLOG_ABORT(...) panic(__VA_ARGS__) 7756e5ad5fSMatt Macy #else 7856e5ad5fSMatt Macy #include <assert.h> 7956e5ad5fSMatt Macy #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 8056e5ad5fSMatt Macy #define PJDLOG_RASSERT(expr, ...) assert(expr) 8156e5ad5fSMatt Macy #define PJDLOG_ABORT(...) abort() 8256e5ad5fSMatt Macy #endif 8356e5ad5fSMatt Macy #endif 8456e5ad5fSMatt Macy 8556e5ad5fSMatt Macy #define NVPAIR_MAGIC 0x6e7670 /* "nvp" */ 8656e5ad5fSMatt Macy struct nvpair { 8756e5ad5fSMatt Macy int nvp_magic; 8856e5ad5fSMatt Macy char *nvp_name; 8956e5ad5fSMatt Macy int nvp_type; 9056e5ad5fSMatt Macy uint64_t nvp_data; 9156e5ad5fSMatt Macy size_t nvp_datasize; 9256e5ad5fSMatt Macy size_t nvp_nitems; /* Used only for array types. */ 9356e5ad5fSMatt Macy nvlist_t *nvp_list; 9456e5ad5fSMatt Macy TAILQ_ENTRY(nvpair) nvp_next; 9556e5ad5fSMatt Macy }; 9656e5ad5fSMatt Macy 9756e5ad5fSMatt Macy #define NVPAIR_ASSERT(nvp) do { \ 9856e5ad5fSMatt Macy PJDLOG_ASSERT((nvp) != NULL); \ 9956e5ad5fSMatt Macy PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \ 10056e5ad5fSMatt Macy } while (0) 10156e5ad5fSMatt Macy 10256e5ad5fSMatt Macy struct nvpair_header { 10356e5ad5fSMatt Macy uint8_t nvph_type; 10456e5ad5fSMatt Macy uint16_t nvph_namesize; 10556e5ad5fSMatt Macy uint64_t nvph_datasize; 10656e5ad5fSMatt Macy uint64_t nvph_nitems; 10756e5ad5fSMatt Macy } __packed; 10856e5ad5fSMatt Macy 10956e5ad5fSMatt Macy 11056e5ad5fSMatt Macy void 11156e5ad5fSMatt Macy nvpair_assert(const nvpair_t *nvp __unused) 11256e5ad5fSMatt Macy { 11356e5ad5fSMatt Macy 11456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 11556e5ad5fSMatt Macy } 11656e5ad5fSMatt Macy 11756e5ad5fSMatt Macy static nvpair_t * 11856e5ad5fSMatt Macy nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize, 11956e5ad5fSMatt Macy size_t nitems) 12056e5ad5fSMatt Macy { 12156e5ad5fSMatt Macy nvpair_t *nvp; 12256e5ad5fSMatt Macy size_t namelen; 12356e5ad5fSMatt Macy 12456e5ad5fSMatt Macy PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); 12556e5ad5fSMatt Macy 12656e5ad5fSMatt Macy namelen = strlen(name); 12756e5ad5fSMatt Macy if (namelen >= NV_NAME_MAX) { 12856e5ad5fSMatt Macy ERRNO_SET(ENAMETOOLONG); 12956e5ad5fSMatt Macy return (NULL); 13056e5ad5fSMatt Macy } 13156e5ad5fSMatt Macy 13256e5ad5fSMatt Macy nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1); 13356e5ad5fSMatt Macy if (nvp != NULL) { 13456e5ad5fSMatt Macy nvp->nvp_name = (char *)(nvp + 1); 13556e5ad5fSMatt Macy memcpy(nvp->nvp_name, name, namelen); 13656e5ad5fSMatt Macy nvp->nvp_name[namelen] = '\0'; 13756e5ad5fSMatt Macy nvp->nvp_type = type; 13856e5ad5fSMatt Macy nvp->nvp_data = data; 13956e5ad5fSMatt Macy nvp->nvp_datasize = datasize; 14056e5ad5fSMatt Macy nvp->nvp_nitems = nitems; 14156e5ad5fSMatt Macy nvp->nvp_magic = NVPAIR_MAGIC; 14256e5ad5fSMatt Macy } 14356e5ad5fSMatt Macy 14456e5ad5fSMatt Macy return (nvp); 14556e5ad5fSMatt Macy } 14656e5ad5fSMatt Macy 14756e5ad5fSMatt Macy static int 14856e5ad5fSMatt Macy nvpair_append(nvpair_t *nvp, const void *value, size_t valsize, size_t datasize) 14956e5ad5fSMatt Macy { 15056e5ad5fSMatt Macy void *olddata, *data, *valp; 15156e5ad5fSMatt Macy size_t oldlen; 15256e5ad5fSMatt Macy 15356e5ad5fSMatt Macy oldlen = nvp->nvp_nitems * valsize; 15456e5ad5fSMatt Macy olddata = (void *)(uintptr_t)nvp->nvp_data; 15556e5ad5fSMatt Macy data = nv_realloc(olddata, oldlen + valsize); 15656e5ad5fSMatt Macy if (data == NULL) { 15756e5ad5fSMatt Macy ERRNO_SET(ENOMEM); 15856e5ad5fSMatt Macy return (-1); 15956e5ad5fSMatt Macy } 16056e5ad5fSMatt Macy valp = (unsigned char *)data + oldlen; 16156e5ad5fSMatt Macy memcpy(valp, value, valsize); 16256e5ad5fSMatt Macy 16356e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)data; 16456e5ad5fSMatt Macy nvp->nvp_datasize += datasize; 16556e5ad5fSMatt Macy nvp->nvp_nitems++; 16656e5ad5fSMatt Macy return (0); 16756e5ad5fSMatt Macy } 16856e5ad5fSMatt Macy 16956e5ad5fSMatt Macy nvlist_t * 17056e5ad5fSMatt Macy nvpair_nvlist(const nvpair_t *nvp) 17156e5ad5fSMatt Macy { 17256e5ad5fSMatt Macy 17356e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 17456e5ad5fSMatt Macy 17556e5ad5fSMatt Macy return (nvp->nvp_list); 17656e5ad5fSMatt Macy } 17756e5ad5fSMatt Macy 17856e5ad5fSMatt Macy nvpair_t * 17956e5ad5fSMatt Macy nvpair_next(const nvpair_t *nvp) 18056e5ad5fSMatt Macy { 18156e5ad5fSMatt Macy 18256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 18356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list != NULL); 18456e5ad5fSMatt Macy 18556e5ad5fSMatt Macy return (TAILQ_NEXT(nvp, nvp_next)); 18656e5ad5fSMatt Macy } 18756e5ad5fSMatt Macy 18856e5ad5fSMatt Macy nvpair_t * 18956e5ad5fSMatt Macy nvpair_prev(const nvpair_t *nvp) 19056e5ad5fSMatt Macy { 19156e5ad5fSMatt Macy 19256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 19356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list != NULL); 19456e5ad5fSMatt Macy 19556e5ad5fSMatt Macy return (TAILQ_PREV(nvp, nvl_head, nvp_next)); 19656e5ad5fSMatt Macy } 19756e5ad5fSMatt Macy 19856e5ad5fSMatt Macy void 19956e5ad5fSMatt Macy nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) 20056e5ad5fSMatt Macy { 20156e5ad5fSMatt Macy 20256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 20356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list == NULL); 20456e5ad5fSMatt Macy PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 || 20556e5ad5fSMatt Macy !nvlist_exists(nvl, nvpair_name(nvp))); 20656e5ad5fSMatt Macy 20756e5ad5fSMatt Macy TAILQ_INSERT_TAIL(head, nvp, nvp_next); 20856e5ad5fSMatt Macy nvp->nvp_list = nvl; 20956e5ad5fSMatt Macy } 21056e5ad5fSMatt Macy 21156e5ad5fSMatt Macy static void 21256e5ad5fSMatt Macy nvpair_remove_nvlist(nvpair_t *nvp) 21356e5ad5fSMatt Macy { 21456e5ad5fSMatt Macy nvlist_t *nvl; 21556e5ad5fSMatt Macy 21656e5ad5fSMatt Macy /* XXX: DECONST is bad, mkay? */ 21756e5ad5fSMatt Macy nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp)); 21856e5ad5fSMatt Macy PJDLOG_ASSERT(nvl != NULL); 21956e5ad5fSMatt Macy nvlist_set_parent(nvl, NULL); 22056e5ad5fSMatt Macy } 22156e5ad5fSMatt Macy 22256e5ad5fSMatt Macy static void 22356e5ad5fSMatt Macy nvpair_remove_nvlist_array(nvpair_t *nvp) 22456e5ad5fSMatt Macy { 22556e5ad5fSMatt Macy nvlist_t **nvlarray; 22656e5ad5fSMatt Macy size_t count, i; 22756e5ad5fSMatt Macy 22856e5ad5fSMatt Macy /* XXX: DECONST is bad, mkay? */ 22956e5ad5fSMatt Macy nvlarray = __DECONST(nvlist_t **, 23056e5ad5fSMatt Macy nvpair_get_nvlist_array(nvp, &count)); 23156e5ad5fSMatt Macy for (i = 0; i < count; i++) { 23256e5ad5fSMatt Macy nvlist_set_array_next(nvlarray[i], NULL); 23356e5ad5fSMatt Macy nvlist_set_parent(nvlarray[i], NULL); 23456e5ad5fSMatt Macy } 23556e5ad5fSMatt Macy } 23656e5ad5fSMatt Macy 23756e5ad5fSMatt Macy void 23856e5ad5fSMatt Macy nvpair_remove(struct nvl_head *head, nvpair_t *nvp, 23956e5ad5fSMatt Macy const nvlist_t *nvl __unused) 24056e5ad5fSMatt Macy { 24156e5ad5fSMatt Macy 24256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 24356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list == nvl); 24456e5ad5fSMatt Macy 24556e5ad5fSMatt Macy if (nvpair_type(nvp) == NV_TYPE_NVLIST) 24656e5ad5fSMatt Macy nvpair_remove_nvlist(nvp); 24756e5ad5fSMatt Macy else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) 24856e5ad5fSMatt Macy nvpair_remove_nvlist_array(nvp); 24956e5ad5fSMatt Macy 25056e5ad5fSMatt Macy TAILQ_REMOVE(head, nvp, nvp_next); 25156e5ad5fSMatt Macy nvp->nvp_list = NULL; 25256e5ad5fSMatt Macy } 25356e5ad5fSMatt Macy 25456e5ad5fSMatt Macy nvpair_t * 25556e5ad5fSMatt Macy nvpair_clone(const nvpair_t *nvp) 25656e5ad5fSMatt Macy { 25756e5ad5fSMatt Macy nvpair_t *newnvp; 25856e5ad5fSMatt Macy const char *name; 25956e5ad5fSMatt Macy const void *data; 26056e5ad5fSMatt Macy size_t datasize; 26156e5ad5fSMatt Macy 26256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 26356e5ad5fSMatt Macy 26456e5ad5fSMatt Macy name = nvpair_name(nvp); 26556e5ad5fSMatt Macy 26656e5ad5fSMatt Macy switch (nvpair_type(nvp)) { 26756e5ad5fSMatt Macy case NV_TYPE_NULL: 26856e5ad5fSMatt Macy newnvp = nvpair_create_null(name); 26956e5ad5fSMatt Macy break; 27056e5ad5fSMatt Macy case NV_TYPE_BOOL: 27156e5ad5fSMatt Macy newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); 27256e5ad5fSMatt Macy break; 27356e5ad5fSMatt Macy case NV_TYPE_NUMBER: 27456e5ad5fSMatt Macy newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); 27556e5ad5fSMatt Macy break; 27656e5ad5fSMatt Macy case NV_TYPE_STRING: 27756e5ad5fSMatt Macy newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); 27856e5ad5fSMatt Macy break; 27956e5ad5fSMatt Macy case NV_TYPE_NVLIST: 28056e5ad5fSMatt Macy newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); 28156e5ad5fSMatt Macy break; 28256e5ad5fSMatt Macy case NV_TYPE_BINARY: 28356e5ad5fSMatt Macy data = nvpair_get_binary(nvp, &datasize); 28456e5ad5fSMatt Macy newnvp = nvpair_create_binary(name, data, datasize); 28556e5ad5fSMatt Macy break; 28656e5ad5fSMatt Macy case NV_TYPE_BOOL_ARRAY: 28756e5ad5fSMatt Macy data = nvpair_get_bool_array(nvp, &datasize); 28856e5ad5fSMatt Macy newnvp = nvpair_create_bool_array(name, data, datasize); 28956e5ad5fSMatt Macy break; 29056e5ad5fSMatt Macy case NV_TYPE_NUMBER_ARRAY: 29156e5ad5fSMatt Macy data = nvpair_get_number_array(nvp, &datasize); 29256e5ad5fSMatt Macy newnvp = nvpair_create_number_array(name, data, datasize); 29356e5ad5fSMatt Macy break; 29456e5ad5fSMatt Macy case NV_TYPE_STRING_ARRAY: 29556e5ad5fSMatt Macy data = nvpair_get_string_array(nvp, &datasize); 29656e5ad5fSMatt Macy newnvp = nvpair_create_string_array(name, data, datasize); 29756e5ad5fSMatt Macy break; 29856e5ad5fSMatt Macy case NV_TYPE_NVLIST_ARRAY: 29956e5ad5fSMatt Macy data = nvpair_get_nvlist_array(nvp, &datasize); 30056e5ad5fSMatt Macy newnvp = nvpair_create_nvlist_array(name, data, datasize); 30156e5ad5fSMatt Macy break; 30256e5ad5fSMatt Macy #ifndef _KERNEL 30356e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR: 30456e5ad5fSMatt Macy newnvp = nvpair_create_descriptor(name, 30556e5ad5fSMatt Macy nvpair_get_descriptor(nvp)); 30656e5ad5fSMatt Macy break; 30756e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR_ARRAY: 30856e5ad5fSMatt Macy data = nvpair_get_descriptor_array(nvp, &datasize); 30956e5ad5fSMatt Macy newnvp = nvpair_create_descriptor_array(name, data, datasize); 31056e5ad5fSMatt Macy break; 31156e5ad5fSMatt Macy #endif 31256e5ad5fSMatt Macy default: 31356e5ad5fSMatt Macy PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 31456e5ad5fSMatt Macy } 31556e5ad5fSMatt Macy 31656e5ad5fSMatt Macy return (newnvp); 31756e5ad5fSMatt Macy } 31856e5ad5fSMatt Macy 31956e5ad5fSMatt Macy size_t 32056e5ad5fSMatt Macy nvpair_header_size(void) 32156e5ad5fSMatt Macy { 32256e5ad5fSMatt Macy 32356e5ad5fSMatt Macy return (sizeof(struct nvpair_header)); 32456e5ad5fSMatt Macy } 32556e5ad5fSMatt Macy 32656e5ad5fSMatt Macy size_t 32756e5ad5fSMatt Macy nvpair_size(const nvpair_t *nvp) 32856e5ad5fSMatt Macy { 32956e5ad5fSMatt Macy 33056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 33156e5ad5fSMatt Macy 33256e5ad5fSMatt Macy return (nvp->nvp_datasize); 33356e5ad5fSMatt Macy } 33456e5ad5fSMatt Macy 33556e5ad5fSMatt Macy unsigned char * 33656e5ad5fSMatt Macy nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 33756e5ad5fSMatt Macy { 33856e5ad5fSMatt Macy struct nvpair_header nvphdr; 33956e5ad5fSMatt Macy size_t namesize; 34056e5ad5fSMatt Macy 34156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 34256e5ad5fSMatt Macy 34356e5ad5fSMatt Macy nvphdr.nvph_type = nvp->nvp_type; 34456e5ad5fSMatt Macy namesize = strlen(nvp->nvp_name) + 1; 34556e5ad5fSMatt Macy PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX); 34656e5ad5fSMatt Macy nvphdr.nvph_namesize = namesize; 34756e5ad5fSMatt Macy nvphdr.nvph_datasize = nvp->nvp_datasize; 34856e5ad5fSMatt Macy nvphdr.nvph_nitems = nvp->nvp_nitems; 34956e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 35056e5ad5fSMatt Macy memcpy(ptr, &nvphdr, sizeof(nvphdr)); 35156e5ad5fSMatt Macy ptr += sizeof(nvphdr); 35256e5ad5fSMatt Macy *leftp -= sizeof(nvphdr); 35356e5ad5fSMatt Macy 35456e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= namesize); 35556e5ad5fSMatt Macy memcpy(ptr, nvp->nvp_name, namesize); 35656e5ad5fSMatt Macy ptr += namesize; 35756e5ad5fSMatt Macy *leftp -= namesize; 35856e5ad5fSMatt Macy 35956e5ad5fSMatt Macy return (ptr); 36056e5ad5fSMatt Macy } 36156e5ad5fSMatt Macy 36256e5ad5fSMatt Macy unsigned char * 36356e5ad5fSMatt Macy nvpair_pack_null(const nvpair_t *nvp __unused, unsigned char *ptr, 36456e5ad5fSMatt Macy size_t *leftp __unused) 36556e5ad5fSMatt Macy { 36656e5ad5fSMatt Macy 36756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 36856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 36956e5ad5fSMatt Macy 37056e5ad5fSMatt Macy return (ptr); 37156e5ad5fSMatt Macy } 37256e5ad5fSMatt Macy 37356e5ad5fSMatt Macy unsigned char * 37456e5ad5fSMatt Macy nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 37556e5ad5fSMatt Macy { 37656e5ad5fSMatt Macy uint8_t value; 37756e5ad5fSMatt Macy 37856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 37956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 38056e5ad5fSMatt Macy 38156e5ad5fSMatt Macy value = (uint8_t)nvp->nvp_data; 38256e5ad5fSMatt Macy 38356e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(value)); 38456e5ad5fSMatt Macy memcpy(ptr, &value, sizeof(value)); 38556e5ad5fSMatt Macy ptr += sizeof(value); 38656e5ad5fSMatt Macy *leftp -= sizeof(value); 38756e5ad5fSMatt Macy 38856e5ad5fSMatt Macy return (ptr); 38956e5ad5fSMatt Macy } 39056e5ad5fSMatt Macy 39156e5ad5fSMatt Macy unsigned char * 39256e5ad5fSMatt Macy nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 39356e5ad5fSMatt Macy { 39456e5ad5fSMatt Macy uint64_t value; 39556e5ad5fSMatt Macy 39656e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 39756e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 39856e5ad5fSMatt Macy 39956e5ad5fSMatt Macy value = (uint64_t)nvp->nvp_data; 40056e5ad5fSMatt Macy 40156e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(value)); 40256e5ad5fSMatt Macy memcpy(ptr, &value, sizeof(value)); 40356e5ad5fSMatt Macy ptr += sizeof(value); 40456e5ad5fSMatt Macy *leftp -= sizeof(value); 40556e5ad5fSMatt Macy 40656e5ad5fSMatt Macy return (ptr); 40756e5ad5fSMatt Macy } 40856e5ad5fSMatt Macy 40956e5ad5fSMatt Macy unsigned char * 41056e5ad5fSMatt Macy nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 41156e5ad5fSMatt Macy { 41256e5ad5fSMatt Macy 41356e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 41456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 41556e5ad5fSMatt Macy 41656e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 41756e5ad5fSMatt Macy memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 41856e5ad5fSMatt Macy ptr += nvp->nvp_datasize; 41956e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize; 42056e5ad5fSMatt Macy 42156e5ad5fSMatt Macy return (ptr); 42256e5ad5fSMatt Macy } 42356e5ad5fSMatt Macy 42456e5ad5fSMatt Macy unsigned char * 42556e5ad5fSMatt Macy nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp) 42656e5ad5fSMatt Macy { 42756e5ad5fSMatt Macy struct nvpair_header nvphdr; 42856e5ad5fSMatt Macy size_t namesize; 42956e5ad5fSMatt Macy const char *name = ""; 43056e5ad5fSMatt Macy 43156e5ad5fSMatt Macy namesize = 1; 43256e5ad5fSMatt Macy nvphdr.nvph_type = NV_TYPE_NVLIST_UP; 43356e5ad5fSMatt Macy nvphdr.nvph_namesize = namesize; 43456e5ad5fSMatt Macy nvphdr.nvph_datasize = 0; 43556e5ad5fSMatt Macy nvphdr.nvph_nitems = 0; 43656e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 43756e5ad5fSMatt Macy memcpy(ptr, &nvphdr, sizeof(nvphdr)); 43856e5ad5fSMatt Macy ptr += sizeof(nvphdr); 43956e5ad5fSMatt Macy *leftp -= sizeof(nvphdr); 44056e5ad5fSMatt Macy 44156e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= namesize); 44256e5ad5fSMatt Macy memcpy(ptr, name, namesize); 44356e5ad5fSMatt Macy ptr += namesize; 44456e5ad5fSMatt Macy *leftp -= namesize; 44556e5ad5fSMatt Macy 44656e5ad5fSMatt Macy return (ptr); 44756e5ad5fSMatt Macy } 44856e5ad5fSMatt Macy 44956e5ad5fSMatt Macy unsigned char * 45056e5ad5fSMatt Macy nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp) 45156e5ad5fSMatt Macy { 45256e5ad5fSMatt Macy struct nvpair_header nvphdr; 45356e5ad5fSMatt Macy size_t namesize; 45456e5ad5fSMatt Macy const char *name = ""; 45556e5ad5fSMatt Macy 45656e5ad5fSMatt Macy namesize = 1; 45756e5ad5fSMatt Macy nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT; 45856e5ad5fSMatt Macy nvphdr.nvph_namesize = namesize; 45956e5ad5fSMatt Macy nvphdr.nvph_datasize = 0; 46056e5ad5fSMatt Macy nvphdr.nvph_nitems = 0; 46156e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 46256e5ad5fSMatt Macy memcpy(ptr, &nvphdr, sizeof(nvphdr)); 46356e5ad5fSMatt Macy ptr += sizeof(nvphdr); 46456e5ad5fSMatt Macy *leftp -= sizeof(nvphdr); 46556e5ad5fSMatt Macy 46656e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= namesize); 46756e5ad5fSMatt Macy memcpy(ptr, name, namesize); 46856e5ad5fSMatt Macy ptr += namesize; 46956e5ad5fSMatt Macy *leftp -= namesize; 47056e5ad5fSMatt Macy 47156e5ad5fSMatt Macy return (ptr); 47256e5ad5fSMatt Macy } 47356e5ad5fSMatt Macy 47456e5ad5fSMatt Macy #ifndef _KERNEL 47556e5ad5fSMatt Macy unsigned char * 47656e5ad5fSMatt Macy nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, 47756e5ad5fSMatt Macy size_t *leftp) 47856e5ad5fSMatt Macy { 47956e5ad5fSMatt Macy int64_t value; 48056e5ad5fSMatt Macy 48156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 48256e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 48356e5ad5fSMatt Macy 48456e5ad5fSMatt Macy value = (int64_t)nvp->nvp_data; 48556e5ad5fSMatt Macy if (value != -1) { 48656e5ad5fSMatt Macy /* 48756e5ad5fSMatt Macy * If there is a real descriptor here, we change its number 48856e5ad5fSMatt Macy * to position in the array of descriptors send via control 48956e5ad5fSMatt Macy * message. 49056e5ad5fSMatt Macy */ 49156e5ad5fSMatt Macy PJDLOG_ASSERT(fdidxp != NULL); 49256e5ad5fSMatt Macy 49356e5ad5fSMatt Macy value = *fdidxp; 49456e5ad5fSMatt Macy (*fdidxp)++; 49556e5ad5fSMatt Macy } 49656e5ad5fSMatt Macy 49756e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(value)); 49856e5ad5fSMatt Macy memcpy(ptr, &value, sizeof(value)); 49956e5ad5fSMatt Macy ptr += sizeof(value); 50056e5ad5fSMatt Macy *leftp -= sizeof(value); 50156e5ad5fSMatt Macy 50256e5ad5fSMatt Macy return (ptr); 50356e5ad5fSMatt Macy } 50456e5ad5fSMatt Macy #endif 50556e5ad5fSMatt Macy 50656e5ad5fSMatt Macy unsigned char * 50756e5ad5fSMatt Macy nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 50856e5ad5fSMatt Macy { 50956e5ad5fSMatt Macy 51056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 51156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 51256e5ad5fSMatt Macy 51356e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 51456e5ad5fSMatt Macy memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 51556e5ad5fSMatt Macy ptr += nvp->nvp_datasize; 51656e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize; 51756e5ad5fSMatt Macy 51856e5ad5fSMatt Macy return (ptr); 51956e5ad5fSMatt Macy } 52056e5ad5fSMatt Macy 52156e5ad5fSMatt Macy unsigned char * 52256e5ad5fSMatt Macy nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 52356e5ad5fSMatt Macy { 52456e5ad5fSMatt Macy 52556e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 52656e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 52756e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 52856e5ad5fSMatt Macy 52956e5ad5fSMatt Macy memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 53056e5ad5fSMatt Macy ptr += nvp->nvp_datasize; 53156e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize; 53256e5ad5fSMatt Macy 53356e5ad5fSMatt Macy return (ptr); 53456e5ad5fSMatt Macy } 53556e5ad5fSMatt Macy 53656e5ad5fSMatt Macy unsigned char * 53756e5ad5fSMatt Macy nvpair_pack_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 53856e5ad5fSMatt Macy { 53956e5ad5fSMatt Macy 54056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 54156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 54256e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 54356e5ad5fSMatt Macy 54456e5ad5fSMatt Macy memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 54556e5ad5fSMatt Macy ptr += nvp->nvp_datasize; 54656e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize; 54756e5ad5fSMatt Macy 54856e5ad5fSMatt Macy return (ptr); 54956e5ad5fSMatt Macy } 55056e5ad5fSMatt Macy 55156e5ad5fSMatt Macy unsigned char * 55256e5ad5fSMatt Macy nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 55356e5ad5fSMatt Macy { 55456e5ad5fSMatt Macy unsigned int ii; 5553fbf4ca6SJohn Baldwin size_t size __unused, len; 55656e5ad5fSMatt Macy const char * const *array; 55756e5ad5fSMatt Macy 55856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 55956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 56056e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 56156e5ad5fSMatt Macy 56256e5ad5fSMatt Macy size = 0; 56356e5ad5fSMatt Macy array = nvpair_get_string_array(nvp, NULL); 56456e5ad5fSMatt Macy PJDLOG_ASSERT(array != NULL); 56556e5ad5fSMatt Macy 56656e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) { 56756e5ad5fSMatt Macy len = strlen(array[ii]) + 1; 56856e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= len); 56956e5ad5fSMatt Macy 57056e5ad5fSMatt Macy memcpy(ptr, (const void *)array[ii], len); 57156e5ad5fSMatt Macy size += len; 57256e5ad5fSMatt Macy ptr += len; 57356e5ad5fSMatt Macy *leftp -= len; 57456e5ad5fSMatt Macy } 57556e5ad5fSMatt Macy 57656e5ad5fSMatt Macy PJDLOG_ASSERT(size == nvp->nvp_datasize); 57756e5ad5fSMatt Macy 57856e5ad5fSMatt Macy return (ptr); 57956e5ad5fSMatt Macy } 58056e5ad5fSMatt Macy 58156e5ad5fSMatt Macy #ifndef _KERNEL 58256e5ad5fSMatt Macy unsigned char * 58356e5ad5fSMatt Macy nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr, 58456e5ad5fSMatt Macy int64_t *fdidxp, size_t *leftp) 58556e5ad5fSMatt Macy { 58656e5ad5fSMatt Macy int64_t value; 58756e5ad5fSMatt Macy const int *array; 58856e5ad5fSMatt Macy unsigned int ii; 58956e5ad5fSMatt Macy 59056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 59156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 59256e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 59356e5ad5fSMatt Macy 59456e5ad5fSMatt Macy array = nvpair_get_descriptor_array(nvp, NULL); 59556e5ad5fSMatt Macy PJDLOG_ASSERT(array != NULL); 59656e5ad5fSMatt Macy 59756e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) { 59856e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(value)); 59956e5ad5fSMatt Macy 60056e5ad5fSMatt Macy value = array[ii]; 60156e5ad5fSMatt Macy if (value != -1) { 60256e5ad5fSMatt Macy /* 60356e5ad5fSMatt Macy * If there is a real descriptor here, we change its 60456e5ad5fSMatt Macy * number to position in the array of descriptors send 60556e5ad5fSMatt Macy * via control message. 60656e5ad5fSMatt Macy */ 60756e5ad5fSMatt Macy PJDLOG_ASSERT(fdidxp != NULL); 60856e5ad5fSMatt Macy 60956e5ad5fSMatt Macy value = *fdidxp; 61056e5ad5fSMatt Macy (*fdidxp)++; 61156e5ad5fSMatt Macy } 61256e5ad5fSMatt Macy memcpy(ptr, &value, sizeof(value)); 61356e5ad5fSMatt Macy ptr += sizeof(value); 61456e5ad5fSMatt Macy *leftp -= sizeof(value); 61556e5ad5fSMatt Macy } 61656e5ad5fSMatt Macy 61756e5ad5fSMatt Macy return (ptr); 61856e5ad5fSMatt Macy } 61956e5ad5fSMatt Macy #endif 62056e5ad5fSMatt Macy 62156e5ad5fSMatt Macy void 62256e5ad5fSMatt Macy nvpair_init_datasize(nvpair_t *nvp) 62356e5ad5fSMatt Macy { 62456e5ad5fSMatt Macy 62556e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 62656e5ad5fSMatt Macy 62756e5ad5fSMatt Macy if (nvp->nvp_type == NV_TYPE_NVLIST) { 62856e5ad5fSMatt Macy if (nvp->nvp_data == 0) { 62956e5ad5fSMatt Macy nvp->nvp_datasize = 0; 63056e5ad5fSMatt Macy } else { 63156e5ad5fSMatt Macy nvp->nvp_datasize = 63256e5ad5fSMatt Macy nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); 63356e5ad5fSMatt Macy } 63456e5ad5fSMatt Macy } 63556e5ad5fSMatt Macy } 63656e5ad5fSMatt Macy 63756e5ad5fSMatt Macy const unsigned char * 63856e5ad5fSMatt Macy nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 63956e5ad5fSMatt Macy size_t *leftp) 64056e5ad5fSMatt Macy { 64156e5ad5fSMatt Macy struct nvpair_header nvphdr; 64256e5ad5fSMatt Macy 64356e5ad5fSMatt Macy if (*leftp < sizeof(nvphdr)) 64456e5ad5fSMatt Macy goto fail; 64556e5ad5fSMatt Macy 64656e5ad5fSMatt Macy memcpy(&nvphdr, ptr, sizeof(nvphdr)); 64756e5ad5fSMatt Macy ptr += sizeof(nvphdr); 64856e5ad5fSMatt Macy *leftp -= sizeof(nvphdr); 64956e5ad5fSMatt Macy 65056e5ad5fSMatt Macy #if NV_TYPE_FIRST > 0 65156e5ad5fSMatt Macy if (nvphdr.nvph_type < NV_TYPE_FIRST) 65256e5ad5fSMatt Macy goto fail; 65356e5ad5fSMatt Macy #endif 65456e5ad5fSMatt Macy if (nvphdr.nvph_type > NV_TYPE_LAST && 65556e5ad5fSMatt Macy nvphdr.nvph_type != NV_TYPE_NVLIST_UP && 65656e5ad5fSMatt Macy nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) { 65756e5ad5fSMatt Macy goto fail; 65856e5ad5fSMatt Macy } 65956e5ad5fSMatt Macy 66056e5ad5fSMatt Macy #if BYTE_ORDER == BIG_ENDIAN 66156e5ad5fSMatt Macy if (!isbe) { 66256e5ad5fSMatt Macy nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize); 66356e5ad5fSMatt Macy nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize); 664e673ac3fSStefan Grundmann nvphdr.nvph_nitems = le64toh(nvphdr.nvph_nitems); 66556e5ad5fSMatt Macy } 66656e5ad5fSMatt Macy #else 66756e5ad5fSMatt Macy if (isbe) { 66856e5ad5fSMatt Macy nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); 66956e5ad5fSMatt Macy nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); 670e673ac3fSStefan Grundmann nvphdr.nvph_nitems = be64toh(nvphdr.nvph_nitems); 67156e5ad5fSMatt Macy } 67256e5ad5fSMatt Macy #endif 67356e5ad5fSMatt Macy 67456e5ad5fSMatt Macy if (nvphdr.nvph_namesize > NV_NAME_MAX) 67556e5ad5fSMatt Macy goto fail; 67656e5ad5fSMatt Macy if (*leftp < nvphdr.nvph_namesize) 67756e5ad5fSMatt Macy goto fail; 67856e5ad5fSMatt Macy if (nvphdr.nvph_namesize < 1) 67956e5ad5fSMatt Macy goto fail; 68056e5ad5fSMatt Macy if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != 68156e5ad5fSMatt Macy (size_t)(nvphdr.nvph_namesize - 1)) { 68256e5ad5fSMatt Macy goto fail; 68356e5ad5fSMatt Macy } 68456e5ad5fSMatt Macy 68556e5ad5fSMatt Macy memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); 68656e5ad5fSMatt Macy ptr += nvphdr.nvph_namesize; 68756e5ad5fSMatt Macy *leftp -= nvphdr.nvph_namesize; 68856e5ad5fSMatt Macy 68956e5ad5fSMatt Macy if (*leftp < nvphdr.nvph_datasize) 69056e5ad5fSMatt Macy goto fail; 69156e5ad5fSMatt Macy 69256e5ad5fSMatt Macy nvp->nvp_type = nvphdr.nvph_type; 69356e5ad5fSMatt Macy nvp->nvp_data = 0; 69456e5ad5fSMatt Macy nvp->nvp_datasize = nvphdr.nvph_datasize; 69556e5ad5fSMatt Macy nvp->nvp_nitems = nvphdr.nvph_nitems; 69656e5ad5fSMatt Macy 69756e5ad5fSMatt Macy return (ptr); 69856e5ad5fSMatt Macy fail: 69956e5ad5fSMatt Macy ERRNO_SET(EINVAL); 70056e5ad5fSMatt Macy return (NULL); 70156e5ad5fSMatt Macy } 70256e5ad5fSMatt Macy 70356e5ad5fSMatt Macy const unsigned char * 70456e5ad5fSMatt Macy nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, 70556e5ad5fSMatt Macy size_t *leftp __unused) 70656e5ad5fSMatt Macy { 70756e5ad5fSMatt Macy 70856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 70956e5ad5fSMatt Macy 71056e5ad5fSMatt Macy if (nvp->nvp_datasize != 0) { 71156e5ad5fSMatt Macy ERRNO_SET(EINVAL); 71256e5ad5fSMatt Macy return (NULL); 71356e5ad5fSMatt Macy } 71456e5ad5fSMatt Macy 71556e5ad5fSMatt Macy return (ptr); 71656e5ad5fSMatt Macy } 71756e5ad5fSMatt Macy 71856e5ad5fSMatt Macy const unsigned char * 71956e5ad5fSMatt Macy nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, 72056e5ad5fSMatt Macy size_t *leftp) 72156e5ad5fSMatt Macy { 72256e5ad5fSMatt Macy uint8_t value; 72356e5ad5fSMatt Macy 72456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 72556e5ad5fSMatt Macy 72656e5ad5fSMatt Macy if (nvp->nvp_datasize != sizeof(value)) { 72756e5ad5fSMatt Macy ERRNO_SET(EINVAL); 72856e5ad5fSMatt Macy return (NULL); 72956e5ad5fSMatt Macy } 73056e5ad5fSMatt Macy if (*leftp < sizeof(value)) { 73156e5ad5fSMatt Macy ERRNO_SET(EINVAL); 73256e5ad5fSMatt Macy return (NULL); 73356e5ad5fSMatt Macy } 73456e5ad5fSMatt Macy 73556e5ad5fSMatt Macy memcpy(&value, ptr, sizeof(value)); 73656e5ad5fSMatt Macy ptr += sizeof(value); 73756e5ad5fSMatt Macy *leftp -= sizeof(value); 73856e5ad5fSMatt Macy 73956e5ad5fSMatt Macy if (value != 0 && value != 1) { 74056e5ad5fSMatt Macy ERRNO_SET(EINVAL); 74156e5ad5fSMatt Macy return (NULL); 74256e5ad5fSMatt Macy } 74356e5ad5fSMatt Macy 74456e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)value; 74556e5ad5fSMatt Macy 74656e5ad5fSMatt Macy return (ptr); 74756e5ad5fSMatt Macy } 74856e5ad5fSMatt Macy 74956e5ad5fSMatt Macy const unsigned char * 75056e5ad5fSMatt Macy nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 75156e5ad5fSMatt Macy size_t *leftp) 75256e5ad5fSMatt Macy { 75356e5ad5fSMatt Macy 75456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 75556e5ad5fSMatt Macy 75656e5ad5fSMatt Macy if (nvp->nvp_datasize != sizeof(uint64_t)) { 75756e5ad5fSMatt Macy ERRNO_SET(EINVAL); 75856e5ad5fSMatt Macy return (NULL); 75956e5ad5fSMatt Macy } 76056e5ad5fSMatt Macy if (*leftp < sizeof(uint64_t)) { 76156e5ad5fSMatt Macy ERRNO_SET(EINVAL); 76256e5ad5fSMatt Macy return (NULL); 76356e5ad5fSMatt Macy } 76456e5ad5fSMatt Macy 76556e5ad5fSMatt Macy if (isbe) 76656e5ad5fSMatt Macy nvp->nvp_data = be64dec(ptr); 76756e5ad5fSMatt Macy else 76856e5ad5fSMatt Macy nvp->nvp_data = le64dec(ptr); 76956e5ad5fSMatt Macy 77056e5ad5fSMatt Macy ptr += sizeof(uint64_t); 77156e5ad5fSMatt Macy *leftp -= sizeof(uint64_t); 77256e5ad5fSMatt Macy 77356e5ad5fSMatt Macy return (ptr); 77456e5ad5fSMatt Macy } 77556e5ad5fSMatt Macy 77656e5ad5fSMatt Macy const unsigned char * 77756e5ad5fSMatt Macy nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp, 77856e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp) 77956e5ad5fSMatt Macy { 78056e5ad5fSMatt Macy 78156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 78256e5ad5fSMatt Macy 78356e5ad5fSMatt Macy if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 78456e5ad5fSMatt Macy ERRNO_SET(EINVAL); 78556e5ad5fSMatt Macy return (NULL); 78656e5ad5fSMatt Macy } 78756e5ad5fSMatt Macy 78856e5ad5fSMatt Macy if (strnlen((const char *)ptr, nvp->nvp_datasize) != 78956e5ad5fSMatt Macy nvp->nvp_datasize - 1) { 79056e5ad5fSMatt Macy ERRNO_SET(EINVAL); 79156e5ad5fSMatt Macy return (NULL); 79256e5ad5fSMatt Macy } 79356e5ad5fSMatt Macy 79456e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr); 79556e5ad5fSMatt Macy if (nvp->nvp_data == 0) 79656e5ad5fSMatt Macy return (NULL); 79756e5ad5fSMatt Macy 79856e5ad5fSMatt Macy ptr += nvp->nvp_datasize; 79956e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize; 80056e5ad5fSMatt Macy 80156e5ad5fSMatt Macy return (ptr); 80256e5ad5fSMatt Macy } 80356e5ad5fSMatt Macy 80456e5ad5fSMatt Macy const unsigned char * 80556e5ad5fSMatt Macy nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp, 80656e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child) 80756e5ad5fSMatt Macy { 80856e5ad5fSMatt Macy nvlist_t *value; 80956e5ad5fSMatt Macy 81056e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 81156e5ad5fSMatt Macy 81256e5ad5fSMatt Macy if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 81356e5ad5fSMatt Macy ERRNO_SET(EINVAL); 81456e5ad5fSMatt Macy return (NULL); 81556e5ad5fSMatt Macy } 81656e5ad5fSMatt Macy 81756e5ad5fSMatt Macy value = nvlist_create(0); 81856e5ad5fSMatt Macy if (value == NULL) 81956e5ad5fSMatt Macy return (NULL); 82056e5ad5fSMatt Macy 82156e5ad5fSMatt Macy ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp); 82256e5ad5fSMatt Macy if (ptr == NULL) 82356e5ad5fSMatt Macy return (NULL); 82456e5ad5fSMatt Macy 82556e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value; 82656e5ad5fSMatt Macy *child = value; 82756e5ad5fSMatt Macy 82856e5ad5fSMatt Macy return (ptr); 82956e5ad5fSMatt Macy } 83056e5ad5fSMatt Macy 83156e5ad5fSMatt Macy #ifndef _KERNEL 83256e5ad5fSMatt Macy const unsigned char * 83356e5ad5fSMatt Macy nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 83456e5ad5fSMatt Macy size_t *leftp, const int *fds, size_t nfds) 83556e5ad5fSMatt Macy { 83656e5ad5fSMatt Macy int64_t idx; 83756e5ad5fSMatt Macy 83856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 83956e5ad5fSMatt Macy 84056e5ad5fSMatt Macy if (nvp->nvp_datasize != sizeof(idx)) { 84156e5ad5fSMatt Macy ERRNO_SET(EINVAL); 84256e5ad5fSMatt Macy return (NULL); 84356e5ad5fSMatt Macy } 84456e5ad5fSMatt Macy if (*leftp < sizeof(idx)) { 84556e5ad5fSMatt Macy ERRNO_SET(EINVAL); 84656e5ad5fSMatt Macy return (NULL); 84756e5ad5fSMatt Macy } 84856e5ad5fSMatt Macy 84956e5ad5fSMatt Macy if (isbe) 85056e5ad5fSMatt Macy idx = be64dec(ptr); 85156e5ad5fSMatt Macy else 85256e5ad5fSMatt Macy idx = le64dec(ptr); 85356e5ad5fSMatt Macy 85456e5ad5fSMatt Macy if (idx < 0) { 85556e5ad5fSMatt Macy ERRNO_SET(EINVAL); 85656e5ad5fSMatt Macy return (NULL); 85756e5ad5fSMatt Macy } 85856e5ad5fSMatt Macy 85956e5ad5fSMatt Macy if ((size_t)idx >= nfds) { 86056e5ad5fSMatt Macy ERRNO_SET(EINVAL); 86156e5ad5fSMatt Macy return (NULL); 86256e5ad5fSMatt Macy } 86356e5ad5fSMatt Macy 86456e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)fds[idx]; 86556e5ad5fSMatt Macy 86656e5ad5fSMatt Macy ptr += sizeof(idx); 86756e5ad5fSMatt Macy *leftp -= sizeof(idx); 86856e5ad5fSMatt Macy 86956e5ad5fSMatt Macy return (ptr); 87056e5ad5fSMatt Macy } 87156e5ad5fSMatt Macy #endif 87256e5ad5fSMatt Macy 87356e5ad5fSMatt Macy const unsigned char * 87456e5ad5fSMatt Macy nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp, 87556e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp) 87656e5ad5fSMatt Macy { 87756e5ad5fSMatt Macy void *value; 87856e5ad5fSMatt Macy 87956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 88056e5ad5fSMatt Macy 88156e5ad5fSMatt Macy if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 88256e5ad5fSMatt Macy ERRNO_SET(EINVAL); 88356e5ad5fSMatt Macy return (NULL); 88456e5ad5fSMatt Macy } 88556e5ad5fSMatt Macy 88656e5ad5fSMatt Macy value = nv_malloc(nvp->nvp_datasize); 88756e5ad5fSMatt Macy if (value == NULL) 88856e5ad5fSMatt Macy return (NULL); 88956e5ad5fSMatt Macy 89056e5ad5fSMatt Macy memcpy(value, ptr, nvp->nvp_datasize); 89156e5ad5fSMatt Macy ptr += nvp->nvp_datasize; 89256e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize; 89356e5ad5fSMatt Macy 89456e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value; 89556e5ad5fSMatt Macy 89656e5ad5fSMatt Macy return (ptr); 89756e5ad5fSMatt Macy } 89856e5ad5fSMatt Macy 89956e5ad5fSMatt Macy const unsigned char * 90056e5ad5fSMatt Macy nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp, 90156e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp) 90256e5ad5fSMatt Macy { 90356e5ad5fSMatt Macy uint8_t *value; 90456e5ad5fSMatt Macy size_t size; 90556e5ad5fSMatt Macy unsigned int i; 90656e5ad5fSMatt Macy 90756e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 90856e5ad5fSMatt Macy 90956e5ad5fSMatt Macy size = sizeof(*value) * nvp->nvp_nitems; 91056e5ad5fSMatt Macy if (nvp->nvp_datasize != size || *leftp < size || 91156e5ad5fSMatt Macy nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 91256e5ad5fSMatt Macy ERRNO_SET(EINVAL); 91356e5ad5fSMatt Macy return (NULL); 91456e5ad5fSMatt Macy } 91556e5ad5fSMatt Macy 91656e5ad5fSMatt Macy value = nv_malloc(size); 91756e5ad5fSMatt Macy if (value == NULL) 91856e5ad5fSMatt Macy return (NULL); 91956e5ad5fSMatt Macy 92056e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) { 92156e5ad5fSMatt Macy value[i] = *(const uint8_t *)ptr; 92256e5ad5fSMatt Macy 92356e5ad5fSMatt Macy ptr += sizeof(*value); 92456e5ad5fSMatt Macy *leftp -= sizeof(*value); 92556e5ad5fSMatt Macy } 92656e5ad5fSMatt Macy 92756e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value; 92856e5ad5fSMatt Macy 92956e5ad5fSMatt Macy return (ptr); 93056e5ad5fSMatt Macy } 93156e5ad5fSMatt Macy 93256e5ad5fSMatt Macy const unsigned char * 93356e5ad5fSMatt Macy nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 93456e5ad5fSMatt Macy size_t *leftp) 93556e5ad5fSMatt Macy { 93656e5ad5fSMatt Macy uint64_t *value; 93756e5ad5fSMatt Macy size_t size; 93856e5ad5fSMatt Macy unsigned int i; 93956e5ad5fSMatt Macy 94056e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 94156e5ad5fSMatt Macy 94256e5ad5fSMatt Macy size = sizeof(*value) * nvp->nvp_nitems; 94356e5ad5fSMatt Macy if (nvp->nvp_datasize != size || *leftp < size || 94456e5ad5fSMatt Macy nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 94556e5ad5fSMatt Macy ERRNO_SET(EINVAL); 94656e5ad5fSMatt Macy return (NULL); 94756e5ad5fSMatt Macy } 94856e5ad5fSMatt Macy 94956e5ad5fSMatt Macy value = nv_malloc(size); 95056e5ad5fSMatt Macy if (value == NULL) 95156e5ad5fSMatt Macy return (NULL); 95256e5ad5fSMatt Macy 95356e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) { 95456e5ad5fSMatt Macy if (isbe) 95556e5ad5fSMatt Macy value[i] = be64dec(ptr); 95656e5ad5fSMatt Macy else 95756e5ad5fSMatt Macy value[i] = le64dec(ptr); 95856e5ad5fSMatt Macy 95956e5ad5fSMatt Macy ptr += sizeof(*value); 96056e5ad5fSMatt Macy *leftp -= sizeof(*value); 96156e5ad5fSMatt Macy } 96256e5ad5fSMatt Macy 96356e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value; 96456e5ad5fSMatt Macy 96556e5ad5fSMatt Macy return (ptr); 96656e5ad5fSMatt Macy } 96756e5ad5fSMatt Macy 96856e5ad5fSMatt Macy const unsigned char * 96956e5ad5fSMatt Macy nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp, 97056e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp) 97156e5ad5fSMatt Macy { 97256e5ad5fSMatt Macy ssize_t size; 97356e5ad5fSMatt Macy size_t len; 97456e5ad5fSMatt Macy const char *tmp; 97556e5ad5fSMatt Macy char **value; 97656e5ad5fSMatt Macy unsigned int ii, j; 97756e5ad5fSMatt Macy 97856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 97956e5ad5fSMatt Macy 98056e5ad5fSMatt Macy if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 || 98156e5ad5fSMatt Macy nvp->nvp_nitems == 0) { 98256e5ad5fSMatt Macy ERRNO_SET(EINVAL); 98356e5ad5fSMatt Macy return (NULL); 98456e5ad5fSMatt Macy } 98556e5ad5fSMatt Macy 98656e5ad5fSMatt Macy size = nvp->nvp_datasize; 98756e5ad5fSMatt Macy tmp = (const char *)ptr; 98856e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) { 98956e5ad5fSMatt Macy len = strnlen(tmp, size - 1) + 1; 99056e5ad5fSMatt Macy size -= len; 99156e5ad5fSMatt Macy if (size < 0) { 99256e5ad5fSMatt Macy ERRNO_SET(EINVAL); 99356e5ad5fSMatt Macy return (NULL); 99456e5ad5fSMatt Macy } 99556e5ad5fSMatt Macy tmp += len; 99656e5ad5fSMatt Macy } 99756e5ad5fSMatt Macy if (size != 0) { 99856e5ad5fSMatt Macy ERRNO_SET(EINVAL); 99956e5ad5fSMatt Macy return (NULL); 100056e5ad5fSMatt Macy } 100156e5ad5fSMatt Macy 1002*36fa90dbSMariusz Zaborski value = nv_calloc(nvp->nvp_nitems, sizeof(*value)); 100356e5ad5fSMatt Macy if (value == NULL) 100456e5ad5fSMatt Macy return (NULL); 100556e5ad5fSMatt Macy 100656e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) { 100756e5ad5fSMatt Macy value[ii] = nv_strdup((const char *)ptr); 100856e5ad5fSMatt Macy if (value[ii] == NULL) 100956e5ad5fSMatt Macy goto out; 101056e5ad5fSMatt Macy len = strlen(value[ii]) + 1; 101156e5ad5fSMatt Macy ptr += len; 101256e5ad5fSMatt Macy *leftp -= len; 101356e5ad5fSMatt Macy } 101456e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value; 101556e5ad5fSMatt Macy 101656e5ad5fSMatt Macy return (ptr); 101756e5ad5fSMatt Macy out: 101856e5ad5fSMatt Macy for (j = 0; j < ii; j++) 101956e5ad5fSMatt Macy nv_free(value[j]); 102056e5ad5fSMatt Macy nv_free(value); 102156e5ad5fSMatt Macy return (NULL); 102256e5ad5fSMatt Macy } 102356e5ad5fSMatt Macy 102456e5ad5fSMatt Macy #ifndef _KERNEL 102556e5ad5fSMatt Macy const unsigned char * 102656e5ad5fSMatt Macy nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp, 102756e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds) 102856e5ad5fSMatt Macy { 102956e5ad5fSMatt Macy int64_t idx; 103056e5ad5fSMatt Macy size_t size; 103156e5ad5fSMatt Macy unsigned int ii; 103256e5ad5fSMatt Macy int *array; 103356e5ad5fSMatt Macy 103456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 103556e5ad5fSMatt Macy 103656e5ad5fSMatt Macy size = sizeof(idx) * nvp->nvp_nitems; 103756e5ad5fSMatt Macy if (nvp->nvp_datasize != size || *leftp < size || 103856e5ad5fSMatt Macy nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 103956e5ad5fSMatt Macy ERRNO_SET(EINVAL); 104056e5ad5fSMatt Macy return (NULL); 104156e5ad5fSMatt Macy } 104256e5ad5fSMatt Macy 104356e5ad5fSMatt Macy array = (int *)nv_malloc(size); 104456e5ad5fSMatt Macy if (array == NULL) 104556e5ad5fSMatt Macy return (NULL); 104656e5ad5fSMatt Macy 104756e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) { 104856e5ad5fSMatt Macy if (isbe) 104956e5ad5fSMatt Macy idx = be64dec(ptr); 105056e5ad5fSMatt Macy else 105156e5ad5fSMatt Macy idx = le64dec(ptr); 105256e5ad5fSMatt Macy 105356e5ad5fSMatt Macy if (idx < 0) { 105456e5ad5fSMatt Macy ERRNO_SET(EINVAL); 105556e5ad5fSMatt Macy nv_free(array); 105656e5ad5fSMatt Macy return (NULL); 105756e5ad5fSMatt Macy } 105856e5ad5fSMatt Macy 105956e5ad5fSMatt Macy if ((size_t)idx >= nfds) { 106056e5ad5fSMatt Macy ERRNO_SET(EINVAL); 106156e5ad5fSMatt Macy nv_free(array); 106256e5ad5fSMatt Macy return (NULL); 106356e5ad5fSMatt Macy } 106456e5ad5fSMatt Macy 106556e5ad5fSMatt Macy array[ii] = (uint64_t)fds[idx]; 106656e5ad5fSMatt Macy 106756e5ad5fSMatt Macy ptr += sizeof(idx); 106856e5ad5fSMatt Macy *leftp -= sizeof(idx); 106956e5ad5fSMatt Macy } 107056e5ad5fSMatt Macy 107156e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)array; 107256e5ad5fSMatt Macy 107356e5ad5fSMatt Macy return (ptr); 107456e5ad5fSMatt Macy } 107556e5ad5fSMatt Macy #endif 107656e5ad5fSMatt Macy 107756e5ad5fSMatt Macy const unsigned char * 107856e5ad5fSMatt Macy nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp, 107956e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp, nvlist_t **firstel) 108056e5ad5fSMatt Macy { 108156e5ad5fSMatt Macy nvlist_t **value; 108256e5ad5fSMatt Macy nvpair_t *tmpnvp; 108356e5ad5fSMatt Macy unsigned int ii, j; 108456e5ad5fSMatt Macy size_t sizeup; 108556e5ad5fSMatt Macy 108656e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 108756e5ad5fSMatt Macy 108856e5ad5fSMatt Macy sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems; 108956e5ad5fSMatt Macy if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems || 109056e5ad5fSMatt Macy sizeup > *leftp) { 109156e5ad5fSMatt Macy ERRNO_SET(EINVAL); 109256e5ad5fSMatt Macy return (NULL); 109356e5ad5fSMatt Macy } 109456e5ad5fSMatt Macy 1095*36fa90dbSMariusz Zaborski value = nv_calloc(nvp->nvp_nitems, sizeof(*value)); 109656e5ad5fSMatt Macy if (value == NULL) 109756e5ad5fSMatt Macy return (NULL); 109856e5ad5fSMatt Macy 109956e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) { 110056e5ad5fSMatt Macy value[ii] = nvlist_create(0); 110156e5ad5fSMatt Macy if (value[ii] == NULL) 110256e5ad5fSMatt Macy goto fail; 110356e5ad5fSMatt Macy if (ii > 0) { 110456e5ad5fSMatt Macy tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 110556e5ad5fSMatt Macy (uint64_t)(uintptr_t)value[ii], 0, 0); 110656e5ad5fSMatt Macy if (tmpnvp == NULL) 110756e5ad5fSMatt Macy goto fail; 110856e5ad5fSMatt Macy nvlist_set_array_next(value[ii - 1], tmpnvp); 110956e5ad5fSMatt Macy } 111056e5ad5fSMatt Macy } 111156e5ad5fSMatt Macy nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY); 111256e5ad5fSMatt Macy 111356e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value; 111456e5ad5fSMatt Macy *firstel = value[0]; 111556e5ad5fSMatt Macy 111656e5ad5fSMatt Macy return (ptr); 111756e5ad5fSMatt Macy fail: 111856e5ad5fSMatt Macy ERRNO_SAVE(); 111956e5ad5fSMatt Macy for (j = 0; j <= ii; j++) 112056e5ad5fSMatt Macy nvlist_destroy(value[j]); 112156e5ad5fSMatt Macy nv_free(value); 112256e5ad5fSMatt Macy ERRNO_RESTORE(); 112356e5ad5fSMatt Macy 112456e5ad5fSMatt Macy return (NULL); 112556e5ad5fSMatt Macy } 112656e5ad5fSMatt Macy 112756e5ad5fSMatt Macy const unsigned char * 112856e5ad5fSMatt Macy nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, 112956e5ad5fSMatt Macy nvpair_t **nvpp) 113056e5ad5fSMatt Macy { 113156e5ad5fSMatt Macy nvpair_t *nvp, *tmp; 113256e5ad5fSMatt Macy 113356e5ad5fSMatt Macy nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); 113456e5ad5fSMatt Macy if (nvp == NULL) 113556e5ad5fSMatt Macy return (NULL); 113656e5ad5fSMatt Macy nvp->nvp_name = (char *)(nvp + 1); 113756e5ad5fSMatt Macy 113856e5ad5fSMatt Macy ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); 113956e5ad5fSMatt Macy if (ptr == NULL) 114056e5ad5fSMatt Macy goto fail; 114156e5ad5fSMatt Macy tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 114256e5ad5fSMatt Macy if (tmp == NULL) 114356e5ad5fSMatt Macy goto fail; 114456e5ad5fSMatt Macy nvp = tmp; 114556e5ad5fSMatt Macy 114656e5ad5fSMatt Macy /* Update nvp_name after realloc(). */ 114756e5ad5fSMatt Macy nvp->nvp_name = (char *)(nvp + 1); 114856e5ad5fSMatt Macy nvp->nvp_data = 0x00; 114956e5ad5fSMatt Macy nvp->nvp_magic = NVPAIR_MAGIC; 115056e5ad5fSMatt Macy *nvpp = nvp; 115156e5ad5fSMatt Macy return (ptr); 115256e5ad5fSMatt Macy fail: 115356e5ad5fSMatt Macy nv_free(nvp); 115456e5ad5fSMatt Macy return (NULL); 115556e5ad5fSMatt Macy } 115656e5ad5fSMatt Macy 115756e5ad5fSMatt Macy int 115856e5ad5fSMatt Macy nvpair_type(const nvpair_t *nvp) 115956e5ad5fSMatt Macy { 116056e5ad5fSMatt Macy 116156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 116256e5ad5fSMatt Macy 116356e5ad5fSMatt Macy return (nvp->nvp_type); 116456e5ad5fSMatt Macy } 116556e5ad5fSMatt Macy 116656e5ad5fSMatt Macy const char * 116756e5ad5fSMatt Macy nvpair_name(const nvpair_t *nvp) 116856e5ad5fSMatt Macy { 116956e5ad5fSMatt Macy 117056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 117156e5ad5fSMatt Macy 117256e5ad5fSMatt Macy return (nvp->nvp_name); 117356e5ad5fSMatt Macy } 117456e5ad5fSMatt Macy 117556e5ad5fSMatt Macy nvpair_t * 117656e5ad5fSMatt Macy nvpair_create_stringf(const char *name, const char *valuefmt, ...) 117756e5ad5fSMatt Macy { 117856e5ad5fSMatt Macy va_list valueap; 117956e5ad5fSMatt Macy nvpair_t *nvp; 118056e5ad5fSMatt Macy 118156e5ad5fSMatt Macy va_start(valueap, valuefmt); 118256e5ad5fSMatt Macy nvp = nvpair_create_stringv(name, valuefmt, valueap); 118356e5ad5fSMatt Macy va_end(valueap); 118456e5ad5fSMatt Macy 118556e5ad5fSMatt Macy return (nvp); 118656e5ad5fSMatt Macy } 118756e5ad5fSMatt Macy 118856e5ad5fSMatt Macy nvpair_t * 118956e5ad5fSMatt Macy nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 119056e5ad5fSMatt Macy { 119156e5ad5fSMatt Macy nvpair_t *nvp; 119256e5ad5fSMatt Macy char *str; 119356e5ad5fSMatt Macy int len; 119456e5ad5fSMatt Macy 119556e5ad5fSMatt Macy len = nv_vasprintf(&str, valuefmt, valueap); 119656e5ad5fSMatt Macy if (len < 0) 119756e5ad5fSMatt Macy return (NULL); 119856e5ad5fSMatt Macy nvp = nvpair_create_string(name, str); 119956e5ad5fSMatt Macy nv_free(str); 120056e5ad5fSMatt Macy return (nvp); 120156e5ad5fSMatt Macy } 120256e5ad5fSMatt Macy 120356e5ad5fSMatt Macy nvpair_t * 120456e5ad5fSMatt Macy nvpair_create_null(const char *name) 120556e5ad5fSMatt Macy { 120656e5ad5fSMatt Macy 120756e5ad5fSMatt Macy return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0)); 120856e5ad5fSMatt Macy } 120956e5ad5fSMatt Macy 121056e5ad5fSMatt Macy nvpair_t * 121156e5ad5fSMatt Macy nvpair_create_bool(const char *name, bool value) 121256e5ad5fSMatt Macy { 121356e5ad5fSMatt Macy 121456e5ad5fSMatt Macy return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0, 121556e5ad5fSMatt Macy sizeof(uint8_t), 0)); 121656e5ad5fSMatt Macy } 121756e5ad5fSMatt Macy 121856e5ad5fSMatt Macy nvpair_t * 121956e5ad5fSMatt Macy nvpair_create_number(const char *name, uint64_t value) 122056e5ad5fSMatt Macy { 122156e5ad5fSMatt Macy 122256e5ad5fSMatt Macy return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0)); 122356e5ad5fSMatt Macy } 122456e5ad5fSMatt Macy 122556e5ad5fSMatt Macy nvpair_t * 122656e5ad5fSMatt Macy nvpair_create_string(const char *name, const char *value) 122756e5ad5fSMatt Macy { 122856e5ad5fSMatt Macy nvpair_t *nvp; 122956e5ad5fSMatt Macy size_t size; 123056e5ad5fSMatt Macy char *data; 123156e5ad5fSMatt Macy 123256e5ad5fSMatt Macy if (value == NULL) { 123356e5ad5fSMatt Macy ERRNO_SET(EINVAL); 123456e5ad5fSMatt Macy return (NULL); 123556e5ad5fSMatt Macy } 123656e5ad5fSMatt Macy 123756e5ad5fSMatt Macy data = nv_strdup(value); 123856e5ad5fSMatt Macy if (data == NULL) 123956e5ad5fSMatt Macy return (NULL); 124056e5ad5fSMatt Macy size = strlen(value) + 1; 124156e5ad5fSMatt Macy 124256e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data, 124356e5ad5fSMatt Macy size, 0); 124456e5ad5fSMatt Macy if (nvp == NULL) 124556e5ad5fSMatt Macy nv_free(data); 124656e5ad5fSMatt Macy 124756e5ad5fSMatt Macy return (nvp); 124856e5ad5fSMatt Macy } 124956e5ad5fSMatt Macy 125056e5ad5fSMatt Macy nvpair_t * 125156e5ad5fSMatt Macy nvpair_create_nvlist(const char *name, const nvlist_t *value) 125256e5ad5fSMatt Macy { 125356e5ad5fSMatt Macy nvlist_t *nvl; 125456e5ad5fSMatt Macy nvpair_t *nvp; 125556e5ad5fSMatt Macy 125656e5ad5fSMatt Macy if (value == NULL) { 125756e5ad5fSMatt Macy ERRNO_SET(EINVAL); 125856e5ad5fSMatt Macy return (NULL); 125956e5ad5fSMatt Macy } 126056e5ad5fSMatt Macy 126156e5ad5fSMatt Macy nvl = nvlist_clone(value); 126256e5ad5fSMatt Macy if (nvl == NULL) 126356e5ad5fSMatt Macy return (NULL); 126456e5ad5fSMatt Macy 126556e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 126656e5ad5fSMatt Macy 0); 126756e5ad5fSMatt Macy if (nvp == NULL) 126856e5ad5fSMatt Macy nvlist_destroy(nvl); 126956e5ad5fSMatt Macy else 127056e5ad5fSMatt Macy nvlist_set_parent(nvl, nvp); 127156e5ad5fSMatt Macy 127256e5ad5fSMatt Macy return (nvp); 127356e5ad5fSMatt Macy } 127456e5ad5fSMatt Macy 127556e5ad5fSMatt Macy #ifndef _KERNEL 127656e5ad5fSMatt Macy nvpair_t * 127756e5ad5fSMatt Macy nvpair_create_descriptor(const char *name, int value) 127856e5ad5fSMatt Macy { 127956e5ad5fSMatt Macy nvpair_t *nvp; 128056e5ad5fSMatt Macy 128156e5ad5fSMatt Macy value = fcntl(value, F_DUPFD_CLOEXEC, 0); 128256e5ad5fSMatt Macy if (value < 0) 128356e5ad5fSMatt Macy return (NULL); 128456e5ad5fSMatt Macy 128556e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 128656e5ad5fSMatt Macy sizeof(int64_t), 0); 128756e5ad5fSMatt Macy if (nvp == NULL) { 128856e5ad5fSMatt Macy ERRNO_SAVE(); 128956e5ad5fSMatt Macy close(value); 129056e5ad5fSMatt Macy ERRNO_RESTORE(); 129156e5ad5fSMatt Macy } 129256e5ad5fSMatt Macy 129356e5ad5fSMatt Macy return (nvp); 129456e5ad5fSMatt Macy } 129556e5ad5fSMatt Macy #endif 129656e5ad5fSMatt Macy 129756e5ad5fSMatt Macy nvpair_t * 129856e5ad5fSMatt Macy nvpair_create_binary(const char *name, const void *value, size_t size) 129956e5ad5fSMatt Macy { 130056e5ad5fSMatt Macy nvpair_t *nvp; 130156e5ad5fSMatt Macy void *data; 130256e5ad5fSMatt Macy 130356e5ad5fSMatt Macy if (value == NULL || size == 0) { 130456e5ad5fSMatt Macy ERRNO_SET(EINVAL); 130556e5ad5fSMatt Macy return (NULL); 130656e5ad5fSMatt Macy } 130756e5ad5fSMatt Macy 130856e5ad5fSMatt Macy data = nv_malloc(size); 130956e5ad5fSMatt Macy if (data == NULL) 131056e5ad5fSMatt Macy return (NULL); 131156e5ad5fSMatt Macy memcpy(data, value, size); 131256e5ad5fSMatt Macy 131356e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, 131456e5ad5fSMatt Macy size, 0); 131556e5ad5fSMatt Macy if (nvp == NULL) 131656e5ad5fSMatt Macy nv_free(data); 131756e5ad5fSMatt Macy 131856e5ad5fSMatt Macy return (nvp); 131956e5ad5fSMatt Macy } 132056e5ad5fSMatt Macy 132156e5ad5fSMatt Macy nvpair_t * 132256e5ad5fSMatt Macy nvpair_create_bool_array(const char *name, const bool *value, size_t nitems) 132356e5ad5fSMatt Macy { 132456e5ad5fSMatt Macy nvpair_t *nvp; 132556e5ad5fSMatt Macy size_t size; 132656e5ad5fSMatt Macy void *data; 132756e5ad5fSMatt Macy 132856e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 132956e5ad5fSMatt Macy ERRNO_SET(EINVAL); 133056e5ad5fSMatt Macy return (NULL); 133156e5ad5fSMatt Macy } 133256e5ad5fSMatt Macy 1333*36fa90dbSMariusz Zaborski data = nv_calloc(nitems, sizeof(value[0])); 133456e5ad5fSMatt Macy if (data == NULL) 133556e5ad5fSMatt Macy return (NULL); 1336*36fa90dbSMariusz Zaborski size = sizeof(value[0]) * nitems; 133756e5ad5fSMatt Macy 133856e5ad5fSMatt Macy memcpy(data, value, size); 133956e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data, 134056e5ad5fSMatt Macy size, nitems); 134156e5ad5fSMatt Macy if (nvp == NULL) { 134256e5ad5fSMatt Macy ERRNO_SAVE(); 134356e5ad5fSMatt Macy nv_free(data); 134456e5ad5fSMatt Macy ERRNO_RESTORE(); 134556e5ad5fSMatt Macy } 134656e5ad5fSMatt Macy 134756e5ad5fSMatt Macy return (nvp); 134856e5ad5fSMatt Macy } 134956e5ad5fSMatt Macy 135056e5ad5fSMatt Macy nvpair_t * 135156e5ad5fSMatt Macy nvpair_create_number_array(const char *name, const uint64_t *value, 135256e5ad5fSMatt Macy size_t nitems) 135356e5ad5fSMatt Macy { 135456e5ad5fSMatt Macy nvpair_t *nvp; 135556e5ad5fSMatt Macy size_t size; 135656e5ad5fSMatt Macy void *data; 135756e5ad5fSMatt Macy 135856e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 135956e5ad5fSMatt Macy ERRNO_SET(EINVAL); 136056e5ad5fSMatt Macy return (NULL); 136156e5ad5fSMatt Macy } 136256e5ad5fSMatt Macy 1363*36fa90dbSMariusz Zaborski data = nv_calloc(nitems, sizeof(value[0])); 136456e5ad5fSMatt Macy if (data == NULL) 136556e5ad5fSMatt Macy return (NULL); 1366*36fa90dbSMariusz Zaborski size = sizeof(value[0]) * nitems; 136756e5ad5fSMatt Macy 136856e5ad5fSMatt Macy memcpy(data, value, size); 136956e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 137056e5ad5fSMatt Macy (uint64_t)(uintptr_t)data, size, nitems); 137156e5ad5fSMatt Macy if (nvp == NULL) { 137256e5ad5fSMatt Macy ERRNO_SAVE(); 137356e5ad5fSMatt Macy nv_free(data); 137456e5ad5fSMatt Macy ERRNO_RESTORE(); 137556e5ad5fSMatt Macy } 137656e5ad5fSMatt Macy 137756e5ad5fSMatt Macy return (nvp); 137856e5ad5fSMatt Macy } 137956e5ad5fSMatt Macy 138056e5ad5fSMatt Macy nvpair_t * 138156e5ad5fSMatt Macy nvpair_create_string_array(const char *name, const char * const *value, 138256e5ad5fSMatt Macy size_t nitems) 138356e5ad5fSMatt Macy { 138456e5ad5fSMatt Macy nvpair_t *nvp; 138556e5ad5fSMatt Macy unsigned int ii; 138656e5ad5fSMatt Macy size_t datasize, size; 138756e5ad5fSMatt Macy char **data; 138856e5ad5fSMatt Macy 138956e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 139056e5ad5fSMatt Macy ERRNO_SET(EINVAL); 139156e5ad5fSMatt Macy return (NULL); 139256e5ad5fSMatt Macy } 139356e5ad5fSMatt Macy 139456e5ad5fSMatt Macy nvp = NULL; 139556e5ad5fSMatt Macy datasize = 0; 1396*36fa90dbSMariusz Zaborski data = nv_calloc(nitems, sizeof(value[0])); 139756e5ad5fSMatt Macy if (data == NULL) 139856e5ad5fSMatt Macy return (NULL); 139956e5ad5fSMatt Macy 140056e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) { 140156e5ad5fSMatt Macy if (value[ii] == NULL) { 140256e5ad5fSMatt Macy ERRNO_SET(EINVAL); 140356e5ad5fSMatt Macy goto fail; 140456e5ad5fSMatt Macy } 140556e5ad5fSMatt Macy 140656e5ad5fSMatt Macy size = strlen(value[ii]) + 1; 140756e5ad5fSMatt Macy datasize += size; 140856e5ad5fSMatt Macy data[ii] = nv_strdup(value[ii]); 140956e5ad5fSMatt Macy if (data[ii] == NULL) 141056e5ad5fSMatt Macy goto fail; 141156e5ad5fSMatt Macy } 141256e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 141356e5ad5fSMatt Macy (uint64_t)(uintptr_t)data, datasize, nitems); 141456e5ad5fSMatt Macy 141556e5ad5fSMatt Macy fail: 141656e5ad5fSMatt Macy if (nvp == NULL) { 141756e5ad5fSMatt Macy ERRNO_SAVE(); 141856e5ad5fSMatt Macy for (; ii > 0; ii--) 141956e5ad5fSMatt Macy nv_free(data[ii - 1]); 142056e5ad5fSMatt Macy nv_free(data); 142156e5ad5fSMatt Macy ERRNO_RESTORE(); 142256e5ad5fSMatt Macy } 142356e5ad5fSMatt Macy 142456e5ad5fSMatt Macy return (nvp); 142556e5ad5fSMatt Macy } 142656e5ad5fSMatt Macy 142756e5ad5fSMatt Macy nvpair_t * 142856e5ad5fSMatt Macy nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value, 142956e5ad5fSMatt Macy size_t nitems) 143056e5ad5fSMatt Macy { 143156e5ad5fSMatt Macy unsigned int ii; 143256e5ad5fSMatt Macy nvlist_t **nvls; 143356e5ad5fSMatt Macy nvpair_t *parent; 143456e5ad5fSMatt Macy int flags; 143556e5ad5fSMatt Macy 143656e5ad5fSMatt Macy nvls = NULL; 143756e5ad5fSMatt Macy 143856e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 143956e5ad5fSMatt Macy ERRNO_SET(EINVAL); 144056e5ad5fSMatt Macy return (NULL); 144156e5ad5fSMatt Macy } 144256e5ad5fSMatt Macy 1443*36fa90dbSMariusz Zaborski nvls = nv_calloc(nitems, sizeof(value[0])); 144456e5ad5fSMatt Macy if (nvls == NULL) 144556e5ad5fSMatt Macy return (NULL); 144656e5ad5fSMatt Macy 144756e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) { 144856e5ad5fSMatt Macy if (value[ii] == NULL) { 144956e5ad5fSMatt Macy ERRNO_SET(EINVAL); 145056e5ad5fSMatt Macy goto fail; 145156e5ad5fSMatt Macy } 145256e5ad5fSMatt Macy 145356e5ad5fSMatt Macy nvls[ii] = nvlist_clone(value[ii]); 145456e5ad5fSMatt Macy if (nvls[ii] == NULL) 145556e5ad5fSMatt Macy goto fail; 145656e5ad5fSMatt Macy 145756e5ad5fSMatt Macy if (ii > 0) { 145856e5ad5fSMatt Macy nvpair_t *nvp; 145956e5ad5fSMatt Macy 146056e5ad5fSMatt Macy nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 146156e5ad5fSMatt Macy (uint64_t)(uintptr_t)nvls[ii], 0, 0); 146256e5ad5fSMatt Macy if (nvp == NULL) { 146356e5ad5fSMatt Macy ERRNO_SAVE(); 146456e5ad5fSMatt Macy nvlist_destroy(nvls[ii]); 146556e5ad5fSMatt Macy ERRNO_RESTORE(); 146656e5ad5fSMatt Macy goto fail; 146756e5ad5fSMatt Macy } 146856e5ad5fSMatt Macy nvlist_set_array_next(nvls[ii - 1], nvp); 146956e5ad5fSMatt Macy } 147056e5ad5fSMatt Macy } 147156e5ad5fSMatt Macy flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY; 147256e5ad5fSMatt Macy nvlist_set_flags(nvls[nitems - 1], flags); 147356e5ad5fSMatt Macy 147456e5ad5fSMatt Macy parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 147556e5ad5fSMatt Macy (uint64_t)(uintptr_t)nvls, 0, nitems); 147656e5ad5fSMatt Macy if (parent == NULL) 147756e5ad5fSMatt Macy goto fail; 147856e5ad5fSMatt Macy 147956e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) 148056e5ad5fSMatt Macy nvlist_set_parent(nvls[ii], parent); 148156e5ad5fSMatt Macy 148256e5ad5fSMatt Macy return (parent); 148356e5ad5fSMatt Macy 148456e5ad5fSMatt Macy fail: 148556e5ad5fSMatt Macy ERRNO_SAVE(); 148656e5ad5fSMatt Macy for (; ii > 0; ii--) 148756e5ad5fSMatt Macy nvlist_destroy(nvls[ii - 1]); 148856e5ad5fSMatt Macy nv_free(nvls); 148956e5ad5fSMatt Macy ERRNO_RESTORE(); 149056e5ad5fSMatt Macy 149156e5ad5fSMatt Macy return (NULL); 149256e5ad5fSMatt Macy } 149356e5ad5fSMatt Macy 149456e5ad5fSMatt Macy #ifndef _KERNEL 149556e5ad5fSMatt Macy nvpair_t * 149656e5ad5fSMatt Macy nvpair_create_descriptor_array(const char *name, const int *value, 149756e5ad5fSMatt Macy size_t nitems) 149856e5ad5fSMatt Macy { 149956e5ad5fSMatt Macy unsigned int ii; 150056e5ad5fSMatt Macy nvpair_t *nvp; 150156e5ad5fSMatt Macy int *fds; 150256e5ad5fSMatt Macy 150356e5ad5fSMatt Macy if (value == NULL) { 150456e5ad5fSMatt Macy ERRNO_SET(EINVAL); 150556e5ad5fSMatt Macy return (NULL); 150656e5ad5fSMatt Macy } 150756e5ad5fSMatt Macy 150856e5ad5fSMatt Macy nvp = NULL; 150956e5ad5fSMatt Macy 1510*36fa90dbSMariusz Zaborski fds = nv_calloc(nitems, sizeof(value[0])); 151156e5ad5fSMatt Macy if (fds == NULL) 151256e5ad5fSMatt Macy return (NULL); 151356e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) { 151456e5ad5fSMatt Macy if (value[ii] == -1) { 151556e5ad5fSMatt Macy fds[ii] = -1; 151656e5ad5fSMatt Macy } else { 151756e5ad5fSMatt Macy fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0); 151856e5ad5fSMatt Macy if (fds[ii] == -1) 151956e5ad5fSMatt Macy goto fail; 152056e5ad5fSMatt Macy } 152156e5ad5fSMatt Macy } 152256e5ad5fSMatt Macy 152356e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 152456e5ad5fSMatt Macy (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems); 152556e5ad5fSMatt Macy 152656e5ad5fSMatt Macy fail: 152756e5ad5fSMatt Macy if (nvp == NULL) { 152856e5ad5fSMatt Macy ERRNO_SAVE(); 152956e5ad5fSMatt Macy for (; ii > 0; ii--) { 153056e5ad5fSMatt Macy if (fds[ii - 1] != -1) 153156e5ad5fSMatt Macy close(fds[ii - 1]); 153256e5ad5fSMatt Macy } 153356e5ad5fSMatt Macy nv_free(fds); 153456e5ad5fSMatt Macy ERRNO_RESTORE(); 153556e5ad5fSMatt Macy } 153656e5ad5fSMatt Macy 153756e5ad5fSMatt Macy return (nvp); 153856e5ad5fSMatt Macy } 153956e5ad5fSMatt Macy #endif 154056e5ad5fSMatt Macy 154156e5ad5fSMatt Macy nvpair_t * 154256e5ad5fSMatt Macy nvpair_move_string(const char *name, char *value) 154356e5ad5fSMatt Macy { 154456e5ad5fSMatt Macy nvpair_t *nvp; 154556e5ad5fSMatt Macy 154656e5ad5fSMatt Macy if (value == NULL) { 154756e5ad5fSMatt Macy ERRNO_SET(EINVAL); 154856e5ad5fSMatt Macy return (NULL); 154956e5ad5fSMatt Macy } 155056e5ad5fSMatt Macy 155156e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 155256e5ad5fSMatt Macy strlen(value) + 1, 0); 155356e5ad5fSMatt Macy if (nvp == NULL) { 155456e5ad5fSMatt Macy ERRNO_SAVE(); 155556e5ad5fSMatt Macy nv_free(value); 155656e5ad5fSMatt Macy ERRNO_RESTORE(); 155756e5ad5fSMatt Macy } 155856e5ad5fSMatt Macy 155956e5ad5fSMatt Macy return (nvp); 156056e5ad5fSMatt Macy } 156156e5ad5fSMatt Macy 156256e5ad5fSMatt Macy nvpair_t * 156356e5ad5fSMatt Macy nvpair_move_nvlist(const char *name, nvlist_t *value) 156456e5ad5fSMatt Macy { 156556e5ad5fSMatt Macy nvpair_t *nvp; 156656e5ad5fSMatt Macy 156756e5ad5fSMatt Macy if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { 156856e5ad5fSMatt Macy ERRNO_SET(EINVAL); 156956e5ad5fSMatt Macy return (NULL); 157056e5ad5fSMatt Macy } 157156e5ad5fSMatt Macy 157256e5ad5fSMatt Macy if (nvlist_error(value) != 0) { 157356e5ad5fSMatt Macy ERRNO_SET(nvlist_error(value)); 157456e5ad5fSMatt Macy nvlist_destroy(value); 157556e5ad5fSMatt Macy return (NULL); 157656e5ad5fSMatt Macy } 157756e5ad5fSMatt Macy 157856e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 157956e5ad5fSMatt Macy 0, 0); 158056e5ad5fSMatt Macy if (nvp == NULL) 158156e5ad5fSMatt Macy nvlist_destroy(value); 158256e5ad5fSMatt Macy else 158356e5ad5fSMatt Macy nvlist_set_parent(value, nvp); 158456e5ad5fSMatt Macy 158556e5ad5fSMatt Macy return (nvp); 158656e5ad5fSMatt Macy } 158756e5ad5fSMatt Macy 158856e5ad5fSMatt Macy #ifndef _KERNEL 158956e5ad5fSMatt Macy nvpair_t * 159056e5ad5fSMatt Macy nvpair_move_descriptor(const char *name, int value) 159156e5ad5fSMatt Macy { 159256e5ad5fSMatt Macy nvpair_t *nvp; 159356e5ad5fSMatt Macy 159456e5ad5fSMatt Macy if (value < 0 || !fd_is_valid(value)) { 159556e5ad5fSMatt Macy ERRNO_SET(EBADF); 159656e5ad5fSMatt Macy return (NULL); 159756e5ad5fSMatt Macy } 159856e5ad5fSMatt Macy 159956e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 160056e5ad5fSMatt Macy sizeof(int64_t), 0); 160156e5ad5fSMatt Macy if (nvp == NULL) { 160256e5ad5fSMatt Macy ERRNO_SAVE(); 160356e5ad5fSMatt Macy close(value); 160456e5ad5fSMatt Macy ERRNO_RESTORE(); 160556e5ad5fSMatt Macy } 160656e5ad5fSMatt Macy 160756e5ad5fSMatt Macy return (nvp); 160856e5ad5fSMatt Macy } 160956e5ad5fSMatt Macy #endif 161056e5ad5fSMatt Macy 161156e5ad5fSMatt Macy nvpair_t * 161256e5ad5fSMatt Macy nvpair_move_binary(const char *name, void *value, size_t size) 161356e5ad5fSMatt Macy { 161456e5ad5fSMatt Macy nvpair_t *nvp; 161556e5ad5fSMatt Macy 161656e5ad5fSMatt Macy if (value == NULL || size == 0) { 161756e5ad5fSMatt Macy ERRNO_SET(EINVAL); 161856e5ad5fSMatt Macy return (NULL); 161956e5ad5fSMatt Macy } 162056e5ad5fSMatt Macy 162156e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, 162256e5ad5fSMatt Macy size, 0); 162356e5ad5fSMatt Macy if (nvp == NULL) { 162456e5ad5fSMatt Macy ERRNO_SAVE(); 162556e5ad5fSMatt Macy nv_free(value); 162656e5ad5fSMatt Macy ERRNO_RESTORE(); 162756e5ad5fSMatt Macy } 162856e5ad5fSMatt Macy 162956e5ad5fSMatt Macy return (nvp); 163056e5ad5fSMatt Macy } 163156e5ad5fSMatt Macy 163256e5ad5fSMatt Macy nvpair_t * 163356e5ad5fSMatt Macy nvpair_move_bool_array(const char *name, bool *value, size_t nitems) 163456e5ad5fSMatt Macy { 163556e5ad5fSMatt Macy nvpair_t *nvp; 163656e5ad5fSMatt Macy 163756e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 163856e5ad5fSMatt Macy ERRNO_SET(EINVAL); 163956e5ad5fSMatt Macy return (NULL); 164056e5ad5fSMatt Macy } 164156e5ad5fSMatt Macy 164256e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, 164356e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 164456e5ad5fSMatt Macy if (nvp == NULL) { 164556e5ad5fSMatt Macy ERRNO_SAVE(); 164656e5ad5fSMatt Macy nv_free(value); 164756e5ad5fSMatt Macy ERRNO_RESTORE(); 164856e5ad5fSMatt Macy } 164956e5ad5fSMatt Macy 165056e5ad5fSMatt Macy return (nvp); 165156e5ad5fSMatt Macy } 165256e5ad5fSMatt Macy 165356e5ad5fSMatt Macy nvpair_t * 165456e5ad5fSMatt Macy nvpair_move_string_array(const char *name, char **value, size_t nitems) 165556e5ad5fSMatt Macy { 165656e5ad5fSMatt Macy nvpair_t *nvp; 165756e5ad5fSMatt Macy size_t i, size; 165856e5ad5fSMatt Macy 165956e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 166056e5ad5fSMatt Macy ERRNO_SET(EINVAL); 166156e5ad5fSMatt Macy return (NULL); 166256e5ad5fSMatt Macy } 166356e5ad5fSMatt Macy 166456e5ad5fSMatt Macy size = 0; 166556e5ad5fSMatt Macy for (i = 0; i < nitems; i++) { 166656e5ad5fSMatt Macy if (value[i] == NULL) { 166756e5ad5fSMatt Macy ERRNO_SET(EINVAL); 166856e5ad5fSMatt Macy return (NULL); 166956e5ad5fSMatt Macy } 167056e5ad5fSMatt Macy 167156e5ad5fSMatt Macy size += strlen(value[i]) + 1; 167256e5ad5fSMatt Macy } 167356e5ad5fSMatt Macy 167456e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 167556e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, size, nitems); 167656e5ad5fSMatt Macy if (nvp == NULL) { 167756e5ad5fSMatt Macy ERRNO_SAVE(); 167856e5ad5fSMatt Macy for (i = 0; i < nitems; i++) 167956e5ad5fSMatt Macy nv_free(value[i]); 168056e5ad5fSMatt Macy nv_free(value); 168156e5ad5fSMatt Macy ERRNO_RESTORE(); 168256e5ad5fSMatt Macy } 168356e5ad5fSMatt Macy 168456e5ad5fSMatt Macy return (nvp); 168556e5ad5fSMatt Macy } 168656e5ad5fSMatt Macy 168756e5ad5fSMatt Macy nvpair_t * 168856e5ad5fSMatt Macy nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems) 168956e5ad5fSMatt Macy { 169056e5ad5fSMatt Macy nvpair_t *nvp; 169156e5ad5fSMatt Macy 169256e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 169356e5ad5fSMatt Macy ERRNO_SET(EINVAL); 169456e5ad5fSMatt Macy return (NULL); 169556e5ad5fSMatt Macy } 169656e5ad5fSMatt Macy 169756e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 169856e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 169956e5ad5fSMatt Macy if (nvp == NULL) { 170056e5ad5fSMatt Macy ERRNO_SAVE(); 170156e5ad5fSMatt Macy nv_free(value); 170256e5ad5fSMatt Macy ERRNO_RESTORE(); 170356e5ad5fSMatt Macy } 170456e5ad5fSMatt Macy 170556e5ad5fSMatt Macy return (nvp); 170656e5ad5fSMatt Macy } 170756e5ad5fSMatt Macy 170856e5ad5fSMatt Macy nvpair_t * 170956e5ad5fSMatt Macy nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems) 171056e5ad5fSMatt Macy { 171156e5ad5fSMatt Macy nvpair_t *parent; 171256e5ad5fSMatt Macy unsigned int ii; 171356e5ad5fSMatt Macy int flags; 171456e5ad5fSMatt Macy 171556e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 171656e5ad5fSMatt Macy ERRNO_SET(EINVAL); 171756e5ad5fSMatt Macy return (NULL); 171856e5ad5fSMatt Macy } 171956e5ad5fSMatt Macy 172056e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) { 172156e5ad5fSMatt Macy if (value == NULL || nvlist_error(value[ii]) != 0 || 172256e5ad5fSMatt Macy nvlist_get_pararr(value[ii], NULL) != NULL) { 172356e5ad5fSMatt Macy ERRNO_SET(EINVAL); 172456e5ad5fSMatt Macy goto fail; 172556e5ad5fSMatt Macy } 172656e5ad5fSMatt Macy if (ii > 0) { 172756e5ad5fSMatt Macy nvpair_t *nvp; 172856e5ad5fSMatt Macy 172956e5ad5fSMatt Macy nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 173056e5ad5fSMatt Macy (uint64_t)(uintptr_t)value[ii], 0, 0); 173156e5ad5fSMatt Macy if (nvp == NULL) 173256e5ad5fSMatt Macy goto fail; 173356e5ad5fSMatt Macy nvlist_set_array_next(value[ii - 1], nvp); 173456e5ad5fSMatt Macy } 173556e5ad5fSMatt Macy } 173656e5ad5fSMatt Macy flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY; 173756e5ad5fSMatt Macy nvlist_set_flags(value[nitems - 1], flags); 173856e5ad5fSMatt Macy 173956e5ad5fSMatt Macy parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 174056e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, 0, nitems); 174156e5ad5fSMatt Macy if (parent == NULL) 174256e5ad5fSMatt Macy goto fail; 174356e5ad5fSMatt Macy 174456e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) 174556e5ad5fSMatt Macy nvlist_set_parent(value[ii], parent); 174656e5ad5fSMatt Macy 174756e5ad5fSMatt Macy return (parent); 174856e5ad5fSMatt Macy fail: 174956e5ad5fSMatt Macy ERRNO_SAVE(); 175056e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) { 175156e5ad5fSMatt Macy if (value[ii] != NULL && 175256e5ad5fSMatt Macy nvlist_get_pararr(value[ii], NULL) != NULL) { 175356e5ad5fSMatt Macy nvlist_destroy(value[ii]); 175456e5ad5fSMatt Macy } 175556e5ad5fSMatt Macy } 175656e5ad5fSMatt Macy nv_free(value); 175756e5ad5fSMatt Macy ERRNO_RESTORE(); 175856e5ad5fSMatt Macy 175956e5ad5fSMatt Macy return (NULL); 176056e5ad5fSMatt Macy } 176156e5ad5fSMatt Macy 176256e5ad5fSMatt Macy #ifndef _KERNEL 176356e5ad5fSMatt Macy nvpair_t * 176456e5ad5fSMatt Macy nvpair_move_descriptor_array(const char *name, int *value, size_t nitems) 176556e5ad5fSMatt Macy { 176656e5ad5fSMatt Macy nvpair_t *nvp; 176756e5ad5fSMatt Macy size_t i; 176856e5ad5fSMatt Macy 176956e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 177056e5ad5fSMatt Macy ERRNO_SET(EINVAL); 177156e5ad5fSMatt Macy return (NULL); 177256e5ad5fSMatt Macy } 177356e5ad5fSMatt Macy 177456e5ad5fSMatt Macy for (i = 0; i < nitems; i++) { 177556e5ad5fSMatt Macy if (value[i] != -1 && !fd_is_valid(value[i])) { 177656e5ad5fSMatt Macy ERRNO_SET(EBADF); 177756e5ad5fSMatt Macy goto fail; 177856e5ad5fSMatt Macy } 177956e5ad5fSMatt Macy } 178056e5ad5fSMatt Macy 178156e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 178256e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 178356e5ad5fSMatt Macy if (nvp == NULL) 178456e5ad5fSMatt Macy goto fail; 178556e5ad5fSMatt Macy 178656e5ad5fSMatt Macy return (nvp); 178756e5ad5fSMatt Macy fail: 178856e5ad5fSMatt Macy ERRNO_SAVE(); 178956e5ad5fSMatt Macy for (i = 0; i < nitems; i++) { 179056e5ad5fSMatt Macy if (fd_is_valid(value[i])) 179156e5ad5fSMatt Macy close(value[i]); 179256e5ad5fSMatt Macy } 179356e5ad5fSMatt Macy nv_free(value); 179456e5ad5fSMatt Macy ERRNO_RESTORE(); 179556e5ad5fSMatt Macy 179656e5ad5fSMatt Macy return (NULL); 179756e5ad5fSMatt Macy } 179856e5ad5fSMatt Macy #endif 179956e5ad5fSMatt Macy 180056e5ad5fSMatt Macy bool 180156e5ad5fSMatt Macy nvpair_get_bool(const nvpair_t *nvp) 180256e5ad5fSMatt Macy { 180356e5ad5fSMatt Macy 180456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 180556e5ad5fSMatt Macy 180656e5ad5fSMatt Macy return (nvp->nvp_data == 1); 180756e5ad5fSMatt Macy } 180856e5ad5fSMatt Macy 180956e5ad5fSMatt Macy uint64_t 181056e5ad5fSMatt Macy nvpair_get_number(const nvpair_t *nvp) 181156e5ad5fSMatt Macy { 181256e5ad5fSMatt Macy 181356e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 181456e5ad5fSMatt Macy 181556e5ad5fSMatt Macy return (nvp->nvp_data); 181656e5ad5fSMatt Macy } 181756e5ad5fSMatt Macy 181856e5ad5fSMatt Macy const char * 181956e5ad5fSMatt Macy nvpair_get_string(const nvpair_t *nvp) 182056e5ad5fSMatt Macy { 182156e5ad5fSMatt Macy 182256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 182356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 182456e5ad5fSMatt Macy 182556e5ad5fSMatt Macy return ((const char *)(intptr_t)nvp->nvp_data); 182656e5ad5fSMatt Macy } 182756e5ad5fSMatt Macy 182856e5ad5fSMatt Macy const nvlist_t * 182956e5ad5fSMatt Macy nvpair_get_nvlist(const nvpair_t *nvp) 183056e5ad5fSMatt Macy { 183156e5ad5fSMatt Macy 183256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 183356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 183456e5ad5fSMatt Macy 183556e5ad5fSMatt Macy return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 183656e5ad5fSMatt Macy } 183756e5ad5fSMatt Macy 183856e5ad5fSMatt Macy #ifndef _KERNEL 183956e5ad5fSMatt Macy int 184056e5ad5fSMatt Macy nvpair_get_descriptor(const nvpair_t *nvp) 184156e5ad5fSMatt Macy { 184256e5ad5fSMatt Macy 184356e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 184456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 184556e5ad5fSMatt Macy 184656e5ad5fSMatt Macy return ((int)nvp->nvp_data); 184756e5ad5fSMatt Macy } 184856e5ad5fSMatt Macy #endif 184956e5ad5fSMatt Macy 185056e5ad5fSMatt Macy const void * 185156e5ad5fSMatt Macy nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 185256e5ad5fSMatt Macy { 185356e5ad5fSMatt Macy 185456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 185556e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 185656e5ad5fSMatt Macy 185756e5ad5fSMatt Macy if (sizep != NULL) 185856e5ad5fSMatt Macy *sizep = nvp->nvp_datasize; 185956e5ad5fSMatt Macy 186056e5ad5fSMatt Macy return ((const void *)(intptr_t)nvp->nvp_data); 186156e5ad5fSMatt Macy } 186256e5ad5fSMatt Macy 186356e5ad5fSMatt Macy const bool * 186456e5ad5fSMatt Macy nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems) 186556e5ad5fSMatt Macy { 186656e5ad5fSMatt Macy 186756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 186856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 186956e5ad5fSMatt Macy 187056e5ad5fSMatt Macy if (nitems != NULL) 187156e5ad5fSMatt Macy *nitems = nvp->nvp_nitems; 187256e5ad5fSMatt Macy 187356e5ad5fSMatt Macy return ((const bool *)(intptr_t)nvp->nvp_data); 187456e5ad5fSMatt Macy } 187556e5ad5fSMatt Macy 187656e5ad5fSMatt Macy const uint64_t * 187756e5ad5fSMatt Macy nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems) 187856e5ad5fSMatt Macy { 187956e5ad5fSMatt Macy 188056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 188156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 188256e5ad5fSMatt Macy 188356e5ad5fSMatt Macy if (nitems != NULL) 188456e5ad5fSMatt Macy *nitems = nvp->nvp_nitems; 188556e5ad5fSMatt Macy 188656e5ad5fSMatt Macy return ((const uint64_t *)(intptr_t)nvp->nvp_data); 188756e5ad5fSMatt Macy } 188856e5ad5fSMatt Macy 188956e5ad5fSMatt Macy const char * const * 189056e5ad5fSMatt Macy nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems) 189156e5ad5fSMatt Macy { 189256e5ad5fSMatt Macy 189356e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 189456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 189556e5ad5fSMatt Macy 189656e5ad5fSMatt Macy if (nitems != NULL) 189756e5ad5fSMatt Macy *nitems = nvp->nvp_nitems; 189856e5ad5fSMatt Macy 189956e5ad5fSMatt Macy return ((const char * const *)(intptr_t)nvp->nvp_data); 190056e5ad5fSMatt Macy } 190156e5ad5fSMatt Macy 190256e5ad5fSMatt Macy const nvlist_t * const * 190356e5ad5fSMatt Macy nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems) 190456e5ad5fSMatt Macy { 190556e5ad5fSMatt Macy 190656e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 190756e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 190856e5ad5fSMatt Macy 190956e5ad5fSMatt Macy if (nitems != NULL) 191056e5ad5fSMatt Macy *nitems = nvp->nvp_nitems; 191156e5ad5fSMatt Macy 191256e5ad5fSMatt Macy return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data)); 191356e5ad5fSMatt Macy } 191456e5ad5fSMatt Macy 191556e5ad5fSMatt Macy #ifndef _KERNEL 191656e5ad5fSMatt Macy const int * 191756e5ad5fSMatt Macy nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems) 191856e5ad5fSMatt Macy { 191956e5ad5fSMatt Macy 192056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 192156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 192256e5ad5fSMatt Macy 192356e5ad5fSMatt Macy if (nitems != NULL) 192456e5ad5fSMatt Macy *nitems = nvp->nvp_nitems; 192556e5ad5fSMatt Macy 192656e5ad5fSMatt Macy return ((const int *)(intptr_t)nvp->nvp_data); 192756e5ad5fSMatt Macy } 192856e5ad5fSMatt Macy #endif 192956e5ad5fSMatt Macy 193056e5ad5fSMatt Macy int 193156e5ad5fSMatt Macy nvpair_append_bool_array(nvpair_t *nvp, const bool value) 193256e5ad5fSMatt Macy { 193356e5ad5fSMatt Macy 193456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 193556e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 193656e5ad5fSMatt Macy return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 193756e5ad5fSMatt Macy } 193856e5ad5fSMatt Macy 193956e5ad5fSMatt Macy int 194056e5ad5fSMatt Macy nvpair_append_number_array(nvpair_t *nvp, const uint64_t value) 194156e5ad5fSMatt Macy { 194256e5ad5fSMatt Macy 194356e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 194456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 194556e5ad5fSMatt Macy return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 194656e5ad5fSMatt Macy } 194756e5ad5fSMatt Macy 194856e5ad5fSMatt Macy int 194956e5ad5fSMatt Macy nvpair_append_string_array(nvpair_t *nvp, const char *value) 195056e5ad5fSMatt Macy { 195156e5ad5fSMatt Macy char *str; 195256e5ad5fSMatt Macy 195356e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 195456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 195556e5ad5fSMatt Macy if (value == NULL) { 195656e5ad5fSMatt Macy ERRNO_SET(EINVAL); 195756e5ad5fSMatt Macy return (-1); 195856e5ad5fSMatt Macy } 195956e5ad5fSMatt Macy str = nv_strdup(value); 196056e5ad5fSMatt Macy if (str == NULL) { 196156e5ad5fSMatt Macy return (-1); 196256e5ad5fSMatt Macy } 196356e5ad5fSMatt Macy if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) { 196456e5ad5fSMatt Macy nv_free(str); 196556e5ad5fSMatt Macy return (-1); 196656e5ad5fSMatt Macy } 196756e5ad5fSMatt Macy return (0); 196856e5ad5fSMatt Macy } 196956e5ad5fSMatt Macy 197056e5ad5fSMatt Macy int 197156e5ad5fSMatt Macy nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value) 197256e5ad5fSMatt Macy { 197356e5ad5fSMatt Macy nvpair_t *tmpnvp; 197456e5ad5fSMatt Macy nvlist_t *nvl, *prev; 197556e5ad5fSMatt Macy int flags; 197656e5ad5fSMatt Macy 197756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 197856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 197956e5ad5fSMatt Macy if (value == NULL || nvlist_error(value) != 0 || 198056e5ad5fSMatt Macy nvlist_get_pararr(value, NULL) != NULL) { 198156e5ad5fSMatt Macy ERRNO_SET(EINVAL); 198256e5ad5fSMatt Macy return (-1); 198356e5ad5fSMatt Macy } 198456e5ad5fSMatt Macy nvl = nvlist_clone(value); 198556e5ad5fSMatt Macy if (nvl == NULL) { 198656e5ad5fSMatt Macy return (-1); 198756e5ad5fSMatt Macy } 198856e5ad5fSMatt Macy flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY; 198956e5ad5fSMatt Macy nvlist_set_flags(nvl, flags); 199056e5ad5fSMatt Macy 199156e5ad5fSMatt Macy tmpnvp = NULL; 199256e5ad5fSMatt Macy prev = NULL; 199356e5ad5fSMatt Macy if (nvp->nvp_nitems > 0) { 199456e5ad5fSMatt Macy nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data; 199556e5ad5fSMatt Macy 199656e5ad5fSMatt Macy prev = nvls[nvp->nvp_nitems - 1]; 199756e5ad5fSMatt Macy PJDLOG_ASSERT(prev != NULL); 199856e5ad5fSMatt Macy 199956e5ad5fSMatt Macy tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 200056e5ad5fSMatt Macy (uint64_t)(uintptr_t)nvl, 0, 0); 200156e5ad5fSMatt Macy if (tmpnvp == NULL) { 200256e5ad5fSMatt Macy goto fail; 200356e5ad5fSMatt Macy } 200456e5ad5fSMatt Macy } 200556e5ad5fSMatt Macy if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) { 200656e5ad5fSMatt Macy goto fail; 200756e5ad5fSMatt Macy } 200856e5ad5fSMatt Macy if (tmpnvp) { 200956e5ad5fSMatt Macy NVPAIR_ASSERT(tmpnvp); 201056e5ad5fSMatt Macy nvlist_set_array_next(prev, tmpnvp); 201156e5ad5fSMatt Macy } 201256e5ad5fSMatt Macy nvlist_set_parent(nvl, nvp); 201356e5ad5fSMatt Macy return (0); 201456e5ad5fSMatt Macy fail: 201556e5ad5fSMatt Macy if (tmpnvp) { 201656e5ad5fSMatt Macy nvpair_free(tmpnvp); 201756e5ad5fSMatt Macy } 201856e5ad5fSMatt Macy nvlist_destroy(nvl); 201956e5ad5fSMatt Macy return (-1); 202056e5ad5fSMatt Macy } 202156e5ad5fSMatt Macy 202256e5ad5fSMatt Macy #ifndef _KERNEL 202356e5ad5fSMatt Macy int 202456e5ad5fSMatt Macy nvpair_append_descriptor_array(nvpair_t *nvp, const int value) 202556e5ad5fSMatt Macy { 202656e5ad5fSMatt Macy int fd; 202756e5ad5fSMatt Macy 202856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 202956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 203056e5ad5fSMatt Macy fd = fcntl(value, F_DUPFD_CLOEXEC, 0); 203156e5ad5fSMatt Macy if (fd == -1) { 203256e5ad5fSMatt Macy return (-1); 203356e5ad5fSMatt Macy } 203456e5ad5fSMatt Macy if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) { 203556e5ad5fSMatt Macy close(fd); 203656e5ad5fSMatt Macy return (-1); 203756e5ad5fSMatt Macy } 203856e5ad5fSMatt Macy return (0); 203956e5ad5fSMatt Macy } 204056e5ad5fSMatt Macy #endif 204156e5ad5fSMatt Macy 204256e5ad5fSMatt Macy void 204356e5ad5fSMatt Macy nvpair_free(nvpair_t *nvp) 204456e5ad5fSMatt Macy { 204556e5ad5fSMatt Macy size_t i; 204656e5ad5fSMatt Macy 204756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 204856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list == NULL); 204956e5ad5fSMatt Macy 205056e5ad5fSMatt Macy nvp->nvp_magic = 0; 205156e5ad5fSMatt Macy switch (nvp->nvp_type) { 205256e5ad5fSMatt Macy #ifndef _KERNEL 205356e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR: 205456e5ad5fSMatt Macy close((int)nvp->nvp_data); 205556e5ad5fSMatt Macy break; 205656e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR_ARRAY: 205756e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) 205856e5ad5fSMatt Macy close(((int *)(intptr_t)nvp->nvp_data)[i]); 205956e5ad5fSMatt Macy nv_free((int *)(intptr_t)nvp->nvp_data); 206056e5ad5fSMatt Macy break; 206156e5ad5fSMatt Macy #endif 206256e5ad5fSMatt Macy case NV_TYPE_NVLIST: 206356e5ad5fSMatt Macy nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 206456e5ad5fSMatt Macy break; 206556e5ad5fSMatt Macy case NV_TYPE_STRING: 206656e5ad5fSMatt Macy nv_free((char *)(intptr_t)nvp->nvp_data); 206756e5ad5fSMatt Macy break; 206856e5ad5fSMatt Macy case NV_TYPE_BINARY: 206956e5ad5fSMatt Macy nv_free((void *)(intptr_t)nvp->nvp_data); 207056e5ad5fSMatt Macy break; 207156e5ad5fSMatt Macy case NV_TYPE_NVLIST_ARRAY: 207256e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) { 207356e5ad5fSMatt Macy nvlist_destroy( 207456e5ad5fSMatt Macy ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]); 207556e5ad5fSMatt Macy } 207656e5ad5fSMatt Macy nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data)); 207756e5ad5fSMatt Macy break; 207856e5ad5fSMatt Macy case NV_TYPE_NUMBER_ARRAY: 207956e5ad5fSMatt Macy nv_free((uint64_t *)(intptr_t)nvp->nvp_data); 208056e5ad5fSMatt Macy break; 208156e5ad5fSMatt Macy case NV_TYPE_BOOL_ARRAY: 208256e5ad5fSMatt Macy nv_free((bool *)(intptr_t)nvp->nvp_data); 208356e5ad5fSMatt Macy break; 208456e5ad5fSMatt Macy case NV_TYPE_STRING_ARRAY: 208556e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) 208656e5ad5fSMatt Macy nv_free(((char **)(intptr_t)nvp->nvp_data)[i]); 208756e5ad5fSMatt Macy nv_free((char **)(intptr_t)nvp->nvp_data); 208856e5ad5fSMatt Macy break; 208956e5ad5fSMatt Macy } 209056e5ad5fSMatt Macy nv_free(nvp); 209156e5ad5fSMatt Macy } 209256e5ad5fSMatt Macy 209356e5ad5fSMatt Macy void 209456e5ad5fSMatt Macy nvpair_free_structure(nvpair_t *nvp) 209556e5ad5fSMatt Macy { 209656e5ad5fSMatt Macy 209756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 209856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list == NULL); 209956e5ad5fSMatt Macy 210056e5ad5fSMatt Macy nvp->nvp_magic = 0; 210156e5ad5fSMatt Macy nv_free(nvp); 210256e5ad5fSMatt Macy } 210356e5ad5fSMatt Macy 210456e5ad5fSMatt Macy const char * 210556e5ad5fSMatt Macy nvpair_type_string(int type) 210656e5ad5fSMatt Macy { 210756e5ad5fSMatt Macy 210856e5ad5fSMatt Macy switch (type) { 210956e5ad5fSMatt Macy case NV_TYPE_NULL: 211056e5ad5fSMatt Macy return ("NULL"); 211156e5ad5fSMatt Macy case NV_TYPE_BOOL: 211256e5ad5fSMatt Macy return ("BOOL"); 211356e5ad5fSMatt Macy case NV_TYPE_NUMBER: 211456e5ad5fSMatt Macy return ("NUMBER"); 211556e5ad5fSMatt Macy case NV_TYPE_STRING: 211656e5ad5fSMatt Macy return ("STRING"); 211756e5ad5fSMatt Macy case NV_TYPE_NVLIST: 211856e5ad5fSMatt Macy return ("NVLIST"); 211956e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR: 212056e5ad5fSMatt Macy return ("DESCRIPTOR"); 212156e5ad5fSMatt Macy case NV_TYPE_BINARY: 212256e5ad5fSMatt Macy return ("BINARY"); 212356e5ad5fSMatt Macy case NV_TYPE_BOOL_ARRAY: 212456e5ad5fSMatt Macy return ("BOOL ARRAY"); 212556e5ad5fSMatt Macy case NV_TYPE_NUMBER_ARRAY: 212656e5ad5fSMatt Macy return ("NUMBER ARRAY"); 212756e5ad5fSMatt Macy case NV_TYPE_STRING_ARRAY: 212856e5ad5fSMatt Macy return ("STRING ARRAY"); 212956e5ad5fSMatt Macy case NV_TYPE_NVLIST_ARRAY: 213056e5ad5fSMatt Macy return ("NVLIST ARRAY"); 213156e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR_ARRAY: 213256e5ad5fSMatt Macy return ("DESCRIPTOR ARRAY"); 213356e5ad5fSMatt Macy default: 213456e5ad5fSMatt Macy return ("<UNKNOWN>"); 213556e5ad5fSMatt Macy } 213656e5ad5fSMatt Macy } 213756e5ad5fSMatt Macy 2138