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