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