1 1.13 riastrad /* $NetBSD: nvpair.c,v 1.13 2024/09/04 12:57:10 riastradh Exp $ */ 2 1.2 christos 3 1.1 christos /*- 4 1.1 christos * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5 1.1 christos * 6 1.1 christos * Copyright (c) 2009-2013 The FreeBSD Foundation 7 1.1 christos * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo (at) FreeBSD.org> 8 1.1 christos * All rights reserved. 9 1.1 christos * 10 1.1 christos * This software was developed by Pawel Jakub Dawidek under sponsorship from 11 1.1 christos * the FreeBSD Foundation. 12 1.1 christos * 13 1.1 christos * Redistribution and use in source and binary forms, with or without 14 1.1 christos * modification, are permitted provided that the following conditions 15 1.1 christos * are met: 16 1.1 christos * 1. Redistributions of source code must retain the above copyright 17 1.1 christos * notice, this list of conditions and the following disclaimer. 18 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 19 1.1 christos * notice, this list of conditions and the following disclaimer in the 20 1.1 christos * documentation and/or other materials provided with the distribution. 21 1.1 christos * 22 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 26 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 christos * SUCH DAMAGE. 33 1.1 christos */ 34 1.1 christos 35 1.1 christos #include <sys/cdefs.h> 36 1.2 christos #ifdef __FreeBSD__ 37 1.1 christos __FBSDID("$FreeBSD: head/sys/contrib/libnv/nvpair.c 335382 2018-06-19 18:43:02Z lwhsu $"); 38 1.2 christos #else 39 1.13 riastrad __RCSID("$NetBSD: nvpair.c,v 1.13 2024/09/04 12:57:10 riastradh Exp $"); 40 1.2 christos #endif 41 1.1 christos 42 1.1 christos #include <sys/param.h> 43 1.1 christos #include <sys/endian.h> 44 1.1 christos #include <sys/queue.h> 45 1.1 christos 46 1.2 christos #if defined(_KERNEL) || defined(_STANDALONE) 47 1.1 christos 48 1.1 christos #include <sys/errno.h> 49 1.1 christos #include <sys/lock.h> 50 1.1 christos #include <sys/malloc.h> 51 1.1 christos #include <sys/systm.h> 52 1.9 sevan #include <sys/kmem.h> 53 1.1 christos 54 1.2 christos #ifdef __FreeBSD__ 55 1.1 christos #include <machine/stdarg.h> 56 1.2 christos #endif 57 1.1 christos 58 1.1 christos #else 59 1.1 christos #include <errno.h> 60 1.1 christos #include <fcntl.h> 61 1.1 christos #include <stdarg.h> 62 1.1 christos #include <stdbool.h> 63 1.1 christos #include <stdint.h> 64 1.1 christos #include <stdlib.h> 65 1.1 christos #include <string.h> 66 1.1 christos #include <unistd.h> 67 1.1 christos 68 1.1 christos #include "common_impl.h" 69 1.1 christos #endif 70 1.1 christos 71 1.1 christos #ifdef HAVE_PJDLOG 72 1.1 christos #include <pjdlog.h> 73 1.1 christos #endif 74 1.1 christos 75 1.2 christos #ifdef __FreeBSD__ 76 1.1 christos #include <sys/nv.h> 77 1.2 christos #else 78 1.2 christos #include "nv.h" 79 1.2 christos #endif 80 1.1 christos 81 1.1 christos #include "nv_impl.h" 82 1.1 christos #include "nvlist_impl.h" 83 1.1 christos #include "nvpair_impl.h" 84 1.1 christos 85 1.1 christos #ifndef HAVE_PJDLOG 86 1.2 christos #if defined(_KERNEL) || defined(_STANDALONE) 87 1.2 christos #ifdef __FreeBSD__ 88 1.1 christos #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) 89 1.2 christos #else 90 1.2 christos #define PJDLOG_ASSERT(...) KASSERT(__VA_ARGS__) 91 1.2 christos #endif 92 1.1 christos #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) 93 1.1 christos #define PJDLOG_ABORT(...) panic(__VA_ARGS__) 94 1.1 christos #else 95 1.2 christos #ifndef __lint__ 96 1.1 christos #include <assert.h> 97 1.1 christos #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 98 1.1 christos #define PJDLOG_RASSERT(expr, ...) assert(expr) 99 1.1 christos #define PJDLOG_ABORT(...) abort() 100 1.2 christos #else 101 1.2 christos #define PJDLOG_ASSERT(...) 102 1.2 christos #define PJDLOG_RASSERT(expr, ...) 103 1.2 christos #define PJDLOG_ABORT(...) 104 1.2 christos #endif 105 1.1 christos #endif 106 1.1 christos #endif 107 1.1 christos 108 1.1 christos #define NVPAIR_MAGIC 0x6e7670 /* "nvp" */ 109 1.1 christos struct nvpair { 110 1.1 christos int nvp_magic; 111 1.1 christos char *nvp_name; 112 1.1 christos int nvp_type; 113 1.1 christos uint64_t nvp_data; 114 1.1 christos size_t nvp_datasize; 115 1.1 christos size_t nvp_nitems; /* Used only for array types. */ 116 1.1 christos nvlist_t *nvp_list; 117 1.1 christos TAILQ_ENTRY(nvpair) nvp_next; 118 1.1 christos }; 119 1.1 christos 120 1.1 christos #define NVPAIR_ASSERT(nvp) do { \ 121 1.1 christos PJDLOG_ASSERT((nvp) != NULL); \ 122 1.1 christos PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \ 123 1.2 christos } while (/*CONSTCOND*/0) 124 1.1 christos 125 1.1 christos struct nvpair_header { 126 1.1 christos uint8_t nvph_type; 127 1.1 christos uint16_t nvph_namesize; 128 1.1 christos uint64_t nvph_datasize; 129 1.1 christos uint64_t nvph_nitems; 130 1.1 christos } __packed; 131 1.1 christos 132 1.1 christos 133 1.1 christos void 134 1.1 christos nvpair_assert(const nvpair_t *nvp) 135 1.1 christos { 136 1.1 christos 137 1.1 christos NVPAIR_ASSERT(nvp); 138 1.1 christos } 139 1.1 christos 140 1.1 christos static nvpair_t * 141 1.1 christos nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize, 142 1.1 christos size_t nitems) 143 1.1 christos { 144 1.1 christos nvpair_t *nvp; 145 1.1 christos size_t namelen; 146 1.1 christos 147 1.1 christos PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); 148 1.1 christos 149 1.1 christos namelen = strlen(name); 150 1.1 christos if (namelen >= NV_NAME_MAX) { 151 1.1 christos ERRNO_SET(ENAMETOOLONG); 152 1.1 christos return (NULL); 153 1.1 christos } 154 1.1 christos 155 1.1 christos nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1); 156 1.1 christos if (nvp != NULL) { 157 1.1 christos nvp->nvp_name = (char *)(nvp + 1); 158 1.1 christos memcpy(nvp->nvp_name, name, namelen); 159 1.1 christos nvp->nvp_name[namelen] = '\0'; 160 1.1 christos nvp->nvp_type = type; 161 1.1 christos nvp->nvp_data = data; 162 1.1 christos nvp->nvp_datasize = datasize; 163 1.1 christos nvp->nvp_nitems = nitems; 164 1.1 christos nvp->nvp_magic = NVPAIR_MAGIC; 165 1.1 christos } 166 1.1 christos 167 1.1 christos return (nvp); 168 1.1 christos } 169 1.1 christos 170 1.1 christos static int 171 1.1 christos nvpair_append(nvpair_t *nvp, const void *value, size_t valsize, size_t datasize) 172 1.1 christos { 173 1.1 christos void *olddata, *data, *valp; 174 1.1 christos size_t oldlen; 175 1.1 christos 176 1.1 christos oldlen = nvp->nvp_nitems * valsize; 177 1.1 christos olddata = (void *)(uintptr_t)nvp->nvp_data; 178 1.1 christos data = nv_realloc(olddata, oldlen + valsize); 179 1.1 christos if (data == NULL) { 180 1.1 christos ERRNO_SET(ENOMEM); 181 1.1 christos return (-1); 182 1.1 christos } 183 1.1 christos valp = (unsigned char *)data + oldlen; 184 1.1 christos memcpy(valp, value, valsize); 185 1.1 christos 186 1.1 christos nvp->nvp_data = (uint64_t)(uintptr_t)data; 187 1.1 christos nvp->nvp_datasize += datasize; 188 1.1 christos nvp->nvp_nitems++; 189 1.1 christos return (0); 190 1.1 christos } 191 1.1 christos 192 1.1 christos nvlist_t * 193 1.1 christos nvpair_nvlist(const nvpair_t *nvp) 194 1.1 christos { 195 1.1 christos 196 1.1 christos NVPAIR_ASSERT(nvp); 197 1.1 christos 198 1.1 christos return (nvp->nvp_list); 199 1.1 christos } 200 1.1 christos 201 1.1 christos nvpair_t * 202 1.1 christos nvpair_next(const nvpair_t *nvp) 203 1.1 christos { 204 1.1 christos 205 1.1 christos NVPAIR_ASSERT(nvp); 206 1.1 christos PJDLOG_ASSERT(nvp->nvp_list != NULL); 207 1.1 christos 208 1.1 christos return (TAILQ_NEXT(nvp, nvp_next)); 209 1.1 christos } 210 1.1 christos 211 1.1 christos nvpair_t * 212 1.1 christos nvpair_prev(const nvpair_t *nvp) 213 1.1 christos { 214 1.1 christos 215 1.1 christos NVPAIR_ASSERT(nvp); 216 1.1 christos PJDLOG_ASSERT(nvp->nvp_list != NULL); 217 1.1 christos 218 1.1 christos return (TAILQ_PREV(nvp, nvl_head, nvp_next)); 219 1.1 christos } 220 1.1 christos 221 1.1 christos void 222 1.1 christos nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) 223 1.1 christos { 224 1.1 christos 225 1.1 christos NVPAIR_ASSERT(nvp); 226 1.1 christos PJDLOG_ASSERT(nvp->nvp_list == NULL); 227 1.1 christos PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 || 228 1.1 christos !nvlist_exists(nvl, nvpair_name(nvp))); 229 1.1 christos 230 1.1 christos TAILQ_INSERT_TAIL(head, nvp, nvp_next); 231 1.1 christos nvp->nvp_list = nvl; 232 1.1 christos } 233 1.1 christos 234 1.1 christos static void 235 1.1 christos nvpair_remove_nvlist(nvpair_t *nvp) 236 1.1 christos { 237 1.1 christos nvlist_t *nvl; 238 1.1 christos 239 1.1 christos /* XXX: DECONST is bad, mkay? */ 240 1.1 christos nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp)); 241 1.1 christos PJDLOG_ASSERT(nvl != NULL); 242 1.1 christos nvlist_set_parent(nvl, NULL); 243 1.1 christos } 244 1.1 christos 245 1.1 christos static void 246 1.1 christos nvpair_remove_nvlist_array(nvpair_t *nvp) 247 1.1 christos { 248 1.1 christos nvlist_t **nvlarray; 249 1.1 christos size_t count, i; 250 1.1 christos 251 1.1 christos /* XXX: DECONST is bad, mkay? */ 252 1.1 christos nvlarray = __DECONST(nvlist_t **, 253 1.1 christos nvpair_get_nvlist_array(nvp, &count)); 254 1.1 christos for (i = 0; i < count; i++) { 255 1.6 rmind nvlist_set_array_next(nvlarray[i], NULL); 256 1.6 rmind nvlist_set_parent(nvlarray[i], NULL); 257 1.1 christos } 258 1.1 christos } 259 1.1 christos 260 1.1 christos void 261 1.1 christos nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl) 262 1.1 christos { 263 1.1 christos 264 1.1 christos NVPAIR_ASSERT(nvp); 265 1.1 christos PJDLOG_ASSERT(nvp->nvp_list == nvl); 266 1.1 christos 267 1.1 christos if (nvpair_type(nvp) == NV_TYPE_NVLIST) 268 1.1 christos nvpair_remove_nvlist(nvp); 269 1.1 christos else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) 270 1.1 christos nvpair_remove_nvlist_array(nvp); 271 1.1 christos 272 1.1 christos TAILQ_REMOVE(head, nvp, nvp_next); 273 1.1 christos nvp->nvp_list = NULL; 274 1.1 christos } 275 1.1 christos 276 1.1 christos nvpair_t * 277 1.1 christos nvpair_clone(const nvpair_t *nvp) 278 1.1 christos { 279 1.1 christos nvpair_t *newnvp; 280 1.1 christos const char *name; 281 1.1 christos const void *data; 282 1.1 christos size_t datasize; 283 1.1 christos 284 1.1 christos NVPAIR_ASSERT(nvp); 285 1.1 christos 286 1.1 christos name = nvpair_name(nvp); 287 1.1 christos 288 1.1 christos switch (nvpair_type(nvp)) { 289 1.1 christos case NV_TYPE_NULL: 290 1.1 christos newnvp = nvpair_create_null(name); 291 1.1 christos break; 292 1.1 christos case NV_TYPE_BOOL: 293 1.1 christos newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); 294 1.1 christos break; 295 1.1 christos case NV_TYPE_NUMBER: 296 1.1 christos newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); 297 1.1 christos break; 298 1.1 christos case NV_TYPE_STRING: 299 1.1 christos newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); 300 1.1 christos break; 301 1.1 christos case NV_TYPE_NVLIST: 302 1.1 christos newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); 303 1.1 christos break; 304 1.1 christos case NV_TYPE_BINARY: 305 1.1 christos data = nvpair_get_binary(nvp, &datasize); 306 1.1 christos newnvp = nvpair_create_binary(name, data, datasize); 307 1.1 christos break; 308 1.1 christos case NV_TYPE_BOOL_ARRAY: 309 1.1 christos data = nvpair_get_bool_array(nvp, &datasize); 310 1.1 christos newnvp = nvpair_create_bool_array(name, data, datasize); 311 1.1 christos break; 312 1.1 christos case NV_TYPE_NUMBER_ARRAY: 313 1.1 christos data = nvpair_get_number_array(nvp, &datasize); 314 1.1 christos newnvp = nvpair_create_number_array(name, data, datasize); 315 1.1 christos break; 316 1.1 christos case NV_TYPE_STRING_ARRAY: 317 1.1 christos data = nvpair_get_string_array(nvp, &datasize); 318 1.1 christos newnvp = nvpair_create_string_array(name, data, datasize); 319 1.1 christos break; 320 1.1 christos case NV_TYPE_NVLIST_ARRAY: 321 1.1 christos data = nvpair_get_nvlist_array(nvp, &datasize); 322 1.1 christos newnvp = nvpair_create_nvlist_array(name, data, datasize); 323 1.1 christos break; 324 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 325 1.1 christos case NV_TYPE_DESCRIPTOR: 326 1.1 christos newnvp = nvpair_create_descriptor(name, 327 1.1 christos nvpair_get_descriptor(nvp)); 328 1.1 christos break; 329 1.1 christos case NV_TYPE_DESCRIPTOR_ARRAY: 330 1.1 christos data = nvpair_get_descriptor_array(nvp, &datasize); 331 1.1 christos newnvp = nvpair_create_descriptor_array(name, data, datasize); 332 1.1 christos break; 333 1.1 christos #endif 334 1.1 christos default: 335 1.1 christos PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 336 1.1 christos } 337 1.1 christos 338 1.1 christos return (newnvp); 339 1.1 christos } 340 1.1 christos 341 1.1 christos size_t 342 1.1 christos nvpair_header_size(void) 343 1.1 christos { 344 1.1 christos 345 1.1 christos return (sizeof(struct nvpair_header)); 346 1.1 christos } 347 1.1 christos 348 1.1 christos size_t 349 1.1 christos nvpair_size(const nvpair_t *nvp) 350 1.1 christos { 351 1.1 christos 352 1.1 christos NVPAIR_ASSERT(nvp); 353 1.1 christos 354 1.1 christos return (nvp->nvp_datasize); 355 1.1 christos } 356 1.1 christos 357 1.1 christos unsigned char * 358 1.1 christos nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 359 1.1 christos { 360 1.1 christos struct nvpair_header nvphdr; 361 1.1 christos size_t namesize; 362 1.1 christos 363 1.1 christos NVPAIR_ASSERT(nvp); 364 1.1 christos 365 1.1 christos nvphdr.nvph_type = nvp->nvp_type; 366 1.1 christos namesize = strlen(nvp->nvp_name) + 1; 367 1.1 christos PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX); 368 1.1 christos nvphdr.nvph_namesize = namesize; 369 1.1 christos nvphdr.nvph_datasize = nvp->nvp_datasize; 370 1.1 christos nvphdr.nvph_nitems = nvp->nvp_nitems; 371 1.1 christos PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 372 1.1 christos memcpy(ptr, &nvphdr, sizeof(nvphdr)); 373 1.1 christos ptr += sizeof(nvphdr); 374 1.1 christos *leftp -= sizeof(nvphdr); 375 1.1 christos 376 1.1 christos PJDLOG_ASSERT(*leftp >= namesize); 377 1.1 christos memcpy(ptr, nvp->nvp_name, namesize); 378 1.1 christos ptr += namesize; 379 1.1 christos *leftp -= namesize; 380 1.1 christos 381 1.1 christos return (ptr); 382 1.1 christos } 383 1.1 christos 384 1.1 christos unsigned char * 385 1.1 christos nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr, 386 1.1 christos size_t *leftp __unused) 387 1.1 christos { 388 1.1 christos 389 1.1 christos NVPAIR_ASSERT(nvp); 390 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 391 1.1 christos 392 1.1 christos return (ptr); 393 1.1 christos } 394 1.1 christos 395 1.1 christos unsigned char * 396 1.1 christos nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 397 1.1 christos { 398 1.1 christos uint8_t value; 399 1.1 christos 400 1.1 christos NVPAIR_ASSERT(nvp); 401 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 402 1.1 christos 403 1.1 christos value = (uint8_t)nvp->nvp_data; 404 1.1 christos 405 1.1 christos PJDLOG_ASSERT(*leftp >= sizeof(value)); 406 1.1 christos memcpy(ptr, &value, sizeof(value)); 407 1.1 christos ptr += sizeof(value); 408 1.1 christos *leftp -= sizeof(value); 409 1.1 christos 410 1.1 christos return (ptr); 411 1.1 christos } 412 1.1 christos 413 1.1 christos unsigned char * 414 1.1 christos nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 415 1.1 christos { 416 1.1 christos uint64_t value; 417 1.1 christos 418 1.1 christos NVPAIR_ASSERT(nvp); 419 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 420 1.1 christos 421 1.1 christos value = (uint64_t)nvp->nvp_data; 422 1.1 christos 423 1.1 christos PJDLOG_ASSERT(*leftp >= sizeof(value)); 424 1.1 christos memcpy(ptr, &value, sizeof(value)); 425 1.1 christos ptr += sizeof(value); 426 1.1 christos *leftp -= sizeof(value); 427 1.1 christos 428 1.1 christos return (ptr); 429 1.1 christos } 430 1.1 christos 431 1.1 christos unsigned char * 432 1.1 christos nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 433 1.1 christos { 434 1.1 christos 435 1.1 christos NVPAIR_ASSERT(nvp); 436 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 437 1.1 christos 438 1.1 christos PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 439 1.1 christos memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 440 1.1 christos ptr += nvp->nvp_datasize; 441 1.1 christos *leftp -= nvp->nvp_datasize; 442 1.1 christos 443 1.1 christos return (ptr); 444 1.1 christos } 445 1.1 christos 446 1.1 christos unsigned char * 447 1.1 christos nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp) 448 1.1 christos { 449 1.1 christos struct nvpair_header nvphdr; 450 1.1 christos size_t namesize; 451 1.1 christos const char *name = ""; 452 1.1 christos 453 1.1 christos namesize = 1; 454 1.1 christos nvphdr.nvph_type = NV_TYPE_NVLIST_UP; 455 1.1 christos nvphdr.nvph_namesize = namesize; 456 1.1 christos nvphdr.nvph_datasize = 0; 457 1.1 christos nvphdr.nvph_nitems = 0; 458 1.1 christos PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 459 1.1 christos memcpy(ptr, &nvphdr, sizeof(nvphdr)); 460 1.1 christos ptr += sizeof(nvphdr); 461 1.1 christos *leftp -= sizeof(nvphdr); 462 1.1 christos 463 1.1 christos PJDLOG_ASSERT(*leftp >= namesize); 464 1.1 christos memcpy(ptr, name, namesize); 465 1.1 christos ptr += namesize; 466 1.1 christos *leftp -= namesize; 467 1.1 christos 468 1.1 christos return (ptr); 469 1.1 christos } 470 1.1 christos 471 1.1 christos unsigned char * 472 1.1 christos nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp) 473 1.1 christos { 474 1.1 christos struct nvpair_header nvphdr; 475 1.1 christos size_t namesize; 476 1.1 christos const char *name = ""; 477 1.1 christos 478 1.1 christos namesize = 1; 479 1.1 christos nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT; 480 1.1 christos nvphdr.nvph_namesize = namesize; 481 1.1 christos nvphdr.nvph_datasize = 0; 482 1.1 christos nvphdr.nvph_nitems = 0; 483 1.1 christos PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); 484 1.1 christos memcpy(ptr, &nvphdr, sizeof(nvphdr)); 485 1.1 christos ptr += sizeof(nvphdr); 486 1.1 christos *leftp -= sizeof(nvphdr); 487 1.1 christos 488 1.1 christos PJDLOG_ASSERT(*leftp >= namesize); 489 1.1 christos memcpy(ptr, name, namesize); 490 1.1 christos ptr += namesize; 491 1.1 christos *leftp -= namesize; 492 1.1 christos 493 1.1 christos return (ptr); 494 1.1 christos } 495 1.1 christos 496 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 497 1.1 christos unsigned char * 498 1.1 christos nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, 499 1.1 christos size_t *leftp) 500 1.1 christos { 501 1.1 christos int64_t value; 502 1.1 christos 503 1.1 christos NVPAIR_ASSERT(nvp); 504 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 505 1.1 christos 506 1.1 christos value = (int64_t)nvp->nvp_data; 507 1.1 christos if (value != -1) { 508 1.1 christos /* 509 1.1 christos * If there is a real descriptor here, we change its number 510 1.1 christos * to position in the array of descriptors send via control 511 1.1 christos * message. 512 1.1 christos */ 513 1.1 christos PJDLOG_ASSERT(fdidxp != NULL); 514 1.1 christos 515 1.1 christos value = *fdidxp; 516 1.1 christos (*fdidxp)++; 517 1.1 christos } 518 1.1 christos 519 1.1 christos PJDLOG_ASSERT(*leftp >= sizeof(value)); 520 1.1 christos memcpy(ptr, &value, sizeof(value)); 521 1.1 christos ptr += sizeof(value); 522 1.1 christos *leftp -= sizeof(value); 523 1.1 christos 524 1.1 christos return (ptr); 525 1.1 christos } 526 1.1 christos #endif 527 1.1 christos 528 1.1 christos unsigned char * 529 1.1 christos nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 530 1.1 christos { 531 1.1 christos 532 1.1 christos NVPAIR_ASSERT(nvp); 533 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 534 1.1 christos 535 1.1 christos PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 536 1.1 christos memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 537 1.1 christos ptr += nvp->nvp_datasize; 538 1.1 christos *leftp -= nvp->nvp_datasize; 539 1.1 christos 540 1.1 christos return (ptr); 541 1.1 christos } 542 1.1 christos 543 1.1 christos unsigned char * 544 1.1 christos nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 545 1.1 christos { 546 1.1 christos 547 1.1 christos NVPAIR_ASSERT(nvp); 548 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 549 1.1 christos PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 550 1.1 christos 551 1.1 christos memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 552 1.1 christos ptr += nvp->nvp_datasize; 553 1.1 christos *leftp -= nvp->nvp_datasize; 554 1.1 christos 555 1.1 christos return (ptr); 556 1.1 christos } 557 1.1 christos 558 1.1 christos unsigned char * 559 1.1 christos nvpair_pack_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 560 1.1 christos { 561 1.1 christos 562 1.1 christos NVPAIR_ASSERT(nvp); 563 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 564 1.1 christos PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 565 1.1 christos 566 1.1 christos memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); 567 1.1 christos ptr += nvp->nvp_datasize; 568 1.1 christos *leftp -= nvp->nvp_datasize; 569 1.1 christos 570 1.1 christos return (ptr); 571 1.1 christos } 572 1.1 christos 573 1.1 christos unsigned char * 574 1.1 christos nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) 575 1.1 christos { 576 1.1 christos unsigned int ii; 577 1.1 christos size_t size, len; 578 1.1 christos const char * const *array; 579 1.1 christos 580 1.1 christos NVPAIR_ASSERT(nvp); 581 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 582 1.1 christos PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 583 1.1 christos 584 1.1 christos size = 0; 585 1.1 christos array = nvpair_get_string_array(nvp, NULL); 586 1.1 christos PJDLOG_ASSERT(array != NULL); 587 1.1 christos 588 1.1 christos for (ii = 0; ii < nvp->nvp_nitems; ii++) { 589 1.1 christos len = strlen(array[ii]) + 1; 590 1.1 christos PJDLOG_ASSERT(*leftp >= len); 591 1.1 christos 592 1.1 christos memcpy(ptr, (const void *)array[ii], len); 593 1.1 christos size += len; 594 1.1 christos ptr += len; 595 1.1 christos *leftp -= len; 596 1.1 christos } 597 1.1 christos 598 1.1 christos PJDLOG_ASSERT(size == nvp->nvp_datasize); 599 1.1 christos 600 1.1 christos return (ptr); 601 1.1 christos } 602 1.1 christos 603 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 604 1.1 christos unsigned char * 605 1.1 christos nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr, 606 1.1 christos int64_t *fdidxp, size_t *leftp) 607 1.1 christos { 608 1.1 christos int64_t value; 609 1.1 christos const int *array; 610 1.1 christos unsigned int ii; 611 1.1 christos 612 1.1 christos NVPAIR_ASSERT(nvp); 613 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 614 1.1 christos PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); 615 1.1 christos 616 1.1 christos array = nvpair_get_descriptor_array(nvp, NULL); 617 1.1 christos PJDLOG_ASSERT(array != NULL); 618 1.1 christos 619 1.1 christos for (ii = 0; ii < nvp->nvp_nitems; ii++) { 620 1.1 christos PJDLOG_ASSERT(*leftp >= sizeof(value)); 621 1.1 christos 622 1.1 christos value = array[ii]; 623 1.1 christos if (value != -1) { 624 1.1 christos /* 625 1.1 christos * If there is a real descriptor here, we change its 626 1.1 christos * number to position in the array of descriptors send 627 1.1 christos * via control message. 628 1.1 christos */ 629 1.1 christos PJDLOG_ASSERT(fdidxp != NULL); 630 1.1 christos 631 1.1 christos value = *fdidxp; 632 1.1 christos (*fdidxp)++; 633 1.1 christos } 634 1.1 christos memcpy(ptr, &value, sizeof(value)); 635 1.1 christos ptr += sizeof(value); 636 1.1 christos *leftp -= sizeof(value); 637 1.1 christos } 638 1.1 christos 639 1.1 christos return (ptr); 640 1.1 christos } 641 1.1 christos #endif 642 1.1 christos 643 1.1 christos void 644 1.1 christos nvpair_init_datasize(nvpair_t *nvp) 645 1.1 christos { 646 1.1 christos 647 1.1 christos NVPAIR_ASSERT(nvp); 648 1.1 christos 649 1.1 christos if (nvp->nvp_type == NV_TYPE_NVLIST) { 650 1.1 christos if (nvp->nvp_data == 0) { 651 1.1 christos nvp->nvp_datasize = 0; 652 1.1 christos } else { 653 1.1 christos nvp->nvp_datasize = 654 1.1 christos nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); 655 1.1 christos } 656 1.1 christos } 657 1.1 christos } 658 1.1 christos 659 1.1 christos const unsigned char * 660 1.1 christos nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 661 1.1 christos size_t *leftp) 662 1.1 christos { 663 1.1 christos struct nvpair_header nvphdr; 664 1.1 christos 665 1.1 christos if (*leftp < sizeof(nvphdr)) 666 1.1 christos goto fail; 667 1.1 christos 668 1.1 christos memcpy(&nvphdr, ptr, sizeof(nvphdr)); 669 1.1 christos ptr += sizeof(nvphdr); 670 1.1 christos *leftp -= sizeof(nvphdr); 671 1.1 christos 672 1.1 christos #if NV_TYPE_FIRST > 0 673 1.1 christos if (nvphdr.nvph_type < NV_TYPE_FIRST) 674 1.1 christos goto fail; 675 1.1 christos #endif 676 1.1 christos if (nvphdr.nvph_type > NV_TYPE_LAST && 677 1.1 christos nvphdr.nvph_type != NV_TYPE_NVLIST_UP && 678 1.1 christos nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) { 679 1.1 christos goto fail; 680 1.1 christos } 681 1.1 christos 682 1.1 christos #if BYTE_ORDER == BIG_ENDIAN 683 1.1 christos if (!isbe) { 684 1.1 christos nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize); 685 1.1 christos nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize); 686 1.1 christos } 687 1.1 christos #else 688 1.1 christos if (isbe) { 689 1.1 christos nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); 690 1.1 christos nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); 691 1.1 christos } 692 1.1 christos #endif 693 1.1 christos 694 1.1 christos if (nvphdr.nvph_namesize > NV_NAME_MAX) 695 1.1 christos goto fail; 696 1.1 christos if (*leftp < nvphdr.nvph_namesize) 697 1.1 christos goto fail; 698 1.1 christos if (nvphdr.nvph_namesize < 1) 699 1.1 christos goto fail; 700 1.1 christos if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != 701 1.1 christos (size_t)(nvphdr.nvph_namesize - 1)) { 702 1.1 christos goto fail; 703 1.1 christos } 704 1.1 christos 705 1.1 christos memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); 706 1.1 christos ptr += nvphdr.nvph_namesize; 707 1.1 christos *leftp -= nvphdr.nvph_namesize; 708 1.1 christos 709 1.1 christos if (*leftp < nvphdr.nvph_datasize) 710 1.1 christos goto fail; 711 1.1 christos 712 1.1 christos nvp->nvp_type = nvphdr.nvph_type; 713 1.1 christos nvp->nvp_data = 0; 714 1.1 christos nvp->nvp_datasize = nvphdr.nvph_datasize; 715 1.1 christos nvp->nvp_nitems = nvphdr.nvph_nitems; 716 1.1 christos 717 1.1 christos return (ptr); 718 1.1 christos fail: 719 1.1 christos ERRNO_SET(EINVAL); 720 1.1 christos return (NULL); 721 1.1 christos } 722 1.1 christos 723 1.1 christos const unsigned char * 724 1.1 christos nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, 725 1.1 christos size_t *leftp __unused) 726 1.1 christos { 727 1.1 christos 728 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); 729 1.1 christos 730 1.1 christos if (nvp->nvp_datasize != 0) { 731 1.1 christos ERRNO_SET(EINVAL); 732 1.1 christos return (NULL); 733 1.1 christos } 734 1.1 christos 735 1.1 christos return (ptr); 736 1.1 christos } 737 1.1 christos 738 1.1 christos const unsigned char * 739 1.1 christos nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, 740 1.1 christos size_t *leftp) 741 1.1 christos { 742 1.1 christos uint8_t value; 743 1.1 christos 744 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); 745 1.1 christos 746 1.1 christos if (nvp->nvp_datasize != sizeof(value)) { 747 1.1 christos ERRNO_SET(EINVAL); 748 1.1 christos return (NULL); 749 1.1 christos } 750 1.1 christos if (*leftp < sizeof(value)) { 751 1.1 christos ERRNO_SET(EINVAL); 752 1.1 christos return (NULL); 753 1.1 christos } 754 1.1 christos 755 1.1 christos memcpy(&value, ptr, sizeof(value)); 756 1.1 christos ptr += sizeof(value); 757 1.1 christos *leftp -= sizeof(value); 758 1.1 christos 759 1.1 christos if (value != 0 && value != 1) { 760 1.1 christos ERRNO_SET(EINVAL); 761 1.1 christos return (NULL); 762 1.1 christos } 763 1.1 christos 764 1.1 christos nvp->nvp_data = (uint64_t)value; 765 1.1 christos 766 1.1 christos return (ptr); 767 1.1 christos } 768 1.1 christos 769 1.1 christos const unsigned char * 770 1.1 christos nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 771 1.1 christos size_t *leftp) 772 1.1 christos { 773 1.1 christos 774 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); 775 1.1 christos 776 1.1 christos if (nvp->nvp_datasize != sizeof(uint64_t)) { 777 1.1 christos ERRNO_SET(EINVAL); 778 1.1 christos return (NULL); 779 1.1 christos } 780 1.1 christos if (*leftp < sizeof(uint64_t)) { 781 1.1 christos ERRNO_SET(EINVAL); 782 1.1 christos return (NULL); 783 1.1 christos } 784 1.1 christos 785 1.1 christos if (isbe) 786 1.1 christos nvp->nvp_data = be64dec(ptr); 787 1.1 christos else 788 1.1 christos nvp->nvp_data = le64dec(ptr); 789 1.1 christos 790 1.1 christos ptr += sizeof(uint64_t); 791 1.1 christos *leftp -= sizeof(uint64_t); 792 1.1 christos 793 1.1 christos return (ptr); 794 1.1 christos } 795 1.1 christos 796 1.1 christos const unsigned char * 797 1.1 christos nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp, 798 1.1 christos const unsigned char *ptr, size_t *leftp) 799 1.1 christos { 800 1.1 christos 801 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 802 1.1 christos 803 1.1 christos if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 804 1.1 christos ERRNO_SET(EINVAL); 805 1.1 christos return (NULL); 806 1.1 christos } 807 1.1 christos 808 1.1 christos if (strnlen((const char *)ptr, nvp->nvp_datasize) != 809 1.1 christos nvp->nvp_datasize - 1) { 810 1.1 christos ERRNO_SET(EINVAL); 811 1.1 christos return (NULL); 812 1.1 christos } 813 1.1 christos 814 1.1 christos nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr); 815 1.1 christos if (nvp->nvp_data == 0) 816 1.1 christos return (NULL); 817 1.1 christos 818 1.1 christos ptr += nvp->nvp_datasize; 819 1.1 christos *leftp -= nvp->nvp_datasize; 820 1.1 christos 821 1.1 christos return (ptr); 822 1.1 christos } 823 1.1 christos 824 1.1 christos const unsigned char * 825 1.1 christos nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp, 826 1.1 christos const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child) 827 1.1 christos { 828 1.1 christos nvlist_t *value; 829 1.1 christos 830 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 831 1.1 christos 832 1.1 christos if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 833 1.1 christos ERRNO_SET(EINVAL); 834 1.1 christos return (NULL); 835 1.1 christos } 836 1.1 christos 837 1.1 christos value = nvlist_create(0); 838 1.1 christos if (value == NULL) 839 1.1 christos return (NULL); 840 1.1 christos 841 1.1 christos ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp); 842 1.1 christos if (ptr == NULL) 843 1.1 christos return (NULL); 844 1.1 christos 845 1.1 christos nvp->nvp_data = (uint64_t)(uintptr_t)value; 846 1.1 christos *child = value; 847 1.1 christos 848 1.1 christos return (ptr); 849 1.1 christos } 850 1.1 christos 851 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 852 1.1 christos const unsigned char * 853 1.1 christos nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 854 1.1 christos size_t *leftp, const int *fds, size_t nfds) 855 1.1 christos { 856 1.1 christos int64_t idx; 857 1.1 christos 858 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 859 1.1 christos 860 1.1 christos if (nvp->nvp_datasize != sizeof(idx)) { 861 1.1 christos ERRNO_SET(EINVAL); 862 1.1 christos return (NULL); 863 1.1 christos } 864 1.1 christos if (*leftp < sizeof(idx)) { 865 1.1 christos ERRNO_SET(EINVAL); 866 1.1 christos return (NULL); 867 1.1 christos } 868 1.1 christos 869 1.1 christos if (isbe) 870 1.1 christos idx = be64dec(ptr); 871 1.1 christos else 872 1.1 christos idx = le64dec(ptr); 873 1.1 christos 874 1.1 christos if (idx < 0) { 875 1.1 christos ERRNO_SET(EINVAL); 876 1.1 christos return (NULL); 877 1.1 christos } 878 1.1 christos 879 1.1 christos if ((size_t)idx >= nfds) { 880 1.1 christos ERRNO_SET(EINVAL); 881 1.1 christos return (NULL); 882 1.1 christos } 883 1.1 christos 884 1.1 christos nvp->nvp_data = (uint64_t)fds[idx]; 885 1.1 christos 886 1.1 christos ptr += sizeof(idx); 887 1.1 christos *leftp -= sizeof(idx); 888 1.1 christos 889 1.1 christos return (ptr); 890 1.1 christos } 891 1.1 christos #endif 892 1.1 christos 893 1.1 christos const unsigned char * 894 1.1 christos nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp, 895 1.1 christos const unsigned char *ptr, size_t *leftp) 896 1.1 christos { 897 1.1 christos void *value; 898 1.1 christos 899 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 900 1.1 christos 901 1.1 christos if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { 902 1.1 christos ERRNO_SET(EINVAL); 903 1.1 christos return (NULL); 904 1.1 christos } 905 1.1 christos 906 1.1 christos value = nv_malloc(nvp->nvp_datasize); 907 1.1 christos if (value == NULL) 908 1.1 christos return (NULL); 909 1.1 christos 910 1.1 christos memcpy(value, ptr, nvp->nvp_datasize); 911 1.1 christos ptr += nvp->nvp_datasize; 912 1.1 christos *leftp -= nvp->nvp_datasize; 913 1.1 christos 914 1.1 christos nvp->nvp_data = (uint64_t)(uintptr_t)value; 915 1.1 christos 916 1.1 christos return (ptr); 917 1.1 christos } 918 1.1 christos 919 1.1 christos const unsigned char * 920 1.1 christos nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp, 921 1.1 christos const unsigned char *ptr, size_t *leftp) 922 1.1 christos { 923 1.1 christos uint8_t *value; 924 1.1 christos size_t size; 925 1.1 christos unsigned int i; 926 1.1 christos 927 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 928 1.1 christos 929 1.1 christos size = sizeof(*value) * nvp->nvp_nitems; 930 1.1 christos if (nvp->nvp_datasize != size || *leftp < size || 931 1.1 christos nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 932 1.1 christos ERRNO_SET(EINVAL); 933 1.1 christos return (NULL); 934 1.1 christos } 935 1.1 christos 936 1.1 christos value = nv_malloc(size); 937 1.1 christos if (value == NULL) 938 1.1 christos return (NULL); 939 1.1 christos 940 1.1 christos for (i = 0; i < nvp->nvp_nitems; i++) { 941 1.1 christos value[i] = *(const uint8_t *)ptr; 942 1.1 christos 943 1.1 christos ptr += sizeof(*value); 944 1.1 christos *leftp -= sizeof(*value); 945 1.1 christos } 946 1.1 christos 947 1.1 christos nvp->nvp_data = (uint64_t)(uintptr_t)value; 948 1.1 christos 949 1.1 christos return (ptr); 950 1.1 christos } 951 1.1 christos 952 1.1 christos const unsigned char * 953 1.1 christos nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr, 954 1.1 christos size_t *leftp) 955 1.1 christos { 956 1.1 christos uint64_t *value; 957 1.1 christos size_t size; 958 1.1 christos unsigned int i; 959 1.1 christos 960 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 961 1.1 christos 962 1.1 christos size = sizeof(*value) * nvp->nvp_nitems; 963 1.1 christos if (nvp->nvp_datasize != size || *leftp < size || 964 1.1 christos nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 965 1.1 christos ERRNO_SET(EINVAL); 966 1.1 christos return (NULL); 967 1.1 christos } 968 1.1 christos 969 1.1 christos value = nv_malloc(size); 970 1.1 christos if (value == NULL) 971 1.1 christos return (NULL); 972 1.1 christos 973 1.1 christos for (i = 0; i < nvp->nvp_nitems; i++) { 974 1.1 christos if (isbe) 975 1.1 christos value[i] = be64dec(ptr); 976 1.1 christos else 977 1.1 christos value[i] = le64dec(ptr); 978 1.1 christos 979 1.1 christos ptr += sizeof(*value); 980 1.1 christos *leftp -= sizeof(*value); 981 1.1 christos } 982 1.1 christos 983 1.1 christos nvp->nvp_data = (uint64_t)(uintptr_t)value; 984 1.1 christos 985 1.1 christos return (ptr); 986 1.1 christos } 987 1.1 christos 988 1.1 christos const unsigned char * 989 1.1 christos nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp, 990 1.1 christos const unsigned char *ptr, size_t *leftp) 991 1.1 christos { 992 1.1 christos ssize_t size; 993 1.1 christos size_t len; 994 1.1 christos const char *tmp; 995 1.1 christos char **value; 996 1.1 christos unsigned int ii, j; 997 1.1 christos 998 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 999 1.1 christos 1000 1.1 christos if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 || 1001 1.1 christos nvp->nvp_nitems == 0) { 1002 1.1 christos ERRNO_SET(EINVAL); 1003 1.1 christos return (NULL); 1004 1.1 christos } 1005 1.1 christos 1006 1.1 christos size = nvp->nvp_datasize; 1007 1.1 christos tmp = (const char *)ptr; 1008 1.1 christos for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1009 1.1 christos len = strnlen(tmp, size - 1) + 1; 1010 1.1 christos size -= len; 1011 1.13 riastrad if (tmp[len - 1] != '\0') { 1012 1.13 riastrad ERRNO_SET(EINVAL); 1013 1.13 riastrad return (NULL); 1014 1.13 riastrad } 1015 1.1 christos if (size < 0) { 1016 1.1 christos ERRNO_SET(EINVAL); 1017 1.1 christos return (NULL); 1018 1.1 christos } 1019 1.1 christos tmp += len; 1020 1.1 christos } 1021 1.1 christos if (size != 0) { 1022 1.1 christos ERRNO_SET(EINVAL); 1023 1.1 christos return (NULL); 1024 1.1 christos } 1025 1.1 christos 1026 1.12 riastrad value = nv_calloc(nvp->nvp_nitems, sizeof(*value)); 1027 1.1 christos if (value == NULL) 1028 1.1 christos return (NULL); 1029 1.1 christos 1030 1.1 christos for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1031 1.1 christos value[ii] = nv_strdup((const char *)ptr); 1032 1.1 christos if (value[ii] == NULL) 1033 1.1 christos goto out; 1034 1.1 christos len = strlen(value[ii]) + 1; 1035 1.1 christos ptr += len; 1036 1.1 christos *leftp -= len; 1037 1.1 christos } 1038 1.1 christos nvp->nvp_data = (uint64_t)(uintptr_t)value; 1039 1.1 christos 1040 1.1 christos return (ptr); 1041 1.1 christos out: 1042 1.1 christos for (j = 0; j < ii; j++) 1043 1.1 christos nv_free(value[j]); 1044 1.1 christos nv_free(value); 1045 1.1 christos return (NULL); 1046 1.1 christos } 1047 1.1 christos 1048 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) && !defined(__NetBSD__) 1049 1.1 christos const unsigned char * 1050 1.1 christos nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp, 1051 1.1 christos const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds) 1052 1.1 christos { 1053 1.1 christos int64_t idx; 1054 1.1 christos size_t size; 1055 1.1 christos unsigned int ii; 1056 1.1 christos int *array; 1057 1.1 christos 1058 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 1059 1.1 christos 1060 1.1 christos size = sizeof(idx) * nvp->nvp_nitems; 1061 1.1 christos if (nvp->nvp_datasize != size || *leftp < size || 1062 1.1 christos nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { 1063 1.1 christos ERRNO_SET(EINVAL); 1064 1.1 christos return (NULL); 1065 1.1 christos } 1066 1.1 christos 1067 1.1 christos array = (int *)nv_malloc(size); 1068 1.1 christos if (array == NULL) 1069 1.1 christos return (NULL); 1070 1.1 christos 1071 1.1 christos for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1072 1.1 christos if (isbe) 1073 1.1 christos idx = be64dec(ptr); 1074 1.1 christos else 1075 1.1 christos idx = le64dec(ptr); 1076 1.1 christos 1077 1.1 christos if (idx < 0) { 1078 1.1 christos ERRNO_SET(EINVAL); 1079 1.1 christos nv_free(array); 1080 1.1 christos return (NULL); 1081 1.1 christos } 1082 1.1 christos 1083 1.1 christos if ((size_t)idx >= nfds) { 1084 1.1 christos ERRNO_SET(EINVAL); 1085 1.1 christos nv_free(array); 1086 1.1 christos return (NULL); 1087 1.1 christos } 1088 1.1 christos 1089 1.1 christos array[ii] = (uint64_t)fds[idx]; 1090 1.1 christos 1091 1.1 christos ptr += sizeof(idx); 1092 1.1 christos *leftp -= sizeof(idx); 1093 1.1 christos } 1094 1.1 christos 1095 1.1 christos nvp->nvp_data = (uint64_t)(uintptr_t)array; 1096 1.1 christos 1097 1.1 christos return (ptr); 1098 1.1 christos } 1099 1.1 christos #endif 1100 1.1 christos 1101 1.1 christos const unsigned char * 1102 1.1 christos nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp, 1103 1.1 christos const unsigned char *ptr, size_t *leftp, nvlist_t **firstel) 1104 1.1 christos { 1105 1.1 christos nvlist_t **value; 1106 1.1 christos nvpair_t *tmpnvp; 1107 1.1 christos unsigned int ii, j; 1108 1.1 christos size_t sizeup; 1109 1.1 christos 1110 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1111 1.1 christos 1112 1.1 christos sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems; 1113 1.1 christos if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems || 1114 1.1 christos sizeup > *leftp) { 1115 1.1 christos ERRNO_SET(EINVAL); 1116 1.1 christos return (NULL); 1117 1.1 christos } 1118 1.1 christos 1119 1.12 riastrad value = nv_calloc(nvp->nvp_nitems, sizeof(*value)); 1120 1.1 christos if (value == NULL) 1121 1.1 christos return (NULL); 1122 1.1 christos 1123 1.1 christos for (ii = 0; ii < nvp->nvp_nitems; ii++) { 1124 1.1 christos value[ii] = nvlist_create(0); 1125 1.1 christos if (value[ii] == NULL) 1126 1.1 christos goto fail; 1127 1.1 christos if (ii > 0) { 1128 1.1 christos tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1129 1.1 christos (uint64_t)(uintptr_t)value[ii], 0, 0); 1130 1.1 christos if (tmpnvp == NULL) 1131 1.1 christos goto fail; 1132 1.1 christos nvlist_set_array_next(value[ii - 1], tmpnvp); 1133 1.1 christos } 1134 1.1 christos } 1135 1.1 christos nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY); 1136 1.1 christos 1137 1.1 christos nvp->nvp_data = (uint64_t)(uintptr_t)value; 1138 1.1 christos *firstel = value[0]; 1139 1.1 christos 1140 1.1 christos return (ptr); 1141 1.1 christos fail: 1142 1.1 christos ERRNO_SAVE(); 1143 1.1 christos for (j = 0; j <= ii; j++) 1144 1.1 christos nvlist_destroy(value[j]); 1145 1.1 christos nv_free(value); 1146 1.1 christos ERRNO_RESTORE(); 1147 1.1 christos 1148 1.1 christos return (NULL); 1149 1.1 christos } 1150 1.1 christos 1151 1.1 christos const unsigned char * 1152 1.1 christos nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, 1153 1.1 christos nvpair_t **nvpp) 1154 1.1 christos { 1155 1.1 christos nvpair_t *nvp, *tmp; 1156 1.1 christos 1157 1.1 christos nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); 1158 1.1 christos if (nvp == NULL) 1159 1.1 christos return (NULL); 1160 1.1 christos nvp->nvp_name = (char *)(nvp + 1); 1161 1.1 christos 1162 1.1 christos ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); 1163 1.1 christos if (ptr == NULL) 1164 1.1 christos goto fail; 1165 1.1 christos tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); 1166 1.1 christos if (tmp == NULL) 1167 1.1 christos goto fail; 1168 1.1 christos nvp = tmp; 1169 1.1 christos 1170 1.1 christos /* Update nvp_name after realloc(). */ 1171 1.1 christos nvp->nvp_name = (char *)(nvp + 1); 1172 1.1 christos nvp->nvp_data = 0x00; 1173 1.1 christos nvp->nvp_magic = NVPAIR_MAGIC; 1174 1.1 christos *nvpp = nvp; 1175 1.1 christos return (ptr); 1176 1.1 christos fail: 1177 1.1 christos nv_free(nvp); 1178 1.1 christos return (NULL); 1179 1.1 christos } 1180 1.1 christos 1181 1.1 christos int 1182 1.1 christos nvpair_type(const nvpair_t *nvp) 1183 1.1 christos { 1184 1.1 christos 1185 1.1 christos NVPAIR_ASSERT(nvp); 1186 1.1 christos 1187 1.1 christos return (nvp->nvp_type); 1188 1.1 christos } 1189 1.1 christos 1190 1.1 christos const char * 1191 1.1 christos nvpair_name(const nvpair_t *nvp) 1192 1.1 christos { 1193 1.1 christos 1194 1.1 christos NVPAIR_ASSERT(nvp); 1195 1.1 christos 1196 1.1 christos return (nvp->nvp_name); 1197 1.1 christos } 1198 1.1 christos 1199 1.7 rmind #if !defined(_STANDALONE) 1200 1.1 christos nvpair_t * 1201 1.1 christos nvpair_create_stringf(const char *name, const char *valuefmt, ...) 1202 1.1 christos { 1203 1.1 christos va_list valueap; 1204 1.1 christos nvpair_t *nvp; 1205 1.1 christos 1206 1.1 christos va_start(valueap, valuefmt); 1207 1.1 christos nvp = nvpair_create_stringv(name, valuefmt, valueap); 1208 1.1 christos va_end(valueap); 1209 1.1 christos 1210 1.1 christos return (nvp); 1211 1.1 christos } 1212 1.1 christos 1213 1.1 christos nvpair_t * 1214 1.1 christos nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) 1215 1.1 christos { 1216 1.1 christos nvpair_t *nvp; 1217 1.1 christos char *str; 1218 1.1 christos int len; 1219 1.1 christos 1220 1.7 rmind len = vasprintf(&str, valuefmt, valueap); 1221 1.1 christos if (len < 0) 1222 1.1 christos return (NULL); 1223 1.1 christos nvp = nvpair_create_string(name, str); 1224 1.11 martin nv_kmem_free(str, len+1); 1225 1.1 christos return (nvp); 1226 1.1 christos } 1227 1.3 christos #endif 1228 1.1 christos 1229 1.1 christos nvpair_t * 1230 1.1 christos nvpair_create_null(const char *name) 1231 1.1 christos { 1232 1.1 christos 1233 1.1 christos return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0)); 1234 1.1 christos } 1235 1.1 christos 1236 1.1 christos nvpair_t * 1237 1.1 christos nvpair_create_bool(const char *name, bool value) 1238 1.1 christos { 1239 1.1 christos 1240 1.1 christos return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0, 1241 1.1 christos sizeof(uint8_t), 0)); 1242 1.1 christos } 1243 1.1 christos 1244 1.1 christos nvpair_t * 1245 1.1 christos nvpair_create_number(const char *name, uint64_t value) 1246 1.1 christos { 1247 1.1 christos 1248 1.1 christos return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0)); 1249 1.1 christos } 1250 1.1 christos 1251 1.1 christos nvpair_t * 1252 1.1 christos nvpair_create_string(const char *name, const char *value) 1253 1.1 christos { 1254 1.1 christos nvpair_t *nvp; 1255 1.1 christos size_t size; 1256 1.1 christos char *data; 1257 1.1 christos 1258 1.1 christos if (value == NULL) { 1259 1.1 christos ERRNO_SET(EINVAL); 1260 1.1 christos return (NULL); 1261 1.1 christos } 1262 1.1 christos 1263 1.1 christos data = nv_strdup(value); 1264 1.1 christos if (data == NULL) 1265 1.1 christos return (NULL); 1266 1.1 christos size = strlen(value) + 1; 1267 1.1 christos 1268 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data, 1269 1.1 christos size, 0); 1270 1.1 christos if (nvp == NULL) 1271 1.1 christos nv_free(data); 1272 1.1 christos 1273 1.1 christos return (nvp); 1274 1.1 christos } 1275 1.1 christos 1276 1.1 christos nvpair_t * 1277 1.1 christos nvpair_create_nvlist(const char *name, const nvlist_t *value) 1278 1.1 christos { 1279 1.1 christos nvlist_t *nvl; 1280 1.1 christos nvpair_t *nvp; 1281 1.1 christos 1282 1.1 christos if (value == NULL) { 1283 1.1 christos ERRNO_SET(EINVAL); 1284 1.1 christos return (NULL); 1285 1.1 christos } 1286 1.1 christos 1287 1.1 christos nvl = nvlist_clone(value); 1288 1.1 christos if (nvl == NULL) 1289 1.1 christos return (NULL); 1290 1.1 christos 1291 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 1292 1.1 christos 0); 1293 1.1 christos if (nvp == NULL) 1294 1.1 christos nvlist_destroy(nvl); 1295 1.1 christos else 1296 1.1 christos nvlist_set_parent(nvl, nvp); 1297 1.1 christos 1298 1.1 christos return (nvp); 1299 1.1 christos } 1300 1.1 christos 1301 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1302 1.1 christos nvpair_t * 1303 1.1 christos nvpair_create_descriptor(const char *name, int value) 1304 1.1 christos { 1305 1.1 christos nvpair_t *nvp; 1306 1.1 christos 1307 1.1 christos if (value < 0 || !fd_is_valid(value)) { 1308 1.1 christos ERRNO_SET(EBADF); 1309 1.1 christos return (NULL); 1310 1.1 christos } 1311 1.1 christos 1312 1.1 christos value = fcntl(value, F_DUPFD_CLOEXEC, 0); 1313 1.1 christos if (value < 0) 1314 1.1 christos return (NULL); 1315 1.1 christos 1316 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1317 1.1 christos sizeof(int64_t), 0); 1318 1.1 christos if (nvp == NULL) { 1319 1.1 christos ERRNO_SAVE(); 1320 1.1 christos close(value); 1321 1.1 christos ERRNO_RESTORE(); 1322 1.1 christos } 1323 1.1 christos 1324 1.1 christos return (nvp); 1325 1.1 christos } 1326 1.1 christos #endif 1327 1.1 christos 1328 1.1 christos nvpair_t * 1329 1.1 christos nvpair_create_binary(const char *name, const void *value, size_t size) 1330 1.1 christos { 1331 1.1 christos nvpair_t *nvp; 1332 1.1 christos void *data; 1333 1.1 christos 1334 1.1 christos if (value == NULL || size == 0) { 1335 1.1 christos ERRNO_SET(EINVAL); 1336 1.1 christos return (NULL); 1337 1.1 christos } 1338 1.1 christos 1339 1.1 christos data = nv_malloc(size); 1340 1.1 christos if (data == NULL) 1341 1.1 christos return (NULL); 1342 1.1 christos memcpy(data, value, size); 1343 1.1 christos 1344 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, 1345 1.1 christos size, 0); 1346 1.1 christos if (nvp == NULL) 1347 1.1 christos nv_free(data); 1348 1.1 christos 1349 1.1 christos return (nvp); 1350 1.1 christos } 1351 1.1 christos 1352 1.1 christos nvpair_t * 1353 1.1 christos nvpair_create_bool_array(const char *name, const bool *value, size_t nitems) 1354 1.1 christos { 1355 1.1 christos nvpair_t *nvp; 1356 1.1 christos size_t size; 1357 1.1 christos void *data; 1358 1.1 christos 1359 1.1 christos if (value == NULL || nitems == 0) { 1360 1.1 christos ERRNO_SET(EINVAL); 1361 1.1 christos return (NULL); 1362 1.1 christos } 1363 1.1 christos 1364 1.12 riastrad data = nv_calloc(nitems, sizeof(value[0])); 1365 1.1 christos if (data == NULL) 1366 1.1 christos return (NULL); 1367 1.12 riastrad size = sizeof(value[0]) * nitems; 1368 1.1 christos 1369 1.1 christos memcpy(data, value, size); 1370 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data, 1371 1.1 christos size, nitems); 1372 1.1 christos if (nvp == NULL) { 1373 1.1 christos ERRNO_SAVE(); 1374 1.1 christos nv_free(data); 1375 1.1 christos ERRNO_RESTORE(); 1376 1.1 christos } 1377 1.1 christos 1378 1.1 christos return (nvp); 1379 1.1 christos } 1380 1.1 christos 1381 1.1 christos nvpair_t * 1382 1.1 christos nvpair_create_number_array(const char *name, const uint64_t *value, 1383 1.1 christos size_t nitems) 1384 1.1 christos { 1385 1.1 christos nvpair_t *nvp; 1386 1.1 christos size_t size; 1387 1.1 christos void *data; 1388 1.1 christos 1389 1.1 christos if (value == NULL || nitems == 0) { 1390 1.1 christos ERRNO_SET(EINVAL); 1391 1.1 christos return (NULL); 1392 1.1 christos } 1393 1.1 christos 1394 1.12 riastrad data = nv_calloc(nitems, sizeof(value[0])); 1395 1.1 christos if (data == NULL) 1396 1.1 christos return (NULL); 1397 1.12 riastrad size = sizeof(value[0]) * nitems; 1398 1.1 christos 1399 1.1 christos memcpy(data, value, size); 1400 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1401 1.1 christos (uint64_t)(uintptr_t)data, size, nitems); 1402 1.1 christos if (nvp == NULL) { 1403 1.1 christos ERRNO_SAVE(); 1404 1.1 christos nv_free(data); 1405 1.1 christos ERRNO_RESTORE(); 1406 1.1 christos } 1407 1.1 christos 1408 1.1 christos return (nvp); 1409 1.1 christos } 1410 1.1 christos 1411 1.1 christos nvpair_t * 1412 1.1 christos nvpair_create_string_array(const char *name, const char * const *value, 1413 1.1 christos size_t nitems) 1414 1.1 christos { 1415 1.1 christos nvpair_t *nvp; 1416 1.1 christos unsigned int ii; 1417 1.1 christos size_t datasize, size; 1418 1.1 christos char **data; 1419 1.1 christos 1420 1.1 christos if (value == NULL || nitems == 0) { 1421 1.1 christos ERRNO_SET(EINVAL); 1422 1.1 christos return (NULL); 1423 1.1 christos } 1424 1.1 christos 1425 1.1 christos nvp = NULL; 1426 1.1 christos datasize = 0; 1427 1.12 riastrad data = nv_calloc(nitems, sizeof(value[0])); 1428 1.1 christos if (data == NULL) 1429 1.1 christos return (NULL); 1430 1.1 christos 1431 1.1 christos for (ii = 0; ii < nitems; ii++) { 1432 1.1 christos if (value[ii] == NULL) { 1433 1.1 christos ERRNO_SET(EINVAL); 1434 1.1 christos goto fail; 1435 1.1 christos } 1436 1.1 christos 1437 1.1 christos size = strlen(value[ii]) + 1; 1438 1.1 christos datasize += size; 1439 1.1 christos data[ii] = nv_strdup(value[ii]); 1440 1.1 christos if (data[ii] == NULL) 1441 1.1 christos goto fail; 1442 1.1 christos } 1443 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1444 1.1 christos (uint64_t)(uintptr_t)data, datasize, nitems); 1445 1.1 christos 1446 1.1 christos fail: 1447 1.1 christos if (nvp == NULL) { 1448 1.1 christos ERRNO_SAVE(); 1449 1.1 christos for (; ii > 0; ii--) 1450 1.1 christos nv_free(data[ii - 1]); 1451 1.1 christos nv_free(data); 1452 1.1 christos ERRNO_RESTORE(); 1453 1.1 christos } 1454 1.1 christos 1455 1.1 christos return (nvp); 1456 1.1 christos } 1457 1.1 christos 1458 1.1 christos nvpair_t * 1459 1.1 christos nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value, 1460 1.1 christos size_t nitems) 1461 1.1 christos { 1462 1.1 christos unsigned int ii; 1463 1.1 christos nvlist_t **nvls; 1464 1.1 christos nvpair_t *parent; 1465 1.1 christos int flags; 1466 1.1 christos 1467 1.1 christos nvls = NULL; 1468 1.1 christos 1469 1.1 christos if (value == NULL || nitems == 0) { 1470 1.1 christos ERRNO_SET(EINVAL); 1471 1.1 christos return (NULL); 1472 1.1 christos } 1473 1.1 christos 1474 1.12 riastrad nvls = nv_calloc(nitems, sizeof(value[0])); 1475 1.1 christos if (nvls == NULL) 1476 1.1 christos return (NULL); 1477 1.1 christos 1478 1.1 christos for (ii = 0; ii < nitems; ii++) { 1479 1.1 christos if (value[ii] == NULL) { 1480 1.1 christos ERRNO_SET(EINVAL); 1481 1.1 christos goto fail; 1482 1.1 christos } 1483 1.1 christos 1484 1.1 christos nvls[ii] = nvlist_clone(value[ii]); 1485 1.1 christos if (nvls[ii] == NULL) 1486 1.1 christos goto fail; 1487 1.1 christos 1488 1.1 christos if (ii > 0) { 1489 1.1 christos nvpair_t *nvp; 1490 1.1 christos 1491 1.1 christos nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1492 1.1 christos (uint64_t)(uintptr_t)nvls[ii], 0, 0); 1493 1.1 christos if (nvp == NULL) { 1494 1.1 christos ERRNO_SAVE(); 1495 1.1 christos nvlist_destroy(nvls[ii]); 1496 1.1 christos ERRNO_RESTORE(); 1497 1.1 christos goto fail; 1498 1.1 christos } 1499 1.1 christos nvlist_set_array_next(nvls[ii - 1], nvp); 1500 1.1 christos } 1501 1.1 christos } 1502 1.1 christos flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY; 1503 1.1 christos nvlist_set_flags(nvls[nitems - 1], flags); 1504 1.1 christos 1505 1.1 christos parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1506 1.1 christos (uint64_t)(uintptr_t)nvls, 0, nitems); 1507 1.1 christos if (parent == NULL) 1508 1.1 christos goto fail; 1509 1.1 christos 1510 1.1 christos for (ii = 0; ii < nitems; ii++) 1511 1.1 christos nvlist_set_parent(nvls[ii], parent); 1512 1.1 christos 1513 1.1 christos return (parent); 1514 1.1 christos 1515 1.1 christos fail: 1516 1.1 christos ERRNO_SAVE(); 1517 1.1 christos for (; ii > 0; ii--) 1518 1.1 christos nvlist_destroy(nvls[ii - 1]); 1519 1.1 christos nv_free(nvls); 1520 1.1 christos ERRNO_RESTORE(); 1521 1.1 christos 1522 1.1 christos return (NULL); 1523 1.1 christos } 1524 1.1 christos 1525 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1526 1.1 christos nvpair_t * 1527 1.1 christos nvpair_create_descriptor_array(const char *name, const int *value, 1528 1.1 christos size_t nitems) 1529 1.1 christos { 1530 1.1 christos unsigned int ii; 1531 1.1 christos nvpair_t *nvp; 1532 1.1 christos int *fds; 1533 1.1 christos 1534 1.1 christos if (value == NULL) { 1535 1.1 christos ERRNO_SET(EINVAL); 1536 1.1 christos return (NULL); 1537 1.1 christos } 1538 1.1 christos 1539 1.1 christos nvp = NULL; 1540 1.1 christos 1541 1.12 riastrad fds = nv_calloc(nitems, sizeof(value[0])); 1542 1.1 christos if (fds == NULL) 1543 1.1 christos return (NULL); 1544 1.1 christos for (ii = 0; ii < nitems; ii++) { 1545 1.1 christos if (value[ii] == -1) { 1546 1.1 christos fds[ii] = -1; 1547 1.1 christos } else { 1548 1.1 christos if (!fd_is_valid(value[ii])) { 1549 1.1 christos ERRNO_SET(EBADF); 1550 1.1 christos goto fail; 1551 1.1 christos } 1552 1.1 christos 1553 1.1 christos fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0); 1554 1.1 christos if (fds[ii] == -1) 1555 1.1 christos goto fail; 1556 1.1 christos } 1557 1.1 christos } 1558 1.1 christos 1559 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1560 1.1 christos (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems); 1561 1.1 christos 1562 1.1 christos fail: 1563 1.1 christos if (nvp == NULL) { 1564 1.1 christos ERRNO_SAVE(); 1565 1.1 christos for (; ii > 0; ii--) { 1566 1.1 christos if (fds[ii - 1] != -1) 1567 1.1 christos close(fds[ii - 1]); 1568 1.1 christos } 1569 1.1 christos nv_free(fds); 1570 1.1 christos ERRNO_RESTORE(); 1571 1.1 christos } 1572 1.1 christos 1573 1.1 christos return (nvp); 1574 1.1 christos } 1575 1.1 christos #endif 1576 1.1 christos 1577 1.1 christos nvpair_t * 1578 1.1 christos nvpair_move_string(const char *name, char *value) 1579 1.1 christos { 1580 1.1 christos nvpair_t *nvp; 1581 1.1 christos 1582 1.1 christos if (value == NULL) { 1583 1.1 christos ERRNO_SET(EINVAL); 1584 1.1 christos return (NULL); 1585 1.1 christos } 1586 1.1 christos 1587 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, 1588 1.1 christos strlen(value) + 1, 0); 1589 1.1 christos if (nvp == NULL) { 1590 1.1 christos ERRNO_SAVE(); 1591 1.1 christos nv_free(value); 1592 1.1 christos ERRNO_RESTORE(); 1593 1.1 christos } 1594 1.1 christos 1595 1.1 christos return (nvp); 1596 1.1 christos } 1597 1.1 christos 1598 1.1 christos nvpair_t * 1599 1.1 christos nvpair_move_nvlist(const char *name, nvlist_t *value) 1600 1.1 christos { 1601 1.1 christos nvpair_t *nvp; 1602 1.1 christos 1603 1.1 christos if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { 1604 1.1 christos ERRNO_SET(EINVAL); 1605 1.1 christos return (NULL); 1606 1.1 christos } 1607 1.1 christos 1608 1.1 christos if (nvlist_error(value) != 0) { 1609 1.1 christos ERRNO_SET(nvlist_error(value)); 1610 1.1 christos nvlist_destroy(value); 1611 1.1 christos return (NULL); 1612 1.1 christos } 1613 1.1 christos 1614 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 1615 1.1 christos 0, 0); 1616 1.1 christos if (nvp == NULL) 1617 1.1 christos nvlist_destroy(value); 1618 1.1 christos else 1619 1.1 christos nvlist_set_parent(value, nvp); 1620 1.1 christos 1621 1.1 christos return (nvp); 1622 1.1 christos } 1623 1.1 christos 1624 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1625 1.1 christos nvpair_t * 1626 1.1 christos nvpair_move_descriptor(const char *name, int value) 1627 1.1 christos { 1628 1.1 christos nvpair_t *nvp; 1629 1.1 christos 1630 1.1 christos if (value < 0 || !fd_is_valid(value)) { 1631 1.1 christos ERRNO_SET(EBADF); 1632 1.1 christos return (NULL); 1633 1.1 christos } 1634 1.1 christos 1635 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, 1636 1.1 christos sizeof(int64_t), 0); 1637 1.1 christos if (nvp == NULL) { 1638 1.1 christos ERRNO_SAVE(); 1639 1.1 christos close(value); 1640 1.1 christos ERRNO_RESTORE(); 1641 1.1 christos } 1642 1.1 christos 1643 1.1 christos return (nvp); 1644 1.1 christos } 1645 1.1 christos #endif 1646 1.1 christos 1647 1.1 christos nvpair_t * 1648 1.1 christos nvpair_move_binary(const char *name, void *value, size_t size) 1649 1.1 christos { 1650 1.1 christos nvpair_t *nvp; 1651 1.1 christos 1652 1.1 christos if (value == NULL || size == 0) { 1653 1.1 christos ERRNO_SET(EINVAL); 1654 1.1 christos return (NULL); 1655 1.1 christos } 1656 1.1 christos 1657 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, 1658 1.1 christos size, 0); 1659 1.1 christos if (nvp == NULL) { 1660 1.1 christos ERRNO_SAVE(); 1661 1.1 christos nv_free(value); 1662 1.1 christos ERRNO_RESTORE(); 1663 1.1 christos } 1664 1.1 christos 1665 1.1 christos return (nvp); 1666 1.1 christos } 1667 1.1 christos 1668 1.1 christos nvpair_t * 1669 1.1 christos nvpair_move_bool_array(const char *name, bool *value, size_t nitems) 1670 1.1 christos { 1671 1.1 christos nvpair_t *nvp; 1672 1.1 christos 1673 1.1 christos if (value == NULL || nitems == 0) { 1674 1.1 christos ERRNO_SET(EINVAL); 1675 1.1 christos return (NULL); 1676 1.1 christos } 1677 1.1 christos 1678 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, 1679 1.1 christos (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1680 1.1 christos if (nvp == NULL) { 1681 1.1 christos ERRNO_SAVE(); 1682 1.1 christos nv_free(value); 1683 1.1 christos ERRNO_RESTORE(); 1684 1.1 christos } 1685 1.1 christos 1686 1.1 christos return (nvp); 1687 1.1 christos } 1688 1.1 christos 1689 1.1 christos nvpair_t * 1690 1.1 christos nvpair_move_string_array(const char *name, char **value, size_t nitems) 1691 1.1 christos { 1692 1.1 christos nvpair_t *nvp; 1693 1.1 christos size_t i, size; 1694 1.1 christos 1695 1.1 christos if (value == NULL || nitems == 0) { 1696 1.1 christos ERRNO_SET(EINVAL); 1697 1.1 christos return (NULL); 1698 1.1 christos } 1699 1.1 christos 1700 1.1 christos size = 0; 1701 1.1 christos for (i = 0; i < nitems; i++) { 1702 1.1 christos if (value[i] == NULL) { 1703 1.1 christos ERRNO_SET(EINVAL); 1704 1.1 christos return (NULL); 1705 1.1 christos } 1706 1.1 christos 1707 1.1 christos size += strlen(value[i]) + 1; 1708 1.1 christos } 1709 1.1 christos 1710 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, 1711 1.1 christos (uint64_t)(uintptr_t)value, size, nitems); 1712 1.1 christos if (nvp == NULL) { 1713 1.1 christos ERRNO_SAVE(); 1714 1.1 christos for (i = 0; i < nitems; i++) 1715 1.1 christos nv_free(value[i]); 1716 1.1 christos nv_free(value); 1717 1.1 christos ERRNO_RESTORE(); 1718 1.1 christos } 1719 1.1 christos 1720 1.1 christos return (nvp); 1721 1.1 christos } 1722 1.1 christos 1723 1.1 christos nvpair_t * 1724 1.1 christos nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems) 1725 1.1 christos { 1726 1.1 christos nvpair_t *nvp; 1727 1.1 christos 1728 1.1 christos if (value == NULL || nitems == 0) { 1729 1.1 christos ERRNO_SET(EINVAL); 1730 1.1 christos return (NULL); 1731 1.1 christos } 1732 1.1 christos 1733 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, 1734 1.1 christos (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1735 1.1 christos if (nvp == NULL) { 1736 1.1 christos ERRNO_SAVE(); 1737 1.1 christos nv_free(value); 1738 1.1 christos ERRNO_RESTORE(); 1739 1.1 christos } 1740 1.1 christos 1741 1.1 christos return (nvp); 1742 1.1 christos } 1743 1.1 christos 1744 1.1 christos nvpair_t * 1745 1.1 christos nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems) 1746 1.1 christos { 1747 1.1 christos nvpair_t *parent; 1748 1.1 christos unsigned int ii; 1749 1.1 christos int flags; 1750 1.1 christos 1751 1.1 christos if (value == NULL || nitems == 0) { 1752 1.1 christos ERRNO_SET(EINVAL); 1753 1.1 christos return (NULL); 1754 1.1 christos } 1755 1.1 christos 1756 1.1 christos for (ii = 0; ii < nitems; ii++) { 1757 1.1 christos if (value == NULL || nvlist_error(value[ii]) != 0 || 1758 1.1 christos nvlist_get_pararr(value[ii], NULL) != NULL) { 1759 1.1 christos ERRNO_SET(EINVAL); 1760 1.1 christos goto fail; 1761 1.1 christos } 1762 1.1 christos if (ii > 0) { 1763 1.1 christos nvpair_t *nvp; 1764 1.1 christos 1765 1.1 christos nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 1766 1.1 christos (uint64_t)(uintptr_t)value[ii], 0, 0); 1767 1.1 christos if (nvp == NULL) 1768 1.1 christos goto fail; 1769 1.1 christos nvlist_set_array_next(value[ii - 1], nvp); 1770 1.1 christos } 1771 1.1 christos } 1772 1.1 christos flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY; 1773 1.1 christos nvlist_set_flags(value[nitems - 1], flags); 1774 1.1 christos 1775 1.1 christos parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, 1776 1.1 christos (uint64_t)(uintptr_t)value, 0, nitems); 1777 1.1 christos if (parent == NULL) 1778 1.1 christos goto fail; 1779 1.1 christos 1780 1.1 christos for (ii = 0; ii < nitems; ii++) 1781 1.1 christos nvlist_set_parent(value[ii], parent); 1782 1.1 christos 1783 1.1 christos return (parent); 1784 1.1 christos fail: 1785 1.1 christos ERRNO_SAVE(); 1786 1.1 christos for (ii = 0; ii < nitems; ii++) { 1787 1.1 christos if (value[ii] != NULL && 1788 1.1 christos nvlist_get_pararr(value[ii], NULL) != NULL) { 1789 1.1 christos nvlist_destroy(value[ii]); 1790 1.1 christos } 1791 1.1 christos } 1792 1.1 christos nv_free(value); 1793 1.1 christos ERRNO_RESTORE(); 1794 1.1 christos 1795 1.1 christos return (NULL); 1796 1.1 christos } 1797 1.1 christos 1798 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1799 1.1 christos nvpair_t * 1800 1.1 christos nvpair_move_descriptor_array(const char *name, int *value, size_t nitems) 1801 1.1 christos { 1802 1.1 christos nvpair_t *nvp; 1803 1.1 christos size_t i; 1804 1.1 christos 1805 1.1 christos if (value == NULL || nitems == 0) { 1806 1.1 christos ERRNO_SET(EINVAL); 1807 1.1 christos return (NULL); 1808 1.1 christos } 1809 1.1 christos 1810 1.1 christos for (i = 0; i < nitems; i++) { 1811 1.1 christos if (value[i] != -1 && !fd_is_valid(value[i])) { 1812 1.1 christos ERRNO_SET(EBADF); 1813 1.1 christos goto fail; 1814 1.1 christos } 1815 1.1 christos } 1816 1.1 christos 1817 1.1 christos nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, 1818 1.1 christos (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); 1819 1.1 christos if (nvp == NULL) 1820 1.1 christos goto fail; 1821 1.1 christos 1822 1.1 christos return (nvp); 1823 1.1 christos fail: 1824 1.1 christos ERRNO_SAVE(); 1825 1.1 christos for (i = 0; i < nitems; i++) { 1826 1.1 christos if (fd_is_valid(value[i])) 1827 1.1 christos close(value[i]); 1828 1.1 christos } 1829 1.1 christos nv_free(value); 1830 1.1 christos ERRNO_RESTORE(); 1831 1.1 christos 1832 1.1 christos return (NULL); 1833 1.1 christos } 1834 1.1 christos #endif 1835 1.1 christos 1836 1.1 christos bool 1837 1.1 christos nvpair_get_bool(const nvpair_t *nvp) 1838 1.1 christos { 1839 1.1 christos 1840 1.1 christos NVPAIR_ASSERT(nvp); 1841 1.1 christos 1842 1.1 christos return (nvp->nvp_data == 1); 1843 1.1 christos } 1844 1.1 christos 1845 1.1 christos uint64_t 1846 1.1 christos nvpair_get_number(const nvpair_t *nvp) 1847 1.1 christos { 1848 1.1 christos 1849 1.1 christos NVPAIR_ASSERT(nvp); 1850 1.1 christos 1851 1.1 christos return (nvp->nvp_data); 1852 1.1 christos } 1853 1.1 christos 1854 1.1 christos const char * 1855 1.1 christos nvpair_get_string(const nvpair_t *nvp) 1856 1.1 christos { 1857 1.1 christos 1858 1.1 christos NVPAIR_ASSERT(nvp); 1859 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); 1860 1.1 christos 1861 1.1 christos return ((const char *)(intptr_t)nvp->nvp_data); 1862 1.1 christos } 1863 1.1 christos 1864 1.1 christos const nvlist_t * 1865 1.1 christos nvpair_get_nvlist(const nvpair_t *nvp) 1866 1.1 christos { 1867 1.1 christos 1868 1.1 christos NVPAIR_ASSERT(nvp); 1869 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); 1870 1.1 christos 1871 1.1 christos return ((const nvlist_t *)(intptr_t)nvp->nvp_data); 1872 1.1 christos } 1873 1.1 christos 1874 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1875 1.1 christos int 1876 1.1 christos nvpair_get_descriptor(const nvpair_t *nvp) 1877 1.1 christos { 1878 1.1 christos 1879 1.1 christos NVPAIR_ASSERT(nvp); 1880 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); 1881 1.1 christos 1882 1.1 christos return ((int)nvp->nvp_data); 1883 1.1 christos } 1884 1.1 christos #endif 1885 1.1 christos 1886 1.1 christos const void * 1887 1.1 christos nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) 1888 1.1 christos { 1889 1.1 christos 1890 1.1 christos NVPAIR_ASSERT(nvp); 1891 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); 1892 1.1 christos 1893 1.1 christos if (sizep != NULL) 1894 1.1 christos *sizep = nvp->nvp_datasize; 1895 1.1 christos 1896 1.1 christos return ((const void *)(intptr_t)nvp->nvp_data); 1897 1.1 christos } 1898 1.1 christos 1899 1.1 christos const bool * 1900 1.1 christos nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems) 1901 1.1 christos { 1902 1.1 christos 1903 1.1 christos NVPAIR_ASSERT(nvp); 1904 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1905 1.1 christos 1906 1.1 christos if (nitems != NULL) 1907 1.1 christos *nitems = nvp->nvp_nitems; 1908 1.1 christos 1909 1.1 christos return ((const bool *)(intptr_t)nvp->nvp_data); 1910 1.1 christos } 1911 1.1 christos 1912 1.1 christos const uint64_t * 1913 1.1 christos nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems) 1914 1.1 christos { 1915 1.1 christos 1916 1.1 christos NVPAIR_ASSERT(nvp); 1917 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1918 1.1 christos 1919 1.1 christos if (nitems != NULL) 1920 1.1 christos *nitems = nvp->nvp_nitems; 1921 1.1 christos 1922 1.1 christos return ((const uint64_t *)(intptr_t)nvp->nvp_data); 1923 1.1 christos } 1924 1.1 christos 1925 1.1 christos const char * const * 1926 1.1 christos nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems) 1927 1.1 christos { 1928 1.1 christos 1929 1.1 christos NVPAIR_ASSERT(nvp); 1930 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1931 1.1 christos 1932 1.1 christos if (nitems != NULL) 1933 1.1 christos *nitems = nvp->nvp_nitems; 1934 1.1 christos 1935 1.1 christos return ((const char * const *)(intptr_t)nvp->nvp_data); 1936 1.1 christos } 1937 1.1 christos 1938 1.1 christos const nvlist_t * const * 1939 1.1 christos nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems) 1940 1.1 christos { 1941 1.1 christos 1942 1.1 christos NVPAIR_ASSERT(nvp); 1943 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 1944 1.1 christos 1945 1.1 christos if (nitems != NULL) 1946 1.1 christos *nitems = nvp->nvp_nitems; 1947 1.1 christos 1948 1.1 christos return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data)); 1949 1.1 christos } 1950 1.1 christos 1951 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1952 1.1 christos const int * 1953 1.1 christos nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems) 1954 1.1 christos { 1955 1.1 christos 1956 1.1 christos NVPAIR_ASSERT(nvp); 1957 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 1958 1.1 christos 1959 1.1 christos if (nitems != NULL) 1960 1.1 christos *nitems = nvp->nvp_nitems; 1961 1.1 christos 1962 1.1 christos return ((const int *)(intptr_t)nvp->nvp_data); 1963 1.1 christos } 1964 1.1 christos #endif 1965 1.1 christos 1966 1.1 christos int 1967 1.1 christos nvpair_append_bool_array(nvpair_t *nvp, const bool value) 1968 1.1 christos { 1969 1.1 christos 1970 1.1 christos NVPAIR_ASSERT(nvp); 1971 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 1972 1.1 christos return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 1973 1.1 christos } 1974 1.1 christos 1975 1.1 christos int 1976 1.1 christos nvpair_append_number_array(nvpair_t *nvp, const uint64_t value) 1977 1.1 christos { 1978 1.1 christos 1979 1.1 christos NVPAIR_ASSERT(nvp); 1980 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 1981 1.1 christos return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); 1982 1.1 christos } 1983 1.1 christos 1984 1.1 christos int 1985 1.1 christos nvpair_append_string_array(nvpair_t *nvp, const char *value) 1986 1.1 christos { 1987 1.1 christos char *str; 1988 1.1 christos 1989 1.1 christos NVPAIR_ASSERT(nvp); 1990 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); 1991 1.1 christos if (value == NULL) { 1992 1.1 christos ERRNO_SET(EINVAL); 1993 1.1 christos return (-1); 1994 1.1 christos } 1995 1.1 christos str = nv_strdup(value); 1996 1.1 christos if (str == NULL) { 1997 1.1 christos return (-1); 1998 1.1 christos } 1999 1.1 christos if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) { 2000 1.1 christos nv_free(str); 2001 1.1 christos return (-1); 2002 1.1 christos } 2003 1.1 christos return (0); 2004 1.1 christos } 2005 1.1 christos 2006 1.1 christos int 2007 1.1 christos nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value) 2008 1.1 christos { 2009 1.1 christos nvpair_t *tmpnvp; 2010 1.1 christos nvlist_t *nvl, *prev; 2011 1.1 christos int flags; 2012 1.1 christos 2013 1.1 christos NVPAIR_ASSERT(nvp); 2014 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); 2015 1.1 christos if (value == NULL || nvlist_error(value) != 0 || 2016 1.1 christos nvlist_get_pararr(value, NULL) != NULL) { 2017 1.1 christos ERRNO_SET(EINVAL); 2018 1.1 christos return (-1); 2019 1.1 christos } 2020 1.1 christos nvl = nvlist_clone(value); 2021 1.1 christos if (nvl == NULL) { 2022 1.1 christos return (-1); 2023 1.1 christos } 2024 1.1 christos flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY; 2025 1.1 christos nvlist_set_flags(nvl, flags); 2026 1.1 christos 2027 1.1 christos tmpnvp = NULL; 2028 1.1 christos prev = NULL; 2029 1.1 christos if (nvp->nvp_nitems > 0) { 2030 1.1 christos nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data; 2031 1.1 christos 2032 1.1 christos prev = nvls[nvp->nvp_nitems - 1]; 2033 1.1 christos PJDLOG_ASSERT(prev != NULL); 2034 1.1 christos 2035 1.1 christos tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, 2036 1.1 christos (uint64_t)(uintptr_t)nvl, 0, 0); 2037 1.1 christos if (tmpnvp == NULL) { 2038 1.1 christos goto fail; 2039 1.1 christos } 2040 1.1 christos } 2041 1.1 christos if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) { 2042 1.1 christos goto fail; 2043 1.1 christos } 2044 1.1 christos if (tmpnvp) { 2045 1.1 christos NVPAIR_ASSERT(tmpnvp); 2046 1.1 christos nvlist_set_array_next(prev, tmpnvp); 2047 1.1 christos } 2048 1.1 christos nvlist_set_parent(nvl, nvp); 2049 1.1 christos return (0); 2050 1.1 christos fail: 2051 1.1 christos if (tmpnvp) { 2052 1.1 christos nvpair_free(tmpnvp); 2053 1.1 christos } 2054 1.1 christos nvlist_destroy(nvl); 2055 1.1 christos return (-1); 2056 1.1 christos } 2057 1.1 christos 2058 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 2059 1.1 christos int 2060 1.1 christos nvpair_append_descriptor_array(nvpair_t *nvp, const int value) 2061 1.1 christos { 2062 1.1 christos int fd; 2063 1.1 christos 2064 1.1 christos NVPAIR_ASSERT(nvp); 2065 1.1 christos PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); 2066 1.1 christos if (value < 0 || !fd_is_valid(value)) { 2067 1.1 christos ERRNO_SET(EBADF); 2068 1.1 christos return -1; 2069 1.1 christos } 2070 1.1 christos fd = fcntl(value, F_DUPFD_CLOEXEC, 0); 2071 1.1 christos if (fd == -1) { 2072 1.1 christos return (-1); 2073 1.1 christos } 2074 1.1 christos if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) { 2075 1.1 christos close(fd); 2076 1.1 christos return (-1); 2077 1.1 christos } 2078 1.1 christos return (0); 2079 1.1 christos } 2080 1.1 christos #endif 2081 1.1 christos 2082 1.1 christos void 2083 1.1 christos nvpair_free(nvpair_t *nvp) 2084 1.1 christos { 2085 1.1 christos size_t i; 2086 1.1 christos 2087 1.1 christos NVPAIR_ASSERT(nvp); 2088 1.1 christos PJDLOG_ASSERT(nvp->nvp_list == NULL); 2089 1.1 christos 2090 1.1 christos nvp->nvp_magic = 0; 2091 1.1 christos switch (nvp->nvp_type) { 2092 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 2093 1.1 christos case NV_TYPE_DESCRIPTOR: 2094 1.1 christos close((int)nvp->nvp_data); 2095 1.1 christos break; 2096 1.1 christos case NV_TYPE_DESCRIPTOR_ARRAY: 2097 1.1 christos for (i = 0; i < nvp->nvp_nitems; i++) 2098 1.1 christos close(((int *)(intptr_t)nvp->nvp_data)[i]); 2099 1.5 rmind nv_free((int *)(intptr_t)nvp->nvp_data); 2100 1.1 christos break; 2101 1.1 christos #endif 2102 1.1 christos case NV_TYPE_NVLIST: 2103 1.1 christos nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); 2104 1.1 christos break; 2105 1.1 christos case NV_TYPE_STRING: 2106 1.1 christos nv_free((char *)(intptr_t)nvp->nvp_data); 2107 1.1 christos break; 2108 1.1 christos case NV_TYPE_BINARY: 2109 1.1 christos nv_free((void *)(intptr_t)nvp->nvp_data); 2110 1.1 christos break; 2111 1.1 christos case NV_TYPE_NVLIST_ARRAY: 2112 1.1 christos for (i = 0; i < nvp->nvp_nitems; i++) { 2113 1.1 christos nvlist_destroy( 2114 1.1 christos ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]); 2115 1.1 christos } 2116 1.1 christos nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data)); 2117 1.1 christos break; 2118 1.1 christos case NV_TYPE_NUMBER_ARRAY: 2119 1.1 christos nv_free((uint64_t *)(intptr_t)nvp->nvp_data); 2120 1.1 christos break; 2121 1.1 christos case NV_TYPE_BOOL_ARRAY: 2122 1.1 christos nv_free((bool *)(intptr_t)nvp->nvp_data); 2123 1.1 christos break; 2124 1.1 christos case NV_TYPE_STRING_ARRAY: 2125 1.1 christos for (i = 0; i < nvp->nvp_nitems; i++) 2126 1.1 christos nv_free(((char **)(intptr_t)nvp->nvp_data)[i]); 2127 1.1 christos nv_free((char **)(intptr_t)nvp->nvp_data); 2128 1.1 christos break; 2129 1.1 christos } 2130 1.1 christos nv_free(nvp); 2131 1.1 christos } 2132 1.1 christos 2133 1.1 christos void 2134 1.1 christos nvpair_free_structure(nvpair_t *nvp) 2135 1.1 christos { 2136 1.1 christos 2137 1.1 christos NVPAIR_ASSERT(nvp); 2138 1.1 christos PJDLOG_ASSERT(nvp->nvp_list == NULL); 2139 1.1 christos 2140 1.1 christos nvp->nvp_magic = 0; 2141 1.1 christos nv_free(nvp); 2142 1.1 christos } 2143 1.1 christos 2144 1.1 christos const char * 2145 1.1 christos nvpair_type_string(int type) 2146 1.1 christos { 2147 1.1 christos 2148 1.1 christos switch (type) { 2149 1.1 christos case NV_TYPE_NULL: 2150 1.1 christos return ("NULL"); 2151 1.1 christos case NV_TYPE_BOOL: 2152 1.1 christos return ("BOOL"); 2153 1.1 christos case NV_TYPE_NUMBER: 2154 1.1 christos return ("NUMBER"); 2155 1.1 christos case NV_TYPE_STRING: 2156 1.1 christos return ("STRING"); 2157 1.1 christos case NV_TYPE_NVLIST: 2158 1.1 christos return ("NVLIST"); 2159 1.1 christos case NV_TYPE_DESCRIPTOR: 2160 1.1 christos return ("DESCRIPTOR"); 2161 1.1 christos case NV_TYPE_BINARY: 2162 1.1 christos return ("BINARY"); 2163 1.1 christos case NV_TYPE_BOOL_ARRAY: 2164 1.1 christos return ("BOOL ARRAY"); 2165 1.1 christos case NV_TYPE_NUMBER_ARRAY: 2166 1.1 christos return ("NUMBER ARRAY"); 2167 1.1 christos case NV_TYPE_STRING_ARRAY: 2168 1.1 christos return ("STRING ARRAY"); 2169 1.1 christos case NV_TYPE_NVLIST_ARRAY: 2170 1.1 christos return ("NVLIST ARRAY"); 2171 1.1 christos case NV_TYPE_DESCRIPTOR_ARRAY: 2172 1.1 christos return ("DESCRIPTOR ARRAY"); 2173 1.1 christos default: 2174 1.1 christos return ("<UNKNOWN>"); 2175 1.1 christos } 2176 1.1 christos } 2177 1.1 christos 2178