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; 991*3aaaca1bSMariusz Zaborski if (tmp[len - 1] != '\0') { 992*3aaaca1bSMariusz Zaborski ERRNO_SET(EINVAL); 993*3aaaca1bSMariusz Zaborski return (NULL); 994*3aaaca1bSMariusz Zaborski } 99556e5ad5fSMatt Macy if (size < 0) { 99656e5ad5fSMatt Macy ERRNO_SET(EINVAL); 99756e5ad5fSMatt Macy return (NULL); 99856e5ad5fSMatt Macy } 99956e5ad5fSMatt Macy tmp += len; 100056e5ad5fSMatt Macy } 100156e5ad5fSMatt Macy if (size != 0) { 100256e5ad5fSMatt Macy ERRNO_SET(EINVAL); 100356e5ad5fSMatt Macy return (NULL); 100456e5ad5fSMatt Macy } 100556e5ad5fSMatt Macy 100636fa90dbSMariusz Zaborski value = nv_calloc(nvp->nvp_nitems, sizeof(*value)); 100756e5ad5fSMatt Macy if (value == NULL) 100856e5ad5fSMatt Macy return (NULL); 100956e5ad5fSMatt Macy 101056e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) { 101156e5ad5fSMatt Macy value[ii] = nv_strdup((const char *)ptr); 101256e5ad5fSMatt Macy if (value[ii] == NULL) 101356e5ad5fSMatt Macy goto out; 101456e5ad5fSMatt Macy len = strlen(value[ii]) + 1; 101556e5ad5fSMatt Macy ptr += len; 101656e5ad5fSMatt Macy *leftp -= len; 101756e5ad5fSMatt Macy } 101856e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value; 101956e5ad5fSMatt Macy 102056e5ad5fSMatt Macy return (ptr); 102156e5ad5fSMatt Macy out: 102256e5ad5fSMatt Macy for (j = 0; j < ii; j++) 102356e5ad5fSMatt Macy nv_free(value[j]); 102456e5ad5fSMatt Macy nv_free(value); 102556e5ad5fSMatt Macy return (NULL); 102656e5ad5fSMatt Macy } 102756e5ad5fSMatt Macy 102856e5ad5fSMatt Macy #ifndef _KERNEL 102956e5ad5fSMatt Macy const unsigned char * 103056e5ad5fSMatt Macy nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp, 103156e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds) 103256e5ad5fSMatt Macy { 103356e5ad5fSMatt Macy int64_t idx; 103456e5ad5fSMatt Macy size_t size; 103556e5ad5fSMatt Macy unsigned int ii; 103656e5ad5fSMatt Macy int *array; 103756e5ad5fSMatt Macy 103856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 103956e5ad5fSMatt Macy 104056e5ad5fSMatt Macy size = sizeof(idx) * nvp->nvp_nitems; 104156e5ad5fSMatt Macy if (nvp->nvp_datasize != size || *leftp < size || 104256e5ad5fSMatt Macy nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 104356e5ad5fSMatt Macy ERRNO_SET(EINVAL); 104456e5ad5fSMatt Macy return (NULL); 104556e5ad5fSMatt Macy } 104656e5ad5fSMatt Macy 104756e5ad5fSMatt Macy array = (int *)nv_malloc(size); 104856e5ad5fSMatt Macy if (array == NULL) 104956e5ad5fSMatt Macy return (NULL); 105056e5ad5fSMatt Macy 105156e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) { 105256e5ad5fSMatt Macy if (isbe) 105356e5ad5fSMatt Macy idx = be64dec(ptr); 105456e5ad5fSMatt Macy else 105556e5ad5fSMatt Macy idx = le64dec(ptr); 105656e5ad5fSMatt Macy 105756e5ad5fSMatt Macy if (idx < 0) { 105856e5ad5fSMatt Macy ERRNO_SET(EINVAL); 105956e5ad5fSMatt Macy nv_free(array); 106056e5ad5fSMatt Macy return (NULL); 106156e5ad5fSMatt Macy } 106256e5ad5fSMatt Macy 106356e5ad5fSMatt Macy if ((size_t)idx >= nfds) { 106456e5ad5fSMatt Macy ERRNO_SET(EINVAL); 106556e5ad5fSMatt Macy nv_free(array); 106656e5ad5fSMatt Macy return (NULL); 106756e5ad5fSMatt Macy } 106856e5ad5fSMatt Macy 106956e5ad5fSMatt Macy array[ii] = (uint64_t)fds[idx]; 107056e5ad5fSMatt Macy 107156e5ad5fSMatt Macy ptr += sizeof(idx); 107256e5ad5fSMatt Macy *leftp -= sizeof(idx); 107356e5ad5fSMatt Macy } 107456e5ad5fSMatt Macy 107556e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)array; 107656e5ad5fSMatt Macy 107756e5ad5fSMatt Macy return (ptr); 107856e5ad5fSMatt Macy } 107956e5ad5fSMatt Macy #endif 108056e5ad5fSMatt Macy 108156e5ad5fSMatt Macy const unsigned char * 108256e5ad5fSMatt Macy nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp, 108356e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp, nvlist_t **firstel) 108456e5ad5fSMatt Macy { 108556e5ad5fSMatt Macy nvlist_t **value; 108656e5ad5fSMatt Macy nvpair_t *tmpnvp; 108756e5ad5fSMatt Macy unsigned int ii, j; 108856e5ad5fSMatt Macy size_t sizeup; 108956e5ad5fSMatt Macy 109056e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 109156e5ad5fSMatt Macy 109256e5ad5fSMatt Macy sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems; 109356e5ad5fSMatt Macy if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems || 109456e5ad5fSMatt Macy sizeup > *leftp) { 109556e5ad5fSMatt Macy ERRNO_SET(EINVAL); 109656e5ad5fSMatt Macy return (NULL); 109756e5ad5fSMatt Macy } 109856e5ad5fSMatt Macy 109936fa90dbSMariusz Zaborski value = nv_calloc(nvp->nvp_nitems, sizeof(*value)); 110056e5ad5fSMatt Macy if (value == NULL) 110156e5ad5fSMatt Macy return (NULL); 110256e5ad5fSMatt Macy 110356e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) { 110456e5ad5fSMatt Macy value[ii] = nvlist_create(0); 110556e5ad5fSMatt Macy if (value[ii] == NULL) 110656e5ad5fSMatt Macy goto fail; 110756e5ad5fSMatt Macy if (ii > 0) { 110856e5ad5fSMatt Macy tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 110956e5ad5fSMatt Macy (uint64_t)(uintptr_t)value[ii], 0, 0); 111056e5ad5fSMatt Macy if (tmpnvp == NULL) 111156e5ad5fSMatt Macy goto fail; 111256e5ad5fSMatt Macy nvlist_set_array_next(value[ii - 1], tmpnvp); 111356e5ad5fSMatt Macy } 111456e5ad5fSMatt Macy } 111556e5ad5fSMatt Macy nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY); 111656e5ad5fSMatt Macy 111756e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value; 111856e5ad5fSMatt Macy *firstel = value[0]; 111956e5ad5fSMatt Macy 112056e5ad5fSMatt Macy return (ptr); 112156e5ad5fSMatt Macy fail: 112256e5ad5fSMatt Macy ERRNO_SAVE(); 112356e5ad5fSMatt Macy for (j = 0; j <= ii; j++) 112456e5ad5fSMatt Macy nvlist_destroy(value[j]); 112556e5ad5fSMatt Macy nv_free(value); 112656e5ad5fSMatt Macy ERRNO_RESTORE(); 112756e5ad5fSMatt Macy 112856e5ad5fSMatt Macy return (NULL); 112956e5ad5fSMatt Macy } 113056e5ad5fSMatt Macy 113156e5ad5fSMatt Macy const unsigned char * 113256e5ad5fSMatt Macy nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, 113356e5ad5fSMatt Macy nvpair_t **nvpp) 113456e5ad5fSMatt Macy { 113556e5ad5fSMatt Macy nvpair_t *nvp, *tmp; 113656e5ad5fSMatt Macy 113756e5ad5fSMatt Macy nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); 113856e5ad5fSMatt Macy if (nvp == NULL) 113956e5ad5fSMatt Macy return (NULL); 114056e5ad5fSMatt Macy nvp->nvp_name = (char *)(nvp + 1); 114156e5ad5fSMatt Macy 114256e5ad5fSMatt Macy ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); 114356e5ad5fSMatt Macy if (ptr == NULL) 114456e5ad5fSMatt Macy goto fail; 114556e5ad5fSMatt Macy tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 114656e5ad5fSMatt Macy if (tmp == NULL) 114756e5ad5fSMatt Macy goto fail; 114856e5ad5fSMatt Macy nvp = tmp; 114956e5ad5fSMatt Macy 115056e5ad5fSMatt Macy /* Update nvp_name after realloc(). */ 115156e5ad5fSMatt Macy nvp->nvp_name = (char *)(nvp + 1); 115256e5ad5fSMatt Macy nvp->nvp_data = 0x00; 115356e5ad5fSMatt Macy nvp->nvp_magic = NVPAIR_MAGIC; 115456e5ad5fSMatt Macy *nvpp = nvp; 115556e5ad5fSMatt Macy return (ptr); 115656e5ad5fSMatt Macy fail: 115756e5ad5fSMatt Macy nv_free(nvp); 115856e5ad5fSMatt Macy return (NULL); 115956e5ad5fSMatt Macy } 116056e5ad5fSMatt Macy 116156e5ad5fSMatt Macy int 116256e5ad5fSMatt Macy nvpair_type(const nvpair_t *nvp) 116356e5ad5fSMatt Macy { 116456e5ad5fSMatt Macy 116556e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 116656e5ad5fSMatt Macy 116756e5ad5fSMatt Macy return (nvp->nvp_type); 116856e5ad5fSMatt Macy } 116956e5ad5fSMatt Macy 117056e5ad5fSMatt Macy const char * 117156e5ad5fSMatt Macy nvpair_name(const nvpair_t *nvp) 117256e5ad5fSMatt Macy { 117356e5ad5fSMatt Macy 117456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 117556e5ad5fSMatt Macy 117656e5ad5fSMatt Macy return (nvp->nvp_name); 117756e5ad5fSMatt Macy } 117856e5ad5fSMatt Macy 117956e5ad5fSMatt Macy nvpair_t * 118056e5ad5fSMatt Macy nvpair_create_stringf(const char *name, const char *valuefmt, ...) 118156e5ad5fSMatt Macy { 118256e5ad5fSMatt Macy va_list valueap; 118356e5ad5fSMatt Macy nvpair_t *nvp; 118456e5ad5fSMatt Macy 118556e5ad5fSMatt Macy va_start(valueap, valuefmt); 118656e5ad5fSMatt Macy nvp = nvpair_create_stringv(name, valuefmt, valueap); 118756e5ad5fSMatt Macy va_end(valueap); 118856e5ad5fSMatt Macy 118956e5ad5fSMatt Macy return (nvp); 119056e5ad5fSMatt Macy } 119156e5ad5fSMatt Macy 119256e5ad5fSMatt Macy nvpair_t * 119356e5ad5fSMatt Macy nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 119456e5ad5fSMatt Macy { 119556e5ad5fSMatt Macy nvpair_t *nvp; 119656e5ad5fSMatt Macy char *str; 119756e5ad5fSMatt Macy int len; 119856e5ad5fSMatt Macy 119956e5ad5fSMatt Macy len = nv_vasprintf(&str, valuefmt, valueap); 120056e5ad5fSMatt Macy if (len < 0) 120156e5ad5fSMatt Macy return (NULL); 120256e5ad5fSMatt Macy nvp = nvpair_create_string(name, str); 120356e5ad5fSMatt Macy nv_free(str); 120456e5ad5fSMatt Macy return (nvp); 120556e5ad5fSMatt Macy } 120656e5ad5fSMatt Macy 120756e5ad5fSMatt Macy nvpair_t * 120856e5ad5fSMatt Macy nvpair_create_null(const char *name) 120956e5ad5fSMatt Macy { 121056e5ad5fSMatt Macy 121156e5ad5fSMatt Macy return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0)); 121256e5ad5fSMatt Macy } 121356e5ad5fSMatt Macy 121456e5ad5fSMatt Macy nvpair_t * 121556e5ad5fSMatt Macy nvpair_create_bool(const char *name, bool value) 121656e5ad5fSMatt Macy { 121756e5ad5fSMatt Macy 121856e5ad5fSMatt Macy return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0, 121956e5ad5fSMatt Macy sizeof(uint8_t), 0)); 122056e5ad5fSMatt Macy } 122156e5ad5fSMatt Macy 122256e5ad5fSMatt Macy nvpair_t * 122356e5ad5fSMatt Macy nvpair_create_number(const char *name, uint64_t value) 122456e5ad5fSMatt Macy { 122556e5ad5fSMatt Macy 122656e5ad5fSMatt Macy return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0)); 122756e5ad5fSMatt Macy } 122856e5ad5fSMatt Macy 122956e5ad5fSMatt Macy nvpair_t * 123056e5ad5fSMatt Macy nvpair_create_string(const char *name, const char *value) 123156e5ad5fSMatt Macy { 123256e5ad5fSMatt Macy nvpair_t *nvp; 123356e5ad5fSMatt Macy size_t size; 123456e5ad5fSMatt Macy char *data; 123556e5ad5fSMatt Macy 123656e5ad5fSMatt Macy if (value == NULL) { 123756e5ad5fSMatt Macy ERRNO_SET(EINVAL); 123856e5ad5fSMatt Macy return (NULL); 123956e5ad5fSMatt Macy } 124056e5ad5fSMatt Macy 124156e5ad5fSMatt Macy data = nv_strdup(value); 124256e5ad5fSMatt Macy if (data == NULL) 124356e5ad5fSMatt Macy return (NULL); 124456e5ad5fSMatt Macy size = strlen(value) + 1; 124556e5ad5fSMatt Macy 124656e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data, 124756e5ad5fSMatt Macy size, 0); 124856e5ad5fSMatt Macy if (nvp == NULL) 124956e5ad5fSMatt Macy nv_free(data); 125056e5ad5fSMatt Macy 125156e5ad5fSMatt Macy return (nvp); 125256e5ad5fSMatt Macy } 125356e5ad5fSMatt Macy 125456e5ad5fSMatt Macy nvpair_t * 125556e5ad5fSMatt Macy nvpair_create_nvlist(const char *name, const nvlist_t *value) 125656e5ad5fSMatt Macy { 125756e5ad5fSMatt Macy nvlist_t *nvl; 125856e5ad5fSMatt Macy nvpair_t *nvp; 125956e5ad5fSMatt Macy 126056e5ad5fSMatt Macy if (value == NULL) { 126156e5ad5fSMatt Macy ERRNO_SET(EINVAL); 126256e5ad5fSMatt Macy return (NULL); 126356e5ad5fSMatt Macy } 126456e5ad5fSMatt Macy 126556e5ad5fSMatt Macy nvl = nvlist_clone(value); 126656e5ad5fSMatt Macy if (nvl == NULL) 126756e5ad5fSMatt Macy return (NULL); 126856e5ad5fSMatt Macy 126956e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 127056e5ad5fSMatt Macy 0); 127156e5ad5fSMatt Macy if (nvp == NULL) 127256e5ad5fSMatt Macy nvlist_destroy(nvl); 127356e5ad5fSMatt Macy else 127456e5ad5fSMatt Macy nvlist_set_parent(nvl, nvp); 127556e5ad5fSMatt Macy 127656e5ad5fSMatt Macy return (nvp); 127756e5ad5fSMatt Macy } 127856e5ad5fSMatt Macy 127956e5ad5fSMatt Macy #ifndef _KERNEL 128056e5ad5fSMatt Macy nvpair_t * 128156e5ad5fSMatt Macy nvpair_create_descriptor(const char *name, int value) 128256e5ad5fSMatt Macy { 128356e5ad5fSMatt Macy nvpair_t *nvp; 128456e5ad5fSMatt Macy 128556e5ad5fSMatt Macy value = fcntl(value, F_DUPFD_CLOEXEC, 0); 128656e5ad5fSMatt Macy if (value < 0) 128756e5ad5fSMatt Macy return (NULL); 128856e5ad5fSMatt Macy 128956e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 129056e5ad5fSMatt Macy sizeof(int64_t), 0); 129156e5ad5fSMatt Macy if (nvp == NULL) { 129256e5ad5fSMatt Macy ERRNO_SAVE(); 129356e5ad5fSMatt Macy close(value); 129456e5ad5fSMatt Macy ERRNO_RESTORE(); 129556e5ad5fSMatt Macy } 129656e5ad5fSMatt Macy 129756e5ad5fSMatt Macy return (nvp); 129856e5ad5fSMatt Macy } 129956e5ad5fSMatt Macy #endif 130056e5ad5fSMatt Macy 130156e5ad5fSMatt Macy nvpair_t * 130256e5ad5fSMatt Macy nvpair_create_binary(const char *name, const void *value, size_t size) 130356e5ad5fSMatt Macy { 130456e5ad5fSMatt Macy nvpair_t *nvp; 130556e5ad5fSMatt Macy void *data; 130656e5ad5fSMatt Macy 130756e5ad5fSMatt Macy if (value == NULL || size == 0) { 130856e5ad5fSMatt Macy ERRNO_SET(EINVAL); 130956e5ad5fSMatt Macy return (NULL); 131056e5ad5fSMatt Macy } 131156e5ad5fSMatt Macy 131256e5ad5fSMatt Macy data = nv_malloc(size); 131356e5ad5fSMatt Macy if (data == NULL) 131456e5ad5fSMatt Macy return (NULL); 131556e5ad5fSMatt Macy memcpy(data, value, size); 131656e5ad5fSMatt Macy 131756e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, 131856e5ad5fSMatt Macy size, 0); 131956e5ad5fSMatt Macy if (nvp == NULL) 132056e5ad5fSMatt Macy nv_free(data); 132156e5ad5fSMatt Macy 132256e5ad5fSMatt Macy return (nvp); 132356e5ad5fSMatt Macy } 132456e5ad5fSMatt Macy 132556e5ad5fSMatt Macy nvpair_t * 132656e5ad5fSMatt Macy nvpair_create_bool_array(const char *name, const bool *value, size_t nitems) 132756e5ad5fSMatt Macy { 132856e5ad5fSMatt Macy nvpair_t *nvp; 132956e5ad5fSMatt Macy size_t size; 133056e5ad5fSMatt Macy void *data; 133156e5ad5fSMatt Macy 133256e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 133356e5ad5fSMatt Macy ERRNO_SET(EINVAL); 133456e5ad5fSMatt Macy return (NULL); 133556e5ad5fSMatt Macy } 133656e5ad5fSMatt Macy 133736fa90dbSMariusz Zaborski data = nv_calloc(nitems, sizeof(value[0])); 133856e5ad5fSMatt Macy if (data == NULL) 133956e5ad5fSMatt Macy return (NULL); 134036fa90dbSMariusz Zaborski size = sizeof(value[0]) * nitems; 134156e5ad5fSMatt Macy 134256e5ad5fSMatt Macy memcpy(data, value, size); 134356e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data, 134456e5ad5fSMatt Macy size, nitems); 134556e5ad5fSMatt Macy if (nvp == NULL) { 134656e5ad5fSMatt Macy ERRNO_SAVE(); 134756e5ad5fSMatt Macy nv_free(data); 134856e5ad5fSMatt Macy ERRNO_RESTORE(); 134956e5ad5fSMatt Macy } 135056e5ad5fSMatt Macy 135156e5ad5fSMatt Macy return (nvp); 135256e5ad5fSMatt Macy } 135356e5ad5fSMatt Macy 135456e5ad5fSMatt Macy nvpair_t * 135556e5ad5fSMatt Macy nvpair_create_number_array(const char *name, const uint64_t *value, 135656e5ad5fSMatt Macy size_t nitems) 135756e5ad5fSMatt Macy { 135856e5ad5fSMatt Macy nvpair_t *nvp; 135956e5ad5fSMatt Macy size_t size; 136056e5ad5fSMatt Macy void *data; 136156e5ad5fSMatt Macy 136256e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 136356e5ad5fSMatt Macy ERRNO_SET(EINVAL); 136456e5ad5fSMatt Macy return (NULL); 136556e5ad5fSMatt Macy } 136656e5ad5fSMatt Macy 136736fa90dbSMariusz Zaborski data = nv_calloc(nitems, sizeof(value[0])); 136856e5ad5fSMatt Macy if (data == NULL) 136956e5ad5fSMatt Macy return (NULL); 137036fa90dbSMariusz Zaborski size = sizeof(value[0]) * nitems; 137156e5ad5fSMatt Macy 137256e5ad5fSMatt Macy memcpy(data, value, size); 137356e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 137456e5ad5fSMatt Macy (uint64_t)(uintptr_t)data, size, nitems); 137556e5ad5fSMatt Macy if (nvp == NULL) { 137656e5ad5fSMatt Macy ERRNO_SAVE(); 137756e5ad5fSMatt Macy nv_free(data); 137856e5ad5fSMatt Macy ERRNO_RESTORE(); 137956e5ad5fSMatt Macy } 138056e5ad5fSMatt Macy 138156e5ad5fSMatt Macy return (nvp); 138256e5ad5fSMatt Macy } 138356e5ad5fSMatt Macy 138456e5ad5fSMatt Macy nvpair_t * 138556e5ad5fSMatt Macy nvpair_create_string_array(const char *name, const char * const *value, 138656e5ad5fSMatt Macy size_t nitems) 138756e5ad5fSMatt Macy { 138856e5ad5fSMatt Macy nvpair_t *nvp; 138956e5ad5fSMatt Macy unsigned int ii; 139056e5ad5fSMatt Macy size_t datasize, size; 139156e5ad5fSMatt Macy char **data; 139256e5ad5fSMatt Macy 139356e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 139456e5ad5fSMatt Macy ERRNO_SET(EINVAL); 139556e5ad5fSMatt Macy return (NULL); 139656e5ad5fSMatt Macy } 139756e5ad5fSMatt Macy 139856e5ad5fSMatt Macy nvp = NULL; 139956e5ad5fSMatt Macy datasize = 0; 140036fa90dbSMariusz Zaborski data = nv_calloc(nitems, sizeof(value[0])); 140156e5ad5fSMatt Macy if (data == NULL) 140256e5ad5fSMatt Macy return (NULL); 140356e5ad5fSMatt Macy 140456e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) { 140556e5ad5fSMatt Macy if (value[ii] == NULL) { 140656e5ad5fSMatt Macy ERRNO_SET(EINVAL); 140756e5ad5fSMatt Macy goto fail; 140856e5ad5fSMatt Macy } 140956e5ad5fSMatt Macy 141056e5ad5fSMatt Macy size = strlen(value[ii]) + 1; 141156e5ad5fSMatt Macy datasize += size; 141256e5ad5fSMatt Macy data[ii] = nv_strdup(value[ii]); 141356e5ad5fSMatt Macy if (data[ii] == NULL) 141456e5ad5fSMatt Macy goto fail; 141556e5ad5fSMatt Macy } 141656e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 141756e5ad5fSMatt Macy (uint64_t)(uintptr_t)data, datasize, nitems); 141856e5ad5fSMatt Macy 141956e5ad5fSMatt Macy fail: 142056e5ad5fSMatt Macy if (nvp == NULL) { 142156e5ad5fSMatt Macy ERRNO_SAVE(); 142256e5ad5fSMatt Macy for (; ii > 0; ii--) 142356e5ad5fSMatt Macy nv_free(data[ii - 1]); 142456e5ad5fSMatt Macy nv_free(data); 142556e5ad5fSMatt Macy ERRNO_RESTORE(); 142656e5ad5fSMatt Macy } 142756e5ad5fSMatt Macy 142856e5ad5fSMatt Macy return (nvp); 142956e5ad5fSMatt Macy } 143056e5ad5fSMatt Macy 143156e5ad5fSMatt Macy nvpair_t * 143256e5ad5fSMatt Macy nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value, 143356e5ad5fSMatt Macy size_t nitems) 143456e5ad5fSMatt Macy { 143556e5ad5fSMatt Macy unsigned int ii; 143656e5ad5fSMatt Macy nvlist_t **nvls; 143756e5ad5fSMatt Macy nvpair_t *parent; 143856e5ad5fSMatt Macy int flags; 143956e5ad5fSMatt Macy 144056e5ad5fSMatt Macy nvls = NULL; 144156e5ad5fSMatt Macy 144256e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 144356e5ad5fSMatt Macy ERRNO_SET(EINVAL); 144456e5ad5fSMatt Macy return (NULL); 144556e5ad5fSMatt Macy } 144656e5ad5fSMatt Macy 144736fa90dbSMariusz Zaborski nvls = nv_calloc(nitems, sizeof(value[0])); 144856e5ad5fSMatt Macy if (nvls == NULL) 144956e5ad5fSMatt Macy return (NULL); 145056e5ad5fSMatt Macy 145156e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) { 145256e5ad5fSMatt Macy if (value[ii] == NULL) { 145356e5ad5fSMatt Macy ERRNO_SET(EINVAL); 145456e5ad5fSMatt Macy goto fail; 145556e5ad5fSMatt Macy } 145656e5ad5fSMatt Macy 145756e5ad5fSMatt Macy nvls[ii] = nvlist_clone(value[ii]); 145856e5ad5fSMatt Macy if (nvls[ii] == NULL) 145956e5ad5fSMatt Macy goto fail; 146056e5ad5fSMatt Macy 146156e5ad5fSMatt Macy if (ii > 0) { 146256e5ad5fSMatt Macy nvpair_t *nvp; 146356e5ad5fSMatt Macy 146456e5ad5fSMatt Macy nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 146556e5ad5fSMatt Macy (uint64_t)(uintptr_t)nvls[ii], 0, 0); 146656e5ad5fSMatt Macy if (nvp == NULL) { 146756e5ad5fSMatt Macy ERRNO_SAVE(); 146856e5ad5fSMatt Macy nvlist_destroy(nvls[ii]); 146956e5ad5fSMatt Macy ERRNO_RESTORE(); 147056e5ad5fSMatt Macy goto fail; 147156e5ad5fSMatt Macy } 147256e5ad5fSMatt Macy nvlist_set_array_next(nvls[ii - 1], nvp); 147356e5ad5fSMatt Macy } 147456e5ad5fSMatt Macy } 147556e5ad5fSMatt Macy flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY; 147656e5ad5fSMatt Macy nvlist_set_flags(nvls[nitems - 1], flags); 147756e5ad5fSMatt Macy 147856e5ad5fSMatt Macy parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 147956e5ad5fSMatt Macy (uint64_t)(uintptr_t)nvls, 0, nitems); 148056e5ad5fSMatt Macy if (parent == NULL) 148156e5ad5fSMatt Macy goto fail; 148256e5ad5fSMatt Macy 148356e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) 148456e5ad5fSMatt Macy nvlist_set_parent(nvls[ii], parent); 148556e5ad5fSMatt Macy 148656e5ad5fSMatt Macy return (parent); 148756e5ad5fSMatt Macy 148856e5ad5fSMatt Macy fail: 148956e5ad5fSMatt Macy ERRNO_SAVE(); 149056e5ad5fSMatt Macy for (; ii > 0; ii--) 149156e5ad5fSMatt Macy nvlist_destroy(nvls[ii - 1]); 149256e5ad5fSMatt Macy nv_free(nvls); 149356e5ad5fSMatt Macy ERRNO_RESTORE(); 149456e5ad5fSMatt Macy 149556e5ad5fSMatt Macy return (NULL); 149656e5ad5fSMatt Macy } 149756e5ad5fSMatt Macy 149856e5ad5fSMatt Macy #ifndef _KERNEL 149956e5ad5fSMatt Macy nvpair_t * 150056e5ad5fSMatt Macy nvpair_create_descriptor_array(const char *name, const int *value, 150156e5ad5fSMatt Macy size_t nitems) 150256e5ad5fSMatt Macy { 150356e5ad5fSMatt Macy unsigned int ii; 150456e5ad5fSMatt Macy nvpair_t *nvp; 150556e5ad5fSMatt Macy int *fds; 150656e5ad5fSMatt Macy 150756e5ad5fSMatt Macy if (value == NULL) { 150856e5ad5fSMatt Macy ERRNO_SET(EINVAL); 150956e5ad5fSMatt Macy return (NULL); 151056e5ad5fSMatt Macy } 151156e5ad5fSMatt Macy 151256e5ad5fSMatt Macy nvp = NULL; 151356e5ad5fSMatt Macy 151436fa90dbSMariusz Zaborski fds = nv_calloc(nitems, sizeof(value[0])); 151556e5ad5fSMatt Macy if (fds == NULL) 151656e5ad5fSMatt Macy return (NULL); 151756e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) { 151856e5ad5fSMatt Macy if (value[ii] == -1) { 151956e5ad5fSMatt Macy fds[ii] = -1; 152056e5ad5fSMatt Macy } else { 152156e5ad5fSMatt Macy fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0); 152256e5ad5fSMatt Macy if (fds[ii] == -1) 152356e5ad5fSMatt Macy goto fail; 152456e5ad5fSMatt Macy } 152556e5ad5fSMatt Macy } 152656e5ad5fSMatt Macy 152756e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 152856e5ad5fSMatt Macy (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems); 152956e5ad5fSMatt Macy 153056e5ad5fSMatt Macy fail: 153156e5ad5fSMatt Macy if (nvp == NULL) { 153256e5ad5fSMatt Macy ERRNO_SAVE(); 153356e5ad5fSMatt Macy for (; ii > 0; ii--) { 153456e5ad5fSMatt Macy if (fds[ii - 1] != -1) 153556e5ad5fSMatt Macy close(fds[ii - 1]); 153656e5ad5fSMatt Macy } 153756e5ad5fSMatt Macy nv_free(fds); 153856e5ad5fSMatt Macy ERRNO_RESTORE(); 153956e5ad5fSMatt Macy } 154056e5ad5fSMatt Macy 154156e5ad5fSMatt Macy return (nvp); 154256e5ad5fSMatt Macy } 154356e5ad5fSMatt Macy #endif 154456e5ad5fSMatt Macy 154556e5ad5fSMatt Macy nvpair_t * 154656e5ad5fSMatt Macy nvpair_move_string(const char *name, char *value) 154756e5ad5fSMatt Macy { 154856e5ad5fSMatt Macy nvpair_t *nvp; 154956e5ad5fSMatt Macy 155056e5ad5fSMatt Macy if (value == NULL) { 155156e5ad5fSMatt Macy ERRNO_SET(EINVAL); 155256e5ad5fSMatt Macy return (NULL); 155356e5ad5fSMatt Macy } 155456e5ad5fSMatt Macy 155556e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 155656e5ad5fSMatt Macy strlen(value) + 1, 0); 155756e5ad5fSMatt Macy if (nvp == NULL) { 155856e5ad5fSMatt Macy ERRNO_SAVE(); 155956e5ad5fSMatt Macy nv_free(value); 156056e5ad5fSMatt Macy ERRNO_RESTORE(); 156156e5ad5fSMatt Macy } 156256e5ad5fSMatt Macy 156356e5ad5fSMatt Macy return (nvp); 156456e5ad5fSMatt Macy } 156556e5ad5fSMatt Macy 156656e5ad5fSMatt Macy nvpair_t * 156756e5ad5fSMatt Macy nvpair_move_nvlist(const char *name, nvlist_t *value) 156856e5ad5fSMatt Macy { 156956e5ad5fSMatt Macy nvpair_t *nvp; 157056e5ad5fSMatt Macy 157156e5ad5fSMatt Macy if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { 157256e5ad5fSMatt Macy ERRNO_SET(EINVAL); 157356e5ad5fSMatt Macy return (NULL); 157456e5ad5fSMatt Macy } 157556e5ad5fSMatt Macy 157656e5ad5fSMatt Macy if (nvlist_error(value) != 0) { 157756e5ad5fSMatt Macy ERRNO_SET(nvlist_error(value)); 157856e5ad5fSMatt Macy nvlist_destroy(value); 157956e5ad5fSMatt Macy return (NULL); 158056e5ad5fSMatt Macy } 158156e5ad5fSMatt Macy 158256e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 158356e5ad5fSMatt Macy 0, 0); 158456e5ad5fSMatt Macy if (nvp == NULL) 158556e5ad5fSMatt Macy nvlist_destroy(value); 158656e5ad5fSMatt Macy else 158756e5ad5fSMatt Macy nvlist_set_parent(value, nvp); 158856e5ad5fSMatt Macy 158956e5ad5fSMatt Macy return (nvp); 159056e5ad5fSMatt Macy } 159156e5ad5fSMatt Macy 159256e5ad5fSMatt Macy #ifndef _KERNEL 159356e5ad5fSMatt Macy nvpair_t * 159456e5ad5fSMatt Macy nvpair_move_descriptor(const char *name, int value) 159556e5ad5fSMatt Macy { 159656e5ad5fSMatt Macy nvpair_t *nvp; 159756e5ad5fSMatt Macy 159856e5ad5fSMatt Macy if (value < 0 || !fd_is_valid(value)) { 159956e5ad5fSMatt Macy ERRNO_SET(EBADF); 160056e5ad5fSMatt Macy return (NULL); 160156e5ad5fSMatt Macy } 160256e5ad5fSMatt Macy 160356e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 160456e5ad5fSMatt Macy sizeof(int64_t), 0); 160556e5ad5fSMatt Macy if (nvp == NULL) { 160656e5ad5fSMatt Macy ERRNO_SAVE(); 160756e5ad5fSMatt Macy close(value); 160856e5ad5fSMatt Macy ERRNO_RESTORE(); 160956e5ad5fSMatt Macy } 161056e5ad5fSMatt Macy 161156e5ad5fSMatt Macy return (nvp); 161256e5ad5fSMatt Macy } 161356e5ad5fSMatt Macy #endif 161456e5ad5fSMatt Macy 161556e5ad5fSMatt Macy nvpair_t * 161656e5ad5fSMatt Macy nvpair_move_binary(const char *name, void *value, size_t size) 161756e5ad5fSMatt Macy { 161856e5ad5fSMatt Macy nvpair_t *nvp; 161956e5ad5fSMatt Macy 162056e5ad5fSMatt Macy if (value == NULL || size == 0) { 162156e5ad5fSMatt Macy ERRNO_SET(EINVAL); 162256e5ad5fSMatt Macy return (NULL); 162356e5ad5fSMatt Macy } 162456e5ad5fSMatt Macy 162556e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, 162656e5ad5fSMatt Macy size, 0); 162756e5ad5fSMatt Macy if (nvp == NULL) { 162856e5ad5fSMatt Macy ERRNO_SAVE(); 162956e5ad5fSMatt Macy nv_free(value); 163056e5ad5fSMatt Macy ERRNO_RESTORE(); 163156e5ad5fSMatt Macy } 163256e5ad5fSMatt Macy 163356e5ad5fSMatt Macy return (nvp); 163456e5ad5fSMatt Macy } 163556e5ad5fSMatt Macy 163656e5ad5fSMatt Macy nvpair_t * 163756e5ad5fSMatt Macy nvpair_move_bool_array(const char *name, bool *value, size_t nitems) 163856e5ad5fSMatt Macy { 163956e5ad5fSMatt Macy nvpair_t *nvp; 164056e5ad5fSMatt Macy 164156e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 164256e5ad5fSMatt Macy ERRNO_SET(EINVAL); 164356e5ad5fSMatt Macy return (NULL); 164456e5ad5fSMatt Macy } 164556e5ad5fSMatt Macy 164656e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, 164756e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 164856e5ad5fSMatt Macy if (nvp == NULL) { 164956e5ad5fSMatt Macy ERRNO_SAVE(); 165056e5ad5fSMatt Macy nv_free(value); 165156e5ad5fSMatt Macy ERRNO_RESTORE(); 165256e5ad5fSMatt Macy } 165356e5ad5fSMatt Macy 165456e5ad5fSMatt Macy return (nvp); 165556e5ad5fSMatt Macy } 165656e5ad5fSMatt Macy 165756e5ad5fSMatt Macy nvpair_t * 165856e5ad5fSMatt Macy nvpair_move_string_array(const char *name, char **value, size_t nitems) 165956e5ad5fSMatt Macy { 166056e5ad5fSMatt Macy nvpair_t *nvp; 166156e5ad5fSMatt Macy size_t i, size; 166256e5ad5fSMatt Macy 166356e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 166456e5ad5fSMatt Macy ERRNO_SET(EINVAL); 166556e5ad5fSMatt Macy return (NULL); 166656e5ad5fSMatt Macy } 166756e5ad5fSMatt Macy 166856e5ad5fSMatt Macy size = 0; 166956e5ad5fSMatt Macy for (i = 0; i < nitems; i++) { 167056e5ad5fSMatt Macy if (value[i] == NULL) { 167156e5ad5fSMatt Macy ERRNO_SET(EINVAL); 167256e5ad5fSMatt Macy return (NULL); 167356e5ad5fSMatt Macy } 167456e5ad5fSMatt Macy 167556e5ad5fSMatt Macy size += strlen(value[i]) + 1; 167656e5ad5fSMatt Macy } 167756e5ad5fSMatt Macy 167856e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 167956e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, size, nitems); 168056e5ad5fSMatt Macy if (nvp == NULL) { 168156e5ad5fSMatt Macy ERRNO_SAVE(); 168256e5ad5fSMatt Macy for (i = 0; i < nitems; i++) 168356e5ad5fSMatt Macy nv_free(value[i]); 168456e5ad5fSMatt Macy nv_free(value); 168556e5ad5fSMatt Macy ERRNO_RESTORE(); 168656e5ad5fSMatt Macy } 168756e5ad5fSMatt Macy 168856e5ad5fSMatt Macy return (nvp); 168956e5ad5fSMatt Macy } 169056e5ad5fSMatt Macy 169156e5ad5fSMatt Macy nvpair_t * 169256e5ad5fSMatt Macy nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems) 169356e5ad5fSMatt Macy { 169456e5ad5fSMatt Macy nvpair_t *nvp; 169556e5ad5fSMatt Macy 169656e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 169756e5ad5fSMatt Macy ERRNO_SET(EINVAL); 169856e5ad5fSMatt Macy return (NULL); 169956e5ad5fSMatt Macy } 170056e5ad5fSMatt Macy 170156e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 170256e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 170356e5ad5fSMatt Macy if (nvp == NULL) { 170456e5ad5fSMatt Macy ERRNO_SAVE(); 170556e5ad5fSMatt Macy nv_free(value); 170656e5ad5fSMatt Macy ERRNO_RESTORE(); 170756e5ad5fSMatt Macy } 170856e5ad5fSMatt Macy 170956e5ad5fSMatt Macy return (nvp); 171056e5ad5fSMatt Macy } 171156e5ad5fSMatt Macy 171256e5ad5fSMatt Macy nvpair_t * 171356e5ad5fSMatt Macy nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems) 171456e5ad5fSMatt Macy { 171556e5ad5fSMatt Macy nvpair_t *parent; 171656e5ad5fSMatt Macy unsigned int ii; 171756e5ad5fSMatt Macy int flags; 171856e5ad5fSMatt Macy 171956e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 172056e5ad5fSMatt Macy ERRNO_SET(EINVAL); 172156e5ad5fSMatt Macy return (NULL); 172256e5ad5fSMatt Macy } 172356e5ad5fSMatt Macy 172456e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) { 172556e5ad5fSMatt Macy if (value == NULL || nvlist_error(value[ii]) != 0 || 172656e5ad5fSMatt Macy nvlist_get_pararr(value[ii], NULL) != NULL) { 172756e5ad5fSMatt Macy ERRNO_SET(EINVAL); 172856e5ad5fSMatt Macy goto fail; 172956e5ad5fSMatt Macy } 173056e5ad5fSMatt Macy if (ii > 0) { 173156e5ad5fSMatt Macy nvpair_t *nvp; 173256e5ad5fSMatt Macy 173356e5ad5fSMatt Macy nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 173456e5ad5fSMatt Macy (uint64_t)(uintptr_t)value[ii], 0, 0); 173556e5ad5fSMatt Macy if (nvp == NULL) 173656e5ad5fSMatt Macy goto fail; 173756e5ad5fSMatt Macy nvlist_set_array_next(value[ii - 1], nvp); 173856e5ad5fSMatt Macy } 173956e5ad5fSMatt Macy } 174056e5ad5fSMatt Macy flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY; 174156e5ad5fSMatt Macy nvlist_set_flags(value[nitems - 1], flags); 174256e5ad5fSMatt Macy 174356e5ad5fSMatt Macy parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 174456e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, 0, nitems); 174556e5ad5fSMatt Macy if (parent == NULL) 174656e5ad5fSMatt Macy goto fail; 174756e5ad5fSMatt Macy 174856e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) 174956e5ad5fSMatt Macy nvlist_set_parent(value[ii], parent); 175056e5ad5fSMatt Macy 175156e5ad5fSMatt Macy return (parent); 175256e5ad5fSMatt Macy fail: 175356e5ad5fSMatt Macy ERRNO_SAVE(); 175456e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) { 175556e5ad5fSMatt Macy if (value[ii] != NULL && 175656e5ad5fSMatt Macy nvlist_get_pararr(value[ii], NULL) != NULL) { 175756e5ad5fSMatt Macy nvlist_destroy(value[ii]); 175856e5ad5fSMatt Macy } 175956e5ad5fSMatt Macy } 176056e5ad5fSMatt Macy nv_free(value); 176156e5ad5fSMatt Macy ERRNO_RESTORE(); 176256e5ad5fSMatt Macy 176356e5ad5fSMatt Macy return (NULL); 176456e5ad5fSMatt Macy } 176556e5ad5fSMatt Macy 176656e5ad5fSMatt Macy #ifndef _KERNEL 176756e5ad5fSMatt Macy nvpair_t * 176856e5ad5fSMatt Macy nvpair_move_descriptor_array(const char *name, int *value, size_t nitems) 176956e5ad5fSMatt Macy { 177056e5ad5fSMatt Macy nvpair_t *nvp; 177156e5ad5fSMatt Macy size_t i; 177256e5ad5fSMatt Macy 177356e5ad5fSMatt Macy if (value == NULL || nitems == 0) { 177456e5ad5fSMatt Macy ERRNO_SET(EINVAL); 177556e5ad5fSMatt Macy return (NULL); 177656e5ad5fSMatt Macy } 177756e5ad5fSMatt Macy 177856e5ad5fSMatt Macy for (i = 0; i < nitems; i++) { 177956e5ad5fSMatt Macy if (value[i] != -1 && !fd_is_valid(value[i])) { 178056e5ad5fSMatt Macy ERRNO_SET(EBADF); 178156e5ad5fSMatt Macy goto fail; 178256e5ad5fSMatt Macy } 178356e5ad5fSMatt Macy } 178456e5ad5fSMatt Macy 178556e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 178656e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 178756e5ad5fSMatt Macy if (nvp == NULL) 178856e5ad5fSMatt Macy goto fail; 178956e5ad5fSMatt Macy 179056e5ad5fSMatt Macy return (nvp); 179156e5ad5fSMatt Macy fail: 179256e5ad5fSMatt Macy ERRNO_SAVE(); 179356e5ad5fSMatt Macy for (i = 0; i < nitems; i++) { 179456e5ad5fSMatt Macy if (fd_is_valid(value[i])) 179556e5ad5fSMatt Macy close(value[i]); 179656e5ad5fSMatt Macy } 179756e5ad5fSMatt Macy nv_free(value); 179856e5ad5fSMatt Macy ERRNO_RESTORE(); 179956e5ad5fSMatt Macy 180056e5ad5fSMatt Macy return (NULL); 180156e5ad5fSMatt Macy } 180256e5ad5fSMatt Macy #endif 180356e5ad5fSMatt Macy 180456e5ad5fSMatt Macy bool 180556e5ad5fSMatt Macy nvpair_get_bool(const nvpair_t *nvp) 180656e5ad5fSMatt Macy { 180756e5ad5fSMatt Macy 180856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 180956e5ad5fSMatt Macy 181056e5ad5fSMatt Macy return (nvp->nvp_data == 1); 181156e5ad5fSMatt Macy } 181256e5ad5fSMatt Macy 181356e5ad5fSMatt Macy uint64_t 181456e5ad5fSMatt Macy nvpair_get_number(const nvpair_t *nvp) 181556e5ad5fSMatt Macy { 181656e5ad5fSMatt Macy 181756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 181856e5ad5fSMatt Macy 181956e5ad5fSMatt Macy return (nvp->nvp_data); 182056e5ad5fSMatt Macy } 182156e5ad5fSMatt Macy 182256e5ad5fSMatt Macy const char * 182356e5ad5fSMatt Macy nvpair_get_string(const nvpair_t *nvp) 182456e5ad5fSMatt Macy { 182556e5ad5fSMatt Macy 182656e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 182756e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 182856e5ad5fSMatt Macy 182956e5ad5fSMatt Macy return ((const char *)(intptr_t)nvp->nvp_data); 183056e5ad5fSMatt Macy } 183156e5ad5fSMatt Macy 183256e5ad5fSMatt Macy const nvlist_t * 183356e5ad5fSMatt Macy nvpair_get_nvlist(const nvpair_t *nvp) 183456e5ad5fSMatt Macy { 183556e5ad5fSMatt Macy 183656e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 183756e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 183856e5ad5fSMatt Macy 183956e5ad5fSMatt Macy return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 184056e5ad5fSMatt Macy } 184156e5ad5fSMatt Macy 184256e5ad5fSMatt Macy #ifndef _KERNEL 184356e5ad5fSMatt Macy int 184456e5ad5fSMatt Macy nvpair_get_descriptor(const nvpair_t *nvp) 184556e5ad5fSMatt Macy { 184656e5ad5fSMatt Macy 184756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 184856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 184956e5ad5fSMatt Macy 185056e5ad5fSMatt Macy return ((int)nvp->nvp_data); 185156e5ad5fSMatt Macy } 185256e5ad5fSMatt Macy #endif 185356e5ad5fSMatt Macy 185456e5ad5fSMatt Macy const void * 185556e5ad5fSMatt Macy nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 185656e5ad5fSMatt Macy { 185756e5ad5fSMatt Macy 185856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 185956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 186056e5ad5fSMatt Macy 186156e5ad5fSMatt Macy if (sizep != NULL) 186256e5ad5fSMatt Macy *sizep = nvp->nvp_datasize; 186356e5ad5fSMatt Macy 186456e5ad5fSMatt Macy return ((const void *)(intptr_t)nvp->nvp_data); 186556e5ad5fSMatt Macy } 186656e5ad5fSMatt Macy 186756e5ad5fSMatt Macy const bool * 186856e5ad5fSMatt Macy nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems) 186956e5ad5fSMatt Macy { 187056e5ad5fSMatt Macy 187156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 187256e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 187356e5ad5fSMatt Macy 187456e5ad5fSMatt Macy if (nitems != NULL) 187556e5ad5fSMatt Macy *nitems = nvp->nvp_nitems; 187656e5ad5fSMatt Macy 187756e5ad5fSMatt Macy return ((const bool *)(intptr_t)nvp->nvp_data); 187856e5ad5fSMatt Macy } 187956e5ad5fSMatt Macy 188056e5ad5fSMatt Macy const uint64_t * 188156e5ad5fSMatt Macy nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems) 188256e5ad5fSMatt Macy { 188356e5ad5fSMatt Macy 188456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 188556e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 188656e5ad5fSMatt Macy 188756e5ad5fSMatt Macy if (nitems != NULL) 188856e5ad5fSMatt Macy *nitems = nvp->nvp_nitems; 188956e5ad5fSMatt Macy 189056e5ad5fSMatt Macy return ((const uint64_t *)(intptr_t)nvp->nvp_data); 189156e5ad5fSMatt Macy } 189256e5ad5fSMatt Macy 189356e5ad5fSMatt Macy const char * const * 189456e5ad5fSMatt Macy nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems) 189556e5ad5fSMatt Macy { 189656e5ad5fSMatt Macy 189756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 189856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 189956e5ad5fSMatt Macy 190056e5ad5fSMatt Macy if (nitems != NULL) 190156e5ad5fSMatt Macy *nitems = nvp->nvp_nitems; 190256e5ad5fSMatt Macy 190356e5ad5fSMatt Macy return ((const char * const *)(intptr_t)nvp->nvp_data); 190456e5ad5fSMatt Macy } 190556e5ad5fSMatt Macy 190656e5ad5fSMatt Macy const nvlist_t * const * 190756e5ad5fSMatt Macy nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems) 190856e5ad5fSMatt Macy { 190956e5ad5fSMatt Macy 191056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 191156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 191256e5ad5fSMatt Macy 191356e5ad5fSMatt Macy if (nitems != NULL) 191456e5ad5fSMatt Macy *nitems = nvp->nvp_nitems; 191556e5ad5fSMatt Macy 191656e5ad5fSMatt Macy return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data)); 191756e5ad5fSMatt Macy } 191856e5ad5fSMatt Macy 191956e5ad5fSMatt Macy #ifndef _KERNEL 192056e5ad5fSMatt Macy const int * 192156e5ad5fSMatt Macy nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems) 192256e5ad5fSMatt Macy { 192356e5ad5fSMatt Macy 192456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 192556e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 192656e5ad5fSMatt Macy 192756e5ad5fSMatt Macy if (nitems != NULL) 192856e5ad5fSMatt Macy *nitems = nvp->nvp_nitems; 192956e5ad5fSMatt Macy 193056e5ad5fSMatt Macy return ((const int *)(intptr_t)nvp->nvp_data); 193156e5ad5fSMatt Macy } 193256e5ad5fSMatt Macy #endif 193356e5ad5fSMatt Macy 193456e5ad5fSMatt Macy int 193556e5ad5fSMatt Macy nvpair_append_bool_array(nvpair_t *nvp, const bool value) 193656e5ad5fSMatt Macy { 193756e5ad5fSMatt Macy 193856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 193956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 194056e5ad5fSMatt Macy return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 194156e5ad5fSMatt Macy } 194256e5ad5fSMatt Macy 194356e5ad5fSMatt Macy int 194456e5ad5fSMatt Macy nvpair_append_number_array(nvpair_t *nvp, const uint64_t value) 194556e5ad5fSMatt Macy { 194656e5ad5fSMatt Macy 194756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 194856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 194956e5ad5fSMatt Macy return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 195056e5ad5fSMatt Macy } 195156e5ad5fSMatt Macy 195256e5ad5fSMatt Macy int 195356e5ad5fSMatt Macy nvpair_append_string_array(nvpair_t *nvp, const char *value) 195456e5ad5fSMatt Macy { 195556e5ad5fSMatt Macy char *str; 195656e5ad5fSMatt Macy 195756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 195856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 195956e5ad5fSMatt Macy if (value == NULL) { 196056e5ad5fSMatt Macy ERRNO_SET(EINVAL); 196156e5ad5fSMatt Macy return (-1); 196256e5ad5fSMatt Macy } 196356e5ad5fSMatt Macy str = nv_strdup(value); 196456e5ad5fSMatt Macy if (str == NULL) { 196556e5ad5fSMatt Macy return (-1); 196656e5ad5fSMatt Macy } 196756e5ad5fSMatt Macy if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) { 196856e5ad5fSMatt Macy nv_free(str); 196956e5ad5fSMatt Macy return (-1); 197056e5ad5fSMatt Macy } 197156e5ad5fSMatt Macy return (0); 197256e5ad5fSMatt Macy } 197356e5ad5fSMatt Macy 197456e5ad5fSMatt Macy int 197556e5ad5fSMatt Macy nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value) 197656e5ad5fSMatt Macy { 197756e5ad5fSMatt Macy nvpair_t *tmpnvp; 197856e5ad5fSMatt Macy nvlist_t *nvl, *prev; 197956e5ad5fSMatt Macy int flags; 198056e5ad5fSMatt Macy 198156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 198256e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 198356e5ad5fSMatt Macy if (value == NULL || nvlist_error(value) != 0 || 198456e5ad5fSMatt Macy nvlist_get_pararr(value, NULL) != NULL) { 198556e5ad5fSMatt Macy ERRNO_SET(EINVAL); 198656e5ad5fSMatt Macy return (-1); 198756e5ad5fSMatt Macy } 198856e5ad5fSMatt Macy nvl = nvlist_clone(value); 198956e5ad5fSMatt Macy if (nvl == NULL) { 199056e5ad5fSMatt Macy return (-1); 199156e5ad5fSMatt Macy } 199256e5ad5fSMatt Macy flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY; 199356e5ad5fSMatt Macy nvlist_set_flags(nvl, flags); 199456e5ad5fSMatt Macy 199556e5ad5fSMatt Macy tmpnvp = NULL; 199656e5ad5fSMatt Macy prev = NULL; 199756e5ad5fSMatt Macy if (nvp->nvp_nitems > 0) { 199856e5ad5fSMatt Macy nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data; 199956e5ad5fSMatt Macy 200056e5ad5fSMatt Macy prev = nvls[nvp->nvp_nitems - 1]; 200156e5ad5fSMatt Macy PJDLOG_ASSERT(prev != NULL); 200256e5ad5fSMatt Macy 200356e5ad5fSMatt Macy tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 200456e5ad5fSMatt Macy (uint64_t)(uintptr_t)nvl, 0, 0); 200556e5ad5fSMatt Macy if (tmpnvp == NULL) { 200656e5ad5fSMatt Macy goto fail; 200756e5ad5fSMatt Macy } 200856e5ad5fSMatt Macy } 200956e5ad5fSMatt Macy if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) { 201056e5ad5fSMatt Macy goto fail; 201156e5ad5fSMatt Macy } 201256e5ad5fSMatt Macy if (tmpnvp) { 201356e5ad5fSMatt Macy NVPAIR_ASSERT(tmpnvp); 201456e5ad5fSMatt Macy nvlist_set_array_next(prev, tmpnvp); 201556e5ad5fSMatt Macy } 201656e5ad5fSMatt Macy nvlist_set_parent(nvl, nvp); 201756e5ad5fSMatt Macy return (0); 201856e5ad5fSMatt Macy fail: 201956e5ad5fSMatt Macy if (tmpnvp) { 202056e5ad5fSMatt Macy nvpair_free(tmpnvp); 202156e5ad5fSMatt Macy } 202256e5ad5fSMatt Macy nvlist_destroy(nvl); 202356e5ad5fSMatt Macy return (-1); 202456e5ad5fSMatt Macy } 202556e5ad5fSMatt Macy 202656e5ad5fSMatt Macy #ifndef _KERNEL 202756e5ad5fSMatt Macy int 202856e5ad5fSMatt Macy nvpair_append_descriptor_array(nvpair_t *nvp, const int value) 202956e5ad5fSMatt Macy { 203056e5ad5fSMatt Macy int fd; 203156e5ad5fSMatt Macy 203256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 203356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 203456e5ad5fSMatt Macy fd = fcntl(value, F_DUPFD_CLOEXEC, 0); 203556e5ad5fSMatt Macy if (fd == -1) { 203656e5ad5fSMatt Macy return (-1); 203756e5ad5fSMatt Macy } 203856e5ad5fSMatt Macy if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) { 203956e5ad5fSMatt Macy close(fd); 204056e5ad5fSMatt Macy return (-1); 204156e5ad5fSMatt Macy } 204256e5ad5fSMatt Macy return (0); 204356e5ad5fSMatt Macy } 204456e5ad5fSMatt Macy #endif 204556e5ad5fSMatt Macy 204656e5ad5fSMatt Macy void 204756e5ad5fSMatt Macy nvpair_free(nvpair_t *nvp) 204856e5ad5fSMatt Macy { 204956e5ad5fSMatt Macy size_t i; 205056e5ad5fSMatt Macy 205156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 205256e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list == NULL); 205356e5ad5fSMatt Macy 205456e5ad5fSMatt Macy nvp->nvp_magic = 0; 205556e5ad5fSMatt Macy switch (nvp->nvp_type) { 205656e5ad5fSMatt Macy #ifndef _KERNEL 205756e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR: 205856e5ad5fSMatt Macy close((int)nvp->nvp_data); 205956e5ad5fSMatt Macy break; 206056e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR_ARRAY: 206156e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) 206256e5ad5fSMatt Macy close(((int *)(intptr_t)nvp->nvp_data)[i]); 206356e5ad5fSMatt Macy nv_free((int *)(intptr_t)nvp->nvp_data); 206456e5ad5fSMatt Macy break; 206556e5ad5fSMatt Macy #endif 206656e5ad5fSMatt Macy case NV_TYPE_NVLIST: 206756e5ad5fSMatt Macy nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 206856e5ad5fSMatt Macy break; 206956e5ad5fSMatt Macy case NV_TYPE_STRING: 207056e5ad5fSMatt Macy nv_free((char *)(intptr_t)nvp->nvp_data); 207156e5ad5fSMatt Macy break; 207256e5ad5fSMatt Macy case NV_TYPE_BINARY: 207356e5ad5fSMatt Macy nv_free((void *)(intptr_t)nvp->nvp_data); 207456e5ad5fSMatt Macy break; 207556e5ad5fSMatt Macy case NV_TYPE_NVLIST_ARRAY: 207656e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) { 207756e5ad5fSMatt Macy nvlist_destroy( 207856e5ad5fSMatt Macy ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]); 207956e5ad5fSMatt Macy } 208056e5ad5fSMatt Macy nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data)); 208156e5ad5fSMatt Macy break; 208256e5ad5fSMatt Macy case NV_TYPE_NUMBER_ARRAY: 208356e5ad5fSMatt Macy nv_free((uint64_t *)(intptr_t)nvp->nvp_data); 208456e5ad5fSMatt Macy break; 208556e5ad5fSMatt Macy case NV_TYPE_BOOL_ARRAY: 208656e5ad5fSMatt Macy nv_free((bool *)(intptr_t)nvp->nvp_data); 208756e5ad5fSMatt Macy break; 208856e5ad5fSMatt Macy case NV_TYPE_STRING_ARRAY: 208956e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) 209056e5ad5fSMatt Macy nv_free(((char **)(intptr_t)nvp->nvp_data)[i]); 209156e5ad5fSMatt Macy nv_free((char **)(intptr_t)nvp->nvp_data); 209256e5ad5fSMatt Macy break; 209356e5ad5fSMatt Macy } 209456e5ad5fSMatt Macy nv_free(nvp); 209556e5ad5fSMatt Macy } 209656e5ad5fSMatt Macy 209756e5ad5fSMatt Macy void 209856e5ad5fSMatt Macy nvpair_free_structure(nvpair_t *nvp) 209956e5ad5fSMatt Macy { 210056e5ad5fSMatt Macy 210156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp); 210256e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list == NULL); 210356e5ad5fSMatt Macy 210456e5ad5fSMatt Macy nvp->nvp_magic = 0; 210556e5ad5fSMatt Macy nv_free(nvp); 210656e5ad5fSMatt Macy } 210756e5ad5fSMatt Macy 210856e5ad5fSMatt Macy const char * 210956e5ad5fSMatt Macy nvpair_type_string(int type) 211056e5ad5fSMatt Macy { 211156e5ad5fSMatt Macy 211256e5ad5fSMatt Macy switch (type) { 211356e5ad5fSMatt Macy case NV_TYPE_NULL: 211456e5ad5fSMatt Macy return ("NULL"); 211556e5ad5fSMatt Macy case NV_TYPE_BOOL: 211656e5ad5fSMatt Macy return ("BOOL"); 211756e5ad5fSMatt Macy case NV_TYPE_NUMBER: 211856e5ad5fSMatt Macy return ("NUMBER"); 211956e5ad5fSMatt Macy case NV_TYPE_STRING: 212056e5ad5fSMatt Macy return ("STRING"); 212156e5ad5fSMatt Macy case NV_TYPE_NVLIST: 212256e5ad5fSMatt Macy return ("NVLIST"); 212356e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR: 212456e5ad5fSMatt Macy return ("DESCRIPTOR"); 212556e5ad5fSMatt Macy case NV_TYPE_BINARY: 212656e5ad5fSMatt Macy return ("BINARY"); 212756e5ad5fSMatt Macy case NV_TYPE_BOOL_ARRAY: 212856e5ad5fSMatt Macy return ("BOOL ARRAY"); 212956e5ad5fSMatt Macy case NV_TYPE_NUMBER_ARRAY: 213056e5ad5fSMatt Macy return ("NUMBER ARRAY"); 213156e5ad5fSMatt Macy case NV_TYPE_STRING_ARRAY: 213256e5ad5fSMatt Macy return ("STRING ARRAY"); 213356e5ad5fSMatt Macy case NV_TYPE_NVLIST_ARRAY: 213456e5ad5fSMatt Macy return ("NVLIST ARRAY"); 213556e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR_ARRAY: 213656e5ad5fSMatt Macy return ("DESCRIPTOR ARRAY"); 213756e5ad5fSMatt Macy default: 213856e5ad5fSMatt Macy return ("<UNKNOWN>"); 213956e5ad5fSMatt Macy } 214056e5ad5fSMatt Macy } 214156e5ad5fSMatt Macy 2142