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