1 /*-
2 * Copyright (c) 2009-2013 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/endian.h>
35 #include <sys/queue.h>
36
37 #ifdef _KERNEL
38
39 #include <sys/errno.h>
40 #include <sys/lock.h>
41 #include <sys/malloc.h>
42 #include <sys/systm.h>
43
44 #include <machine/stdarg.h>
45
46 #else
47 #include <errno.h>
48 #include <fcntl.h>
49 #include <stdarg.h>
50 #include <stdbool.h>
51 #include <stdint.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55
56 #include "common_impl.h"
57 #endif
58
59 #ifdef HAVE_PJDLOG
60 #include <pjdlog.h>
61 #endif
62
63 #include <sys/nv.h>
64 #include <sys/nv_impl.h>
65 #include <sys/nvlist_impl.h>
66 #include <sys/nvpair_impl.h>
67
68 #ifndef HAVE_PJDLOG
69 #ifdef _KERNEL
70 #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
71 #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
72 #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
73 #else
74 #include <assert.h>
75 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
76 #define PJDLOG_RASSERT(expr, ...) assert(expr)
77 #define PJDLOG_ABORT(...) abort()
78 #endif
79 #endif
80
81 #define NVPAIR_MAGIC 0x6e7670 /* "nvp" */
82 struct nvpair {
83 int nvp_magic;
84 char *nvp_name;
85 int nvp_type;
86 uint64_t nvp_data;
87 size_t nvp_datasize;
88 nvlist_t *nvp_list;
89 TAILQ_ENTRY(nvpair) nvp_next;
90 };
91
92 #define NVPAIR_ASSERT(nvp) do { \
93 PJDLOG_ASSERT((nvp) != NULL); \
94 PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \
95 } while (0)
96
97 struct nvpair_header {
98 uint8_t nvph_type;
99 uint16_t nvph_namesize;
100 uint64_t nvph_datasize;
101 } __packed;
102
103
104 void
nvpair_assert(const nvpair_t * nvp)105 nvpair_assert(const nvpair_t *nvp)
106 {
107
108 NVPAIR_ASSERT(nvp);
109 }
110
111 nvlist_t *
nvpair_nvlist(const nvpair_t * nvp)112 nvpair_nvlist(const nvpair_t *nvp)
113 {
114
115 NVPAIR_ASSERT(nvp);
116
117 return (nvp->nvp_list);
118 }
119
120 nvpair_t *
nvpair_next(const nvpair_t * nvp)121 nvpair_next(const nvpair_t *nvp)
122 {
123
124 NVPAIR_ASSERT(nvp);
125 PJDLOG_ASSERT(nvp->nvp_list != NULL);
126
127 return (TAILQ_NEXT(nvp, nvp_next));
128 }
129
130 nvpair_t *
nvpair_prev(const nvpair_t * nvp)131 nvpair_prev(const nvpair_t *nvp)
132 {
133
134 NVPAIR_ASSERT(nvp);
135 PJDLOG_ASSERT(nvp->nvp_list != NULL);
136
137 return (TAILQ_PREV(nvp, nvl_head, nvp_next));
138 }
139
140 void
nvpair_insert(struct nvl_head * head,nvpair_t * nvp,nvlist_t * nvl)141 nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
142 {
143
144 NVPAIR_ASSERT(nvp);
145 PJDLOG_ASSERT(nvp->nvp_list == NULL);
146 PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp)));
147
148 TAILQ_INSERT_TAIL(head, nvp, nvp_next);
149 nvp->nvp_list = nvl;
150 }
151
152 static void
nvpair_remove_nvlist(nvpair_t * nvp)153 nvpair_remove_nvlist(nvpair_t *nvp)
154 {
155 nvlist_t *nvl;
156
157 /* XXX: DECONST is bad, mkay? */
158 nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
159 PJDLOG_ASSERT(nvl != NULL);
160 nvlist_set_parent(nvl, NULL);
161 }
162
163 void
nvpair_remove(struct nvl_head * head,nvpair_t * nvp,const nvlist_t * nvl)164 nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
165 {
166
167 NVPAIR_ASSERT(nvp);
168 PJDLOG_ASSERT(nvp->nvp_list == nvl);
169
170 if (nvpair_type(nvp) == NV_TYPE_NVLIST ||
171 nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY ||
172 nvpair_type(nvp) == NV_TYPE_NVLIST_DICTIONARY)
173 nvpair_remove_nvlist(nvp);
174
175 TAILQ_REMOVE(head, nvp, nvp_next);
176 nvp->nvp_list = NULL;
177 }
178
179 nvpair_t *
nvpair_clone(const nvpair_t * nvp)180 nvpair_clone(const nvpair_t *nvp)
181 {
182 nvpair_t *newnvp;
183 const char *name;
184 const void *data;
185 size_t datasize;
186
187 NVPAIR_ASSERT(nvp);
188
189 name = nvpair_name(nvp);
190
191 switch (nvpair_type(nvp)) {
192 case NV_TYPE_NULL:
193 newnvp = nvpair_create_null(name);
194 break;
195 case NV_TYPE_BOOL:
196 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
197 break;
198 case NV_TYPE_NUMBER:
199 case NV_TYPE_PTR:
200 case NV_TYPE_UINT64:
201 case NV_TYPE_INT64:
202 case NV_TYPE_ENDPOINT:
203 newnvp = nvpair_create_number_type(name, nvpair_get_number(nvp), nvpair_type(nvp));
204 break;
205 case NV_TYPE_STRING:
206 newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
207 break;
208 case NV_TYPE_NVLIST:
209 case NV_TYPE_NVLIST_ARRAY:
210 case NV_TYPE_NVLIST_DICTIONARY:
211 newnvp = nvpair_create_nvlist_type(name, nvpair_get_nvlist(nvp), nvpair_type(nvp));
212 break;
213 #ifndef _KERNEL
214 case NV_TYPE_DESCRIPTOR:
215 newnvp = nvpair_create_descriptor(name,
216 nvpair_get_descriptor(nvp));
217 break;
218 #endif
219 case NV_TYPE_BINARY:
220 data = nvpair_get_binary(nvp, &datasize);
221 newnvp = nvpair_create_binary(name, data, datasize);
222 break;
223 case NV_TYPE_UUID:
224 data = nvpair_get_uuid(nvp);
225 newnvp = nvpair_create_uuid(name, data);
226 break;
227 default:
228 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
229 }
230
231 return (newnvp);
232 }
233
234 size_t
nvpair_header_size(void)235 nvpair_header_size(void)
236 {
237
238 return (sizeof(struct nvpair_header));
239 }
240
241 size_t
nvpair_size(const nvpair_t * nvp)242 nvpair_size(const nvpair_t *nvp)
243 {
244
245 NVPAIR_ASSERT(nvp);
246
247 return (nvp->nvp_datasize);
248 }
249
250 unsigned char *
nvpair_pack_header(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)251 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
252 {
253 struct nvpair_header nvphdr;
254 size_t namesize;
255
256 NVPAIR_ASSERT(nvp);
257
258 nvphdr.nvph_type = nvp->nvp_type;
259 namesize = strlen(nvp->nvp_name) + 1;
260 PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
261 nvphdr.nvph_namesize = namesize;
262 nvphdr.nvph_datasize = nvp->nvp_datasize;
263 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
264 memcpy(ptr, &nvphdr, sizeof(nvphdr));
265 ptr += sizeof(nvphdr);
266 *leftp -= sizeof(nvphdr);
267
268 PJDLOG_ASSERT(*leftp >= namesize);
269 memcpy(ptr, nvp->nvp_name, namesize);
270 ptr += namesize;
271 *leftp -= namesize;
272
273 return (ptr);
274 }
275
276 unsigned char *
nvpair_pack_null(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp __unused)277 nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
278 size_t *leftp __unused)
279 {
280
281 NVPAIR_ASSERT(nvp);
282 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
283
284 return (ptr);
285 }
286
287 unsigned char *
nvpair_pack_bool(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)288 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
289 {
290 uint8_t value;
291
292 NVPAIR_ASSERT(nvp);
293 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
294
295 value = (uint8_t)nvp->nvp_data;
296
297 PJDLOG_ASSERT(*leftp >= sizeof(value));
298 memcpy(ptr, &value, sizeof(value));
299 ptr += sizeof(value);
300 *leftp -= sizeof(value);
301
302 return (ptr);
303 }
304
305 unsigned char *
nvpair_pack_number(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)306 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
307 {
308 uint64_t value;
309
310 NVPAIR_ASSERT(nvp);
311 PJDLOG_ASSERT(
312 nvp->nvp_type == NV_TYPE_NUMBER ||
313 nvp->nvp_type == NV_TYPE_PTR ||
314 nvp->nvp_type == NV_TYPE_UINT64 ||
315 nvp->nvp_type == NV_TYPE_INT64 ||
316 nvp->nvp_type == NV_TYPE_ENDPOINT ||
317 nvp->nvp_type == NV_TYPE_DATE
318 );
319
320 value = (uint64_t)nvp->nvp_data;
321
322 PJDLOG_ASSERT(*leftp >= sizeof(value));
323 memcpy(ptr, &value, sizeof(value));
324 ptr += sizeof(value);
325 *leftp -= sizeof(value);
326
327 return (ptr);
328 }
329
330 unsigned char *
nvpair_pack_string(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)331 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
332 {
333
334 NVPAIR_ASSERT(nvp);
335 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
336
337 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
338 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
339 ptr += nvp->nvp_datasize;
340 *leftp -= nvp->nvp_datasize;
341
342 return (ptr);
343 }
344
345 unsigned char *
nvpair_pack_nvlist_up(unsigned char * ptr,size_t * leftp)346 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
347 {
348 struct nvpair_header nvphdr;
349 size_t namesize;
350 const char *name = "";
351
352 namesize = 1;
353 nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
354 nvphdr.nvph_namesize = namesize;
355 nvphdr.nvph_datasize = 0;
356 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
357 memcpy(ptr, &nvphdr, sizeof(nvphdr));
358 ptr += sizeof(nvphdr);
359 *leftp -= sizeof(nvphdr);
360
361 PJDLOG_ASSERT(*leftp >= namesize);
362 memcpy(ptr, name, namesize);
363 ptr += namesize;
364 *leftp -= namesize;
365
366 return (ptr);
367 }
368
369 #ifndef _KERNEL
370 unsigned char *
nvpair_pack_descriptor(const nvpair_t * nvp,unsigned char * ptr,int64_t * fdidxp,size_t * leftp)371 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
372 size_t *leftp)
373 {
374 int64_t value;
375
376 NVPAIR_ASSERT(nvp);
377 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
378
379 value = (int64_t)nvp->nvp_data;
380 if (value != -1) {
381 /*
382 * If there is a real descriptor here, we change its number
383 * to position in the array of descriptors send via control
384 * message.
385 */
386 PJDLOG_ASSERT(fdidxp != NULL);
387
388 value = *fdidxp;
389 (*fdidxp)++;
390 }
391
392 PJDLOG_ASSERT(*leftp >= sizeof(value));
393 memcpy(ptr, &value, sizeof(value));
394 ptr += sizeof(value);
395 *leftp -= sizeof(value);
396
397 return (ptr);
398 }
399 #endif
400
401 unsigned char *
nvpair_pack_binary(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)402 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
403 {
404
405 NVPAIR_ASSERT(nvp);
406 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
407
408 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
409 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
410 ptr += nvp->nvp_datasize;
411 *leftp -= nvp->nvp_datasize;
412
413 return (ptr);
414 }
415
416 void
nvpair_init_datasize(nvpair_t * nvp)417 nvpair_init_datasize(nvpair_t *nvp)
418 {
419
420 NVPAIR_ASSERT(nvp);
421
422 if (nvp->nvp_type == NV_TYPE_NVLIST_ARRAY ||
423 nvp->nvp_type == NV_TYPE_NVLIST_DICTIONARY ||
424 nvp->nvp_type == NV_TYPE_NVLIST) {
425 if (nvp->nvp_data == 0) {
426 nvp->nvp_datasize = 0;
427 } else {
428 nvp->nvp_datasize =
429 nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
430 }
431 }
432 }
433
434 const unsigned char *
nvpair_unpack_header(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)435 nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
436 size_t *leftp)
437 {
438 struct nvpair_header nvphdr;
439
440 if (*leftp < sizeof(nvphdr))
441 goto failed;
442
443 memcpy(&nvphdr, ptr, sizeof(nvphdr));
444 ptr += sizeof(nvphdr);
445 *leftp -= sizeof(nvphdr);
446
447 #if NV_TYPE_FIRST > 0
448 if (nvphdr.nvph_type < NV_TYPE_FIRST)
449 goto failed;
450 #endif
451 if (nvphdr.nvph_type > NV_TYPE_LAST &&
452 nvphdr.nvph_type != NV_TYPE_NVLIST_UP) {
453 goto failed;
454 }
455
456 #if BYTE_ORDER == BIG_ENDIAN
457 if (!isbe) {
458 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
459 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
460 }
461 #else
462 if (isbe) {
463 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
464 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
465 }
466 #endif
467
468 if (nvphdr.nvph_namesize > NV_NAME_MAX)
469 goto failed;
470 if (*leftp < nvphdr.nvph_namesize)
471 goto failed;
472 if (nvphdr.nvph_namesize < 1)
473 goto failed;
474 if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
475 (size_t)(nvphdr.nvph_namesize - 1)) {
476 goto failed;
477 }
478
479 memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
480 ptr += nvphdr.nvph_namesize;
481 *leftp -= nvphdr.nvph_namesize;
482
483 if (*leftp < nvphdr.nvph_datasize)
484 goto failed;
485
486 nvp->nvp_type = nvphdr.nvph_type;
487 nvp->nvp_data = 0;
488 nvp->nvp_datasize = nvphdr.nvph_datasize;
489
490 return (ptr);
491 failed:
492 RESTORE_ERRNO(EINVAL);
493 return (NULL);
494 }
495
496 const unsigned char *
nvpair_unpack_null(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp __unused)497 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
498 size_t *leftp __unused)
499 {
500
501 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
502
503 if (nvp->nvp_datasize != 0) {
504 RESTORE_ERRNO(EINVAL);
505 return (NULL);
506 }
507
508 return (ptr);
509 }
510
511 const unsigned char *
nvpair_unpack_bool(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)512 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
513 size_t *leftp)
514 {
515 uint8_t value;
516
517 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
518
519 if (nvp->nvp_datasize != sizeof(value)) {
520 RESTORE_ERRNO(EINVAL);
521 return (NULL);
522 }
523 if (*leftp < sizeof(value)) {
524 RESTORE_ERRNO(EINVAL);
525 return (NULL);
526 }
527
528 memcpy(&value, ptr, sizeof(value));
529 ptr += sizeof(value);
530 *leftp -= sizeof(value);
531
532 if (value != 0 && value != 1) {
533 RESTORE_ERRNO(EINVAL);
534 return (NULL);
535 }
536
537 nvp->nvp_data = (uint64_t)value;
538
539 return (ptr);
540 }
541
542 const unsigned char *
nvpair_unpack_number(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)543 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
544 size_t *leftp)
545 {
546
547 PJDLOG_ASSERT(
548 nvp->nvp_type == NV_TYPE_NUMBER ||
549 nvp->nvp_type == NV_TYPE_PTR ||
550 nvp->nvp_type == NV_TYPE_UINT64 ||
551 nvp->nvp_type == NV_TYPE_INT64 ||
552 nvp->nvp_type == NV_TYPE_ENDPOINT ||
553 nvp->nvp_type == NV_TYPE_DATE
554 );
555
556 if (nvp->nvp_datasize != sizeof(uint64_t)) {
557 RESTORE_ERRNO(EINVAL);
558 return (NULL);
559 }
560 if (*leftp < sizeof(uint64_t)) {
561 RESTORE_ERRNO(EINVAL);
562 return (NULL);
563 }
564
565 if (isbe)
566 nvp->nvp_data = be64dec(ptr);
567 else
568 nvp->nvp_data = le64dec(ptr);
569 ptr += sizeof(uint64_t);
570 *leftp -= sizeof(uint64_t);
571
572 return (ptr);
573 }
574
575 const unsigned char *
nvpair_unpack_string(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)576 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
577 const unsigned char *ptr, size_t *leftp)
578 {
579
580 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
581
582 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
583 RESTORE_ERRNO(EINVAL);
584 return (NULL);
585 }
586
587 if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
588 nvp->nvp_datasize - 1) {
589 RESTORE_ERRNO(EINVAL);
590 return (NULL);
591 }
592
593 nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
594 if (nvp->nvp_data == 0)
595 return (NULL);
596
597 ptr += nvp->nvp_datasize;
598 *leftp -= nvp->nvp_datasize;
599
600 return (ptr);
601 }
602
603 const unsigned char *
nvpair_unpack_nvlist(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,size_t nfds,nvlist_t ** child)604 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
605 const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
606 {
607 nvlist_t *value;
608
609 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST ||
610 nvp->nvp_type == NV_TYPE_NVLIST_ARRAY ||
611 nvp->nvp_type == NV_TYPE_NVLIST_DICTIONARY);
612
613 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
614 RESTORE_ERRNO(EINVAL);
615 return (NULL);
616 }
617
618 switch (nvp->nvp_type) {
619 case NV_TYPE_NVLIST:
620 value = nvlist_create(0);
621 break;
622 case NV_TYPE_NVLIST_ARRAY:
623 value = nvlist_create_array(0);
624 break;
625 case NV_TYPE_NVLIST_DICTIONARY:
626 value = nvlist_create_dictionary(0);
627 }
628
629 if (value == NULL)
630 return (NULL);
631
632 ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
633 if (ptr == NULL)
634 return (NULL);
635
636 nvp->nvp_data = (uint64_t)(uintptr_t)value;
637 *child = value;
638
639 return (ptr);
640 }
641
642 #ifndef _KERNEL
643 const unsigned char *
nvpair_unpack_descriptor(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,const int * fds,size_t nfds)644 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
645 size_t *leftp, const int *fds, size_t nfds)
646 {
647 int64_t idx;
648
649 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
650
651 if (nvp->nvp_datasize != sizeof(idx)) {
652 errno = EINVAL;
653 return (NULL);
654 }
655 if (*leftp < sizeof(idx)) {
656 errno = EINVAL;
657 return (NULL);
658 }
659
660 if (isbe)
661 idx = be64dec(ptr);
662 else
663 idx = le64dec(ptr);
664
665 if (idx < 0) {
666 errno = EINVAL;
667 return (NULL);
668 }
669
670 if ((size_t)idx >= nfds) {
671 errno = EINVAL;
672 return (NULL);
673 }
674
675 nvp->nvp_data = (uint64_t)fds[idx];
676
677 ptr += sizeof(idx);
678 *leftp -= sizeof(idx);
679
680 return (ptr);
681 }
682 #endif
683
684 const unsigned char *
nvpair_unpack_binary(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)685 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
686 const unsigned char *ptr, size_t *leftp)
687 {
688 void *value;
689
690 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
691
692 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
693 RESTORE_ERRNO(EINVAL);
694 return (NULL);
695 }
696
697 value = nv_malloc(nvp->nvp_datasize);
698 if (value == NULL)
699 return (NULL);
700
701 memcpy(value, ptr, nvp->nvp_datasize);
702 ptr += nvp->nvp_datasize;
703 *leftp -= nvp->nvp_datasize;
704
705 nvp->nvp_data = (uint64_t)(uintptr_t)value;
706
707 return (ptr);
708 }
709
710 const unsigned char *
nvpair_unpack(bool isbe,const unsigned char * ptr,size_t * leftp,nvpair_t ** nvpp)711 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
712 nvpair_t **nvpp)
713 {
714 nvpair_t *nvp, *tmp;
715
716 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
717 if (nvp == NULL)
718 return (NULL);
719 nvp->nvp_name = (char *)(nvp + 1);
720
721 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
722 if (ptr == NULL)
723 goto failed;
724 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
725 if (tmp == NULL)
726 goto failed;
727 nvp = tmp;
728
729 /* Update nvp_name after realloc(). */
730 nvp->nvp_name = (char *)(nvp + 1);
731 nvp->nvp_data = 0x00;
732 nvp->nvp_magic = NVPAIR_MAGIC;
733 *nvpp = nvp;
734 return (ptr);
735 failed:
736 nv_free(nvp);
737 return (NULL);
738 }
739
740 int
nvpair_type(const nvpair_t * nvp)741 nvpair_type(const nvpair_t *nvp)
742 {
743
744 NVPAIR_ASSERT(nvp);
745
746 return (nvp->nvp_type);
747 }
748
749 const char *
nvpair_name(const nvpair_t * nvp)750 nvpair_name(const nvpair_t *nvp)
751 {
752
753 NVPAIR_ASSERT(nvp);
754
755 return (nvp->nvp_name);
756 }
757
758 static nvpair_t *
nvpair_allocv(int type,uint64_t data,size_t datasize,const char * namefmt,va_list nameap)759 nvpair_allocv(int type, uint64_t data, size_t datasize, const char *namefmt,
760 va_list nameap)
761 {
762 nvpair_t *nvp;
763 char *name;
764 int namelen;
765
766 PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
767
768 namelen = nv_vasprintf(&name, namefmt, nameap);
769 if (namelen < 0)
770 return (NULL);
771
772 PJDLOG_ASSERT(namelen > 0);
773 if (namelen >= NV_NAME_MAX) {
774 nv_free(name);
775 RESTORE_ERRNO(ENAMETOOLONG);
776 return (NULL);
777 }
778
779 nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
780 if (nvp != NULL) {
781 nvp->nvp_name = (char *)(nvp + 1);
782 memcpy(nvp->nvp_name, name, namelen + 1);
783 nvp->nvp_type = type;
784 nvp->nvp_data = data;
785 nvp->nvp_datasize = datasize;
786 nvp->nvp_magic = NVPAIR_MAGIC;
787 }
788 nv_free(name);
789
790 return (nvp);
791 };
792
793 nvpair_t *
nvpair_create_null(const char * name)794 nvpair_create_null(const char *name)
795 {
796
797 return (nvpair_createf_null("%s", name));
798 }
799
800 nvpair_t *
nvpair_create_bool(const char * name,bool value)801 nvpair_create_bool(const char *name, bool value)
802 {
803
804 return (nvpair_createf_bool(value, "%s", name));
805 }
806
807 nvpair_t *
nvpair_create_number_type(const char * name,uint64_t value,int type)808 nvpair_create_number_type(const char *name, uint64_t value, int type)
809 {
810
811 return (nvpair_createf_number_type(value, type, "%s", name));
812 }
813
814 nvpair_t *
nvpair_create_string(const char * name,const char * value)815 nvpair_create_string(const char *name, const char *value)
816 {
817
818 return (nvpair_createf_string(value, "%s", name));
819 }
820
821 nvpair_t *
nvpair_create_stringf(const char * name,const char * valuefmt,...)822 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
823 {
824 va_list valueap;
825 nvpair_t *nvp;
826
827 va_start(valueap, valuefmt);
828 nvp = nvpair_create_stringv(name, valuefmt, valueap);
829 va_end(valueap);
830
831 return (nvp);
832 }
833
834 nvpair_t *
nvpair_create_stringv(const char * name,const char * valuefmt,va_list valueap)835 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
836 {
837 nvpair_t *nvp;
838 char *str;
839 int len;
840
841 len = nv_vasprintf(&str, valuefmt, valueap);
842 if (len < 0)
843 return (NULL);
844 nvp = nvpair_create_string(name, str);
845 if (nvp == NULL)
846 nv_free(str);
847 return (nvp);
848 }
849
850 nvpair_t *
nvpair_create_nvlist_type(const char * name,const nvlist_t * value,int type)851 nvpair_create_nvlist_type(const char *name, const nvlist_t *value, int type)
852 {
853
854 return (nvpair_createf_nvlist_type(value, type, "%s", name));
855 }
856
857 #ifndef _KERNEL
858 nvpair_t *
nvpair_create_descriptor(const char * name,int value)859 nvpair_create_descriptor(const char *name, int value)
860 {
861
862 return (nvpair_createf_descriptor(value, "%s", name));
863 }
864 #endif
865
866 nvpair_t *
nvpair_create_binary(const char * name,const void * value,size_t size)867 nvpair_create_binary(const char *name, const void *value, size_t size)
868 {
869
870 return (nvpair_createf_binary(value, size, "%s", name));
871 }
872
873 nvpair_t *
nvpair_create_uuid(const char * name,const uuid_t * value)874 nvpair_create_uuid(const char *name, const uuid_t *value)
875 {
876
877 return (nvpair_createf_uuid(value, "%s", name));
878 }
879
880 nvpair_t *
nvpair_createf_null(const char * namefmt,...)881 nvpair_createf_null(const char *namefmt, ...)
882 {
883 va_list nameap;
884 nvpair_t *nvp;
885
886 va_start(nameap, namefmt);
887 nvp = nvpair_createv_null(namefmt, nameap);
888 va_end(nameap);
889
890 return (nvp);
891 }
892
893 nvpair_t *
nvpair_createf_bool(bool value,const char * namefmt,...)894 nvpair_createf_bool(bool value, const char *namefmt, ...)
895 {
896 va_list nameap;
897 nvpair_t *nvp;
898
899 va_start(nameap, namefmt);
900 nvp = nvpair_createv_bool(value, namefmt, nameap);
901 va_end(nameap);
902
903 return (nvp);
904 }
905
906 nvpair_t *
nvpair_createf_number_type(uint64_t value,int type,const char * namefmt,...)907 nvpair_createf_number_type(uint64_t value, int type, const char *namefmt, ...)
908 {
909 va_list nameap;
910 nvpair_t *nvp;
911
912 va_start(nameap, namefmt);
913 nvp = nvpair_createv_number_type(value, type, namefmt, nameap);
914 va_end(nameap);
915
916 return (nvp);
917 }
918
919 nvpair_t *
nvpair_createf_string(const char * value,const char * namefmt,...)920 nvpair_createf_string(const char *value, const char *namefmt, ...)
921 {
922 va_list nameap;
923 nvpair_t *nvp;
924
925 va_start(nameap, namefmt);
926 nvp = nvpair_createv_string(value, namefmt, nameap);
927 va_end(nameap);
928
929 return (nvp);
930 }
931
932 nvpair_t *
nvpair_createf_nvlist_type(const nvlist_t * value,int type,const char * namefmt,...)933 nvpair_createf_nvlist_type(const nvlist_t *value, int type, const char *namefmt, ...)
934 {
935 va_list nameap;
936 nvpair_t *nvp;
937
938 va_start(nameap, namefmt);
939 nvp = nvpair_createv_nvlist_type(value, type, namefmt, nameap);
940 va_end(nameap);
941
942 return (nvp);
943 }
944
945 #ifndef _KERNEL
946 nvpair_t *
nvpair_createf_descriptor(int value,const char * namefmt,...)947 nvpair_createf_descriptor(int value, const char *namefmt, ...)
948 {
949 va_list nameap;
950 nvpair_t *nvp;
951
952 va_start(nameap, namefmt);
953 nvp = nvpair_createv_descriptor(value, namefmt, nameap);
954 va_end(nameap);
955
956 return (nvp);
957 }
958 #endif
959
960 nvpair_t *
nvpair_createf_binary(const void * value,size_t size,const char * namefmt,...)961 nvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...)
962 {
963 va_list nameap;
964 nvpair_t *nvp;
965
966 va_start(nameap, namefmt);
967 nvp = nvpair_createv_binary(value, size, namefmt, nameap);
968 va_end(nameap);
969
970 return (nvp);
971 }
972
973 nvpair_t *
nvpair_createf_uuid(const uuid_t * value,const char * namefmt,...)974 nvpair_createf_uuid(const uuid_t *value, const char *namefmt, ...)
975 {
976 va_list nameap;
977 nvpair_t *nvp;
978
979 va_start(nameap, namefmt);
980 nvp = nvpair_createv_uuid(value, namefmt, nameap);
981 va_end(nameap);
982
983 return (nvp);
984 }
985
986 nvpair_t *
nvpair_createv_null(const char * namefmt,va_list nameap)987 nvpair_createv_null(const char *namefmt, va_list nameap)
988 {
989
990 return (nvpair_allocv(NV_TYPE_NULL, 0, 0, namefmt, nameap));
991 }
992
993 nvpair_t *
nvpair_createv_bool(bool value,const char * namefmt,va_list nameap)994 nvpair_createv_bool(bool value, const char *namefmt, va_list nameap)
995 {
996
997 return (nvpair_allocv(NV_TYPE_BOOL, value ? 1 : 0, sizeof(uint8_t),
998 namefmt, nameap));
999 }
1000
1001 nvpair_t *
nvpair_createv_number_type(uint64_t value,int type,const char * namefmt,va_list nameap)1002 nvpair_createv_number_type(uint64_t value, int type, const char *namefmt, va_list nameap)
1003 {
1004 if (type > NV_TYPE_NUMBER_MAX || type < NV_TYPE_NUMBER_MIN)
1005 return (NULL);
1006
1007 return (nvpair_allocv(type, value, sizeof(value), namefmt,
1008 nameap));
1009 }
1010
1011 nvpair_t *
nvpair_createv_string(const char * value,const char * namefmt,va_list nameap)1012 nvpair_createv_string(const char *value, const char *namefmt, va_list nameap)
1013 {
1014 nvpair_t *nvp;
1015 size_t size;
1016 char *data;
1017
1018 if (value == NULL) {
1019 RESTORE_ERRNO(EINVAL);
1020 return (NULL);
1021 }
1022
1023 data = nv_strdup(value);
1024 if (data == NULL)
1025 return (NULL);
1026 size = strlen(value) + 1;
1027
1028 nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)data, size,
1029 namefmt, nameap);
1030 if (nvp == NULL)
1031 nv_free(data);
1032
1033 return (nvp);
1034 }
1035
1036 nvpair_t *
nvpair_createv_nvlist_type(const nvlist_t * value,int type,const char * namefmt,va_list nameap)1037 nvpair_createv_nvlist_type(const nvlist_t *value, int type, const char *namefmt,
1038 va_list nameap)
1039 {
1040 nvlist_t *nvl;
1041 nvpair_t *nvp;
1042
1043 if (value == NULL) {
1044 RESTORE_ERRNO(EINVAL);
1045 return (NULL);
1046 }
1047
1048 nvl = nvlist_clone(value);
1049 if (nvl == NULL)
1050 return (NULL);
1051
1052 nvp = nvpair_allocv(type, (uint64_t)(uintptr_t)nvl, 0,
1053 namefmt, nameap);
1054 if (nvp == NULL)
1055 nvlist_destroy(nvl);
1056 else
1057 nvlist_set_parent(nvl, nvp);
1058
1059 return (nvp);
1060 }
1061
1062 #ifndef _KERNEL
1063 nvpair_t *
nvpair_createv_descriptor(int value,const char * namefmt,va_list nameap)1064 nvpair_createv_descriptor(int value, const char *namefmt, va_list nameap)
1065 {
1066 nvpair_t *nvp;
1067
1068 if (value < 0 || !fd_is_valid(value)) {
1069 errno = EBADF;
1070 return (NULL);
1071 }
1072
1073 value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1074 if (value < 0)
1075 return (NULL);
1076
1077 nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value,
1078 sizeof(int64_t), namefmt, nameap);
1079 if (nvp == NULL)
1080 close(value);
1081
1082 return (nvp);
1083 }
1084 #endif
1085
1086 nvpair_t *
nvpair_createv_binary(const void * value,size_t size,const char * namefmt,va_list nameap)1087 nvpair_createv_binary(const void *value, size_t size, const char *namefmt,
1088 va_list nameap)
1089 {
1090 nvpair_t *nvp;
1091 void *data;
1092
1093 if (value == NULL || size == 0) {
1094 RESTORE_ERRNO(EINVAL);
1095 return (NULL);
1096 }
1097
1098 data = nv_malloc(size);
1099 if (data == NULL)
1100 return (NULL);
1101 memcpy(data, value, size);
1102
1103 nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, size,
1104 namefmt, nameap);
1105 if (nvp == NULL)
1106 nv_free(data);
1107
1108 return (nvp);
1109 }
1110
1111 nvpair_t *
nvpair_createv_uuid(const uuid_t * value,const char * namefmt,va_list nameap)1112 nvpair_createv_uuid(const uuid_t *value, const char *namefmt,
1113 va_list nameap)
1114 {
1115 nvpair_t *nvp;
1116 void *data;
1117 size_t size;
1118
1119 size = sizeof(uuid_t);
1120
1121 if (value == NULL) {
1122 RESTORE_ERRNO(EINVAL);
1123 return (NULL);
1124 }
1125
1126 data = nv_malloc(size);
1127 if (data == NULL)
1128 return (NULL);
1129 memcpy(data, value, size);
1130
1131 nvp = nvpair_allocv(NV_TYPE_UUID, (uint64_t)(uintptr_t)data, size,
1132 namefmt, nameap);
1133 if (nvp == NULL)
1134 nv_free(data);
1135
1136 return (nvp);
1137 }
1138
1139 nvpair_t *
nvpair_move_string(const char * name,char * value)1140 nvpair_move_string(const char *name, char *value)
1141 {
1142
1143 return (nvpair_movef_string(value, "%s", name));
1144 }
1145
1146 nvpair_t *
nvpair_move_nvlist(const char * name,nvlist_t * value)1147 nvpair_move_nvlist(const char *name, nvlist_t *value)
1148 {
1149
1150 return (nvpair_movef_nvlist_type(value, NV_TYPE_NVLIST, "%s", name));
1151 }
1152
1153 nvpair_t *
nvpair_move_nvlist_type(const char * name,nvlist_t * value,int type)1154 nvpair_move_nvlist_type(const char *name, nvlist_t *value, int type)
1155 {
1156
1157 return (nvpair_movef_nvlist_type(value, type, "%s", name));
1158 }
1159
1160 #ifndef _KERNEL
1161 nvpair_t *
nvpair_move_descriptor(const char * name,int value)1162 nvpair_move_descriptor(const char *name, int value)
1163 {
1164
1165 return (nvpair_movef_descriptor(value, "%s", name));
1166 }
1167 #endif
1168
1169 nvpair_t *
nvpair_move_binary(const char * name,void * value,size_t size)1170 nvpair_move_binary(const char *name, void *value, size_t size)
1171 {
1172
1173 return (nvpair_movef_binary(value, size, "%s", name));
1174 }
1175
1176 nvpair_t *
nvpair_movef_string(char * value,const char * namefmt,...)1177 nvpair_movef_string(char *value, const char *namefmt, ...)
1178 {
1179 va_list nameap;
1180 nvpair_t *nvp;
1181
1182 va_start(nameap, namefmt);
1183 nvp = nvpair_movev_string(value, namefmt, nameap);
1184 va_end(nameap);
1185
1186 return (nvp);
1187 }
1188
1189 nvpair_t *
nvpair_movef_nvlist_type(nvlist_t * value,int type,const char * namefmt,...)1190 nvpair_movef_nvlist_type(nvlist_t *value, int type, const char *namefmt, ...)
1191 {
1192 va_list nameap;
1193 nvpair_t *nvp;
1194
1195 va_start(nameap, namefmt);
1196 nvp = nvpair_movev_nvlist_type(value, type, namefmt, nameap);
1197 va_end(nameap);
1198
1199 return (nvp);
1200 }
1201
1202 #ifndef _KERNEL
1203 nvpair_t *
nvpair_movef_descriptor(int value,const char * namefmt,...)1204 nvpair_movef_descriptor(int value, const char *namefmt, ...)
1205 {
1206 va_list nameap;
1207 nvpair_t *nvp;
1208
1209 va_start(nameap, namefmt);
1210 nvp = nvpair_movev_descriptor(value, namefmt, nameap);
1211 va_end(nameap);
1212
1213 return (nvp);
1214 }
1215 #endif
1216
1217 nvpair_t *
nvpair_movef_binary(void * value,size_t size,const char * namefmt,...)1218 nvpair_movef_binary(void *value, size_t size, const char *namefmt, ...)
1219 {
1220 va_list nameap;
1221 nvpair_t *nvp;
1222
1223 va_start(nameap, namefmt);
1224 nvp = nvpair_movev_binary(value, size, namefmt, nameap);
1225 va_end(nameap);
1226
1227 return (nvp);
1228 }
1229
1230 nvpair_t *
nvpair_movef_uuid(uuid_t * value,const char * namefmt,...)1231 nvpair_movef_uuid(uuid_t *value, const char *namefmt, ...)
1232 {
1233 va_list nameap;
1234 nvpair_t *nvp;
1235
1236 va_start(nameap, namefmt);
1237 nvp = nvpair_movev_uuid(value, namefmt, nameap);
1238 va_end(nameap);
1239
1240 return (nvp);
1241 }
1242
1243 nvpair_t *
nvpair_movev_string(char * value,const char * namefmt,va_list nameap)1244 nvpair_movev_string(char *value, const char *namefmt, va_list nameap)
1245 {
1246 nvpair_t *nvp;
1247 int serrno;
1248
1249 if (value == NULL) {
1250 RESTORE_ERRNO(EINVAL);
1251 return (NULL);
1252 }
1253
1254 nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1255 strlen(value) + 1, namefmt, nameap);
1256 if (nvp == NULL) {
1257 SAVE_ERRNO(serrno);
1258 nv_free(value);
1259 RESTORE_ERRNO(serrno);
1260 }
1261
1262 return (nvp);
1263 }
1264
1265 nvpair_t *
nvpair_movev_nvlist_type(nvlist_t * value,int type,const char * namefmt,va_list nameap)1266 nvpair_movev_nvlist_type(nvlist_t *value, int type, const char *namefmt, va_list nameap)
1267 {
1268 nvpair_t *nvp;
1269
1270 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1271 RESTORE_ERRNO(EINVAL);
1272 return (NULL);
1273 }
1274
1275 if (nvlist_error(value) != 0) {
1276 RESTORE_ERRNO(nvlist_error(value));
1277 nvlist_destroy(value);
1278 return (NULL);
1279 }
1280
1281 nvp = nvpair_allocv(type, (uint64_t)(uintptr_t)value, 0,
1282 namefmt, nameap);
1283 if (nvp == NULL)
1284 nvlist_destroy(value);
1285 else
1286 nvlist_set_parent(value, nvp);
1287
1288 return (nvp);
1289 }
1290
1291 #ifndef _KERNEL
1292 nvpair_t *
nvpair_movev_descriptor(int value,const char * namefmt,va_list nameap)1293 nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap)
1294 {
1295 nvpair_t *nvp;
1296 int serrno;
1297
1298 if (value < 0 || !fd_is_valid(value)) {
1299 errno = EBADF;
1300 return (NULL);
1301 }
1302
1303 nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value,
1304 sizeof(int64_t), namefmt, nameap);
1305 if (nvp == NULL) {
1306 serrno = errno;
1307 close(value);
1308 errno = serrno;
1309 }
1310
1311 return (nvp);
1312 }
1313 #endif
1314
1315 nvpair_t *
nvpair_movev_binary(void * value,size_t size,const char * namefmt,va_list nameap)1316 nvpair_movev_binary(void *value, size_t size, const char *namefmt,
1317 va_list nameap)
1318 {
1319 nvpair_t *nvp;
1320 int serrno;
1321
1322 if (value == NULL || size == 0) {
1323 RESTORE_ERRNO(EINVAL);
1324 return (NULL);
1325 }
1326
1327 nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size,
1328 namefmt, nameap);
1329 if (nvp == NULL) {
1330 SAVE_ERRNO(serrno);
1331 nv_free(value);
1332 RESTORE_ERRNO(serrno);
1333 }
1334
1335 return (nvp);
1336 }
1337
1338 nvpair_t *
nvpair_movev_uuid(uuid_t * value,const char * namefmt,va_list nameap)1339 nvpair_movev_uuid(uuid_t *value, const char *namefmt,
1340 va_list nameap)
1341 {
1342
1343 if (value == NULL) {
1344 RESTORE_ERRNO(EINVAL);
1345 return (NULL);
1346 }
1347
1348 return (nvpair_allocv(NV_TYPE_UUID, (uint64_t)(uintptr_t)value,
1349 sizeof(uuid_t), namefmt, nameap));
1350 }
1351
1352 bool
nvpair_get_bool(const nvpair_t * nvp)1353 nvpair_get_bool(const nvpair_t *nvp)
1354 {
1355
1356 NVPAIR_ASSERT(nvp);
1357
1358 return (nvp->nvp_data == 1);
1359 }
1360
1361 uint64_t
nvpair_get_number(const nvpair_t * nvp)1362 nvpair_get_number(const nvpair_t *nvp)
1363 {
1364
1365 NVPAIR_ASSERT(nvp);
1366
1367 return (nvp->nvp_data);
1368 }
1369
1370 const char *
nvpair_get_string(const nvpair_t * nvp)1371 nvpair_get_string(const nvpair_t *nvp)
1372 {
1373
1374 NVPAIR_ASSERT(nvp);
1375 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1376
1377 return ((const char *)(intptr_t)nvp->nvp_data);
1378 }
1379
1380 const nvlist_t *
nvpair_get_nvlist(const nvpair_t * nvp)1381 nvpair_get_nvlist(const nvpair_t *nvp)
1382 {
1383
1384 NVPAIR_ASSERT(nvp);
1385 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY ||
1386 nvp->nvp_type == NV_TYPE_NVLIST_DICTIONARY ||
1387 nvp->nvp_type == NV_TYPE_NVLIST);
1388
1389 return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1390 }
1391
1392 #ifndef _KERNEL
1393 int
nvpair_get_descriptor(const nvpair_t * nvp)1394 nvpair_get_descriptor(const nvpair_t *nvp)
1395 {
1396
1397 NVPAIR_ASSERT(nvp);
1398 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1399
1400 return ((int)nvp->nvp_data);
1401 }
1402 #endif
1403
1404 const void *
nvpair_get_binary(const nvpair_t * nvp,size_t * sizep)1405 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1406 {
1407
1408 NVPAIR_ASSERT(nvp);
1409 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1410
1411 if (sizep != NULL)
1412 *sizep = nvp->nvp_datasize;
1413 return ((const void *)(intptr_t)nvp->nvp_data);
1414 }
1415
1416 const uuid_t *
nvpair_get_uuid(const nvpair_t * nvp)1417 nvpair_get_uuid(const nvpair_t *nvp)
1418 {
1419
1420 NVPAIR_ASSERT(nvp);
1421 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_UUID);
1422
1423 return ((const uuid_t *)(intptr_t)nvp->nvp_data);
1424 }
1425
1426 void
nvpair_free(nvpair_t * nvp)1427 nvpair_free(nvpair_t *nvp)
1428 {
1429
1430 NVPAIR_ASSERT(nvp);
1431 PJDLOG_ASSERT(nvp->nvp_list == NULL);
1432
1433 nvp->nvp_magic = 0;
1434 switch (nvp->nvp_type) {
1435 #ifndef _KERNEL
1436 case NV_TYPE_DESCRIPTOR:
1437 close((int)nvp->nvp_data);
1438 break;
1439 #endif
1440 case NV_TYPE_NVLIST:
1441 case NV_TYPE_NVLIST_ARRAY:
1442 case NV_TYPE_NVLIST_DICTIONARY:
1443 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
1444 break;
1445 case NV_TYPE_STRING:
1446 nv_free((char *)(intptr_t)nvp->nvp_data);
1447 break;
1448 case NV_TYPE_BINARY:
1449 nv_free((void *)(intptr_t)nvp->nvp_data);
1450 break;
1451 case NV_TYPE_UUID:
1452 nv_free((void *)(intptr_t)nvp->nvp_data);
1453 break;
1454 }
1455 nv_free(nvp);
1456 }
1457
1458 void
nvpair_free_structure(nvpair_t * nvp)1459 nvpair_free_structure(nvpair_t *nvp)
1460 {
1461
1462 NVPAIR_ASSERT(nvp);
1463 PJDLOG_ASSERT(nvp->nvp_list == NULL);
1464
1465 nvp->nvp_magic = 0;
1466 nv_free(nvp);
1467 }
1468
1469 const char *
nvpair_type_string(int type)1470 nvpair_type_string(int type)
1471 {
1472
1473 switch (type) {
1474 case NV_TYPE_NULL:
1475 return ("NULL");
1476 case NV_TYPE_BOOL:
1477 return ("BOOL");
1478 case NV_TYPE_NUMBER:
1479 return ("NUMBER");
1480 case NV_TYPE_STRING:
1481 return ("STRING");
1482 case NV_TYPE_NVLIST:
1483 return ("NVLIST");
1484 case NV_TYPE_NVLIST_ARRAY:
1485 return ("NVLIST_ARRAY");
1486 case NV_TYPE_NVLIST_DICTIONARY:
1487 return ("NVLIST_DICTIONARY");
1488 case NV_TYPE_DESCRIPTOR:
1489 return ("DESCRIPTOR");
1490 case NV_TYPE_BINARY:
1491 return ("BINARY");
1492 case NV_TYPE_PTR:
1493 return ("PTR");
1494 case NV_TYPE_UINT64:
1495 return ("UINT64");
1496 case NV_TYPE_INT64:
1497 return ("INT64");
1498 case NV_TYPE_ENDPOINT:
1499 return ("ENDPOINT");
1500 case NV_TYPE_UUID:
1501 return ("UUID");
1502 default:
1503 return ("<UNKNOWN>");
1504 }
1505 }
1506