nvlist.c revision 1.7 1 1.7 rmind /* $NetBSD: nvlist.c,v 1.7 2019/02/12 12:49:23 rmind 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.7 rmind __RCSID("$NetBSD: nvlist.c,v 1.7 2019/02/12 12:49:23 rmind 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.1 christos fds = nv_malloc(sizeof(fds[0]) * (nitems + 1));
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.1 christos if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
1078 1.1 christos ERRNO_SET(EINVAL);
1079 1.1 christos return (false);
1080 1.1 christos }
1081 1.1 christos if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
1082 1.1 christos ERRNO_SET(EINVAL);
1083 1.1 christos return (false);
1084 1.1 christos }
1085 1.1 christos #if BYTE_ORDER == BIG_ENDIAN
1086 1.1 christos if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
1087 1.1 christos nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
1088 1.1 christos nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
1089 1.1 christos }
1090 1.1 christos #else
1091 1.1 christos if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
1092 1.1 christos nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
1093 1.1 christos nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
1094 1.1 christos }
1095 1.1 christos #endif
1096 1.1 christos return (true);
1097 1.1 christos }
1098 1.1 christos
1099 1.1 christos const unsigned char *
1100 1.1 christos nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
1101 1.1 christos bool *isbep, size_t *leftp)
1102 1.1 christos {
1103 1.1 christos struct nvlist_header nvlhdr;
1104 1.1 christos int inarrayf;
1105 1.1 christos
1106 1.1 christos if (*leftp < sizeof(nvlhdr))
1107 1.1 christos goto fail;
1108 1.1 christos
1109 1.1 christos memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
1110 1.1 christos
1111 1.1 christos if (!nvlist_check_header(&nvlhdr))
1112 1.1 christos goto fail;
1113 1.1 christos
1114 1.1 christos if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
1115 1.1 christos goto fail;
1116 1.1 christos
1117 1.1 christos /*
1118 1.1 christos * nvlh_descriptors might be smaller than nfds in embedded nvlists.
1119 1.1 christos */
1120 1.1 christos if (nvlhdr.nvlh_descriptors > nfds)
1121 1.1 christos goto fail;
1122 1.1 christos
1123 1.1 christos if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
1124 1.1 christos goto fail;
1125 1.1 christos
1126 1.1 christos inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY);
1127 1.1 christos nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf;
1128 1.1 christos
1129 1.1 christos ptr += sizeof(nvlhdr);
1130 1.1 christos if (isbep != NULL)
1131 1.1 christos *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
1132 1.1 christos *leftp -= sizeof(nvlhdr);
1133 1.1 christos
1134 1.1 christos return (ptr);
1135 1.1 christos fail:
1136 1.1 christos ERRNO_SET(EINVAL);
1137 1.1 christos return (NULL);
1138 1.1 christos }
1139 1.1 christos
1140 1.1 christos static nvlist_t *
1141 1.1 christos nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
1142 1.1 christos int flags)
1143 1.1 christos {
1144 1.1 christos const unsigned char *ptr;
1145 1.1 christos nvlist_t *nvl, *retnvl, *tmpnvl, *array;
1146 1.1 christos nvpair_t *nvp;
1147 1.1 christos size_t left;
1148 1.1 christos bool isbe;
1149 1.1 christos
1150 1.1 christos PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
1151 1.1 christos
1152 1.1 christos left = size;
1153 1.1 christos ptr = buf;
1154 1.1 christos
1155 1.1 christos tmpnvl = array = NULL;
1156 1.1 christos nvl = retnvl = nvlist_create(0);
1157 1.1 christos if (nvl == NULL)
1158 1.1 christos goto fail;
1159 1.1 christos
1160 1.1 christos ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
1161 1.1 christos if (ptr == NULL)
1162 1.1 christos goto fail;
1163 1.1 christos if (nvl->nvl_flags != flags) {
1164 1.1 christos ERRNO_SET(EILSEQ);
1165 1.1 christos goto fail;
1166 1.1 christos }
1167 1.1 christos
1168 1.1 christos while (left > 0) {
1169 1.1 christos ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
1170 1.1 christos if (ptr == NULL)
1171 1.1 christos goto fail;
1172 1.1 christos switch (nvpair_type(nvp)) {
1173 1.1 christos case NV_TYPE_NULL:
1174 1.1 christos ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
1175 1.1 christos break;
1176 1.1 christos case NV_TYPE_BOOL:
1177 1.1 christos ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
1178 1.1 christos break;
1179 1.1 christos case NV_TYPE_NUMBER:
1180 1.1 christos ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
1181 1.1 christos break;
1182 1.1 christos case NV_TYPE_STRING:
1183 1.1 christos ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
1184 1.1 christos break;
1185 1.1 christos case NV_TYPE_NVLIST:
1186 1.1 christos ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
1187 1.1 christos &tmpnvl);
1188 1.1 christos if (tmpnvl == NULL || ptr == NULL)
1189 1.1 christos goto fail;
1190 1.1 christos nvlist_set_parent(tmpnvl, nvp);
1191 1.1 christos break;
1192 1.6 rmind #if !defined(_KERNEL) && !defined(_STANDALONE) && !defined(__NetBSD__)
1193 1.1 christos case NV_TYPE_DESCRIPTOR:
1194 1.1 christos ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
1195 1.1 christos fds, nfds);
1196 1.1 christos break;
1197 1.1 christos case NV_TYPE_DESCRIPTOR_ARRAY:
1198 1.1 christos ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr,
1199 1.1 christos &left, fds, nfds);
1200 1.1 christos break;
1201 1.1 christos #endif
1202 1.1 christos case NV_TYPE_BINARY:
1203 1.1 christos ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
1204 1.1 christos break;
1205 1.1 christos case NV_TYPE_NVLIST_UP:
1206 1.1 christos if (nvl->nvl_parent == NULL)
1207 1.1 christos goto fail;
1208 1.1 christos nvl = nvpair_nvlist(nvl->nvl_parent);
1209 1.1 christos nvpair_free_structure(nvp);
1210 1.1 christos continue;
1211 1.1 christos case NV_TYPE_NVLIST_ARRAY_NEXT:
1212 1.1 christos if (nvl->nvl_array_next == NULL) {
1213 1.1 christos if (nvl->nvl_parent == NULL)
1214 1.1 christos goto fail;
1215 1.1 christos nvl = nvpair_nvlist(nvl->nvl_parent);
1216 1.1 christos } else {
1217 1.1 christos nvl = __DECONST(nvlist_t *,
1218 1.1 christos nvlist_get_array_next(nvl));
1219 1.1 christos ptr = nvlist_unpack_header(nvl, ptr, nfds,
1220 1.1 christos &isbe, &left);
1221 1.1 christos if (ptr == NULL)
1222 1.1 christos goto fail;
1223 1.1 christos }
1224 1.1 christos nvpair_free_structure(nvp);
1225 1.1 christos continue;
1226 1.1 christos case NV_TYPE_BOOL_ARRAY:
1227 1.1 christos ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left);
1228 1.1 christos break;
1229 1.1 christos case NV_TYPE_NUMBER_ARRAY:
1230 1.1 christos ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left);
1231 1.1 christos break;
1232 1.1 christos case NV_TYPE_STRING_ARRAY:
1233 1.1 christos ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left);
1234 1.1 christos break;
1235 1.1 christos case NV_TYPE_NVLIST_ARRAY:
1236 1.1 christos ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left,
1237 1.1 christos &array);
1238 1.1 christos if (ptr == NULL)
1239 1.1 christos goto fail;
1240 1.1 christos PJDLOG_ASSERT(array != NULL);
1241 1.1 christos tmpnvl = array;
1242 1.1 christos do {
1243 1.1 christos nvlist_set_parent(array, nvp);
1244 1.1 christos array = __DECONST(nvlist_t *,
1245 1.1 christos nvlist_get_array_next(array));
1246 1.1 christos } while (array != NULL);
1247 1.1 christos ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe,
1248 1.1 christos &left);
1249 1.1 christos break;
1250 1.1 christos default:
1251 1.1 christos PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
1252 1.1 christos }
1253 1.1 christos if (ptr == NULL)
1254 1.1 christos goto fail;
1255 1.1 christos if (!nvlist_move_nvpair(nvl, nvp))
1256 1.1 christos goto fail;
1257 1.1 christos if (tmpnvl != NULL) {
1258 1.1 christos nvl = tmpnvl;
1259 1.1 christos tmpnvl = NULL;
1260 1.1 christos }
1261 1.1 christos }
1262 1.1 christos
1263 1.1 christos return (retnvl);
1264 1.1 christos fail:
1265 1.1 christos nvlist_destroy(retnvl);
1266 1.1 christos return (NULL);
1267 1.1 christos }
1268 1.1 christos
1269 1.1 christos nvlist_t *
1270 1.1 christos nvlist_unpack(const void *buf, size_t size, int flags)
1271 1.1 christos {
1272 1.1 christos
1273 1.1 christos return (nvlist_xunpack(buf, size, NULL, 0, flags));
1274 1.1 christos }
1275 1.1 christos
1276 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(WITH_MSGIO)
1277 1.1 christos int
1278 1.1 christos nvlist_send(int sock, const nvlist_t *nvl)
1279 1.1 christos {
1280 1.1 christos size_t datasize, nfds;
1281 1.1 christos int *fds;
1282 1.1 christos void *data;
1283 1.1 christos int64_t fdidx;
1284 1.1 christos int ret;
1285 1.1 christos
1286 1.1 christos if (nvlist_error(nvl) != 0) {
1287 1.1 christos ERRNO_SET(nvlist_error(nvl));
1288 1.1 christos return (-1);
1289 1.1 christos }
1290 1.1 christos
1291 1.1 christos fds = nvlist_descriptors(nvl, &nfds);
1292 1.1 christos if (fds == NULL)
1293 1.1 christos return (-1);
1294 1.1 christos
1295 1.1 christos ret = -1;
1296 1.1 christos fdidx = 0;
1297 1.1 christos
1298 1.1 christos data = nvlist_xpack(nvl, &fdidx, &datasize);
1299 1.1 christos if (data == NULL)
1300 1.1 christos goto out;
1301 1.1 christos
1302 1.1 christos if (buf_send(sock, data, datasize) == -1)
1303 1.1 christos goto out;
1304 1.1 christos
1305 1.1 christos if (nfds > 0) {
1306 1.1 christos if (fd_send(sock, fds, nfds) == -1)
1307 1.1 christos goto out;
1308 1.1 christos }
1309 1.1 christos
1310 1.1 christos ret = 0;
1311 1.1 christos out:
1312 1.1 christos ERRNO_SAVE();
1313 1.1 christos nv_free(fds);
1314 1.1 christos nv_free(data);
1315 1.1 christos ERRNO_RESTORE();
1316 1.1 christos return (ret);
1317 1.1 christos }
1318 1.1 christos
1319 1.1 christos nvlist_t *
1320 1.1 christos nvlist_recv(int sock, int flags)
1321 1.1 christos {
1322 1.1 christos struct nvlist_header nvlhdr;
1323 1.1 christos nvlist_t *nvl, *ret;
1324 1.1 christos unsigned char *buf;
1325 1.1 christos size_t nfds, size, i;
1326 1.1 christos int *fds;
1327 1.1 christos
1328 1.1 christos if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
1329 1.1 christos return (NULL);
1330 1.1 christos
1331 1.1 christos if (!nvlist_check_header(&nvlhdr))
1332 1.1 christos return (NULL);
1333 1.1 christos
1334 1.1 christos nfds = (size_t)nvlhdr.nvlh_descriptors;
1335 1.1 christos size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
1336 1.1 christos
1337 1.1 christos buf = nv_malloc(size);
1338 1.1 christos if (buf == NULL)
1339 1.1 christos return (NULL);
1340 1.1 christos
1341 1.1 christos memcpy(buf, &nvlhdr, sizeof(nvlhdr));
1342 1.1 christos
1343 1.1 christos ret = NULL;
1344 1.1 christos fds = NULL;
1345 1.1 christos
1346 1.1 christos if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
1347 1.1 christos goto out;
1348 1.1 christos
1349 1.1 christos if (nfds > 0) {
1350 1.1 christos fds = nv_malloc(nfds * sizeof(fds[0]));
1351 1.1 christos if (fds == NULL)
1352 1.1 christos goto out;
1353 1.1 christos if (fd_recv(sock, fds, nfds) == -1)
1354 1.1 christos goto out;
1355 1.1 christos }
1356 1.1 christos
1357 1.1 christos nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
1358 1.1 christos if (nvl == NULL) {
1359 1.1 christos ERRNO_SAVE();
1360 1.1 christos for (i = 0; i < nfds; i++)
1361 1.1 christos close(fds[i]);
1362 1.1 christos ERRNO_RESTORE();
1363 1.1 christos goto out;
1364 1.1 christos }
1365 1.1 christos
1366 1.1 christos ret = nvl;
1367 1.1 christos out:
1368 1.1 christos ERRNO_SAVE();
1369 1.1 christos nv_free(buf);
1370 1.1 christos nv_free(fds);
1371 1.1 christos ERRNO_RESTORE();
1372 1.1 christos
1373 1.1 christos return (ret);
1374 1.1 christos }
1375 1.1 christos
1376 1.1 christos nvlist_t *
1377 1.1 christos nvlist_xfer(int sock, nvlist_t *nvl, int flags)
1378 1.1 christos {
1379 1.1 christos
1380 1.1 christos if (nvlist_send(sock, nvl) < 0) {
1381 1.1 christos nvlist_destroy(nvl);
1382 1.1 christos return (NULL);
1383 1.1 christos }
1384 1.1 christos nvlist_destroy(nvl);
1385 1.1 christos return (nvlist_recv(sock, flags));
1386 1.1 christos }
1387 1.1 christos #endif
1388 1.1 christos
1389 1.1 christos nvpair_t *
1390 1.1 christos nvlist_first_nvpair(const nvlist_t *nvl)
1391 1.1 christos {
1392 1.1 christos
1393 1.1 christos NVLIST_ASSERT(nvl);
1394 1.1 christos
1395 1.1 christos return (TAILQ_FIRST(&nvl->nvl_head));
1396 1.1 christos }
1397 1.1 christos
1398 1.1 christos nvpair_t *
1399 1.1 christos nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1400 1.1 christos {
1401 1.1 christos nvpair_t *retnvp;
1402 1.1 christos
1403 1.1 christos NVLIST_ASSERT(nvl);
1404 1.1 christos NVPAIR_ASSERT(nvp);
1405 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1406 1.1 christos
1407 1.1 christos retnvp = nvpair_next(nvp);
1408 1.1 christos PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
1409 1.1 christos
1410 1.1 christos return (retnvp);
1411 1.1 christos
1412 1.1 christos }
1413 1.1 christos
1414 1.1 christos nvpair_t *
1415 1.1 christos nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
1416 1.1 christos {
1417 1.1 christos nvpair_t *retnvp;
1418 1.1 christos
1419 1.1 christos NVLIST_ASSERT(nvl);
1420 1.1 christos NVPAIR_ASSERT(nvp);
1421 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
1422 1.1 christos
1423 1.1 christos retnvp = nvpair_prev(nvp);
1424 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
1425 1.1 christos
1426 1.1 christos return (retnvp);
1427 1.1 christos }
1428 1.1 christos
1429 1.1 christos const char *
1430 1.1 christos nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
1431 1.1 christos {
1432 1.1 christos nvpair_t *nvp;
1433 1.1 christos
1434 1.1 christos NVLIST_ASSERT(nvl);
1435 1.1 christos
1436 1.1 christos if (cookiep == NULL || *cookiep == NULL)
1437 1.1 christos nvp = nvlist_first_nvpair(nvl);
1438 1.1 christos else
1439 1.1 christos nvp = nvlist_next_nvpair(nvl, *cookiep);
1440 1.1 christos if (nvp == NULL)
1441 1.1 christos return (NULL);
1442 1.1 christos if (typep != NULL)
1443 1.1 christos *typep = nvpair_type(nvp);
1444 1.1 christos if (cookiep != NULL)
1445 1.1 christos *cookiep = nvp;
1446 1.1 christos return (nvpair_name(nvp));
1447 1.1 christos }
1448 1.1 christos
1449 1.1 christos bool
1450 1.1 christos nvlist_exists(const nvlist_t *nvl, const char *name)
1451 1.1 christos {
1452 1.1 christos
1453 1.1 christos return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
1454 1.1 christos }
1455 1.1 christos
1456 1.1 christos #define NVLIST_EXISTS(type, TYPE) \
1457 1.1 christos bool \
1458 1.1 christos nvlist_exists_##type(const nvlist_t *nvl, const char *name) \
1459 1.1 christos { \
1460 1.1 christos \
1461 1.1 christos return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \
1462 1.1 christos }
1463 1.1 christos
1464 1.1 christos NVLIST_EXISTS(null, NULL)
1465 1.1 christos NVLIST_EXISTS(bool, BOOL)
1466 1.1 christos NVLIST_EXISTS(number, NUMBER)
1467 1.1 christos NVLIST_EXISTS(string, STRING)
1468 1.1 christos NVLIST_EXISTS(nvlist, NVLIST)
1469 1.1 christos NVLIST_EXISTS(binary, BINARY)
1470 1.1 christos NVLIST_EXISTS(bool_array, BOOL_ARRAY)
1471 1.1 christos NVLIST_EXISTS(number_array, NUMBER_ARRAY)
1472 1.1 christos NVLIST_EXISTS(string_array, STRING_ARRAY)
1473 1.1 christos NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY)
1474 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
1475 1.1 christos NVLIST_EXISTS(descriptor, DESCRIPTOR)
1476 1.1 christos NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY)
1477 1.1 christos #endif
1478 1.1 christos
1479 1.1 christos #undef NVLIST_EXISTS
1480 1.1 christos
1481 1.1 christos void
1482 1.1 christos nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
1483 1.1 christos {
1484 1.1 christos nvpair_t *newnvp;
1485 1.1 christos
1486 1.1 christos NVPAIR_ASSERT(nvp);
1487 1.1 christos
1488 1.1 christos if (nvlist_error(nvl) != 0) {
1489 1.1 christos ERRNO_SET(nvlist_error(nvl));
1490 1.1 christos return;
1491 1.1 christos }
1492 1.1 christos if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1493 1.1 christos if (nvlist_exists(nvl, nvpair_name(nvp))) {
1494 1.1 christos nvl->nvl_error = EEXIST;
1495 1.1 christos ERRNO_SET(nvlist_error(nvl));
1496 1.1 christos return;
1497 1.1 christos }
1498 1.1 christos }
1499 1.1 christos
1500 1.1 christos newnvp = nvpair_clone(nvp);
1501 1.1 christos if (newnvp == NULL) {
1502 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1503 1.1 christos ERRNO_SET(nvlist_error(nvl));
1504 1.1 christos return;
1505 1.1 christos }
1506 1.1 christos
1507 1.1 christos nvpair_insert(&nvl->nvl_head, newnvp, nvl);
1508 1.1 christos }
1509 1.1 christos
1510 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE) && !defined(__NetBSD__)
1511 1.1 christos void
1512 1.1 christos nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
1513 1.1 christos {
1514 1.1 christos va_list valueap;
1515 1.1 christos
1516 1.1 christos va_start(valueap, valuefmt);
1517 1.1 christos nvlist_add_stringv(nvl, name, valuefmt, valueap);
1518 1.1 christos va_end(valueap);
1519 1.1 christos }
1520 1.1 christos
1521 1.1 christos void
1522 1.1 christos nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
1523 1.1 christos va_list valueap)
1524 1.1 christos {
1525 1.1 christos nvpair_t *nvp;
1526 1.1 christos
1527 1.1 christos if (nvlist_error(nvl) != 0) {
1528 1.1 christos ERRNO_SET(nvlist_error(nvl));
1529 1.1 christos return;
1530 1.1 christos }
1531 1.1 christos
1532 1.1 christos nvp = nvpair_create_stringv(name, valuefmt, valueap);
1533 1.1 christos if (nvp == NULL) {
1534 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1535 1.1 christos ERRNO_SET(nvl->nvl_error);
1536 1.1 christos } else {
1537 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1538 1.1 christos }
1539 1.1 christos }
1540 1.4 christos #endif
1541 1.1 christos
1542 1.1 christos void
1543 1.1 christos nvlist_add_null(nvlist_t *nvl, const char *name)
1544 1.1 christos {
1545 1.1 christos nvpair_t *nvp;
1546 1.1 christos
1547 1.1 christos if (nvlist_error(nvl) != 0) {
1548 1.1 christos ERRNO_SET(nvlist_error(nvl));
1549 1.1 christos return;
1550 1.1 christos }
1551 1.1 christos
1552 1.1 christos nvp = nvpair_create_null(name);
1553 1.1 christos if (nvp == NULL) {
1554 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1555 1.1 christos ERRNO_SET(nvl->nvl_error);
1556 1.1 christos } else {
1557 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1558 1.1 christos }
1559 1.1 christos }
1560 1.1 christos
1561 1.1 christos void
1562 1.1 christos nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
1563 1.1 christos size_t size)
1564 1.1 christos {
1565 1.1 christos nvpair_t *nvp;
1566 1.1 christos
1567 1.1 christos if (nvlist_error(nvl) != 0) {
1568 1.1 christos ERRNO_SET(nvlist_error(nvl));
1569 1.1 christos return;
1570 1.1 christos }
1571 1.1 christos
1572 1.1 christos nvp = nvpair_create_binary(name, value, size);
1573 1.1 christos if (nvp == NULL) {
1574 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1575 1.1 christos ERRNO_SET(nvl->nvl_error);
1576 1.1 christos } else {
1577 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1578 1.1 christos }
1579 1.1 christos }
1580 1.1 christos
1581 1.1 christos
1582 1.1 christos #define NVLIST_ADD(vtype, type) \
1583 1.1 christos void \
1584 1.1 christos nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \
1585 1.1 christos { \
1586 1.1 christos nvpair_t *nvp; \
1587 1.1 christos \
1588 1.1 christos if (nvlist_error(nvl) != 0) { \
1589 1.1 christos ERRNO_SET(nvlist_error(nvl)); \
1590 1.1 christos return; \
1591 1.1 christos } \
1592 1.1 christos \
1593 1.1 christos nvp = nvpair_create_##type(name, value); \
1594 1.1 christos if (nvp == NULL) { \
1595 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1596 1.1 christos ERRNO_SET(nvl->nvl_error); \
1597 1.1 christos } else { \
1598 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); \
1599 1.1 christos } \
1600 1.1 christos }
1601 1.1 christos
1602 1.1 christos NVLIST_ADD(bool, bool)
1603 1.1 christos NVLIST_ADD(uint64_t, number)
1604 1.1 christos NVLIST_ADD(const char *, string)
1605 1.1 christos NVLIST_ADD(const nvlist_t *, nvlist)
1606 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
1607 1.1 christos NVLIST_ADD(int, descriptor);
1608 1.1 christos #endif
1609 1.1 christos
1610 1.1 christos #undef NVLIST_ADD
1611 1.1 christos
1612 1.1 christos #define NVLIST_ADD_ARRAY(vtype, type) \
1613 1.1 christos void \
1614 1.1 christos nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value, \
1615 1.1 christos size_t nitems) \
1616 1.1 christos { \
1617 1.1 christos nvpair_t *nvp; \
1618 1.1 christos \
1619 1.1 christos if (nvlist_error(nvl) != 0) { \
1620 1.1 christos ERRNO_SET(nvlist_error(nvl)); \
1621 1.1 christos return; \
1622 1.1 christos } \
1623 1.1 christos \
1624 1.1 christos nvp = nvpair_create_##type##_array(name, value, nitems); \
1625 1.1 christos if (nvp == NULL) { \
1626 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1627 1.1 christos ERRNO_SET(nvl->nvl_error); \
1628 1.1 christos } else { \
1629 1.1 christos (void)nvlist_move_nvpair(nvl, nvp); \
1630 1.1 christos } \
1631 1.1 christos }
1632 1.1 christos
1633 1.1 christos NVLIST_ADD_ARRAY(const bool *, bool)
1634 1.1 christos NVLIST_ADD_ARRAY(const uint64_t *, number)
1635 1.1 christos NVLIST_ADD_ARRAY(const char * const *, string)
1636 1.1 christos NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist)
1637 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
1638 1.1 christos NVLIST_ADD_ARRAY(const int *, descriptor)
1639 1.1 christos #endif
1640 1.1 christos
1641 1.1 christos #undef NVLIST_ADD_ARRAY
1642 1.1 christos
1643 1.1 christos #define NVLIST_APPEND_ARRAY(vtype, type, TYPE) \
1644 1.1 christos void \
1645 1.1 christos nvlist_append_##type##_array(nvlist_t *nvl, const char *name, vtype value)\
1646 1.1 christos { \
1647 1.1 christos nvpair_t *nvp; \
1648 1.1 christos \
1649 1.1 christos if (nvlist_error(nvl) != 0) { \
1650 1.1 christos ERRNO_SET(nvlist_error(nvl)); \
1651 1.1 christos return; \
1652 1.1 christos } \
1653 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \
1654 1.1 christos if (nvp == NULL) { \
1655 1.1 christos nvlist_add_##type##_array(nvl, name, &value, 1); \
1656 1.1 christos return; \
1657 1.1 christos } \
1658 1.1 christos if (nvpair_append_##type##_array(nvp, value) == -1) { \
1659 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \
1660 1.1 christos ERRNO_SET(nvl->nvl_error); \
1661 1.1 christos } \
1662 1.1 christos }
1663 1.1 christos
1664 1.1 christos NVLIST_APPEND_ARRAY(const bool, bool, BOOL)
1665 1.1 christos NVLIST_APPEND_ARRAY(const uint64_t, number, NUMBER)
1666 1.1 christos NVLIST_APPEND_ARRAY(const char *, string, STRING)
1667 1.1 christos NVLIST_APPEND_ARRAY(const nvlist_t *, nvlist, NVLIST)
1668 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
1669 1.1 christos NVLIST_APPEND_ARRAY(const int, descriptor, DESCRIPTOR)
1670 1.1 christos #endif
1671 1.1 christos
1672 1.1 christos #undef NVLIST_APPEND_ARRAY
1673 1.1 christos
1674 1.1 christos bool
1675 1.1 christos nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1676 1.1 christos {
1677 1.1 christos
1678 1.1 christos NVPAIR_ASSERT(nvp);
1679 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
1680 1.1 christos
1681 1.1 christos if (nvlist_error(nvl) != 0) {
1682 1.1 christos nvpair_free(nvp);
1683 1.1 christos ERRNO_SET(nvlist_error(nvl));
1684 1.1 christos return (false);
1685 1.1 christos }
1686 1.1 christos if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
1687 1.1 christos if (nvlist_exists(nvl, nvpair_name(nvp))) {
1688 1.1 christos nvpair_free(nvp);
1689 1.1 christos nvl->nvl_error = EEXIST;
1690 1.1 christos ERRNO_SET(nvl->nvl_error);
1691 1.1 christos return (false);
1692 1.1 christos }
1693 1.1 christos }
1694 1.1 christos
1695 1.1 christos nvpair_insert(&nvl->nvl_head, nvp, nvl);
1696 1.1 christos return (true);
1697 1.1 christos }
1698 1.1 christos
1699 1.1 christos void
1700 1.1 christos nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
1701 1.1 christos {
1702 1.1 christos nvpair_t *nvp;
1703 1.1 christos
1704 1.1 christos if (nvlist_error(nvl) != 0) {
1705 1.1 christos nv_free(value);
1706 1.1 christos ERRNO_SET(nvlist_error(nvl));
1707 1.1 christos return;
1708 1.1 christos }
1709 1.1 christos
1710 1.1 christos nvp = nvpair_move_string(name, value);
1711 1.1 christos if (nvp == NULL) {
1712 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1713 1.1 christos ERRNO_SET(nvl->nvl_error);
1714 1.1 christos } else {
1715 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1716 1.1 christos }
1717 1.1 christos }
1718 1.1 christos
1719 1.1 christos void
1720 1.1 christos nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
1721 1.1 christos {
1722 1.1 christos nvpair_t *nvp;
1723 1.1 christos
1724 1.1 christos if (nvlist_error(nvl) != 0) {
1725 1.1 christos if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
1726 1.1 christos nvlist_destroy(value);
1727 1.1 christos ERRNO_SET(nvlist_error(nvl));
1728 1.1 christos return;
1729 1.1 christos }
1730 1.1 christos
1731 1.1 christos nvp = nvpair_move_nvlist(name, value);
1732 1.1 christos if (nvp == NULL) {
1733 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1734 1.1 christos ERRNO_SET(nvl->nvl_error);
1735 1.1 christos } else {
1736 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1737 1.1 christos }
1738 1.1 christos }
1739 1.1 christos
1740 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
1741 1.1 christos void
1742 1.1 christos nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
1743 1.1 christos {
1744 1.1 christos nvpair_t *nvp;
1745 1.1 christos
1746 1.1 christos if (nvlist_error(nvl) != 0) {
1747 1.1 christos close(value);
1748 1.1 christos ERRNO_SET(nvlist_error(nvl));
1749 1.1 christos return;
1750 1.1 christos }
1751 1.1 christos
1752 1.1 christos nvp = nvpair_move_descriptor(name, value);
1753 1.1 christos if (nvp == NULL) {
1754 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1755 1.1 christos ERRNO_SET(nvl->nvl_error);
1756 1.1 christos } else {
1757 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1758 1.1 christos }
1759 1.1 christos }
1760 1.1 christos #endif
1761 1.1 christos
1762 1.1 christos void
1763 1.1 christos nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
1764 1.1 christos {
1765 1.1 christos nvpair_t *nvp;
1766 1.1 christos
1767 1.1 christos if (nvlist_error(nvl) != 0) {
1768 1.1 christos nv_free(value);
1769 1.1 christos ERRNO_SET(nvlist_error(nvl));
1770 1.1 christos return;
1771 1.1 christos }
1772 1.1 christos
1773 1.1 christos nvp = nvpair_move_binary(name, value, size);
1774 1.1 christos if (nvp == NULL) {
1775 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1776 1.1 christos ERRNO_SET(nvl->nvl_error);
1777 1.1 christos } else {
1778 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1779 1.1 christos }
1780 1.1 christos }
1781 1.1 christos
1782 1.1 christos void
1783 1.1 christos nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value,
1784 1.1 christos size_t nitems)
1785 1.1 christos {
1786 1.1 christos nvpair_t *nvp;
1787 1.1 christos
1788 1.1 christos if (nvlist_error(nvl) != 0) {
1789 1.1 christos nv_free(value);
1790 1.1 christos ERRNO_SET(nvlist_error(nvl));
1791 1.1 christos return;
1792 1.1 christos }
1793 1.1 christos
1794 1.1 christos nvp = nvpair_move_bool_array(name, value, nitems);
1795 1.1 christos if (nvp == NULL) {
1796 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1797 1.1 christos ERRNO_SET(nvl->nvl_error);
1798 1.1 christos } else {
1799 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1800 1.1 christos }
1801 1.1 christos }
1802 1.1 christos
1803 1.1 christos void
1804 1.1 christos nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value,
1805 1.1 christos size_t nitems)
1806 1.1 christos {
1807 1.1 christos nvpair_t *nvp;
1808 1.1 christos size_t i;
1809 1.1 christos
1810 1.1 christos if (nvlist_error(nvl) != 0) {
1811 1.1 christos if (value != NULL) {
1812 1.1 christos for (i = 0; i < nitems; i++)
1813 1.1 christos nv_free(value[i]);
1814 1.1 christos nv_free(value);
1815 1.1 christos }
1816 1.1 christos ERRNO_SET(nvlist_error(nvl));
1817 1.1 christos return;
1818 1.1 christos }
1819 1.1 christos
1820 1.1 christos nvp = nvpair_move_string_array(name, value, nitems);
1821 1.1 christos if (nvp == NULL) {
1822 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1823 1.1 christos ERRNO_SET(nvl->nvl_error);
1824 1.1 christos } else {
1825 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1826 1.1 christos }
1827 1.1 christos }
1828 1.1 christos
1829 1.1 christos void
1830 1.1 christos nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value,
1831 1.1 christos size_t nitems)
1832 1.1 christos {
1833 1.1 christos nvpair_t *nvp;
1834 1.1 christos size_t i;
1835 1.1 christos
1836 1.1 christos if (nvlist_error(nvl) != 0) {
1837 1.1 christos if (value != NULL) {
1838 1.1 christos for (i = 0; i < nitems; i++) {
1839 1.1 christos if (nvlist_get_pararr(value[i], NULL) == NULL)
1840 1.1 christos nvlist_destroy(value[i]);
1841 1.1 christos }
1842 1.1 christos }
1843 1.1 christos nv_free(value);
1844 1.1 christos ERRNO_SET(nvlist_error(nvl));
1845 1.1 christos return;
1846 1.1 christos }
1847 1.1 christos
1848 1.1 christos nvp = nvpair_move_nvlist_array(name, value, nitems);
1849 1.1 christos if (nvp == NULL) {
1850 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1851 1.1 christos ERRNO_SET(nvl->nvl_error);
1852 1.1 christos } else {
1853 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1854 1.1 christos }
1855 1.1 christos }
1856 1.1 christos
1857 1.1 christos void
1858 1.1 christos nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value,
1859 1.1 christos size_t nitems)
1860 1.1 christos {
1861 1.1 christos nvpair_t *nvp;
1862 1.1 christos
1863 1.1 christos if (nvlist_error(nvl) != 0) {
1864 1.1 christos nv_free(value);
1865 1.1 christos ERRNO_SET(nvlist_error(nvl));
1866 1.1 christos return;
1867 1.1 christos }
1868 1.1 christos
1869 1.1 christos nvp = nvpair_move_number_array(name, value, nitems);
1870 1.1 christos if (nvp == NULL) {
1871 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1872 1.1 christos ERRNO_SET(nvl->nvl_error);
1873 1.1 christos } else {
1874 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1875 1.1 christos }
1876 1.1 christos }
1877 1.1 christos
1878 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
1879 1.1 christos void
1880 1.1 christos nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value,
1881 1.1 christos size_t nitems)
1882 1.1 christos {
1883 1.1 christos nvpair_t *nvp;
1884 1.1 christos size_t i;
1885 1.1 christos
1886 1.1 christos if (nvlist_error(nvl) != 0) {
1887 1.1 christos if (value != 0) {
1888 1.1 christos for (i = 0; i < nitems; i++)
1889 1.1 christos close(value[i]);
1890 1.1 christos nv_free(value);
1891 1.1 christos }
1892 1.1 christos
1893 1.1 christos ERRNO_SET(nvlist_error(nvl));
1894 1.1 christos return;
1895 1.1 christos }
1896 1.1 christos
1897 1.1 christos nvp = nvpair_move_descriptor_array(name, value, nitems);
1898 1.1 christos if (nvp == NULL) {
1899 1.1 christos nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
1900 1.1 christos ERRNO_SET(nvl->nvl_error);
1901 1.1 christos } else {
1902 1.1 christos (void)nvlist_move_nvpair(nvl, nvp);
1903 1.1 christos }
1904 1.1 christos }
1905 1.1 christos #endif
1906 1.1 christos
1907 1.1 christos const nvpair_t *
1908 1.1 christos nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
1909 1.1 christos {
1910 1.1 christos
1911 1.1 christos return (nvlist_find(nvl, NV_TYPE_NONE, name));
1912 1.1 christos }
1913 1.1 christos
1914 1.1 christos #define NVLIST_GET(ftype, type, TYPE) \
1915 1.1 christos ftype \
1916 1.1 christos nvlist_get_##type(const nvlist_t *nvl, const char *name) \
1917 1.1 christos { \
1918 1.1 christos const nvpair_t *nvp; \
1919 1.1 christos \
1920 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1921 1.1 christos if (nvp == NULL) \
1922 1.1 christos nvlist_report_missing(NV_TYPE_##TYPE, name); \
1923 1.1 christos return (nvpair_get_##type(nvp)); \
1924 1.1 christos }
1925 1.1 christos
1926 1.1 christos NVLIST_GET(bool, bool, BOOL)
1927 1.1 christos NVLIST_GET(uint64_t, number, NUMBER)
1928 1.1 christos NVLIST_GET(const char *, string, STRING)
1929 1.1 christos NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
1930 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
1931 1.1 christos NVLIST_GET(int, descriptor, DESCRIPTOR)
1932 1.1 christos #endif
1933 1.1 christos
1934 1.1 christos #undef NVLIST_GET
1935 1.1 christos
1936 1.1 christos const void *
1937 1.1 christos nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
1938 1.1 christos {
1939 1.1 christos nvpair_t *nvp;
1940 1.1 christos
1941 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
1942 1.1 christos if (nvp == NULL)
1943 1.1 christos nvlist_report_missing(NV_TYPE_BINARY, name);
1944 1.1 christos
1945 1.1 christos return (nvpair_get_binary(nvp, sizep));
1946 1.1 christos }
1947 1.1 christos
1948 1.1 christos #define NVLIST_GET_ARRAY(ftype, type, TYPE) \
1949 1.1 christos ftype \
1950 1.1 christos nvlist_get_##type##_array(const nvlist_t *nvl, const char *name, \
1951 1.1 christos size_t *nitems) \
1952 1.1 christos { \
1953 1.1 christos const nvpair_t *nvp; \
1954 1.1 christos \
1955 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \
1956 1.1 christos if (nvp == NULL) \
1957 1.1 christos nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \
1958 1.1 christos return (nvpair_get_##type##_array(nvp, nitems)); \
1959 1.1 christos }
1960 1.1 christos
1961 1.1 christos NVLIST_GET_ARRAY(const bool *, bool, BOOL)
1962 1.1 christos NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER)
1963 1.1 christos NVLIST_GET_ARRAY(const char * const *, string, STRING)
1964 1.1 christos NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST)
1965 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
1966 1.1 christos NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR)
1967 1.1 christos #endif
1968 1.1 christos
1969 1.1 christos #undef NVLIST_GET_ARRAY
1970 1.1 christos
1971 1.1 christos #define NVLIST_TAKE(ftype, type, TYPE) \
1972 1.1 christos ftype \
1973 1.1 christos nvlist_take_##type(nvlist_t *nvl, const char *name) \
1974 1.1 christos { \
1975 1.1 christos nvpair_t *nvp; \
1976 1.1 christos ftype value; \
1977 1.1 christos \
1978 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \
1979 1.1 christos if (nvp == NULL) \
1980 1.1 christos nvlist_report_missing(NV_TYPE_##TYPE, name); \
1981 1.1 christos value = (ftype)(intptr_t)nvpair_get_##type(nvp); \
1982 1.1 christos nvlist_remove_nvpair(nvl, nvp); \
1983 1.1 christos nvpair_free_structure(nvp); \
1984 1.1 christos return (value); \
1985 1.1 christos }
1986 1.1 christos
1987 1.1 christos NVLIST_TAKE(bool, bool, BOOL)
1988 1.1 christos NVLIST_TAKE(uint64_t, number, NUMBER)
1989 1.1 christos NVLIST_TAKE(char *, string, STRING)
1990 1.1 christos NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
1991 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
1992 1.1 christos NVLIST_TAKE(int, descriptor, DESCRIPTOR)
1993 1.1 christos #endif
1994 1.1 christos
1995 1.1 christos #undef NVLIST_TAKE
1996 1.1 christos
1997 1.1 christos void *
1998 1.1 christos nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
1999 1.1 christos {
2000 1.1 christos nvpair_t *nvp;
2001 1.1 christos void *value;
2002 1.1 christos
2003 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
2004 1.1 christos if (nvp == NULL)
2005 1.1 christos nvlist_report_missing(NV_TYPE_BINARY, name);
2006 1.1 christos
2007 1.1 christos value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
2008 1.1 christos nvlist_remove_nvpair(nvl, nvp);
2009 1.1 christos nvpair_free_structure(nvp);
2010 1.1 christos return (value);
2011 1.1 christos }
2012 1.1 christos
2013 1.1 christos #define NVLIST_TAKE_ARRAY(ftype, type, TYPE) \
2014 1.1 christos ftype \
2015 1.1 christos nvlist_take_##type##_array(nvlist_t *nvl, const char *name, \
2016 1.1 christos size_t *nitems) \
2017 1.1 christos { \
2018 1.1 christos nvpair_t *nvp; \
2019 1.1 christos ftype value; \
2020 1.1 christos \
2021 1.1 christos nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \
2022 1.1 christos if (nvp == NULL) \
2023 1.1 christos nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \
2024 1.1 christos value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\
2025 1.1 christos nvlist_remove_nvpair(nvl, nvp); \
2026 1.1 christos nvpair_free_structure(nvp); \
2027 1.1 christos return (value); \
2028 1.1 christos }
2029 1.1 christos
2030 1.1 christos NVLIST_TAKE_ARRAY(bool *, bool, BOOL)
2031 1.1 christos NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER)
2032 1.1 christos NVLIST_TAKE_ARRAY(char **, string, STRING)
2033 1.1 christos NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST)
2034 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
2035 1.1 christos NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR)
2036 1.1 christos #endif
2037 1.1 christos
2038 1.1 christos void
2039 1.1 christos nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
2040 1.1 christos {
2041 1.1 christos
2042 1.1 christos NVLIST_ASSERT(nvl);
2043 1.1 christos NVPAIR_ASSERT(nvp);
2044 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
2045 1.1 christos
2046 1.1 christos nvpair_remove(&nvl->nvl_head, nvp, nvl);
2047 1.1 christos }
2048 1.1 christos
2049 1.1 christos void
2050 1.1 christos nvlist_free(nvlist_t *nvl, const char *name)
2051 1.1 christos {
2052 1.1 christos
2053 1.1 christos nvlist_free_type(nvl, name, NV_TYPE_NONE);
2054 1.1 christos }
2055 1.1 christos
2056 1.1 christos #define NVLIST_FREE(type, TYPE) \
2057 1.1 christos void \
2058 1.1 christos nvlist_free_##type(nvlist_t *nvl, const char *name) \
2059 1.1 christos { \
2060 1.1 christos \
2061 1.1 christos nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \
2062 1.1 christos }
2063 1.1 christos
2064 1.1 christos NVLIST_FREE(null, NULL)
2065 1.1 christos NVLIST_FREE(bool, BOOL)
2066 1.1 christos NVLIST_FREE(number, NUMBER)
2067 1.1 christos NVLIST_FREE(string, STRING)
2068 1.1 christos NVLIST_FREE(nvlist, NVLIST)
2069 1.1 christos NVLIST_FREE(binary, BINARY)
2070 1.1 christos NVLIST_FREE(bool_array, BOOL_ARRAY)
2071 1.1 christos NVLIST_FREE(number_array, NUMBER_ARRAY)
2072 1.1 christos NVLIST_FREE(string_array, STRING_ARRAY)
2073 1.1 christos NVLIST_FREE(nvlist_array, NVLIST_ARRAY)
2074 1.2 christos #if !defined(_KERNEL) && !defined(_STANDALONE)
2075 1.1 christos NVLIST_FREE(descriptor, DESCRIPTOR)
2076 1.1 christos NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY)
2077 1.1 christos #endif
2078 1.1 christos
2079 1.1 christos #undef NVLIST_FREE
2080 1.1 christos
2081 1.1 christos void
2082 1.1 christos nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
2083 1.1 christos {
2084 1.1 christos
2085 1.1 christos NVLIST_ASSERT(nvl);
2086 1.1 christos NVPAIR_ASSERT(nvp);
2087 1.1 christos PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
2088 1.1 christos
2089 1.1 christos nvlist_remove_nvpair(nvl, nvp);
2090 1.1 christos nvpair_free(nvp);
2091 1.1 christos }
2092 1.1 christos
2093