nvpair.c revision 1.6 1 /* $NetBSD: nvpair.c,v 1.6 2019/02/15 22:49:24 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.6 2019/02/15 22:49:24 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_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 nv_free(str);
1220 return (nvp);
1221 }
1222 #endif
1223
1224 nvpair_t *
1225 nvpair_create_null(const char *name)
1226 {
1227
1228 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1229 }
1230
1231 nvpair_t *
1232 nvpair_create_bool(const char *name, bool value)
1233 {
1234
1235 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1236 sizeof(uint8_t), 0));
1237 }
1238
1239 nvpair_t *
1240 nvpair_create_number(const char *name, uint64_t value)
1241 {
1242
1243 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1244 }
1245
1246 nvpair_t *
1247 nvpair_create_string(const char *name, const char *value)
1248 {
1249 nvpair_t *nvp;
1250 size_t size;
1251 char *data;
1252
1253 if (value == NULL) {
1254 ERRNO_SET(EINVAL);
1255 return (NULL);
1256 }
1257
1258 data = nv_strdup(value);
1259 if (data == NULL)
1260 return (NULL);
1261 size = strlen(value) + 1;
1262
1263 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1264 size, 0);
1265 if (nvp == NULL)
1266 nv_free(data);
1267
1268 return (nvp);
1269 }
1270
1271 nvpair_t *
1272 nvpair_create_nvlist(const char *name, const nvlist_t *value)
1273 {
1274 nvlist_t *nvl;
1275 nvpair_t *nvp;
1276
1277 if (value == NULL) {
1278 ERRNO_SET(EINVAL);
1279 return (NULL);
1280 }
1281
1282 nvl = nvlist_clone(value);
1283 if (nvl == NULL)
1284 return (NULL);
1285
1286 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1287 0);
1288 if (nvp == NULL)
1289 nvlist_destroy(nvl);
1290 else
1291 nvlist_set_parent(nvl, nvp);
1292
1293 return (nvp);
1294 }
1295
1296 #if !defined(_KERNEL) && !defined(_STANDALONE)
1297 nvpair_t *
1298 nvpair_create_descriptor(const char *name, int value)
1299 {
1300 nvpair_t *nvp;
1301
1302 if (value < 0 || !fd_is_valid(value)) {
1303 ERRNO_SET(EBADF);
1304 return (NULL);
1305 }
1306
1307 value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1308 if (value < 0)
1309 return (NULL);
1310
1311 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1312 sizeof(int64_t), 0);
1313 if (nvp == NULL) {
1314 ERRNO_SAVE();
1315 close(value);
1316 ERRNO_RESTORE();
1317 }
1318
1319 return (nvp);
1320 }
1321 #endif
1322
1323 nvpair_t *
1324 nvpair_create_binary(const char *name, const void *value, size_t size)
1325 {
1326 nvpair_t *nvp;
1327 void *data;
1328
1329 if (value == NULL || size == 0) {
1330 ERRNO_SET(EINVAL);
1331 return (NULL);
1332 }
1333
1334 data = nv_malloc(size);
1335 if (data == NULL)
1336 return (NULL);
1337 memcpy(data, value, size);
1338
1339 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1340 size, 0);
1341 if (nvp == NULL)
1342 nv_free(data);
1343
1344 return (nvp);
1345 }
1346
1347 nvpair_t *
1348 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1349 {
1350 nvpair_t *nvp;
1351 size_t size;
1352 void *data;
1353
1354 if (value == NULL || nitems == 0) {
1355 ERRNO_SET(EINVAL);
1356 return (NULL);
1357 }
1358
1359 size = sizeof(value[0]) * nitems;
1360 data = nv_malloc(size);
1361 if (data == NULL)
1362 return (NULL);
1363
1364 memcpy(data, value, size);
1365 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1366 size, nitems);
1367 if (nvp == NULL) {
1368 ERRNO_SAVE();
1369 nv_free(data);
1370 ERRNO_RESTORE();
1371 }
1372
1373 return (nvp);
1374 }
1375
1376 nvpair_t *
1377 nvpair_create_number_array(const char *name, const uint64_t *value,
1378 size_t nitems)
1379 {
1380 nvpair_t *nvp;
1381 size_t size;
1382 void *data;
1383
1384 if (value == NULL || nitems == 0) {
1385 ERRNO_SET(EINVAL);
1386 return (NULL);
1387 }
1388
1389 size = sizeof(value[0]) * nitems;
1390 data = nv_malloc(size);
1391 if (data == NULL)
1392 return (NULL);
1393
1394 memcpy(data, value, size);
1395 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1396 (uint64_t)(uintptr_t)data, size, nitems);
1397 if (nvp == NULL) {
1398 ERRNO_SAVE();
1399 nv_free(data);
1400 ERRNO_RESTORE();
1401 }
1402
1403 return (nvp);
1404 }
1405
1406 nvpair_t *
1407 nvpair_create_string_array(const char *name, const char * const *value,
1408 size_t nitems)
1409 {
1410 nvpair_t *nvp;
1411 unsigned int ii;
1412 size_t datasize, size;
1413 char **data;
1414
1415 if (value == NULL || nitems == 0) {
1416 ERRNO_SET(EINVAL);
1417 return (NULL);
1418 }
1419
1420 nvp = NULL;
1421 datasize = 0;
1422 data = nv_malloc(sizeof(value[0]) * nitems);
1423 if (data == NULL)
1424 return (NULL);
1425
1426 for (ii = 0; ii < nitems; ii++) {
1427 if (value[ii] == NULL) {
1428 ERRNO_SET(EINVAL);
1429 goto fail;
1430 }
1431
1432 size = strlen(value[ii]) + 1;
1433 datasize += size;
1434 data[ii] = nv_strdup(value[ii]);
1435 if (data[ii] == NULL)
1436 goto fail;
1437 }
1438 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1439 (uint64_t)(uintptr_t)data, datasize, nitems);
1440
1441 fail:
1442 if (nvp == NULL) {
1443 ERRNO_SAVE();
1444 for (; ii > 0; ii--)
1445 nv_free(data[ii - 1]);
1446 nv_free(data);
1447 ERRNO_RESTORE();
1448 }
1449
1450 return (nvp);
1451 }
1452
1453 nvpair_t *
1454 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1455 size_t nitems)
1456 {
1457 unsigned int ii;
1458 nvlist_t **nvls;
1459 nvpair_t *parent;
1460 int flags;
1461
1462 nvls = NULL;
1463
1464 if (value == NULL || nitems == 0) {
1465 ERRNO_SET(EINVAL);
1466 return (NULL);
1467 }
1468
1469 nvls = nv_malloc(sizeof(value[0]) * nitems);
1470 if (nvls == NULL)
1471 return (NULL);
1472
1473 for (ii = 0; ii < nitems; ii++) {
1474 if (value[ii] == NULL) {
1475 ERRNO_SET(EINVAL);
1476 goto fail;
1477 }
1478
1479 nvls[ii] = nvlist_clone(value[ii]);
1480 if (nvls[ii] == NULL)
1481 goto fail;
1482
1483 if (ii > 0) {
1484 nvpair_t *nvp;
1485
1486 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1487 (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1488 if (nvp == NULL) {
1489 ERRNO_SAVE();
1490 nvlist_destroy(nvls[ii]);
1491 ERRNO_RESTORE();
1492 goto fail;
1493 }
1494 nvlist_set_array_next(nvls[ii - 1], nvp);
1495 }
1496 }
1497 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1498 nvlist_set_flags(nvls[nitems - 1], flags);
1499
1500 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1501 (uint64_t)(uintptr_t)nvls, 0, nitems);
1502 if (parent == NULL)
1503 goto fail;
1504
1505 for (ii = 0; ii < nitems; ii++)
1506 nvlist_set_parent(nvls[ii], parent);
1507
1508 return (parent);
1509
1510 fail:
1511 ERRNO_SAVE();
1512 for (; ii > 0; ii--)
1513 nvlist_destroy(nvls[ii - 1]);
1514 nv_free(nvls);
1515 ERRNO_RESTORE();
1516
1517 return (NULL);
1518 }
1519
1520 #if !defined(_KERNEL) && !defined(_STANDALONE)
1521 nvpair_t *
1522 nvpair_create_descriptor_array(const char *name, const int *value,
1523 size_t nitems)
1524 {
1525 unsigned int ii;
1526 nvpair_t *nvp;
1527 int *fds;
1528
1529 if (value == NULL) {
1530 ERRNO_SET(EINVAL);
1531 return (NULL);
1532 }
1533
1534 nvp = NULL;
1535
1536 fds = nv_malloc(sizeof(value[0]) * nitems);
1537 if (fds == NULL)
1538 return (NULL);
1539 for (ii = 0; ii < nitems; ii++) {
1540 if (value[ii] == -1) {
1541 fds[ii] = -1;
1542 } else {
1543 if (!fd_is_valid(value[ii])) {
1544 ERRNO_SET(EBADF);
1545 goto fail;
1546 }
1547
1548 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1549 if (fds[ii] == -1)
1550 goto fail;
1551 }
1552 }
1553
1554 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1555 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1556
1557 fail:
1558 if (nvp == NULL) {
1559 ERRNO_SAVE();
1560 for (; ii > 0; ii--) {
1561 if (fds[ii - 1] != -1)
1562 close(fds[ii - 1]);
1563 }
1564 nv_free(fds);
1565 ERRNO_RESTORE();
1566 }
1567
1568 return (nvp);
1569 }
1570 #endif
1571
1572 nvpair_t *
1573 nvpair_move_string(const char *name, char *value)
1574 {
1575 nvpair_t *nvp;
1576
1577 if (value == NULL) {
1578 ERRNO_SET(EINVAL);
1579 return (NULL);
1580 }
1581
1582 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1583 strlen(value) + 1, 0);
1584 if (nvp == NULL) {
1585 ERRNO_SAVE();
1586 nv_free(value);
1587 ERRNO_RESTORE();
1588 }
1589
1590 return (nvp);
1591 }
1592
1593 nvpair_t *
1594 nvpair_move_nvlist(const char *name, nvlist_t *value)
1595 {
1596 nvpair_t *nvp;
1597
1598 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1599 ERRNO_SET(EINVAL);
1600 return (NULL);
1601 }
1602
1603 if (nvlist_error(value) != 0) {
1604 ERRNO_SET(nvlist_error(value));
1605 nvlist_destroy(value);
1606 return (NULL);
1607 }
1608
1609 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1610 0, 0);
1611 if (nvp == NULL)
1612 nvlist_destroy(value);
1613 else
1614 nvlist_set_parent(value, nvp);
1615
1616 return (nvp);
1617 }
1618
1619 #if !defined(_KERNEL) && !defined(_STANDALONE)
1620 nvpair_t *
1621 nvpair_move_descriptor(const char *name, int value)
1622 {
1623 nvpair_t *nvp;
1624
1625 if (value < 0 || !fd_is_valid(value)) {
1626 ERRNO_SET(EBADF);
1627 return (NULL);
1628 }
1629
1630 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1631 sizeof(int64_t), 0);
1632 if (nvp == NULL) {
1633 ERRNO_SAVE();
1634 close(value);
1635 ERRNO_RESTORE();
1636 }
1637
1638 return (nvp);
1639 }
1640 #endif
1641
1642 nvpair_t *
1643 nvpair_move_binary(const char *name, void *value, size_t size)
1644 {
1645 nvpair_t *nvp;
1646
1647 if (value == NULL || size == 0) {
1648 ERRNO_SET(EINVAL);
1649 return (NULL);
1650 }
1651
1652 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1653 size, 0);
1654 if (nvp == NULL) {
1655 ERRNO_SAVE();
1656 nv_free(value);
1657 ERRNO_RESTORE();
1658 }
1659
1660 return (nvp);
1661 }
1662
1663 nvpair_t *
1664 nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1665 {
1666 nvpair_t *nvp;
1667
1668 if (value == NULL || nitems == 0) {
1669 ERRNO_SET(EINVAL);
1670 return (NULL);
1671 }
1672
1673 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1674 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1675 if (nvp == NULL) {
1676 ERRNO_SAVE();
1677 nv_free(value);
1678 ERRNO_RESTORE();
1679 }
1680
1681 return (nvp);
1682 }
1683
1684 nvpair_t *
1685 nvpair_move_string_array(const char *name, char **value, size_t nitems)
1686 {
1687 nvpair_t *nvp;
1688 size_t i, size;
1689
1690 if (value == NULL || nitems == 0) {
1691 ERRNO_SET(EINVAL);
1692 return (NULL);
1693 }
1694
1695 size = 0;
1696 for (i = 0; i < nitems; i++) {
1697 if (value[i] == NULL) {
1698 ERRNO_SET(EINVAL);
1699 return (NULL);
1700 }
1701
1702 size += strlen(value[i]) + 1;
1703 }
1704
1705 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1706 (uint64_t)(uintptr_t)value, size, nitems);
1707 if (nvp == NULL) {
1708 ERRNO_SAVE();
1709 for (i = 0; i < nitems; i++)
1710 nv_free(value[i]);
1711 nv_free(value);
1712 ERRNO_RESTORE();
1713 }
1714
1715 return (nvp);
1716 }
1717
1718 nvpair_t *
1719 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1720 {
1721 nvpair_t *nvp;
1722
1723 if (value == NULL || nitems == 0) {
1724 ERRNO_SET(EINVAL);
1725 return (NULL);
1726 }
1727
1728 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1729 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1730 if (nvp == NULL) {
1731 ERRNO_SAVE();
1732 nv_free(value);
1733 ERRNO_RESTORE();
1734 }
1735
1736 return (nvp);
1737 }
1738
1739 nvpair_t *
1740 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1741 {
1742 nvpair_t *parent;
1743 unsigned int ii;
1744 int flags;
1745
1746 if (value == NULL || nitems == 0) {
1747 ERRNO_SET(EINVAL);
1748 return (NULL);
1749 }
1750
1751 for (ii = 0; ii < nitems; ii++) {
1752 if (value == NULL || nvlist_error(value[ii]) != 0 ||
1753 nvlist_get_pararr(value[ii], NULL) != NULL) {
1754 ERRNO_SET(EINVAL);
1755 goto fail;
1756 }
1757 if (ii > 0) {
1758 nvpair_t *nvp;
1759
1760 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1761 (uint64_t)(uintptr_t)value[ii], 0, 0);
1762 if (nvp == NULL)
1763 goto fail;
1764 nvlist_set_array_next(value[ii - 1], nvp);
1765 }
1766 }
1767 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1768 nvlist_set_flags(value[nitems - 1], flags);
1769
1770 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1771 (uint64_t)(uintptr_t)value, 0, nitems);
1772 if (parent == NULL)
1773 goto fail;
1774
1775 for (ii = 0; ii < nitems; ii++)
1776 nvlist_set_parent(value[ii], parent);
1777
1778 return (parent);
1779 fail:
1780 ERRNO_SAVE();
1781 for (ii = 0; ii < nitems; ii++) {
1782 if (value[ii] != NULL &&
1783 nvlist_get_pararr(value[ii], NULL) != NULL) {
1784 nvlist_destroy(value[ii]);
1785 }
1786 }
1787 nv_free(value);
1788 ERRNO_RESTORE();
1789
1790 return (NULL);
1791 }
1792
1793 #if !defined(_KERNEL) && !defined(_STANDALONE)
1794 nvpair_t *
1795 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1796 {
1797 nvpair_t *nvp;
1798 size_t i;
1799
1800 if (value == NULL || nitems == 0) {
1801 ERRNO_SET(EINVAL);
1802 return (NULL);
1803 }
1804
1805 for (i = 0; i < nitems; i++) {
1806 if (value[i] != -1 && !fd_is_valid(value[i])) {
1807 ERRNO_SET(EBADF);
1808 goto fail;
1809 }
1810 }
1811
1812 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1813 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1814 if (nvp == NULL)
1815 goto fail;
1816
1817 return (nvp);
1818 fail:
1819 ERRNO_SAVE();
1820 for (i = 0; i < nitems; i++) {
1821 if (fd_is_valid(value[i]))
1822 close(value[i]);
1823 }
1824 nv_free(value);
1825 ERRNO_RESTORE();
1826
1827 return (NULL);
1828 }
1829 #endif
1830
1831 bool
1832 nvpair_get_bool(const nvpair_t *nvp)
1833 {
1834
1835 NVPAIR_ASSERT(nvp);
1836
1837 return (nvp->nvp_data == 1);
1838 }
1839
1840 uint64_t
1841 nvpair_get_number(const nvpair_t *nvp)
1842 {
1843
1844 NVPAIR_ASSERT(nvp);
1845
1846 return (nvp->nvp_data);
1847 }
1848
1849 const char *
1850 nvpair_get_string(const nvpair_t *nvp)
1851 {
1852
1853 NVPAIR_ASSERT(nvp);
1854 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1855
1856 return ((const char *)(intptr_t)nvp->nvp_data);
1857 }
1858
1859 const nvlist_t *
1860 nvpair_get_nvlist(const nvpair_t *nvp)
1861 {
1862
1863 NVPAIR_ASSERT(nvp);
1864 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1865
1866 return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1867 }
1868
1869 #if !defined(_KERNEL) && !defined(_STANDALONE)
1870 int
1871 nvpair_get_descriptor(const nvpair_t *nvp)
1872 {
1873
1874 NVPAIR_ASSERT(nvp);
1875 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1876
1877 return ((int)nvp->nvp_data);
1878 }
1879 #endif
1880
1881 const void *
1882 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1883 {
1884
1885 NVPAIR_ASSERT(nvp);
1886 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1887
1888 if (sizep != NULL)
1889 *sizep = nvp->nvp_datasize;
1890
1891 return ((const void *)(intptr_t)nvp->nvp_data);
1892 }
1893
1894 const bool *
1895 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1896 {
1897
1898 NVPAIR_ASSERT(nvp);
1899 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1900
1901 if (nitems != NULL)
1902 *nitems = nvp->nvp_nitems;
1903
1904 return ((const bool *)(intptr_t)nvp->nvp_data);
1905 }
1906
1907 const uint64_t *
1908 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1909 {
1910
1911 NVPAIR_ASSERT(nvp);
1912 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1913
1914 if (nitems != NULL)
1915 *nitems = nvp->nvp_nitems;
1916
1917 return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1918 }
1919
1920 const char * const *
1921 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1922 {
1923
1924 NVPAIR_ASSERT(nvp);
1925 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1926
1927 if (nitems != NULL)
1928 *nitems = nvp->nvp_nitems;
1929
1930 return ((const char * const *)(intptr_t)nvp->nvp_data);
1931 }
1932
1933 const nvlist_t * const *
1934 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1935 {
1936
1937 NVPAIR_ASSERT(nvp);
1938 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1939
1940 if (nitems != NULL)
1941 *nitems = nvp->nvp_nitems;
1942
1943 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1944 }
1945
1946 #if !defined(_KERNEL) && !defined(_STANDALONE)
1947 const int *
1948 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1949 {
1950
1951 NVPAIR_ASSERT(nvp);
1952 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1953
1954 if (nitems != NULL)
1955 *nitems = nvp->nvp_nitems;
1956
1957 return ((const int *)(intptr_t)nvp->nvp_data);
1958 }
1959 #endif
1960
1961 int
1962 nvpair_append_bool_array(nvpair_t *nvp, const bool value)
1963 {
1964
1965 NVPAIR_ASSERT(nvp);
1966 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1967 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1968 }
1969
1970 int
1971 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
1972 {
1973
1974 NVPAIR_ASSERT(nvp);
1975 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1976 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1977 }
1978
1979 int
1980 nvpair_append_string_array(nvpair_t *nvp, const char *value)
1981 {
1982 char *str;
1983
1984 NVPAIR_ASSERT(nvp);
1985 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1986 if (value == NULL) {
1987 ERRNO_SET(EINVAL);
1988 return (-1);
1989 }
1990 str = nv_strdup(value);
1991 if (str == NULL) {
1992 return (-1);
1993 }
1994 if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
1995 nv_free(str);
1996 return (-1);
1997 }
1998 return (0);
1999 }
2000
2001 int
2002 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
2003 {
2004 nvpair_t *tmpnvp;
2005 nvlist_t *nvl, *prev;
2006 int flags;
2007
2008 NVPAIR_ASSERT(nvp);
2009 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
2010 if (value == NULL || nvlist_error(value) != 0 ||
2011 nvlist_get_pararr(value, NULL) != NULL) {
2012 ERRNO_SET(EINVAL);
2013 return (-1);
2014 }
2015 nvl = nvlist_clone(value);
2016 if (nvl == NULL) {
2017 return (-1);
2018 }
2019 flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
2020 nvlist_set_flags(nvl, flags);
2021
2022 tmpnvp = NULL;
2023 prev = NULL;
2024 if (nvp->nvp_nitems > 0) {
2025 nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
2026
2027 prev = nvls[nvp->nvp_nitems - 1];
2028 PJDLOG_ASSERT(prev != NULL);
2029
2030 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
2031 (uint64_t)(uintptr_t)nvl, 0, 0);
2032 if (tmpnvp == NULL) {
2033 goto fail;
2034 }
2035 }
2036 if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
2037 goto fail;
2038 }
2039 if (tmpnvp) {
2040 NVPAIR_ASSERT(tmpnvp);
2041 nvlist_set_array_next(prev, tmpnvp);
2042 }
2043 nvlist_set_parent(nvl, nvp);
2044 return (0);
2045 fail:
2046 if (tmpnvp) {
2047 nvpair_free(tmpnvp);
2048 }
2049 nvlist_destroy(nvl);
2050 return (-1);
2051 }
2052
2053 #if !defined(_KERNEL) && !defined(_STANDALONE)
2054 int
2055 nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
2056 {
2057 int fd;
2058
2059 NVPAIR_ASSERT(nvp);
2060 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
2061 if (value < 0 || !fd_is_valid(value)) {
2062 ERRNO_SET(EBADF);
2063 return -1;
2064 }
2065 fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
2066 if (fd == -1) {
2067 return (-1);
2068 }
2069 if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
2070 close(fd);
2071 return (-1);
2072 }
2073 return (0);
2074 }
2075 #endif
2076
2077 void
2078 nvpair_free(nvpair_t *nvp)
2079 {
2080 size_t i;
2081
2082 NVPAIR_ASSERT(nvp);
2083 PJDLOG_ASSERT(nvp->nvp_list == NULL);
2084
2085 nvp->nvp_magic = 0;
2086 switch (nvp->nvp_type) {
2087 #if !defined(_KERNEL) && !defined(_STANDALONE)
2088 case NV_TYPE_DESCRIPTOR:
2089 close((int)nvp->nvp_data);
2090 break;
2091 case NV_TYPE_DESCRIPTOR_ARRAY:
2092 for (i = 0; i < nvp->nvp_nitems; i++)
2093 close(((int *)(intptr_t)nvp->nvp_data)[i]);
2094 nv_free((int *)(intptr_t)nvp->nvp_data);
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