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