1 1.11 riastrad /* $NetBSD: nvlist.c,v 1.11 2024/09/11 15:01:11 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/nvlist.c 335347 2018-06-18 22:57:32Z oshogbo $"); 38 1.2 christos #else 39 1.11 riastrad __RCSID("$NetBSD: nvlist.c,v 1.11 2024/09/11 15:01:11 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/kernel.h> 50 1.1 christos #include <sys/lock.h> 51 1.1 christos #include <sys/malloc.h> 52 1.1 christos #include <sys/systm.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 <sys/socket.h> 60 1.1 christos 61 1.1 christos #include <errno.h> 62 1.1 christos #include <stdarg.h> 63 1.1 christos #include <stdbool.h> 64 1.1 christos #include <stdint.h> 65 1.1 christos #include <stdio.h> 66 1.1 christos #include <stdlib.h> 67 1.1 christos #include <string.h> 68 1.1 christos #include <unistd.h> 69 1.1 christos 70 1.1 christos #include "msgio.h" 71 1.1 christos #endif 72 1.1 christos 73 1.1 christos #ifdef HAVE_PJDLOG 74 1.1 christos #include <pjdlog.h> 75 1.1 christos #endif 76 1.1 christos 77 1.2 christos #ifdef __FreeBSD__ 78 1.1 christos #include <sys/nv.h> 79 1.2 christos #else 80 1.3 christos #include "nv.h" 81 1.2 christos #endif 82 1.1 christos 83 1.1 christos #include "nv_impl.h" 84 1.1 christos #include "nvlist_impl.h" 85 1.1 christos #include "nvpair_impl.h" 86 1.1 christos 87 1.1 christos #ifndef HAVE_PJDLOG 88 1.2 christos #if defined(_KERNEL) || defined(_STANDALONE) 89 1.2 christos #ifdef __FreeBSD__ 90 1.1 christos #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) 91 1.2 christos #else 92 1.2 christos #define PJDLOG_ASSERT(...) KASSERT(__VA_ARGS__) 93 1.2 christos #endif 94 1.1 christos #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) 95 1.1 christos #define PJDLOG_ABORT(...) panic(__VA_ARGS__) 96 1.1 christos #else 97 1.2 christos #ifndef __lint__ 98 1.1 christos #include <assert.h> 99 1.1 christos #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) 100 1.1 christos #define PJDLOG_RASSERT(expr, ...) assert(expr) 101 1.1 christos #define PJDLOG_ABORT(...) do { \ 102 1.1 christos fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \ 103 1.1 christos fprintf(stderr, __VA_ARGS__); \ 104 1.1 christos fprintf(stderr, "\n"); \ 105 1.1 christos abort(); \ 106 1.2 christos } while (/*CONSTCOND*/0) 107 1.2 christos #else 108 1.2 christos #define PJDLOG_ASSERT(...) 109 1.2 christos #define PJDLOG_RASSERT(expr, ...) 110 1.2 christos #define PJDLOG_ABORT(...) 111 1.2 christos #endif 112 1.1 christos #endif 113 1.1 christos #endif 114 1.1 christos 115 1.1 christos #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN | NV_FLAG_IN_ARRAY) 116 1.1 christos #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE) 117 1.1 christos #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK) 118 1.1 christos 119 1.1 christos #define NVLIST_MAGIC 0x6e766c /* "nvl" */ 120 1.1 christos struct nvlist { 121 1.1 christos int nvl_magic; 122 1.1 christos int nvl_error; 123 1.1 christos int nvl_flags; 124 1.1 christos nvpair_t *nvl_parent; 125 1.1 christos nvpair_t *nvl_array_next; 126 1.1 christos struct nvl_head nvl_head; 127 1.1 christos }; 128 1.1 christos 129 1.1 christos #define NVLIST_ASSERT(nvl) do { \ 130 1.1 christos PJDLOG_ASSERT((nvl) != NULL); \ 131 1.1 christos PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \ 132 1.2 christos } while (/*CONSTCOND*/0) 133 1.1 christos 134 1.1 christos #ifdef _KERNEL 135 1.1 christos MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist"); 136 1.1 christos #endif 137 1.1 christos 138 1.1 christos #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp) 139 1.1 christos 140 1.1 christos #define NVLIST_HEADER_MAGIC 0x6c 141 1.1 christos #define NVLIST_HEADER_VERSION 0x00 142 1.1 christos struct nvlist_header { 143 1.1 christos uint8_t nvlh_magic; 144 1.1 christos uint8_t nvlh_version; 145 1.1 christos uint8_t nvlh_flags; 146 1.1 christos uint64_t nvlh_descriptors; 147 1.1 christos uint64_t nvlh_size; 148 1.1 christos } __packed; 149 1.1 christos 150 1.1 christos nvlist_t * 151 1.1 christos nvlist_create(int flags) 152 1.1 christos { 153 1.1 christos nvlist_t *nvl; 154 1.1 christos 155 1.1 christos PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 156 1.1 christos 157 1.1 christos nvl = nv_malloc(sizeof(*nvl)); 158 1.1 christos if (nvl == NULL) 159 1.1 christos return (NULL); 160 1.1 christos nvl->nvl_error = 0; 161 1.1 christos nvl->nvl_flags = flags; 162 1.1 christos nvl->nvl_parent = NULL; 163 1.1 christos nvl->nvl_array_next = NULL; 164 1.1 christos TAILQ_INIT(&nvl->nvl_head); 165 1.1 christos nvl->nvl_magic = NVLIST_MAGIC; 166 1.1 christos 167 1.1 christos return (nvl); 168 1.1 christos } 169 1.1 christos 170 1.1 christos void 171 1.1 christos nvlist_destroy(nvlist_t *nvl) 172 1.1 christos { 173 1.1 christos nvpair_t *nvp; 174 1.1 christos 175 1.1 christos if (nvl == NULL) 176 1.1 christos return; 177 1.1 christos 178 1.1 christos ERRNO_SAVE(); 179 1.1 christos 180 1.1 christos NVLIST_ASSERT(nvl); 181 1.1 christos 182 1.1 christos while ((nvp = nvlist_first_nvpair(nvl)) != NULL) { 183 1.1 christos nvlist_remove_nvpair(nvl, nvp); 184 1.1 christos nvpair_free(nvp); 185 1.1 christos } 186 1.1 christos if (nvl->nvl_array_next != NULL) 187 1.1 christos nvpair_free_structure(nvl->nvl_array_next); 188 1.1 christos nvl->nvl_array_next = NULL; 189 1.1 christos nvl->nvl_parent = NULL; 190 1.1 christos nvl->nvl_magic = 0; 191 1.1 christos nv_free(nvl); 192 1.1 christos 193 1.1 christos ERRNO_RESTORE(); 194 1.1 christos } 195 1.1 christos 196 1.1 christos void 197 1.1 christos nvlist_set_error(nvlist_t *nvl, int error) 198 1.1 christos { 199 1.1 christos 200 1.1 christos PJDLOG_ASSERT(error != 0); 201 1.1 christos 202 1.1 christos /* 203 1.1 christos * Check for error != 0 so that we don't do the wrong thing if somebody 204 1.1 christos * tries to abuse this API when asserts are disabled. 205 1.1 christos */ 206 1.1 christos if (nvl != NULL && error != 0 && nvl->nvl_error == 0) 207 1.1 christos nvl->nvl_error = error; 208 1.1 christos } 209 1.1 christos 210 1.1 christos int 211 1.1 christos nvlist_error(const nvlist_t *nvl) 212 1.1 christos { 213 1.1 christos 214 1.1 christos if (nvl == NULL) 215 1.1 christos return (ENOMEM); 216 1.1 christos 217 1.1 christos NVLIST_ASSERT(nvl); 218 1.1 christos 219 1.1 christos return (nvl->nvl_error); 220 1.1 christos } 221 1.1 christos 222 1.1 christos nvpair_t * 223 1.1 christos nvlist_get_nvpair_parent(const nvlist_t *nvl) 224 1.1 christos { 225 1.1 christos 226 1.1 christos NVLIST_ASSERT(nvl); 227 1.1 christos 228 1.1 christos return (nvl->nvl_parent); 229 1.1 christos } 230 1.1 christos 231 1.1 christos const nvlist_t * 232 1.1 christos nvlist_get_parent(const nvlist_t *nvl, void **cookiep) 233 1.1 christos { 234 1.1 christos nvpair_t *nvp; 235 1.1 christos 236 1.1 christos NVLIST_ASSERT(nvl); 237 1.1 christos 238 1.1 christos nvp = nvl->nvl_parent; 239 1.1 christos if (cookiep != NULL) 240 1.1 christos *cookiep = nvp; 241 1.1 christos if (nvp == NULL) 242 1.1 christos return (NULL); 243 1.1 christos 244 1.1 christos return (nvpair_nvlist(nvp)); 245 1.1 christos } 246 1.1 christos 247 1.1 christos void 248 1.1 christos nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent) 249 1.1 christos { 250 1.1 christos 251 1.1 christos NVLIST_ASSERT(nvl); 252 1.1 christos 253 1.1 christos nvl->nvl_parent = parent; 254 1.1 christos } 255 1.1 christos 256 1.1 christos void 257 1.1 christos nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele) 258 1.1 christos { 259 1.1 christos 260 1.1 christos NVLIST_ASSERT(nvl); 261 1.1 christos 262 1.1 christos if (ele != NULL) { 263 1.1 christos nvl->nvl_flags |= NV_FLAG_IN_ARRAY; 264 1.1 christos } else { 265 1.1 christos nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY; 266 1.1 christos nv_free(nvl->nvl_array_next); 267 1.1 christos } 268 1.1 christos 269 1.1 christos nvl->nvl_array_next = ele; 270 1.1 christos } 271 1.1 christos 272 1.7 rmind nvpair_t * 273 1.7 rmind nvlist_get_array_next_nvpair(nvlist_t *nvl) 274 1.7 rmind { 275 1.7 rmind 276 1.7 rmind NVLIST_ASSERT(nvl); 277 1.7 rmind 278 1.7 rmind return (nvl->nvl_array_next); 279 1.7 rmind } 280 1.7 rmind 281 1.1 christos bool 282 1.1 christos nvlist_in_array(const nvlist_t *nvl) 283 1.1 christos { 284 1.1 christos 285 1.1 christos NVLIST_ASSERT(nvl); 286 1.1 christos 287 1.1 christos return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0); 288 1.1 christos } 289 1.1 christos 290 1.1 christos const nvlist_t * 291 1.1 christos nvlist_get_array_next(const nvlist_t *nvl) 292 1.1 christos { 293 1.1 christos nvpair_t *nvp; 294 1.1 christos 295 1.1 christos NVLIST_ASSERT(nvl); 296 1.1 christos 297 1.1 christos nvp = nvl->nvl_array_next; 298 1.1 christos if (nvp == NULL) 299 1.1 christos return (NULL); 300 1.1 christos 301 1.1 christos return (nvpair_get_nvlist(nvp)); 302 1.1 christos } 303 1.1 christos 304 1.1 christos const nvlist_t * 305 1.1 christos nvlist_get_pararr(const nvlist_t *nvl, void **cookiep) 306 1.1 christos { 307 1.1 christos const nvlist_t *ret; 308 1.1 christos 309 1.1 christos ret = nvlist_get_array_next(nvl); 310 1.1 christos if (ret != NULL) { 311 1.1 christos if (cookiep != NULL) 312 1.1 christos *cookiep = NULL; 313 1.1 christos return (ret); 314 1.1 christos } 315 1.1 christos 316 1.1 christos return (nvlist_get_parent(nvl, cookiep)); 317 1.1 christos } 318 1.1 christos 319 1.1 christos bool 320 1.1 christos nvlist_empty(const nvlist_t *nvl) 321 1.1 christos { 322 1.1 christos 323 1.1 christos NVLIST_ASSERT(nvl); 324 1.1 christos PJDLOG_ASSERT(nvl->nvl_error == 0); 325 1.1 christos 326 1.1 christos return (nvlist_first_nvpair(nvl) == NULL); 327 1.1 christos } 328 1.1 christos 329 1.1 christos int 330 1.1 christos nvlist_flags(const nvlist_t *nvl) 331 1.1 christos { 332 1.1 christos 333 1.1 christos NVLIST_ASSERT(nvl); 334 1.1 christos PJDLOG_ASSERT(nvl->nvl_error == 0); 335 1.1 christos 336 1.1 christos return (nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); 337 1.1 christos } 338 1.1 christos 339 1.1 christos void 340 1.1 christos nvlist_set_flags(nvlist_t *nvl, int flags) 341 1.1 christos { 342 1.1 christos 343 1.1 christos NVLIST_ASSERT(nvl); 344 1.1 christos PJDLOG_ASSERT(nvl->nvl_error == 0); 345 1.1 christos 346 1.1 christos nvl->nvl_flags = flags; 347 1.1 christos } 348 1.1 christos 349 1.5 christos __dead void 350 1.1 christos nvlist_report_missing(int type, const char *name) 351 1.1 christos { 352 1.1 christos 353 1.1 christos PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", 354 1.1 christos name, nvpair_type_string(type)); 355 1.1 christos } 356 1.1 christos 357 1.1 christos static nvpair_t * 358 1.1 christos nvlist_find(const nvlist_t *nvl, int type, const char *name) 359 1.1 christos { 360 1.1 christos nvpair_t *nvp; 361 1.1 christos 362 1.1 christos NVLIST_ASSERT(nvl); 363 1.1 christos PJDLOG_ASSERT(nvl->nvl_error == 0); 364 1.1 christos PJDLOG_ASSERT(type == NV_TYPE_NONE || 365 1.1 christos (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 366 1.1 christos 367 1.1 christos for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 368 1.1 christos nvp = nvlist_next_nvpair(nvl, nvp)) { 369 1.1 christos if (type != NV_TYPE_NONE && nvpair_type(nvp) != type) 370 1.1 christos continue; 371 1.1 christos if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) { 372 1.1 christos if (strcasecmp(nvpair_name(nvp), name) != 0) 373 1.1 christos continue; 374 1.1 christos } else { 375 1.1 christos if (strcmp(nvpair_name(nvp), name) != 0) 376 1.1 christos continue; 377 1.1 christos } 378 1.1 christos break; 379 1.1 christos } 380 1.1 christos 381 1.1 christos if (nvp == NULL) 382 1.1 christos ERRNO_SET(ENOENT); 383 1.1 christos 384 1.1 christos return (nvp); 385 1.1 christos } 386 1.1 christos 387 1.1 christos bool 388 1.1 christos nvlist_exists_type(const nvlist_t *nvl, const char *name, int type) 389 1.1 christos { 390 1.1 christos 391 1.1 christos NVLIST_ASSERT(nvl); 392 1.1 christos PJDLOG_ASSERT(nvl->nvl_error == 0); 393 1.1 christos PJDLOG_ASSERT(type == NV_TYPE_NONE || 394 1.1 christos (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 395 1.1 christos 396 1.1 christos return (nvlist_find(nvl, type, name) != NULL); 397 1.1 christos } 398 1.1 christos 399 1.1 christos void 400 1.1 christos nvlist_free_type(nvlist_t *nvl, const char *name, int type) 401 1.1 christos { 402 1.1 christos nvpair_t *nvp; 403 1.1 christos 404 1.1 christos NVLIST_ASSERT(nvl); 405 1.1 christos PJDLOG_ASSERT(nvl->nvl_error == 0); 406 1.1 christos PJDLOG_ASSERT(type == NV_TYPE_NONE || 407 1.1 christos (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); 408 1.1 christos 409 1.1 christos nvp = nvlist_find(nvl, type, name); 410 1.1 christos if (nvp != NULL) 411 1.1 christos nvlist_free_nvpair(nvl, nvp); 412 1.1 christos else 413 1.1 christos nvlist_report_missing(type, name); 414 1.1 christos } 415 1.1 christos 416 1.1 christos nvlist_t * 417 1.1 christos nvlist_clone(const nvlist_t *nvl) 418 1.1 christos { 419 1.1 christos nvlist_t *newnvl; 420 1.1 christos nvpair_t *nvp, *newnvp; 421 1.1 christos 422 1.1 christos NVLIST_ASSERT(nvl); 423 1.1 christos 424 1.1 christos if (nvl->nvl_error != 0) { 425 1.1 christos ERRNO_SET(nvl->nvl_error); 426 1.1 christos return (NULL); 427 1.1 christos } 428 1.1 christos 429 1.1 christos newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); 430 1.1 christos for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; 431 1.1 christos nvp = nvlist_next_nvpair(nvl, nvp)) { 432 1.1 christos newnvp = nvpair_clone(nvp); 433 1.1 christos if (newnvp == NULL) 434 1.1 christos break; 435 1.1 christos (void)nvlist_move_nvpair(newnvl, newnvp); 436 1.1 christos } 437 1.1 christos if (nvp != NULL) { 438 1.1 christos nvlist_destroy(newnvl); 439 1.1 christos return (NULL); 440 1.1 christos } 441 1.1 christos return (newnvl); 442 1.1 christos } 443 1.1 christos 444 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 445 1.1 christos static bool 446 1.1 christos nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level) 447 1.1 christos { 448 1.1 christos 449 1.1 christos if (nvlist_error(nvl) != 0) { 450 1.1 christos dprintf(fd, "%*serror: %d\n", level * 4, "", 451 1.1 christos nvlist_error(nvl)); 452 1.1 christos return (true); 453 1.1 christos } 454 1.1 christos 455 1.1 christos return (false); 456 1.1 christos } 457 1.1 christos 458 1.1 christos /* 459 1.1 christos * Dump content of nvlist. 460 1.1 christos */ 461 1.1 christos void 462 1.1 christos nvlist_dump(const nvlist_t *nvl, int fd) 463 1.1 christos { 464 1.1 christos const nvlist_t *tmpnvl; 465 1.1 christos nvpair_t *nvp, *tmpnvp; 466 1.1 christos void *cookie; 467 1.1 christos int level; 468 1.1 christos 469 1.1 christos level = 0; 470 1.1 christos if (nvlist_dump_error_check(nvl, fd, level)) 471 1.1 christos return; 472 1.1 christos 473 1.1 christos nvp = nvlist_first_nvpair(nvl); 474 1.1 christos while (nvp != NULL) { 475 1.1 christos dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), 476 1.1 christos nvpair_type_string(nvpair_type(nvp))); 477 1.1 christos switch (nvpair_type(nvp)) { 478 1.1 christos case NV_TYPE_NULL: 479 1.1 christos dprintf(fd, " null\n"); 480 1.1 christos break; 481 1.1 christos case NV_TYPE_BOOL: 482 1.1 christos dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? 483 1.1 christos "TRUE" : "FALSE"); 484 1.1 christos break; 485 1.1 christos case NV_TYPE_NUMBER: 486 1.1 christos dprintf(fd, " %ju (%jd) (0x%jx)\n", 487 1.1 christos (uintmax_t)nvpair_get_number(nvp), 488 1.1 christos (intmax_t)nvpair_get_number(nvp), 489 1.1 christos (uintmax_t)nvpair_get_number(nvp)); 490 1.1 christos break; 491 1.1 christos case NV_TYPE_STRING: 492 1.1 christos dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); 493 1.1 christos break; 494 1.1 christos case NV_TYPE_NVLIST: 495 1.1 christos dprintf(fd, "\n"); 496 1.1 christos tmpnvl = nvpair_get_nvlist(nvp); 497 1.1 christos if (nvlist_dump_error_check(tmpnvl, fd, level + 1)) 498 1.1 christos break; 499 1.1 christos tmpnvp = nvlist_first_nvpair(tmpnvl); 500 1.1 christos if (tmpnvp != NULL) { 501 1.1 christos nvl = tmpnvl; 502 1.1 christos nvp = tmpnvp; 503 1.1 christos level++; 504 1.1 christos continue; 505 1.1 christos } 506 1.1 christos break; 507 1.1 christos case NV_TYPE_DESCRIPTOR: 508 1.1 christos dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); 509 1.1 christos break; 510 1.1 christos case NV_TYPE_BINARY: 511 1.1 christos { 512 1.1 christos const unsigned char *binary; 513 1.1 christos unsigned int ii; 514 1.1 christos size_t size; 515 1.1 christos 516 1.1 christos binary = nvpair_get_binary(nvp, &size); 517 1.1 christos dprintf(fd, " %zu ", size); 518 1.1 christos for (ii = 0; ii < size; ii++) 519 1.1 christos dprintf(fd, "%02hhx", binary[ii]); 520 1.1 christos dprintf(fd, "\n"); 521 1.1 christos break; 522 1.1 christos } 523 1.1 christos case NV_TYPE_BOOL_ARRAY: 524 1.1 christos { 525 1.1 christos const bool *value; 526 1.1 christos unsigned int ii; 527 1.1 christos size_t nitems; 528 1.1 christos 529 1.1 christos value = nvpair_get_bool_array(nvp, &nitems); 530 1.1 christos dprintf(fd, " [ "); 531 1.1 christos for (ii = 0; ii < nitems; ii++) { 532 1.1 christos dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE"); 533 1.1 christos if (ii != nitems - 1) 534 1.1 christos dprintf(fd, ", "); 535 1.1 christos } 536 1.1 christos dprintf(fd, " ]\n"); 537 1.1 christos break; 538 1.1 christos } 539 1.1 christos case NV_TYPE_STRING_ARRAY: 540 1.1 christos { 541 1.1 christos const char * const *value; 542 1.1 christos unsigned int ii; 543 1.1 christos size_t nitems; 544 1.1 christos 545 1.1 christos value = nvpair_get_string_array(nvp, &nitems); 546 1.1 christos dprintf(fd, " [ "); 547 1.1 christos for (ii = 0; ii < nitems; ii++) { 548 1.1 christos if (value[ii] == NULL) 549 1.1 christos dprintf(fd, "NULL"); 550 1.1 christos else 551 1.1 christos dprintf(fd, "\"%s\"", value[ii]); 552 1.1 christos if (ii != nitems - 1) 553 1.1 christos dprintf(fd, ", "); 554 1.1 christos } 555 1.1 christos dprintf(fd, " ]\n"); 556 1.1 christos break; 557 1.1 christos } 558 1.1 christos case NV_TYPE_NUMBER_ARRAY: 559 1.1 christos { 560 1.1 christos const uint64_t *value; 561 1.1 christos unsigned int ii; 562 1.1 christos size_t nitems; 563 1.1 christos 564 1.1 christos value = nvpair_get_number_array(nvp, &nitems); 565 1.1 christos dprintf(fd, " [ "); 566 1.1 christos for (ii = 0; ii < nitems; ii++) { 567 1.1 christos dprintf(fd, "%ju (%jd) (0x%jx)", 568 1.1 christos value[ii], value[ii], value[ii]); 569 1.1 christos if (ii != nitems - 1) 570 1.1 christos dprintf(fd, ", "); 571 1.1 christos } 572 1.1 christos dprintf(fd, " ]\n"); 573 1.1 christos break; 574 1.1 christos } 575 1.1 christos case NV_TYPE_DESCRIPTOR_ARRAY: 576 1.1 christos { 577 1.1 christos const int *value; 578 1.1 christos unsigned int ii; 579 1.1 christos size_t nitems; 580 1.1 christos 581 1.1 christos value = nvpair_get_descriptor_array(nvp, &nitems); 582 1.1 christos dprintf(fd, " [ "); 583 1.1 christos for (ii = 0; ii < nitems; ii++) { 584 1.1 christos dprintf(fd, "%d", value[ii]); 585 1.1 christos if (ii != nitems - 1) 586 1.1 christos dprintf(fd, ", "); 587 1.1 christos } 588 1.1 christos dprintf(fd, " ]\n"); 589 1.1 christos break; 590 1.1 christos } 591 1.1 christos case NV_TYPE_NVLIST_ARRAY: 592 1.1 christos { 593 1.1 christos const nvlist_t * const *value; 594 1.1 christos unsigned int ii; 595 1.1 christos size_t nitems; 596 1.1 christos 597 1.1 christos value = nvpair_get_nvlist_array(nvp, &nitems); 598 1.1 christos dprintf(fd, " %zu\n", nitems); 599 1.1 christos tmpnvl = NULL; 600 1.1 christos tmpnvp = NULL; 601 1.1 christos for (ii = 0; ii < nitems; ii++) { 602 1.1 christos if (nvlist_dump_error_check(value[ii], fd, 603 1.1 christos level + 1)) { 604 1.1 christos break; 605 1.1 christos } 606 1.1 christos 607 1.1 christos if (tmpnvl == NULL) { 608 1.1 christos tmpnvp = nvlist_first_nvpair(value[ii]); 609 1.1 christos if (tmpnvp != NULL) { 610 1.1 christos tmpnvl = value[ii]; 611 1.1 christos } else { 612 1.1 christos dprintf(fd, "%*s,\n", 613 1.1 christos (level + 1) * 4, ""); 614 1.1 christos } 615 1.1 christos } 616 1.1 christos } 617 1.1 christos if (tmpnvp != NULL) { 618 1.1 christos nvl = tmpnvl; 619 1.1 christos nvp = tmpnvp; 620 1.1 christos level++; 621 1.1 christos continue; 622 1.1 christos } 623 1.1 christos break; 624 1.1 christos } 625 1.1 christos default: 626 1.1 christos PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); 627 1.1 christos } 628 1.1 christos 629 1.1 christos while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 630 1.1 christos do { 631 1.1 christos cookie = NULL; 632 1.1 christos if (nvlist_in_array(nvl)) 633 1.1 christos dprintf(fd, "%*s,\n", level * 4, ""); 634 1.1 christos nvl = nvlist_get_pararr(nvl, &cookie); 635 1.1 christos if (nvl == NULL) 636 1.1 christos return; 637 1.1 christos if (nvlist_in_array(nvl) && cookie == NULL) { 638 1.1 christos nvp = nvlist_first_nvpair(nvl); 639 1.1 christos } else { 640 1.1 christos nvp = cookie; 641 1.1 christos level--; 642 1.1 christos } 643 1.1 christos } while (nvp == NULL); 644 1.1 christos if (nvlist_in_array(nvl) && cookie == NULL) 645 1.1 christos break; 646 1.1 christos } 647 1.1 christos } 648 1.1 christos } 649 1.1 christos 650 1.1 christos void 651 1.1 christos nvlist_fdump(const nvlist_t *nvl, FILE *fp) 652 1.1 christos { 653 1.1 christos 654 1.1 christos fflush(fp); 655 1.1 christos nvlist_dump(nvl, fileno(fp)); 656 1.1 christos } 657 1.1 christos #endif 658 1.1 christos 659 1.1 christos /* 660 1.1 christos * The function obtains size of the nvlist after nvlist_pack(). 661 1.1 christos */ 662 1.1 christos size_t 663 1.1 christos nvlist_size(const nvlist_t *nvl) 664 1.1 christos { 665 1.1 christos const nvlist_t *tmpnvl; 666 1.1 christos const nvlist_t * const *nvlarray; 667 1.1 christos const nvpair_t *nvp, *tmpnvp; 668 1.1 christos void *cookie; 669 1.1 christos size_t size, nitems; 670 1.1 christos unsigned int ii; 671 1.1 christos 672 1.1 christos NVLIST_ASSERT(nvl); 673 1.1 christos PJDLOG_ASSERT(nvl->nvl_error == 0); 674 1.1 christos 675 1.1 christos size = sizeof(struct nvlist_header); 676 1.1 christos nvp = nvlist_first_nvpair(nvl); 677 1.1 christos while (nvp != NULL) { 678 1.1 christos size += nvpair_header_size(); 679 1.1 christos size += strlen(nvpair_name(nvp)) + 1; 680 1.1 christos if (nvpair_type(nvp) == NV_TYPE_NVLIST) { 681 1.1 christos size += sizeof(struct nvlist_header); 682 1.1 christos size += nvpair_header_size() + 1; 683 1.1 christos tmpnvl = nvpair_get_nvlist(nvp); 684 1.1 christos PJDLOG_ASSERT(tmpnvl->nvl_error == 0); 685 1.1 christos tmpnvp = nvlist_first_nvpair(tmpnvl); 686 1.1 christos if (tmpnvp != NULL) { 687 1.1 christos nvl = tmpnvl; 688 1.1 christos nvp = tmpnvp; 689 1.1 christos continue; 690 1.1 christos } 691 1.1 christos } else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) { 692 1.1 christos nvlarray = nvpair_get_nvlist_array(nvp, &nitems); 693 1.1 christos PJDLOG_ASSERT(nitems > 0); 694 1.1 christos 695 1.1 christos size += (nvpair_header_size() + 1) * nitems; 696 1.1 christos size += sizeof(struct nvlist_header) * nitems; 697 1.1 christos 698 1.1 christos tmpnvl = NULL; 699 1.1 christos tmpnvp = NULL; 700 1.1 christos for (ii = 0; ii < nitems; ii++) { 701 1.1 christos PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0); 702 1.1 christos tmpnvp = nvlist_first_nvpair(nvlarray[ii]); 703 1.1 christos if (tmpnvp != NULL) { 704 1.1 christos tmpnvl = nvlarray[ii]; 705 1.1 christos break; 706 1.1 christos } 707 1.1 christos } 708 1.1 christos if (tmpnvp != NULL) { 709 1.1 christos nvp = tmpnvp; 710 1.1 christos nvl = tmpnvl; 711 1.1 christos continue; 712 1.1 christos } 713 1.1 christos 714 1.1 christos } else { 715 1.1 christos size += nvpair_size(nvp); 716 1.1 christos } 717 1.1 christos 718 1.1 christos while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 719 1.1 christos do { 720 1.1 christos cookie = NULL; 721 1.1 christos nvl = nvlist_get_pararr(nvl, &cookie); 722 1.1 christos if (nvl == NULL) 723 1.1 christos goto out; 724 1.1 christos if (nvlist_in_array(nvl) && cookie == NULL) { 725 1.1 christos nvp = nvlist_first_nvpair(nvl); 726 1.1 christos } else { 727 1.1 christos nvp = cookie; 728 1.1 christos } 729 1.1 christos } while (nvp == NULL); 730 1.1 christos if (nvlist_in_array(nvl) && cookie == NULL) 731 1.1 christos break; 732 1.1 christos } 733 1.1 christos } 734 1.1 christos 735 1.1 christos out: 736 1.1 christos return (size); 737 1.1 christos } 738 1.1 christos 739 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 740 1.1 christos static int * 741 1.1 christos nvlist_xdescriptors(const nvlist_t *nvl, int *descs) 742 1.1 christos { 743 1.1 christos void *cookie; 744 1.1 christos nvpair_t *nvp; 745 1.1 christos int type; 746 1.1 christos 747 1.1 christos NVLIST_ASSERT(nvl); 748 1.1 christos PJDLOG_ASSERT(nvl->nvl_error == 0); 749 1.1 christos 750 1.1 christos cookie = NULL; 751 1.1 christos do { 752 1.1 christos while (nvlist_next(nvl, &type, &cookie) != NULL) { 753 1.1 christos nvp = cookie; 754 1.1 christos switch (type) { 755 1.1 christos case NV_TYPE_DESCRIPTOR: 756 1.1 christos *descs = nvpair_get_descriptor(nvp); 757 1.1 christos descs++; 758 1.1 christos break; 759 1.1 christos case NV_TYPE_DESCRIPTOR_ARRAY: 760 1.1 christos { 761 1.1 christos const int *value; 762 1.1 christos size_t nitems; 763 1.1 christos unsigned int ii; 764 1.1 christos 765 1.1 christos value = nvpair_get_descriptor_array(nvp, 766 1.1 christos &nitems); 767 1.1 christos for (ii = 0; ii < nitems; ii++) { 768 1.1 christos *descs = value[ii]; 769 1.1 christos descs++; 770 1.1 christos } 771 1.1 christos break; 772 1.1 christos } 773 1.1 christos case NV_TYPE_NVLIST: 774 1.1 christos nvl = nvpair_get_nvlist(nvp); 775 1.1 christos cookie = NULL; 776 1.1 christos break; 777 1.1 christos case NV_TYPE_NVLIST_ARRAY: 778 1.1 christos { 779 1.1 christos const nvlist_t * const *value; 780 1.1 christos size_t nitems; 781 1.1 christos 782 1.1 christos value = nvpair_get_nvlist_array(nvp, &nitems); 783 1.1 christos PJDLOG_ASSERT(value != NULL); 784 1.1 christos PJDLOG_ASSERT(nitems > 0); 785 1.1 christos 786 1.1 christos nvl = value[0]; 787 1.1 christos cookie = NULL; 788 1.1 christos break; 789 1.1 christos } 790 1.1 christos } 791 1.1 christos } 792 1.1 christos } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL); 793 1.1 christos 794 1.1 christos return (descs); 795 1.1 christos } 796 1.1 christos #endif 797 1.1 christos 798 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 799 1.1 christos int * 800 1.1 christos nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp) 801 1.1 christos { 802 1.1 christos size_t nitems; 803 1.1 christos int *fds; 804 1.1 christos 805 1.1 christos nitems = nvlist_ndescriptors(nvl); 806 1.10 riastrad fds = nv_calloc(nitems + 1, sizeof(fds[0])); 807 1.1 christos if (fds == NULL) 808 1.1 christos return (NULL); 809 1.1 christos if (nitems > 0) 810 1.1 christos nvlist_xdescriptors(nvl, fds); 811 1.1 christos fds[nitems] = -1; 812 1.1 christos if (nitemsp != NULL) 813 1.1 christos *nitemsp = nitems; 814 1.1 christos return (fds); 815 1.1 christos } 816 1.1 christos #endif 817 1.1 christos 818 1.1 christos size_t 819 1.1 christos nvlist_ndescriptors(const nvlist_t *nvl) 820 1.1 christos { 821 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 822 1.1 christos void *cookie; 823 1.1 christos nvpair_t *nvp; 824 1.1 christos size_t ndescs; 825 1.1 christos int type; 826 1.1 christos 827 1.1 christos NVLIST_ASSERT(nvl); 828 1.1 christos PJDLOG_ASSERT(nvl->nvl_error == 0); 829 1.1 christos 830 1.1 christos ndescs = 0; 831 1.1 christos cookie = NULL; 832 1.1 christos do { 833 1.1 christos while (nvlist_next(nvl, &type, &cookie) != NULL) { 834 1.1 christos nvp = cookie; 835 1.1 christos switch (type) { 836 1.1 christos case NV_TYPE_DESCRIPTOR: 837 1.1 christos ndescs++; 838 1.1 christos break; 839 1.1 christos case NV_TYPE_NVLIST: 840 1.1 christos nvl = nvpair_get_nvlist(nvp); 841 1.1 christos cookie = NULL; 842 1.1 christos break; 843 1.1 christos case NV_TYPE_NVLIST_ARRAY: 844 1.1 christos { 845 1.1 christos const nvlist_t * const *value; 846 1.1 christos size_t nitems; 847 1.1 christos 848 1.1 christos value = nvpair_get_nvlist_array(nvp, &nitems); 849 1.1 christos PJDLOG_ASSERT(value != NULL); 850 1.1 christos PJDLOG_ASSERT(nitems > 0); 851 1.1 christos 852 1.1 christos nvl = value[0]; 853 1.1 christos cookie = NULL; 854 1.1 christos break; 855 1.1 christos } 856 1.1 christos case NV_TYPE_DESCRIPTOR_ARRAY: 857 1.1 christos { 858 1.1 christos size_t nitems; 859 1.1 christos 860 1.1 christos (void)nvpair_get_descriptor_array(nvp, 861 1.1 christos &nitems); 862 1.1 christos ndescs += nitems; 863 1.1 christos break; 864 1.1 christos } 865 1.1 christos } 866 1.1 christos } 867 1.1 christos } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL); 868 1.1 christos 869 1.1 christos return (ndescs); 870 1.1 christos #else 871 1.1 christos return (0); 872 1.1 christos #endif 873 1.1 christos } 874 1.1 christos 875 1.1 christos static unsigned char * 876 1.1 christos nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp) 877 1.1 christos { 878 1.1 christos struct nvlist_header nvlhdr; 879 1.1 christos 880 1.1 christos NVLIST_ASSERT(nvl); 881 1.1 christos 882 1.1 christos nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC; 883 1.1 christos nvlhdr.nvlh_version = NVLIST_HEADER_VERSION; 884 1.1 christos nvlhdr.nvlh_flags = nvl->nvl_flags; 885 1.1 christos #if BYTE_ORDER == BIG_ENDIAN 886 1.1 christos nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN; 887 1.1 christos #endif 888 1.1 christos nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl); 889 1.1 christos nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr); 890 1.1 christos PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr)); 891 1.1 christos memcpy(ptr, &nvlhdr, sizeof(nvlhdr)); 892 1.1 christos ptr += sizeof(nvlhdr); 893 1.1 christos *leftp -= sizeof(nvlhdr); 894 1.1 christos 895 1.1 christos return (ptr); 896 1.1 christos } 897 1.1 christos 898 1.1 christos static void * 899 1.1 christos nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) 900 1.1 christos { 901 1.1 christos unsigned char *buf, *ptr; 902 1.1 christos size_t left, size; 903 1.1 christos const nvlist_t *tmpnvl; 904 1.1 christos nvpair_t *nvp, *tmpnvp; 905 1.1 christos void *cookie; 906 1.1 christos 907 1.1 christos NVLIST_ASSERT(nvl); 908 1.1 christos 909 1.1 christos if (nvl->nvl_error != 0) { 910 1.1 christos ERRNO_SET(nvl->nvl_error); 911 1.1 christos return (NULL); 912 1.1 christos } 913 1.1 christos 914 1.1 christos size = nvlist_size(nvl); 915 1.1 christos buf = nv_malloc(size); 916 1.1 christos if (buf == NULL) 917 1.1 christos return (NULL); 918 1.1 christos 919 1.1 christos ptr = buf; 920 1.1 christos left = size; 921 1.1 christos 922 1.1 christos ptr = nvlist_pack_header(nvl, ptr, &left); 923 1.1 christos 924 1.1 christos nvp = nvlist_first_nvpair(nvl); 925 1.1 christos while (nvp != NULL) { 926 1.1 christos NVPAIR_ASSERT(nvp); 927 1.1 christos 928 1.1 christos nvpair_init_datasize(nvp); 929 1.1 christos ptr = nvpair_pack_header(nvp, ptr, &left); 930 1.1 christos if (ptr == NULL) 931 1.1 christos goto fail; 932 1.1 christos switch (nvpair_type(nvp)) { 933 1.1 christos case NV_TYPE_NULL: 934 1.1 christos ptr = nvpair_pack_null(nvp, ptr, &left); 935 1.1 christos break; 936 1.1 christos case NV_TYPE_BOOL: 937 1.1 christos ptr = nvpair_pack_bool(nvp, ptr, &left); 938 1.1 christos break; 939 1.1 christos case NV_TYPE_NUMBER: 940 1.1 christos ptr = nvpair_pack_number(nvp, ptr, &left); 941 1.1 christos break; 942 1.1 christos case NV_TYPE_STRING: 943 1.1 christos ptr = nvpair_pack_string(nvp, ptr, &left); 944 1.1 christos break; 945 1.1 christos case NV_TYPE_NVLIST: 946 1.1 christos tmpnvl = nvpair_get_nvlist(nvp); 947 1.1 christos ptr = nvlist_pack_header(tmpnvl, ptr, &left); 948 1.1 christos if (ptr == NULL) 949 1.1 christos goto fail; 950 1.1 christos tmpnvp = nvlist_first_nvpair(tmpnvl); 951 1.1 christos if (tmpnvp != NULL) { 952 1.1 christos nvl = tmpnvl; 953 1.1 christos nvp = tmpnvp; 954 1.1 christos continue; 955 1.1 christos } 956 1.1 christos ptr = nvpair_pack_nvlist_up(ptr, &left); 957 1.1 christos break; 958 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 959 1.1 christos case NV_TYPE_DESCRIPTOR: 960 1.1 christos ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left); 961 1.1 christos break; 962 1.1 christos case NV_TYPE_DESCRIPTOR_ARRAY: 963 1.1 christos ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp, 964 1.1 christos &left); 965 1.1 christos break; 966 1.1 christos #endif 967 1.1 christos case NV_TYPE_BINARY: 968 1.1 christos ptr = nvpair_pack_binary(nvp, ptr, &left); 969 1.1 christos break; 970 1.1 christos case NV_TYPE_BOOL_ARRAY: 971 1.1 christos ptr = nvpair_pack_bool_array(nvp, ptr, &left); 972 1.1 christos break; 973 1.1 christos case NV_TYPE_NUMBER_ARRAY: 974 1.1 christos ptr = nvpair_pack_number_array(nvp, ptr, &left); 975 1.1 christos break; 976 1.1 christos case NV_TYPE_STRING_ARRAY: 977 1.1 christos ptr = nvpair_pack_string_array(nvp, ptr, &left); 978 1.1 christos break; 979 1.1 christos case NV_TYPE_NVLIST_ARRAY: 980 1.1 christos { 981 1.1 christos const nvlist_t * const * value; 982 1.1 christos size_t nitems; 983 1.1 christos unsigned int ii; 984 1.1 christos 985 1.1 christos tmpnvl = NULL; 986 1.1 christos value = nvpair_get_nvlist_array(nvp, &nitems); 987 1.1 christos for (ii = 0; ii < nitems; ii++) { 988 1.1 christos ptr = nvlist_pack_header(value[ii], ptr, &left); 989 1.1 christos if (ptr == NULL) 990 1.1 christos goto out; 991 1.1 christos tmpnvp = nvlist_first_nvpair(value[ii]); 992 1.1 christos if (tmpnvp != NULL) { 993 1.1 christos tmpnvl = value[ii]; 994 1.1 christos break; 995 1.1 christos } 996 1.1 christos ptr = nvpair_pack_nvlist_array_next(ptr, &left); 997 1.1 christos if (ptr == NULL) 998 1.1 christos goto out; 999 1.1 christos } 1000 1.1 christos if (tmpnvl != NULL) { 1001 1.1 christos nvl = tmpnvl; 1002 1.1 christos nvp = tmpnvp; 1003 1.1 christos continue; 1004 1.1 christos } 1005 1.1 christos break; 1006 1.1 christos } 1007 1.1 christos default: 1008 1.1 christos PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 1009 1.1 christos } 1010 1.1 christos if (ptr == NULL) 1011 1.1 christos goto fail; 1012 1.1 christos while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { 1013 1.1 christos do { 1014 1.1 christos cookie = NULL; 1015 1.1 christos if (nvlist_in_array(nvl)) { 1016 1.1 christos ptr = nvpair_pack_nvlist_array_next(ptr, 1017 1.1 christos &left); 1018 1.1 christos if (ptr == NULL) 1019 1.1 christos goto fail; 1020 1.1 christos } 1021 1.1 christos nvl = nvlist_get_pararr(nvl, &cookie); 1022 1.1 christos if (nvl == NULL) 1023 1.1 christos goto out; 1024 1.1 christos if (nvlist_in_array(nvl) && cookie == NULL) { 1025 1.1 christos nvp = nvlist_first_nvpair(nvl); 1026 1.1 christos ptr = nvlist_pack_header(nvl, ptr, 1027 1.1 christos &left); 1028 1.1 christos if (ptr == NULL) 1029 1.1 christos goto fail; 1030 1.1 christos } else if (nvpair_type((nvpair_t *)cookie) != 1031 1.1 christos NV_TYPE_NVLIST_ARRAY) { 1032 1.1 christos ptr = nvpair_pack_nvlist_up(ptr, &left); 1033 1.1 christos if (ptr == NULL) 1034 1.1 christos goto fail; 1035 1.1 christos nvp = cookie; 1036 1.1 christos } else { 1037 1.1 christos nvp = cookie; 1038 1.1 christos } 1039 1.1 christos } while (nvp == NULL); 1040 1.1 christos if (nvlist_in_array(nvl) && cookie == NULL) 1041 1.1 christos break; 1042 1.1 christos } 1043 1.1 christos } 1044 1.1 christos 1045 1.1 christos out: 1046 1.1 christos if (sizep != NULL) 1047 1.1 christos *sizep = size; 1048 1.1 christos return (buf); 1049 1.1 christos fail: 1050 1.1 christos nv_free(buf); 1051 1.1 christos return (NULL); 1052 1.1 christos } 1053 1.1 christos 1054 1.1 christos void * 1055 1.1 christos nvlist_pack(const nvlist_t *nvl, size_t *sizep) 1056 1.1 christos { 1057 1.1 christos 1058 1.1 christos NVLIST_ASSERT(nvl); 1059 1.1 christos 1060 1.1 christos if (nvl->nvl_error != 0) { 1061 1.1 christos ERRNO_SET(nvl->nvl_error); 1062 1.1 christos return (NULL); 1063 1.1 christos } 1064 1.1 christos 1065 1.1 christos if (nvlist_ndescriptors(nvl) > 0) { 1066 1.1 christos ERRNO_SET(EOPNOTSUPP); 1067 1.1 christos return (NULL); 1068 1.1 christos } 1069 1.1 christos 1070 1.1 christos return (nvlist_xpack(nvl, NULL, sizep)); 1071 1.1 christos } 1072 1.1 christos 1073 1.1 christos static bool 1074 1.1 christos nvlist_check_header(struct nvlist_header *nvlhdrp) 1075 1.1 christos { 1076 1.1 christos 1077 1.11 riastrad if (nvlhdrp->nvlh_size > SIZE_MAX - sizeof(*nvlhdrp)) { 1078 1.9 riastrad ERRNO_SET(EINVAL); 1079 1.9 riastrad return (false); 1080 1.9 riastrad } 1081 1.1 christos if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { 1082 1.1 christos ERRNO_SET(EINVAL); 1083 1.1 christos return (false); 1084 1.1 christos } 1085 1.1 christos if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { 1086 1.1 christos ERRNO_SET(EINVAL); 1087 1.1 christos return (false); 1088 1.1 christos } 1089 1.1 christos #if BYTE_ORDER == BIG_ENDIAN 1090 1.1 christos if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) { 1091 1.1 christos nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size); 1092 1.1 christos nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors); 1093 1.1 christos } 1094 1.1 christos #else 1095 1.1 christos if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) { 1096 1.1 christos nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size); 1097 1.1 christos nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); 1098 1.1 christos } 1099 1.1 christos #endif 1100 1.1 christos return (true); 1101 1.1 christos } 1102 1.1 christos 1103 1.1 christos const unsigned char * 1104 1.1 christos nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, 1105 1.1 christos bool *isbep, size_t *leftp) 1106 1.1 christos { 1107 1.1 christos struct nvlist_header nvlhdr; 1108 1.1 christos int inarrayf; 1109 1.1 christos 1110 1.1 christos if (*leftp < sizeof(nvlhdr)) 1111 1.1 christos goto fail; 1112 1.1 christos 1113 1.1 christos memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); 1114 1.1 christos 1115 1.1 christos if (!nvlist_check_header(&nvlhdr)) 1116 1.1 christos goto fail; 1117 1.1 christos 1118 1.1 christos if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) 1119 1.1 christos goto fail; 1120 1.1 christos 1121 1.1 christos /* 1122 1.1 christos * nvlh_descriptors might be smaller than nfds in embedded nvlists. 1123 1.1 christos */ 1124 1.1 christos if (nvlhdr.nvlh_descriptors > nfds) 1125 1.1 christos goto fail; 1126 1.1 christos 1127 1.1 christos if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) 1128 1.1 christos goto fail; 1129 1.1 christos 1130 1.1 christos inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY); 1131 1.1 christos nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf; 1132 1.1 christos 1133 1.1 christos ptr += sizeof(nvlhdr); 1134 1.1 christos if (isbep != NULL) 1135 1.1 christos *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0); 1136 1.1 christos *leftp -= sizeof(nvlhdr); 1137 1.1 christos 1138 1.1 christos return (ptr); 1139 1.1 christos fail: 1140 1.1 christos ERRNO_SET(EINVAL); 1141 1.1 christos return (NULL); 1142 1.1 christos } 1143 1.1 christos 1144 1.1 christos static nvlist_t * 1145 1.1 christos nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds, 1146 1.1 christos int flags) 1147 1.1 christos { 1148 1.1 christos const unsigned char *ptr; 1149 1.1 christos nvlist_t *nvl, *retnvl, *tmpnvl, *array; 1150 1.1 christos nvpair_t *nvp; 1151 1.1 christos size_t left; 1152 1.1 christos bool isbe; 1153 1.1 christos 1154 1.1 christos PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); 1155 1.1 christos 1156 1.1 christos left = size; 1157 1.1 christos ptr = buf; 1158 1.1 christos 1159 1.1 christos tmpnvl = array = NULL; 1160 1.1 christos nvl = retnvl = nvlist_create(0); 1161 1.1 christos if (nvl == NULL) 1162 1.1 christos goto fail; 1163 1.1 christos 1164 1.1 christos ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); 1165 1.1 christos if (ptr == NULL) 1166 1.1 christos goto fail; 1167 1.1 christos if (nvl->nvl_flags != flags) { 1168 1.1 christos ERRNO_SET(EILSEQ); 1169 1.1 christos goto fail; 1170 1.1 christos } 1171 1.1 christos 1172 1.1 christos while (left > 0) { 1173 1.1 christos ptr = nvpair_unpack(isbe, ptr, &left, &nvp); 1174 1.1 christos if (ptr == NULL) 1175 1.1 christos goto fail; 1176 1.1 christos switch (nvpair_type(nvp)) { 1177 1.1 christos case NV_TYPE_NULL: 1178 1.1 christos ptr = nvpair_unpack_null(isbe, nvp, ptr, &left); 1179 1.1 christos break; 1180 1.1 christos case NV_TYPE_BOOL: 1181 1.1 christos ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left); 1182 1.1 christos break; 1183 1.1 christos case NV_TYPE_NUMBER: 1184 1.1 christos ptr = nvpair_unpack_number(isbe, nvp, ptr, &left); 1185 1.1 christos break; 1186 1.1 christos case NV_TYPE_STRING: 1187 1.1 christos ptr = nvpair_unpack_string(isbe, nvp, ptr, &left); 1188 1.1 christos break; 1189 1.1 christos case NV_TYPE_NVLIST: 1190 1.1 christos ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds, 1191 1.1 christos &tmpnvl); 1192 1.1 christos if (tmpnvl == NULL || ptr == NULL) 1193 1.1 christos goto fail; 1194 1.1 christos nvlist_set_parent(tmpnvl, nvp); 1195 1.1 christos break; 1196 1.6 rmind #if !defined(_KERNEL) && !defined(_STANDALONE) && !defined(__NetBSD__) 1197 1.1 christos case NV_TYPE_DESCRIPTOR: 1198 1.1 christos ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left, 1199 1.1 christos fds, nfds); 1200 1.1 christos break; 1201 1.1 christos case NV_TYPE_DESCRIPTOR_ARRAY: 1202 1.1 christos ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr, 1203 1.1 christos &left, fds, nfds); 1204 1.1 christos break; 1205 1.1 christos #endif 1206 1.1 christos case NV_TYPE_BINARY: 1207 1.1 christos ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left); 1208 1.1 christos break; 1209 1.1 christos case NV_TYPE_NVLIST_UP: 1210 1.1 christos if (nvl->nvl_parent == NULL) 1211 1.1 christos goto fail; 1212 1.1 christos nvl = nvpair_nvlist(nvl->nvl_parent); 1213 1.1 christos nvpair_free_structure(nvp); 1214 1.1 christos continue; 1215 1.1 christos case NV_TYPE_NVLIST_ARRAY_NEXT: 1216 1.1 christos if (nvl->nvl_array_next == NULL) { 1217 1.1 christos if (nvl->nvl_parent == NULL) 1218 1.1 christos goto fail; 1219 1.1 christos nvl = nvpair_nvlist(nvl->nvl_parent); 1220 1.1 christos } else { 1221 1.1 christos nvl = __DECONST(nvlist_t *, 1222 1.1 christos nvlist_get_array_next(nvl)); 1223 1.1 christos ptr = nvlist_unpack_header(nvl, ptr, nfds, 1224 1.1 christos &isbe, &left); 1225 1.1 christos if (ptr == NULL) 1226 1.1 christos goto fail; 1227 1.1 christos } 1228 1.1 christos nvpair_free_structure(nvp); 1229 1.1 christos continue; 1230 1.1 christos case NV_TYPE_BOOL_ARRAY: 1231 1.1 christos ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left); 1232 1.1 christos break; 1233 1.1 christos case NV_TYPE_NUMBER_ARRAY: 1234 1.1 christos ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left); 1235 1.1 christos break; 1236 1.1 christos case NV_TYPE_STRING_ARRAY: 1237 1.1 christos ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left); 1238 1.1 christos break; 1239 1.1 christos case NV_TYPE_NVLIST_ARRAY: 1240 1.1 christos ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left, 1241 1.1 christos &array); 1242 1.1 christos if (ptr == NULL) 1243 1.1 christos goto fail; 1244 1.1 christos PJDLOG_ASSERT(array != NULL); 1245 1.1 christos tmpnvl = array; 1246 1.1 christos do { 1247 1.1 christos nvlist_set_parent(array, nvp); 1248 1.1 christos array = __DECONST(nvlist_t *, 1249 1.1 christos nvlist_get_array_next(array)); 1250 1.1 christos } while (array != NULL); 1251 1.1 christos ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe, 1252 1.1 christos &left); 1253 1.1 christos break; 1254 1.1 christos default: 1255 1.1 christos PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); 1256 1.1 christos } 1257 1.1 christos if (ptr == NULL) 1258 1.1 christos goto fail; 1259 1.1 christos if (!nvlist_move_nvpair(nvl, nvp)) 1260 1.1 christos goto fail; 1261 1.1 christos if (tmpnvl != NULL) { 1262 1.1 christos nvl = tmpnvl; 1263 1.1 christos tmpnvl = NULL; 1264 1.1 christos } 1265 1.1 christos } 1266 1.1 christos 1267 1.1 christos return (retnvl); 1268 1.1 christos fail: 1269 1.1 christos nvlist_destroy(retnvl); 1270 1.1 christos return (NULL); 1271 1.1 christos } 1272 1.1 christos 1273 1.1 christos nvlist_t * 1274 1.1 christos nvlist_unpack(const void *buf, size_t size, int flags) 1275 1.1 christos { 1276 1.1 christos 1277 1.1 christos return (nvlist_xunpack(buf, size, NULL, 0, flags)); 1278 1.1 christos } 1279 1.1 christos 1280 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(WITH_MSGIO) 1281 1.1 christos int 1282 1.1 christos nvlist_send(int sock, const nvlist_t *nvl) 1283 1.1 christos { 1284 1.1 christos size_t datasize, nfds; 1285 1.1 christos int *fds; 1286 1.1 christos void *data; 1287 1.1 christos int64_t fdidx; 1288 1.1 christos int ret; 1289 1.1 christos 1290 1.1 christos if (nvlist_error(nvl) != 0) { 1291 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1292 1.1 christos return (-1); 1293 1.1 christos } 1294 1.1 christos 1295 1.1 christos fds = nvlist_descriptors(nvl, &nfds); 1296 1.1 christos if (fds == NULL) 1297 1.1 christos return (-1); 1298 1.1 christos 1299 1.1 christos ret = -1; 1300 1.1 christos fdidx = 0; 1301 1.1 christos 1302 1.1 christos data = nvlist_xpack(nvl, &fdidx, &datasize); 1303 1.1 christos if (data == NULL) 1304 1.1 christos goto out; 1305 1.1 christos 1306 1.1 christos if (buf_send(sock, data, datasize) == -1) 1307 1.1 christos goto out; 1308 1.1 christos 1309 1.1 christos if (nfds > 0) { 1310 1.1 christos if (fd_send(sock, fds, nfds) == -1) 1311 1.1 christos goto out; 1312 1.1 christos } 1313 1.1 christos 1314 1.1 christos ret = 0; 1315 1.1 christos out: 1316 1.1 christos ERRNO_SAVE(); 1317 1.1 christos nv_free(fds); 1318 1.1 christos nv_free(data); 1319 1.1 christos ERRNO_RESTORE(); 1320 1.1 christos return (ret); 1321 1.1 christos } 1322 1.1 christos 1323 1.1 christos nvlist_t * 1324 1.1 christos nvlist_recv(int sock, int flags) 1325 1.1 christos { 1326 1.1 christos struct nvlist_header nvlhdr; 1327 1.1 christos nvlist_t *nvl, *ret; 1328 1.1 christos unsigned char *buf; 1329 1.1 christos size_t nfds, size, i; 1330 1.1 christos int *fds; 1331 1.1 christos 1332 1.1 christos if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1) 1333 1.1 christos return (NULL); 1334 1.1 christos 1335 1.1 christos if (!nvlist_check_header(&nvlhdr)) 1336 1.1 christos return (NULL); 1337 1.1 christos 1338 1.1 christos nfds = (size_t)nvlhdr.nvlh_descriptors; 1339 1.1 christos size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size; 1340 1.1 christos 1341 1.1 christos buf = nv_malloc(size); 1342 1.1 christos if (buf == NULL) 1343 1.1 christos return (NULL); 1344 1.1 christos 1345 1.1 christos memcpy(buf, &nvlhdr, sizeof(nvlhdr)); 1346 1.1 christos 1347 1.1 christos ret = NULL; 1348 1.1 christos fds = NULL; 1349 1.1 christos 1350 1.1 christos if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1) 1351 1.1 christos goto out; 1352 1.1 christos 1353 1.1 christos if (nfds > 0) { 1354 1.10 riastrad fds = nv_calloc(nfds, sizeof(fds[0])); 1355 1.1 christos if (fds == NULL) 1356 1.1 christos goto out; 1357 1.1 christos if (fd_recv(sock, fds, nfds) == -1) 1358 1.1 christos goto out; 1359 1.1 christos } 1360 1.1 christos 1361 1.1 christos nvl = nvlist_xunpack(buf, size, fds, nfds, flags); 1362 1.1 christos if (nvl == NULL) { 1363 1.1 christos ERRNO_SAVE(); 1364 1.1 christos for (i = 0; i < nfds; i++) 1365 1.1 christos close(fds[i]); 1366 1.1 christos ERRNO_RESTORE(); 1367 1.1 christos goto out; 1368 1.1 christos } 1369 1.1 christos 1370 1.1 christos ret = nvl; 1371 1.1 christos out: 1372 1.1 christos ERRNO_SAVE(); 1373 1.1 christos nv_free(buf); 1374 1.1 christos nv_free(fds); 1375 1.1 christos ERRNO_RESTORE(); 1376 1.1 christos 1377 1.1 christos return (ret); 1378 1.1 christos } 1379 1.1 christos 1380 1.1 christos nvlist_t * 1381 1.1 christos nvlist_xfer(int sock, nvlist_t *nvl, int flags) 1382 1.1 christos { 1383 1.1 christos 1384 1.1 christos if (nvlist_send(sock, nvl) < 0) { 1385 1.1 christos nvlist_destroy(nvl); 1386 1.1 christos return (NULL); 1387 1.1 christos } 1388 1.1 christos nvlist_destroy(nvl); 1389 1.1 christos return (nvlist_recv(sock, flags)); 1390 1.1 christos } 1391 1.1 christos #endif 1392 1.1 christos 1393 1.1 christos nvpair_t * 1394 1.1 christos nvlist_first_nvpair(const nvlist_t *nvl) 1395 1.1 christos { 1396 1.1 christos 1397 1.1 christos NVLIST_ASSERT(nvl); 1398 1.1 christos 1399 1.1 christos return (TAILQ_FIRST(&nvl->nvl_head)); 1400 1.1 christos } 1401 1.1 christos 1402 1.1 christos nvpair_t * 1403 1.1 christos nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 1404 1.1 christos { 1405 1.1 christos nvpair_t *retnvp; 1406 1.1 christos 1407 1.1 christos NVLIST_ASSERT(nvl); 1408 1.1 christos NVPAIR_ASSERT(nvp); 1409 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 1410 1.1 christos 1411 1.1 christos retnvp = nvpair_next(nvp); 1412 1.1 christos PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl); 1413 1.1 christos 1414 1.1 christos return (retnvp); 1415 1.1 christos 1416 1.1 christos } 1417 1.1 christos 1418 1.1 christos nvpair_t * 1419 1.1 christos nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) 1420 1.1 christos { 1421 1.1 christos nvpair_t *retnvp; 1422 1.1 christos 1423 1.1 christos NVLIST_ASSERT(nvl); 1424 1.1 christos NVPAIR_ASSERT(nvp); 1425 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 1426 1.1 christos 1427 1.1 christos retnvp = nvpair_prev(nvp); 1428 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl); 1429 1.1 christos 1430 1.1 christos return (retnvp); 1431 1.1 christos } 1432 1.1 christos 1433 1.1 christos const char * 1434 1.1 christos nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep) 1435 1.1 christos { 1436 1.1 christos nvpair_t *nvp; 1437 1.1 christos 1438 1.1 christos NVLIST_ASSERT(nvl); 1439 1.1 christos 1440 1.1 christos if (cookiep == NULL || *cookiep == NULL) 1441 1.1 christos nvp = nvlist_first_nvpair(nvl); 1442 1.1 christos else 1443 1.1 christos nvp = nvlist_next_nvpair(nvl, *cookiep); 1444 1.1 christos if (nvp == NULL) 1445 1.1 christos return (NULL); 1446 1.1 christos if (typep != NULL) 1447 1.1 christos *typep = nvpair_type(nvp); 1448 1.1 christos if (cookiep != NULL) 1449 1.1 christos *cookiep = nvp; 1450 1.1 christos return (nvpair_name(nvp)); 1451 1.1 christos } 1452 1.1 christos 1453 1.1 christos bool 1454 1.1 christos nvlist_exists(const nvlist_t *nvl, const char *name) 1455 1.1 christos { 1456 1.1 christos 1457 1.1 christos return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL); 1458 1.1 christos } 1459 1.1 christos 1460 1.1 christos #define NVLIST_EXISTS(type, TYPE) \ 1461 1.1 christos bool \ 1462 1.1 christos nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ 1463 1.1 christos { \ 1464 1.1 christos \ 1465 1.1 christos return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \ 1466 1.1 christos } 1467 1.1 christos 1468 1.1 christos NVLIST_EXISTS(null, NULL) 1469 1.1 christos NVLIST_EXISTS(bool, BOOL) 1470 1.1 christos NVLIST_EXISTS(number, NUMBER) 1471 1.1 christos NVLIST_EXISTS(string, STRING) 1472 1.1 christos NVLIST_EXISTS(nvlist, NVLIST) 1473 1.1 christos NVLIST_EXISTS(binary, BINARY) 1474 1.1 christos NVLIST_EXISTS(bool_array, BOOL_ARRAY) 1475 1.1 christos NVLIST_EXISTS(number_array, NUMBER_ARRAY) 1476 1.1 christos NVLIST_EXISTS(string_array, STRING_ARRAY) 1477 1.1 christos NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY) 1478 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1479 1.1 christos NVLIST_EXISTS(descriptor, DESCRIPTOR) 1480 1.1 christos NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY) 1481 1.1 christos #endif 1482 1.1 christos 1483 1.1 christos #undef NVLIST_EXISTS 1484 1.1 christos 1485 1.1 christos void 1486 1.1 christos nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) 1487 1.1 christos { 1488 1.1 christos nvpair_t *newnvp; 1489 1.1 christos 1490 1.1 christos NVPAIR_ASSERT(nvp); 1491 1.1 christos 1492 1.1 christos if (nvlist_error(nvl) != 0) { 1493 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1494 1.1 christos return; 1495 1.1 christos } 1496 1.1 christos if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { 1497 1.1 christos if (nvlist_exists(nvl, nvpair_name(nvp))) { 1498 1.1 christos nvl->nvl_error = EEXIST; 1499 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1500 1.1 christos return; 1501 1.1 christos } 1502 1.1 christos } 1503 1.1 christos 1504 1.1 christos newnvp = nvpair_clone(nvp); 1505 1.1 christos if (newnvp == NULL) { 1506 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1507 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1508 1.1 christos return; 1509 1.1 christos } 1510 1.1 christos 1511 1.1 christos nvpair_insert(&nvl->nvl_head, newnvp, nvl); 1512 1.1 christos } 1513 1.1 christos 1514 1.8 rmind #if !defined(_STANDALONE) 1515 1.1 christos void 1516 1.1 christos nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) 1517 1.1 christos { 1518 1.1 christos va_list valueap; 1519 1.1 christos 1520 1.1 christos va_start(valueap, valuefmt); 1521 1.1 christos nvlist_add_stringv(nvl, name, valuefmt, valueap); 1522 1.1 christos va_end(valueap); 1523 1.1 christos } 1524 1.1 christos 1525 1.1 christos void 1526 1.1 christos nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, 1527 1.1 christos va_list valueap) 1528 1.1 christos { 1529 1.1 christos nvpair_t *nvp; 1530 1.1 christos 1531 1.1 christos if (nvlist_error(nvl) != 0) { 1532 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1533 1.1 christos return; 1534 1.1 christos } 1535 1.1 christos 1536 1.1 christos nvp = nvpair_create_stringv(name, valuefmt, valueap); 1537 1.1 christos if (nvp == NULL) { 1538 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1539 1.1 christos ERRNO_SET(nvl->nvl_error); 1540 1.1 christos } else { 1541 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1542 1.1 christos } 1543 1.1 christos } 1544 1.4 christos #endif 1545 1.1 christos 1546 1.1 christos void 1547 1.1 christos nvlist_add_null(nvlist_t *nvl, const char *name) 1548 1.1 christos { 1549 1.1 christos nvpair_t *nvp; 1550 1.1 christos 1551 1.1 christos if (nvlist_error(nvl) != 0) { 1552 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1553 1.1 christos return; 1554 1.1 christos } 1555 1.1 christos 1556 1.1 christos nvp = nvpair_create_null(name); 1557 1.1 christos if (nvp == NULL) { 1558 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1559 1.1 christos ERRNO_SET(nvl->nvl_error); 1560 1.1 christos } else { 1561 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1562 1.1 christos } 1563 1.1 christos } 1564 1.1 christos 1565 1.1 christos void 1566 1.1 christos nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, 1567 1.1 christos size_t size) 1568 1.1 christos { 1569 1.1 christos nvpair_t *nvp; 1570 1.1 christos 1571 1.1 christos if (nvlist_error(nvl) != 0) { 1572 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1573 1.1 christos return; 1574 1.1 christos } 1575 1.1 christos 1576 1.1 christos nvp = nvpair_create_binary(name, value, size); 1577 1.1 christos if (nvp == NULL) { 1578 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1579 1.1 christos ERRNO_SET(nvl->nvl_error); 1580 1.1 christos } else { 1581 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1582 1.1 christos } 1583 1.1 christos } 1584 1.1 christos 1585 1.1 christos 1586 1.1 christos #define NVLIST_ADD(vtype, type) \ 1587 1.1 christos void \ 1588 1.1 christos nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \ 1589 1.1 christos { \ 1590 1.1 christos nvpair_t *nvp; \ 1591 1.1 christos \ 1592 1.1 christos if (nvlist_error(nvl) != 0) { \ 1593 1.1 christos ERRNO_SET(nvlist_error(nvl)); \ 1594 1.1 christos return; \ 1595 1.1 christos } \ 1596 1.1 christos \ 1597 1.1 christos nvp = nvpair_create_##type(name, value); \ 1598 1.1 christos if (nvp == NULL) { \ 1599 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 1600 1.1 christos ERRNO_SET(nvl->nvl_error); \ 1601 1.1 christos } else { \ 1602 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); \ 1603 1.1 christos } \ 1604 1.1 christos } 1605 1.1 christos 1606 1.1 christos NVLIST_ADD(bool, bool) 1607 1.1 christos NVLIST_ADD(uint64_t, number) 1608 1.1 christos NVLIST_ADD(const char *, string) 1609 1.1 christos NVLIST_ADD(const nvlist_t *, nvlist) 1610 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1611 1.1 christos NVLIST_ADD(int, descriptor); 1612 1.1 christos #endif 1613 1.1 christos 1614 1.1 christos #undef NVLIST_ADD 1615 1.1 christos 1616 1.1 christos #define NVLIST_ADD_ARRAY(vtype, type) \ 1617 1.1 christos void \ 1618 1.1 christos nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value, \ 1619 1.1 christos size_t nitems) \ 1620 1.1 christos { \ 1621 1.1 christos nvpair_t *nvp; \ 1622 1.1 christos \ 1623 1.1 christos if (nvlist_error(nvl) != 0) { \ 1624 1.1 christos ERRNO_SET(nvlist_error(nvl)); \ 1625 1.1 christos return; \ 1626 1.1 christos } \ 1627 1.1 christos \ 1628 1.1 christos nvp = nvpair_create_##type##_array(name, value, nitems); \ 1629 1.1 christos if (nvp == NULL) { \ 1630 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 1631 1.1 christos ERRNO_SET(nvl->nvl_error); \ 1632 1.1 christos } else { \ 1633 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); \ 1634 1.1 christos } \ 1635 1.1 christos } 1636 1.1 christos 1637 1.1 christos NVLIST_ADD_ARRAY(const bool *, bool) 1638 1.1 christos NVLIST_ADD_ARRAY(const uint64_t *, number) 1639 1.1 christos NVLIST_ADD_ARRAY(const char * const *, string) 1640 1.1 christos NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist) 1641 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1642 1.1 christos NVLIST_ADD_ARRAY(const int *, descriptor) 1643 1.1 christos #endif 1644 1.1 christos 1645 1.1 christos #undef NVLIST_ADD_ARRAY 1646 1.1 christos 1647 1.1 christos #define NVLIST_APPEND_ARRAY(vtype, type, TYPE) \ 1648 1.1 christos void \ 1649 1.1 christos nvlist_append_##type##_array(nvlist_t *nvl, const char *name, vtype value)\ 1650 1.1 christos { \ 1651 1.1 christos nvpair_t *nvp; \ 1652 1.1 christos \ 1653 1.1 christos if (nvlist_error(nvl) != 0) { \ 1654 1.1 christos ERRNO_SET(nvlist_error(nvl)); \ 1655 1.1 christos return; \ 1656 1.1 christos } \ 1657 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 1658 1.1 christos if (nvp == NULL) { \ 1659 1.1 christos nvlist_add_##type##_array(nvl, name, &value, 1); \ 1660 1.1 christos return; \ 1661 1.1 christos } \ 1662 1.1 christos if (nvpair_append_##type##_array(nvp, value) == -1) { \ 1663 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ 1664 1.1 christos ERRNO_SET(nvl->nvl_error); \ 1665 1.1 christos } \ 1666 1.1 christos } 1667 1.1 christos 1668 1.1 christos NVLIST_APPEND_ARRAY(const bool, bool, BOOL) 1669 1.1 christos NVLIST_APPEND_ARRAY(const uint64_t, number, NUMBER) 1670 1.1 christos NVLIST_APPEND_ARRAY(const char *, string, STRING) 1671 1.1 christos NVLIST_APPEND_ARRAY(const nvlist_t *, nvlist, NVLIST) 1672 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1673 1.1 christos NVLIST_APPEND_ARRAY(const int, descriptor, DESCRIPTOR) 1674 1.1 christos #endif 1675 1.1 christos 1676 1.1 christos #undef NVLIST_APPEND_ARRAY 1677 1.1 christos 1678 1.1 christos bool 1679 1.1 christos nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) 1680 1.1 christos { 1681 1.1 christos 1682 1.1 christos NVPAIR_ASSERT(nvp); 1683 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); 1684 1.1 christos 1685 1.1 christos if (nvlist_error(nvl) != 0) { 1686 1.1 christos nvpair_free(nvp); 1687 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1688 1.1 christos return (false); 1689 1.1 christos } 1690 1.1 christos if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { 1691 1.1 christos if (nvlist_exists(nvl, nvpair_name(nvp))) { 1692 1.1 christos nvpair_free(nvp); 1693 1.1 christos nvl->nvl_error = EEXIST; 1694 1.1 christos ERRNO_SET(nvl->nvl_error); 1695 1.1 christos return (false); 1696 1.1 christos } 1697 1.1 christos } 1698 1.1 christos 1699 1.1 christos nvpair_insert(&nvl->nvl_head, nvp, nvl); 1700 1.1 christos return (true); 1701 1.1 christos } 1702 1.1 christos 1703 1.1 christos void 1704 1.1 christos nvlist_move_string(nvlist_t *nvl, const char *name, char *value) 1705 1.1 christos { 1706 1.1 christos nvpair_t *nvp; 1707 1.1 christos 1708 1.1 christos if (nvlist_error(nvl) != 0) { 1709 1.1 christos nv_free(value); 1710 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1711 1.1 christos return; 1712 1.1 christos } 1713 1.1 christos 1714 1.1 christos nvp = nvpair_move_string(name, value); 1715 1.1 christos if (nvp == NULL) { 1716 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1717 1.1 christos ERRNO_SET(nvl->nvl_error); 1718 1.1 christos } else { 1719 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1720 1.1 christos } 1721 1.1 christos } 1722 1.1 christos 1723 1.1 christos void 1724 1.1 christos nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value) 1725 1.1 christos { 1726 1.1 christos nvpair_t *nvp; 1727 1.1 christos 1728 1.1 christos if (nvlist_error(nvl) != 0) { 1729 1.1 christos if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) 1730 1.1 christos nvlist_destroy(value); 1731 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1732 1.1 christos return; 1733 1.1 christos } 1734 1.1 christos 1735 1.1 christos nvp = nvpair_move_nvlist(name, value); 1736 1.1 christos if (nvp == NULL) { 1737 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1738 1.1 christos ERRNO_SET(nvl->nvl_error); 1739 1.1 christos } else { 1740 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1741 1.1 christos } 1742 1.1 christos } 1743 1.1 christos 1744 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1745 1.1 christos void 1746 1.1 christos nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value) 1747 1.1 christos { 1748 1.1 christos nvpair_t *nvp; 1749 1.1 christos 1750 1.1 christos if (nvlist_error(nvl) != 0) { 1751 1.1 christos close(value); 1752 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1753 1.1 christos return; 1754 1.1 christos } 1755 1.1 christos 1756 1.1 christos nvp = nvpair_move_descriptor(name, value); 1757 1.1 christos if (nvp == NULL) { 1758 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1759 1.1 christos ERRNO_SET(nvl->nvl_error); 1760 1.1 christos } else { 1761 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1762 1.1 christos } 1763 1.1 christos } 1764 1.1 christos #endif 1765 1.1 christos 1766 1.1 christos void 1767 1.1 christos nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size) 1768 1.1 christos { 1769 1.1 christos nvpair_t *nvp; 1770 1.1 christos 1771 1.1 christos if (nvlist_error(nvl) != 0) { 1772 1.1 christos nv_free(value); 1773 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1774 1.1 christos return; 1775 1.1 christos } 1776 1.1 christos 1777 1.1 christos nvp = nvpair_move_binary(name, value, size); 1778 1.1 christos if (nvp == NULL) { 1779 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1780 1.1 christos ERRNO_SET(nvl->nvl_error); 1781 1.1 christos } else { 1782 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1783 1.1 christos } 1784 1.1 christos } 1785 1.1 christos 1786 1.1 christos void 1787 1.1 christos nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value, 1788 1.1 christos size_t nitems) 1789 1.1 christos { 1790 1.1 christos nvpair_t *nvp; 1791 1.1 christos 1792 1.1 christos if (nvlist_error(nvl) != 0) { 1793 1.1 christos nv_free(value); 1794 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1795 1.1 christos return; 1796 1.1 christos } 1797 1.1 christos 1798 1.1 christos nvp = nvpair_move_bool_array(name, value, nitems); 1799 1.1 christos if (nvp == NULL) { 1800 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1801 1.1 christos ERRNO_SET(nvl->nvl_error); 1802 1.1 christos } else { 1803 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1804 1.1 christos } 1805 1.1 christos } 1806 1.1 christos 1807 1.1 christos void 1808 1.1 christos nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value, 1809 1.1 christos size_t nitems) 1810 1.1 christos { 1811 1.1 christos nvpair_t *nvp; 1812 1.1 christos size_t i; 1813 1.1 christos 1814 1.1 christos if (nvlist_error(nvl) != 0) { 1815 1.1 christos if (value != NULL) { 1816 1.1 christos for (i = 0; i < nitems; i++) 1817 1.1 christos nv_free(value[i]); 1818 1.1 christos nv_free(value); 1819 1.1 christos } 1820 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1821 1.1 christos return; 1822 1.1 christos } 1823 1.1 christos 1824 1.1 christos nvp = nvpair_move_string_array(name, value, nitems); 1825 1.1 christos if (nvp == NULL) { 1826 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1827 1.1 christos ERRNO_SET(nvl->nvl_error); 1828 1.1 christos } else { 1829 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1830 1.1 christos } 1831 1.1 christos } 1832 1.1 christos 1833 1.1 christos void 1834 1.1 christos nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value, 1835 1.1 christos size_t nitems) 1836 1.1 christos { 1837 1.1 christos nvpair_t *nvp; 1838 1.1 christos size_t i; 1839 1.1 christos 1840 1.1 christos if (nvlist_error(nvl) != 0) { 1841 1.1 christos if (value != NULL) { 1842 1.1 christos for (i = 0; i < nitems; i++) { 1843 1.1 christos if (nvlist_get_pararr(value[i], NULL) == NULL) 1844 1.1 christos nvlist_destroy(value[i]); 1845 1.1 christos } 1846 1.1 christos } 1847 1.1 christos nv_free(value); 1848 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1849 1.1 christos return; 1850 1.1 christos } 1851 1.1 christos 1852 1.1 christos nvp = nvpair_move_nvlist_array(name, value, nitems); 1853 1.1 christos if (nvp == NULL) { 1854 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1855 1.1 christos ERRNO_SET(nvl->nvl_error); 1856 1.1 christos } else { 1857 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1858 1.1 christos } 1859 1.1 christos } 1860 1.1 christos 1861 1.1 christos void 1862 1.1 christos nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value, 1863 1.1 christos size_t nitems) 1864 1.1 christos { 1865 1.1 christos nvpair_t *nvp; 1866 1.1 christos 1867 1.1 christos if (nvlist_error(nvl) != 0) { 1868 1.1 christos nv_free(value); 1869 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1870 1.1 christos return; 1871 1.1 christos } 1872 1.1 christos 1873 1.1 christos nvp = nvpair_move_number_array(name, value, nitems); 1874 1.1 christos if (nvp == NULL) { 1875 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1876 1.1 christos ERRNO_SET(nvl->nvl_error); 1877 1.1 christos } else { 1878 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1879 1.1 christos } 1880 1.1 christos } 1881 1.1 christos 1882 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1883 1.1 christos void 1884 1.1 christos nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value, 1885 1.1 christos size_t nitems) 1886 1.1 christos { 1887 1.1 christos nvpair_t *nvp; 1888 1.1 christos size_t i; 1889 1.1 christos 1890 1.1 christos if (nvlist_error(nvl) != 0) { 1891 1.1 christos if (value != 0) { 1892 1.1 christos for (i = 0; i < nitems; i++) 1893 1.1 christos close(value[i]); 1894 1.1 christos nv_free(value); 1895 1.1 christos } 1896 1.1 christos 1897 1.1 christos ERRNO_SET(nvlist_error(nvl)); 1898 1.1 christos return; 1899 1.1 christos } 1900 1.1 christos 1901 1.1 christos nvp = nvpair_move_descriptor_array(name, value, nitems); 1902 1.1 christos if (nvp == NULL) { 1903 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); 1904 1.1 christos ERRNO_SET(nvl->nvl_error); 1905 1.1 christos } else { 1906 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); 1907 1.1 christos } 1908 1.1 christos } 1909 1.1 christos #endif 1910 1.1 christos 1911 1.1 christos const nvpair_t * 1912 1.1 christos nvlist_get_nvpair(const nvlist_t *nvl, const char *name) 1913 1.1 christos { 1914 1.1 christos 1915 1.1 christos return (nvlist_find(nvl, NV_TYPE_NONE, name)); 1916 1.1 christos } 1917 1.1 christos 1918 1.1 christos #define NVLIST_GET(ftype, type, TYPE) \ 1919 1.1 christos ftype \ 1920 1.1 christos nvlist_get_##type(const nvlist_t *nvl, const char *name) \ 1921 1.1 christos { \ 1922 1.1 christos const nvpair_t *nvp; \ 1923 1.1 christos \ 1924 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 1925 1.1 christos if (nvp == NULL) \ 1926 1.1 christos nvlist_report_missing(NV_TYPE_##TYPE, name); \ 1927 1.1 christos return (nvpair_get_##type(nvp)); \ 1928 1.1 christos } 1929 1.1 christos 1930 1.1 christos NVLIST_GET(bool, bool, BOOL) 1931 1.1 christos NVLIST_GET(uint64_t, number, NUMBER) 1932 1.1 christos NVLIST_GET(const char *, string, STRING) 1933 1.1 christos NVLIST_GET(const nvlist_t *, nvlist, NVLIST) 1934 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1935 1.1 christos NVLIST_GET(int, descriptor, DESCRIPTOR) 1936 1.1 christos #endif 1937 1.1 christos 1938 1.1 christos #undef NVLIST_GET 1939 1.1 christos 1940 1.1 christos const void * 1941 1.1 christos nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) 1942 1.1 christos { 1943 1.1 christos nvpair_t *nvp; 1944 1.1 christos 1945 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 1946 1.1 christos if (nvp == NULL) 1947 1.1 christos nvlist_report_missing(NV_TYPE_BINARY, name); 1948 1.1 christos 1949 1.1 christos return (nvpair_get_binary(nvp, sizep)); 1950 1.1 christos } 1951 1.1 christos 1952 1.1 christos #define NVLIST_GET_ARRAY(ftype, type, TYPE) \ 1953 1.1 christos ftype \ 1954 1.1 christos nvlist_get_##type##_array(const nvlist_t *nvl, const char *name, \ 1955 1.1 christos size_t *nitems) \ 1956 1.1 christos { \ 1957 1.1 christos const nvpair_t *nvp; \ 1958 1.1 christos \ 1959 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 1960 1.1 christos if (nvp == NULL) \ 1961 1.1 christos nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ 1962 1.1 christos return (nvpair_get_##type##_array(nvp, nitems)); \ 1963 1.1 christos } 1964 1.1 christos 1965 1.1 christos NVLIST_GET_ARRAY(const bool *, bool, BOOL) 1966 1.1 christos NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER) 1967 1.1 christos NVLIST_GET_ARRAY(const char * const *, string, STRING) 1968 1.1 christos NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST) 1969 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1970 1.1 christos NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR) 1971 1.1 christos #endif 1972 1.1 christos 1973 1.1 christos #undef NVLIST_GET_ARRAY 1974 1.1 christos 1975 1.1 christos #define NVLIST_TAKE(ftype, type, TYPE) \ 1976 1.1 christos ftype \ 1977 1.1 christos nvlist_take_##type(nvlist_t *nvl, const char *name) \ 1978 1.1 christos { \ 1979 1.1 christos nvpair_t *nvp; \ 1980 1.1 christos ftype value; \ 1981 1.1 christos \ 1982 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ 1983 1.1 christos if (nvp == NULL) \ 1984 1.1 christos nvlist_report_missing(NV_TYPE_##TYPE, name); \ 1985 1.1 christos value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ 1986 1.1 christos nvlist_remove_nvpair(nvl, nvp); \ 1987 1.1 christos nvpair_free_structure(nvp); \ 1988 1.1 christos return (value); \ 1989 1.1 christos } 1990 1.1 christos 1991 1.1 christos NVLIST_TAKE(bool, bool, BOOL) 1992 1.1 christos NVLIST_TAKE(uint64_t, number, NUMBER) 1993 1.1 christos NVLIST_TAKE(char *, string, STRING) 1994 1.1 christos NVLIST_TAKE(nvlist_t *, nvlist, NVLIST) 1995 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 1996 1.1 christos NVLIST_TAKE(int, descriptor, DESCRIPTOR) 1997 1.1 christos #endif 1998 1.1 christos 1999 1.1 christos #undef NVLIST_TAKE 2000 1.1 christos 2001 1.1 christos void * 2002 1.1 christos nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) 2003 1.1 christos { 2004 1.1 christos nvpair_t *nvp; 2005 1.1 christos void *value; 2006 1.1 christos 2007 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); 2008 1.1 christos if (nvp == NULL) 2009 1.1 christos nvlist_report_missing(NV_TYPE_BINARY, name); 2010 1.1 christos 2011 1.1 christos value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); 2012 1.1 christos nvlist_remove_nvpair(nvl, nvp); 2013 1.1 christos nvpair_free_structure(nvp); 2014 1.1 christos return (value); 2015 1.1 christos } 2016 1.1 christos 2017 1.1 christos #define NVLIST_TAKE_ARRAY(ftype, type, TYPE) \ 2018 1.1 christos ftype \ 2019 1.1 christos nvlist_take_##type##_array(nvlist_t *nvl, const char *name, \ 2020 1.1 christos size_t *nitems) \ 2021 1.1 christos { \ 2022 1.1 christos nvpair_t *nvp; \ 2023 1.1 christos ftype value; \ 2024 1.1 christos \ 2025 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ 2026 1.1 christos if (nvp == NULL) \ 2027 1.1 christos nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ 2028 1.1 christos value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\ 2029 1.1 christos nvlist_remove_nvpair(nvl, nvp); \ 2030 1.1 christos nvpair_free_structure(nvp); \ 2031 1.1 christos return (value); \ 2032 1.1 christos } 2033 1.1 christos 2034 1.1 christos NVLIST_TAKE_ARRAY(bool *, bool, BOOL) 2035 1.1 christos NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER) 2036 1.1 christos NVLIST_TAKE_ARRAY(char **, string, STRING) 2037 1.1 christos NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST) 2038 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 2039 1.1 christos NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR) 2040 1.1 christos #endif 2041 1.1 christos 2042 1.1 christos void 2043 1.1 christos nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) 2044 1.1 christos { 2045 1.1 christos 2046 1.1 christos NVLIST_ASSERT(nvl); 2047 1.1 christos NVPAIR_ASSERT(nvp); 2048 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 2049 1.1 christos 2050 1.1 christos nvpair_remove(&nvl->nvl_head, nvp, nvl); 2051 1.1 christos } 2052 1.1 christos 2053 1.1 christos void 2054 1.1 christos nvlist_free(nvlist_t *nvl, const char *name) 2055 1.1 christos { 2056 1.1 christos 2057 1.1 christos nvlist_free_type(nvl, name, NV_TYPE_NONE); 2058 1.1 christos } 2059 1.1 christos 2060 1.1 christos #define NVLIST_FREE(type, TYPE) \ 2061 1.1 christos void \ 2062 1.1 christos nvlist_free_##type(nvlist_t *nvl, const char *name) \ 2063 1.1 christos { \ 2064 1.1 christos \ 2065 1.1 christos nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ 2066 1.1 christos } 2067 1.1 christos 2068 1.1 christos NVLIST_FREE(null, NULL) 2069 1.1 christos NVLIST_FREE(bool, BOOL) 2070 1.1 christos NVLIST_FREE(number, NUMBER) 2071 1.1 christos NVLIST_FREE(string, STRING) 2072 1.1 christos NVLIST_FREE(nvlist, NVLIST) 2073 1.1 christos NVLIST_FREE(binary, BINARY) 2074 1.1 christos NVLIST_FREE(bool_array, BOOL_ARRAY) 2075 1.1 christos NVLIST_FREE(number_array, NUMBER_ARRAY) 2076 1.1 christos NVLIST_FREE(string_array, STRING_ARRAY) 2077 1.1 christos NVLIST_FREE(nvlist_array, NVLIST_ARRAY) 2078 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) 2079 1.1 christos NVLIST_FREE(descriptor, DESCRIPTOR) 2080 1.1 christos NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY) 2081 1.1 christos #endif 2082 1.1 christos 2083 1.1 christos #undef NVLIST_FREE 2084 1.1 christos 2085 1.1 christos void 2086 1.1 christos nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) 2087 1.1 christos { 2088 1.1 christos 2089 1.1 christos NVLIST_ASSERT(nvl); 2090 1.1 christos NVPAIR_ASSERT(nvp); 2091 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); 2092 1.1 christos 2093 1.1 christos nvlist_remove_nvpair(nvl, nvp); 2094 1.1 christos nvpair_free(nvp); 2095 1.1 christos } 2096 1.1 christos 2097