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