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
105 nvpair_assert(const nvpair_t *nvp)
106 {
107
108 NVPAIR_ASSERT(nvp);
109 }
110
111 nvlist_t *
112 nvpair_nvlist(const nvpair_t *nvp)
113 {
114
115 NVPAIR_ASSERT(nvp);
116
117 return (nvp->nvp_list);
118 }
119
120 nvpair_t *
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 *
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
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
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
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_remove_nvlist(nvp);
172
173 TAILQ_REMOVE(head, nvp, nvp_next);
174 nvp->nvp_list = NULL;
175 }
176
177 nvpair_t *
178 nvpair_clone(const nvpair_t *nvp)
179 {
180 nvpair_t *newnvp;
181 const char *name;
182 const void *data;
183 size_t datasize;
184
185 NVPAIR_ASSERT(nvp);
186
187 name = nvpair_name(nvp);
188
189 switch (nvpair_type(nvp)) {
190 case NV_TYPE_NULL:
191 newnvp = nvpair_create_null(name);
192 break;
193 case NV_TYPE_BOOL:
194 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
195 break;
196 case NV_TYPE_NUMBER:
197 newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
198 break;
199 case NV_TYPE_STRING:
200 newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
201 break;
202 case NV_TYPE_NVLIST:
203 newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
204 break;
205 #ifndef _KERNEL
206 case NV_TYPE_DESCRIPTOR:
207 newnvp = nvpair_create_descriptor(name,
208 nvpair_get_descriptor(nvp));
209 break;
210 #endif
211 case NV_TYPE_BINARY:
212 data = nvpair_get_binary(nvp, &datasize);
213 newnvp = nvpair_create_binary(name, data, datasize);
214 break;
215 default:
216 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
217 }
218
219 return (newnvp);
220 }
221
222 size_t
223 nvpair_header_size(void)
224 {
225
226 return (sizeof(struct nvpair_header));
227 }
228
229 size_t
230 nvpair_size(const nvpair_t *nvp)
231 {
232
233 NVPAIR_ASSERT(nvp);
234
235 return (nvp->nvp_datasize);
236 }
237
238 unsigned char *
239 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
240 {
241 struct nvpair_header nvphdr;
242 size_t namesize;
243
244 NVPAIR_ASSERT(nvp);
245
246 nvphdr.nvph_type = nvp->nvp_type;
247 namesize = strlen(nvp->nvp_name) + 1;
248 PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
249 nvphdr.nvph_namesize = namesize;
250 nvphdr.nvph_datasize = nvp->nvp_datasize;
251 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
252 memcpy(ptr, &nvphdr, sizeof(nvphdr));
253 ptr += sizeof(nvphdr);
254 *leftp -= sizeof(nvphdr);
255
256 PJDLOG_ASSERT(*leftp >= namesize);
257 memcpy(ptr, nvp->nvp_name, namesize);
258 ptr += namesize;
259 *leftp -= namesize;
260
261 return (ptr);
262 }
263
264 unsigned char *
265 nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
266 size_t *leftp __unused)
267 {
268
269 NVPAIR_ASSERT(nvp);
270 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
271
272 return (ptr);
273 }
274
275 unsigned char *
276 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
277 {
278 uint8_t value;
279
280 NVPAIR_ASSERT(nvp);
281 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
282
283 value = (uint8_t)nvp->nvp_data;
284
285 PJDLOG_ASSERT(*leftp >= sizeof(value));
286 memcpy(ptr, &value, sizeof(value));
287 ptr += sizeof(value);
288 *leftp -= sizeof(value);
289
290 return (ptr);
291 }
292
293 unsigned char *
294 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
295 {
296 uint64_t value;
297
298 NVPAIR_ASSERT(nvp);
299 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
300
301 value = (uint64_t)nvp->nvp_data;
302
303 PJDLOG_ASSERT(*leftp >= sizeof(value));
304 memcpy(ptr, &value, sizeof(value));
305 ptr += sizeof(value);
306 *leftp -= sizeof(value);
307
308 return (ptr);
309 }
310
311 unsigned char *
312 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
313 {
314
315 NVPAIR_ASSERT(nvp);
316 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
317
318 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
319 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
320 ptr += nvp->nvp_datasize;
321 *leftp -= nvp->nvp_datasize;
322
323 return (ptr);
324 }
325
326 unsigned char *
327 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
328 {
329 struct nvpair_header nvphdr;
330 size_t namesize;
331 const char *name = "";
332
333 namesize = 1;
334 nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
335 nvphdr.nvph_namesize = namesize;
336 nvphdr.nvph_datasize = 0;
337 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
338 memcpy(ptr, &nvphdr, sizeof(nvphdr));
339 ptr += sizeof(nvphdr);
340 *leftp -= sizeof(nvphdr);
341
342 PJDLOG_ASSERT(*leftp >= namesize);
343 memcpy(ptr, name, namesize);
344 ptr += namesize;
345 *leftp -= namesize;
346
347 return (ptr);
348 }
349
350 #ifndef _KERNEL
351 unsigned char *
352 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
353 size_t *leftp)
354 {
355 int64_t value;
356
357 NVPAIR_ASSERT(nvp);
358 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
359
360 value = (int64_t)nvp->nvp_data;
361 if (value != -1) {
362 /*
363 * If there is a real descriptor here, we change its number
364 * to position in the array of descriptors send via control
365 * message.
366 */
367 PJDLOG_ASSERT(fdidxp != NULL);
368
369 value = *fdidxp;
370 (*fdidxp)++;
371 }
372
373 PJDLOG_ASSERT(*leftp >= sizeof(value));
374 memcpy(ptr, &value, sizeof(value));
375 ptr += sizeof(value);
376 *leftp -= sizeof(value);
377
378 return (ptr);
379 }
380 #endif
381
382 unsigned char *
383 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
384 {
385
386 NVPAIR_ASSERT(nvp);
387 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
388
389 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
390 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
391 ptr += nvp->nvp_datasize;
392 *leftp -= nvp->nvp_datasize;
393
394 return (ptr);
395 }
396
397 void
398 nvpair_init_datasize(nvpair_t *nvp)
399 {
400
401 NVPAIR_ASSERT(nvp);
402
403 if (nvp->nvp_type == NV_TYPE_NVLIST) {
404 if (nvp->nvp_data == 0) {
405 nvp->nvp_datasize = 0;
406 } else {
407 nvp->nvp_datasize =
408 nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
409 }
410 }
411 }
412
413 const unsigned char *
414 nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
415 size_t *leftp)
416 {
417 struct nvpair_header nvphdr;
418
419 if (*leftp < sizeof(nvphdr))
420 goto failed;
421
422 memcpy(&nvphdr, ptr, sizeof(nvphdr));
423 ptr += sizeof(nvphdr);
424 *leftp -= sizeof(nvphdr);
425
426 #if NV_TYPE_FIRST > 0
427 if (nvphdr.nvph_type < NV_TYPE_FIRST)
428 goto failed;
429 #endif
430 if (nvphdr.nvph_type > NV_TYPE_LAST &&
431 nvphdr.nvph_type != NV_TYPE_NVLIST_UP) {
432 goto failed;
433 }
434
435 #if BYTE_ORDER == BIG_ENDIAN
436 if (!isbe) {
437 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
438 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
439 }
440 #else
441 if (isbe) {
442 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
443 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
444 }
445 #endif
446
447 if (nvphdr.nvph_namesize > NV_NAME_MAX)
448 goto failed;
449 if (*leftp < nvphdr.nvph_namesize)
450 goto failed;
451 if (nvphdr.nvph_namesize < 1)
452 goto failed;
453 if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
454 (size_t)(nvphdr.nvph_namesize - 1)) {
455 goto failed;
456 }
457
458 memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
459 ptr += nvphdr.nvph_namesize;
460 *leftp -= nvphdr.nvph_namesize;
461
462 if (*leftp < nvphdr.nvph_datasize)
463 goto failed;
464
465 nvp->nvp_type = nvphdr.nvph_type;
466 nvp->nvp_data = 0;
467 nvp->nvp_datasize = nvphdr.nvph_datasize;
468
469 return (ptr);
470 failed:
471 RESTORE_ERRNO(EINVAL);
472 return (NULL);
473 }
474
475 const unsigned char *
476 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
477 size_t *leftp __unused)
478 {
479
480 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
481
482 if (nvp->nvp_datasize != 0) {
483 RESTORE_ERRNO(EINVAL);
484 return (NULL);
485 }
486
487 return (ptr);
488 }
489
490 const unsigned char *
491 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
492 size_t *leftp)
493 {
494 uint8_t value;
495
496 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
497
498 if (nvp->nvp_datasize != sizeof(value)) {
499 RESTORE_ERRNO(EINVAL);
500 return (NULL);
501 }
502 if (*leftp < sizeof(value)) {
503 RESTORE_ERRNO(EINVAL);
504 return (NULL);
505 }
506
507 memcpy(&value, ptr, sizeof(value));
508 ptr += sizeof(value);
509 *leftp -= sizeof(value);
510
511 if (value != 0 && value != 1) {
512 RESTORE_ERRNO(EINVAL);
513 return (NULL);
514 }
515
516 nvp->nvp_data = (uint64_t)value;
517
518 return (ptr);
519 }
520
521 const unsigned char *
522 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
523 size_t *leftp)
524 {
525
526 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
527
528 if (nvp->nvp_datasize != sizeof(uint64_t)) {
529 RESTORE_ERRNO(EINVAL);
530 return (NULL);
531 }
532 if (*leftp < sizeof(uint64_t)) {
533 RESTORE_ERRNO(EINVAL);
534 return (NULL);
535 }
536
537 if (isbe)
538 nvp->nvp_data = be64dec(ptr);
539 else
540 nvp->nvp_data = le64dec(ptr);
541 ptr += sizeof(uint64_t);
542 *leftp -= sizeof(uint64_t);
543
544 return (ptr);
545 }
546
547 const unsigned char *
548 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
549 const unsigned char *ptr, size_t *leftp)
550 {
551
552 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
553
554 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
555 RESTORE_ERRNO(EINVAL);
556 return (NULL);
557 }
558
559 if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
560 nvp->nvp_datasize - 1) {
561 RESTORE_ERRNO(EINVAL);
562 return (NULL);
563 }
564
565 nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
566 if (nvp->nvp_data == 0)
567 return (NULL);
568
569 ptr += nvp->nvp_datasize;
570 *leftp -= nvp->nvp_datasize;
571
572 return (ptr);
573 }
574
575 const unsigned char *
576 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
577 const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
578 {
579 nvlist_t *value;
580
581 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
582
583 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
584 RESTORE_ERRNO(EINVAL);
585 return (NULL);
586 }
587
588 value = nvlist_create(0);
589 if (value == NULL)
590 return (NULL);
591
592 ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
593 if (ptr == NULL)
594 return (NULL);
595
596 nvp->nvp_data = (uint64_t)(uintptr_t)value;
597 *child = value;
598
599 return (ptr);
600 }
601
602 #ifndef _KERNEL
603 const unsigned char *
604 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
605 size_t *leftp, const int *fds, size_t nfds)
606 {
607 int64_t idx;
608
609 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
610
611 if (nvp->nvp_datasize != sizeof(idx)) {
612 errno = EINVAL;
613 return (NULL);
614 }
615 if (*leftp < sizeof(idx)) {
616 errno = EINVAL;
617 return (NULL);
618 }
619
620 if (isbe)
621 idx = be64dec(ptr);
622 else
623 idx = le64dec(ptr);
624
625 if (idx < 0) {
626 errno = EINVAL;
627 return (NULL);
628 }
629
630 if ((size_t)idx >= nfds) {
631 errno = EINVAL;
632 return (NULL);
633 }
634
635 nvp->nvp_data = (uint64_t)fds[idx];
636
637 ptr += sizeof(idx);
638 *leftp -= sizeof(idx);
639
640 return (ptr);
641 }
642 #endif
643
644 const unsigned char *
645 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
646 const unsigned char *ptr, size_t *leftp)
647 {
648 void *value;
649
650 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
651
652 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
653 RESTORE_ERRNO(EINVAL);
654 return (NULL);
655 }
656
657 value = nv_malloc(nvp->nvp_datasize);
658 if (value == NULL)
659 return (NULL);
660
661 memcpy(value, ptr, nvp->nvp_datasize);
662 ptr += nvp->nvp_datasize;
663 *leftp -= nvp->nvp_datasize;
664
665 nvp->nvp_data = (uint64_t)(uintptr_t)value;
666
667 return (ptr);
668 }
669
670 const unsigned char *
671 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
672 nvpair_t **nvpp)
673 {
674 nvpair_t *nvp, *tmp;
675
676 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
677 if (nvp == NULL)
678 return (NULL);
679 nvp->nvp_name = (char *)(nvp + 1);
680
681 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
682 if (ptr == NULL)
683 goto failed;
684 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
685 if (tmp == NULL)
686 goto failed;
687 nvp = tmp;
688
689 /* Update nvp_name after realloc(). */
690 nvp->nvp_name = (char *)(nvp + 1);
691 nvp->nvp_data = 0x00;
692 nvp->nvp_magic = NVPAIR_MAGIC;
693 *nvpp = nvp;
694 return (ptr);
695 failed:
696 nv_free(nvp);
697 return (NULL);
698 }
699
700 int
701 nvpair_type(const nvpair_t *nvp)
702 {
703
704 NVPAIR_ASSERT(nvp);
705
706 return (nvp->nvp_type);
707 }
708
709 const char *
710 nvpair_name(const nvpair_t *nvp)
711 {
712
713 NVPAIR_ASSERT(nvp);
714
715 return (nvp->nvp_name);
716 }
717
718 static nvpair_t *
719 nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize)
720 {
721 nvpair_t *nvp;
722 size_t namelen;
723
724 PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
725
726 namelen = strlen(name);
727 if (namelen >= NV_NAME_MAX) {
728 RESTORE_ERRNO(ENAMETOOLONG);
729 return (NULL);
730 }
731
732 nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
733 if (nvp != NULL) {
734 nvp->nvp_name = (char *)(nvp + 1);
735 memcpy(nvp->nvp_name, name, namelen);
736 nvp->nvp_name[namelen + 1] = '\0';
737 nvp->nvp_type = type;
738 nvp->nvp_data = data;
739 nvp->nvp_datasize = datasize;
740 nvp->nvp_magic = NVPAIR_MAGIC;
741 }
742
743 return (nvp);
744 };
745
746 nvpair_t *
747 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
748 {
749 va_list valueap;
750 nvpair_t *nvp;
751
752 va_start(valueap, valuefmt);
753 nvp = nvpair_create_stringv(name, valuefmt, valueap);
754 va_end(valueap);
755
756 return (nvp);
757 }
758
759 nvpair_t *
760 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
761 {
762 nvpair_t *nvp;
763 char *str;
764 int len;
765
766 len = nv_vasprintf(&str, valuefmt, valueap);
767 if (len < 0)
768 return (NULL);
769 nvp = nvpair_create_string(name, str);
770 if (nvp == NULL)
771 nv_free(str);
772 return (nvp);
773 }
774
775 nvpair_t *
776 nvpair_create_null(const char *name)
777 {
778
779 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0));
780 }
781
782 nvpair_t *
783 nvpair_create_bool(const char *name, bool value)
784 {
785
786 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
787 sizeof(uint8_t)));
788 }
789
790 nvpair_t *
791 nvpair_create_number(const char *name, uint64_t value)
792 {
793
794 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value)));
795 }
796
797 nvpair_t *
798 nvpair_create_string(const char *name, const char *value)
799 {
800 nvpair_t *nvp;
801 size_t size;
802 char *data;
803
804 if (value == NULL) {
805 RESTORE_ERRNO(EINVAL);
806 return (NULL);
807 }
808
809 data = nv_strdup(value);
810 if (data == NULL)
811 return (NULL);
812 size = strlen(value) + 1;
813
814 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
815 size);
816 if (nvp == NULL)
817 nv_free(data);
818
819 return (nvp);
820 }
821
822 nvpair_t *
823 nvpair_create_nvlist(const char *name, const nvlist_t *value)
824 {
825 nvlist_t *nvl;
826 nvpair_t *nvp;
827
828 if (value == NULL) {
829 RESTORE_ERRNO(EINVAL);
830 return (NULL);
831 }
832
833 nvl = nvlist_clone(value);
834 if (nvl == NULL)
835 return (NULL);
836
837 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0);
838 if (nvp == NULL)
839 nvlist_destroy(nvl);
840 else
841 nvlist_set_parent(nvl, nvp);
842
843 return (nvp);
844 }
845
846 #ifndef _KERNEL
847 nvpair_t *
848 nvpair_create_descriptor(const char *name, int value)
849 {
850 nvpair_t *nvp;
851
852 if (value < 0 || !fd_is_valid(value)) {
853 errno = EBADF;
854 return (NULL);
855 }
856
857 value = fcntl(value, F_DUPFD_CLOEXEC, 0);
858 if (value < 0)
859 return (NULL);
860
861 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
862 sizeof(int64_t));
863 if (nvp == NULL)
864 close(value);
865
866 return (nvp);
867 }
868 #endif
869
870 nvpair_t *
871 nvpair_create_binary(const char *name, const void *value, size_t size)
872 {
873 nvpair_t *nvp;
874 void *data;
875
876 if (value == NULL || size == 0) {
877 RESTORE_ERRNO(EINVAL);
878 return (NULL);
879 }
880
881 data = nv_malloc(size);
882 if (data == NULL)
883 return (NULL);
884 memcpy(data, value, size);
885
886 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
887 size);
888 if (nvp == NULL)
889 nv_free(data);
890
891 return (nvp);
892 }
893
894 nvpair_t *
895 nvpair_move_string(const char *name, char *value)
896 {
897 nvpair_t *nvp;
898 int serrno;
899
900 if (value == NULL) {
901 RESTORE_ERRNO(EINVAL);
902 return (NULL);
903 }
904
905 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
906 strlen(value) + 1);
907 if (nvp == NULL) {
908 SAVE_ERRNO(serrno);
909 nv_free(value);
910 RESTORE_ERRNO(serrno);
911 }
912
913 return (nvp);
914 }
915
916 nvpair_t *
917 nvpair_move_nvlist(const char *name, nvlist_t *value)
918 {
919 nvpair_t *nvp;
920
921 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
922 RESTORE_ERRNO(EINVAL);
923 return (NULL);
924 }
925
926 if (nvlist_error(value) != 0) {
927 RESTORE_ERRNO(nvlist_error(value));
928 nvlist_destroy(value);
929 return (NULL);
930 }
931
932 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
933 0);
934 if (nvp == NULL)
935 nvlist_destroy(value);
936 else
937 nvlist_set_parent(value, nvp);
938
939 return (nvp);
940 }
941
942 #ifndef _KERNEL
943 nvpair_t *
944 nvpair_move_descriptor(const char *name, int value)
945 {
946 nvpair_t *nvp;
947 int serrno;
948
949 if (value < 0 || !fd_is_valid(value)) {
950 errno = EBADF;
951 return (NULL);
952 }
953
954 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
955 sizeof(int64_t));
956 if (nvp == NULL) {
957 serrno = errno;
958 close(value);
959 errno = serrno;
960 }
961
962 return (nvp);
963 }
964 #endif
965
966 nvpair_t *
967 nvpair_move_binary(const char *name, void *value, size_t size)
968 {
969 nvpair_t *nvp;
970 int serrno;
971
972 if (value == NULL || size == 0) {
973 RESTORE_ERRNO(EINVAL);
974 return (NULL);
975 }
976
977 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
978 size);
979 if (nvp == NULL) {
980 SAVE_ERRNO(serrno);
981 nv_free(value);
982 RESTORE_ERRNO(serrno);
983 }
984
985 return (nvp);
986 }
987
988 bool
989 nvpair_get_bool(const nvpair_t *nvp)
990 {
991
992 NVPAIR_ASSERT(nvp);
993
994 return (nvp->nvp_data == 1);
995 }
996
997 uint64_t
998 nvpair_get_number(const nvpair_t *nvp)
999 {
1000
1001 NVPAIR_ASSERT(nvp);
1002
1003 return (nvp->nvp_data);
1004 }
1005
1006 const char *
1007 nvpair_get_string(const nvpair_t *nvp)
1008 {
1009
1010 NVPAIR_ASSERT(nvp);
1011 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1012
1013 return ((const char *)(intptr_t)nvp->nvp_data);
1014 }
1015
1016 const nvlist_t *
1017 nvpair_get_nvlist(const nvpair_t *nvp)
1018 {
1019
1020 NVPAIR_ASSERT(nvp);
1021 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1022
1023 return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1024 }
1025
1026 #ifndef _KERNEL
1027 int
1028 nvpair_get_descriptor(const nvpair_t *nvp)
1029 {
1030
1031 NVPAIR_ASSERT(nvp);
1032 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1033
1034 return ((int)nvp->nvp_data);
1035 }
1036 #endif
1037
1038 const void *
1039 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1040 {
1041
1042 NVPAIR_ASSERT(nvp);
1043 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1044
1045 if (sizep != NULL)
1046 *sizep = nvp->nvp_datasize;
1047 return ((const void *)(intptr_t)nvp->nvp_data);
1048 }
1049
1050 void
1051 nvpair_free(nvpair_t *nvp)
1052 {
1053
1054 NVPAIR_ASSERT(nvp);
1055 PJDLOG_ASSERT(nvp->nvp_list == NULL);
1056
1057 nvp->nvp_magic = 0;
1058 switch (nvp->nvp_type) {
1059 #ifndef _KERNEL
1060 case NV_TYPE_DESCRIPTOR:
1061 close((int)nvp->nvp_data);
1062 break;
1063 #endif
1064 case NV_TYPE_NVLIST:
1065 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
1066 break;
1067 case NV_TYPE_STRING:
1068 nv_free((char *)(intptr_t)nvp->nvp_data);
1069 break;
1070 case NV_TYPE_BINARY:
1071 nv_free((void *)(intptr_t)nvp->nvp_data);
1072 break;
1073 }
1074 nv_free(nvp);
1075 }
1076
1077 void
1078 nvpair_free_structure(nvpair_t *nvp)
1079 {
1080
1081 NVPAIR_ASSERT(nvp);
1082 PJDLOG_ASSERT(nvp->nvp_list == NULL);
1083
1084 nvp->nvp_magic = 0;
1085 nv_free(nvp);
1086 }
1087
1088 const char *
1089 nvpair_type_string(int type)
1090 {
1091
1092 switch (type) {
1093 case NV_TYPE_NULL:
1094 return ("NULL");
1095 case NV_TYPE_BOOL:
1096 return ("BOOL");
1097 case NV_TYPE_NUMBER:
1098 return ("NUMBER");
1099 case NV_TYPE_STRING:
1100 return ("STRING");
1101 case NV_TYPE_NVLIST:
1102 return ("NVLIST");
1103 case NV_TYPE_DESCRIPTOR:
1104 return ("DESCRIPTOR");
1105 case NV_TYPE_BINARY:
1106 return ("BINARY");
1107 default:
1108 return ("<UNKNOWN>");
1109 }
1110 }
1111
Cache object: b78ac3f630a785dc466a9b0981aff2ed
|