]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libnv/nvpair.c
Import pjdfstest from ^/vendor/pjdfstest/abf03c3a47745d4521b0e4aa141317553ca48f91
[FreeBSD/FreeBSD.git] / lib / libnv / nvpair.c
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 #include <errno.h>
38 #include <fcntl.h>
39 #include <stdarg.h>
40 #include <stdbool.h>
41 #include <stdint.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45
46 #ifdef HAVE_PJDLOG
47 #include <pjdlog.h>
48 #endif
49
50 #include "common_impl.h"
51 #include "nv.h"
52 #include "nv_impl.h"
53 #include "nvlist_impl.h"
54 #include "nvpair_impl.h"
55
56 #ifndef HAVE_PJDLOG
57 #include <assert.h>
58 #define PJDLOG_ASSERT(...)              assert(__VA_ARGS__)
59 #define PJDLOG_RASSERT(expr, ...)       assert(expr)
60 #define PJDLOG_ABORT(...)               abort()
61 #endif
62
63 #define NVPAIR_MAGIC    0x6e7670        /* "nvp" */
64 struct nvpair {
65         int              nvp_magic;
66         char            *nvp_name;
67         int              nvp_type;
68         uint64_t         nvp_data;
69         size_t           nvp_datasize;
70         nvlist_t        *nvp_list;
71         TAILQ_ENTRY(nvpair) nvp_next;
72 };
73
74 #define NVPAIR_ASSERT(nvp)      do {                                    \
75         PJDLOG_ASSERT((nvp) != NULL);                                   \
76         PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC);                \
77 } while (0)
78
79 struct nvpair_header {
80         uint8_t         nvph_type;
81         uint16_t        nvph_namesize;
82         uint64_t        nvph_datasize;
83 } __packed;
84
85
86 void
87 nvpair_assert(const nvpair_t *nvp)
88 {
89
90         NVPAIR_ASSERT(nvp);
91 }
92
93 nvlist_t *
94 nvpair_nvlist(const nvpair_t *nvp)
95 {
96
97         NVPAIR_ASSERT(nvp);
98
99         return (nvp->nvp_list);
100 }
101
102 nvpair_t *
103 nvpair_next(const nvpair_t *nvp)
104 {
105
106         NVPAIR_ASSERT(nvp);
107         PJDLOG_ASSERT(nvp->nvp_list != NULL);
108
109         return (TAILQ_NEXT(nvp, nvp_next));
110 }
111
112 nvpair_t *
113 nvpair_prev(const nvpair_t *nvp)
114 {
115
116         NVPAIR_ASSERT(nvp);
117         PJDLOG_ASSERT(nvp->nvp_list != NULL);
118
119         return (TAILQ_PREV(nvp, nvl_head, nvp_next));
120 }
121
122 void
123 nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
124 {
125
126         NVPAIR_ASSERT(nvp);
127         PJDLOG_ASSERT(nvp->nvp_list == NULL);
128         PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp)));
129
130         TAILQ_INSERT_TAIL(head, nvp, nvp_next);
131         nvp->nvp_list = nvl;
132 }
133
134 static void
135 nvpair_remove_nvlist(nvpair_t *nvp)
136 {
137         nvlist_t *nvl;
138
139         /* XXX: DECONST is bad, mkay? */
140         nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
141         PJDLOG_ASSERT(nvl != NULL);
142         nvlist_set_parent(nvl, NULL);
143 }
144
145 void
146 nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
147 {
148
149         NVPAIR_ASSERT(nvp);
150         PJDLOG_ASSERT(nvp->nvp_list == nvl);
151
152         if (nvpair_type(nvp) == NV_TYPE_NVLIST)
153                 nvpair_remove_nvlist(nvp);
154
155         TAILQ_REMOVE(head, nvp, nvp_next);
156         nvp->nvp_list = NULL;
157 }
158
159 nvpair_t *
160 nvpair_clone(const nvpair_t *nvp)
161 {
162         nvpair_t *newnvp;
163         const char *name;
164         const void *data;
165         size_t datasize;
166
167         NVPAIR_ASSERT(nvp);
168
169         name = nvpair_name(nvp);
170
171         switch (nvpair_type(nvp)) {
172         case NV_TYPE_NULL:
173                 newnvp = nvpair_create_null(name);
174                 break;
175         case NV_TYPE_BOOL:
176                 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
177                 break;
178         case NV_TYPE_NUMBER:
179                 newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
180                 break;
181         case NV_TYPE_STRING:
182                 newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
183                 break;
184         case NV_TYPE_NVLIST:
185                 newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
186                 break;
187         case NV_TYPE_DESCRIPTOR:
188                 newnvp = nvpair_create_descriptor(name,
189                     nvpair_get_descriptor(nvp));
190                 break;
191         case NV_TYPE_BINARY:
192                 data = nvpair_get_binary(nvp, &datasize);
193                 newnvp = nvpair_create_binary(name, data, datasize);
194                 break;
195         default:
196                 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
197         }
198
199         return (newnvp);
200 }
201
202 size_t
203 nvpair_header_size(void)
204 {
205
206         return (sizeof(struct nvpair_header));
207 }
208
209 size_t
210 nvpair_size(const nvpair_t *nvp)
211 {
212
213         NVPAIR_ASSERT(nvp);
214
215         return (nvp->nvp_datasize);
216 }
217
218 unsigned char *
219 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
220 {
221         struct nvpair_header nvphdr;
222         size_t namesize;
223
224         NVPAIR_ASSERT(nvp);
225
226         nvphdr.nvph_type = nvp->nvp_type;
227         namesize = strlen(nvp->nvp_name) + 1;
228         PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
229         nvphdr.nvph_namesize = namesize;
230         nvphdr.nvph_datasize = nvp->nvp_datasize;
231         PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
232         memcpy(ptr, &nvphdr, sizeof(nvphdr));
233         ptr += sizeof(nvphdr);
234         *leftp -= sizeof(nvphdr);
235
236         PJDLOG_ASSERT(*leftp >= namesize);
237         memcpy(ptr, nvp->nvp_name, namesize);
238         ptr += namesize;
239         *leftp -= namesize;
240
241         return (ptr);
242 }
243
244 unsigned char *
245 nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
246     size_t *leftp __unused)
247 {
248
249         NVPAIR_ASSERT(nvp);
250         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
251
252         return (ptr);
253 }
254
255 unsigned char *
256 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
257 {
258         uint8_t value;
259
260         NVPAIR_ASSERT(nvp);
261         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
262
263         value = (uint8_t)nvp->nvp_data;
264
265         PJDLOG_ASSERT(*leftp >= sizeof(value));
266         memcpy(ptr, &value, sizeof(value));
267         ptr += sizeof(value);
268         *leftp -= sizeof(value);
269
270         return (ptr);
271 }
272
273 unsigned char *
274 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
275 {
276         uint64_t value;
277
278         NVPAIR_ASSERT(nvp);
279         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
280
281         value = (uint64_t)nvp->nvp_data;
282
283         PJDLOG_ASSERT(*leftp >= sizeof(value));
284         memcpy(ptr, &value, sizeof(value));
285         ptr += sizeof(value);
286         *leftp -= sizeof(value);
287
288         return (ptr);
289 }
290
291 unsigned char *
292 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
293 {
294
295         NVPAIR_ASSERT(nvp);
296         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
297
298         PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
299         memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
300         ptr += nvp->nvp_datasize;
301         *leftp -= nvp->nvp_datasize;
302
303         return (ptr);
304 }
305
306 unsigned char *
307 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
308 {
309         struct nvpair_header nvphdr;
310         size_t namesize;
311         const char *name = "";
312
313         namesize = 1;
314         nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
315         nvphdr.nvph_namesize = namesize;
316         nvphdr.nvph_datasize = 0;
317         PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
318         memcpy(ptr, &nvphdr, sizeof(nvphdr));
319         ptr += sizeof(nvphdr);
320         *leftp -= sizeof(nvphdr);
321
322         PJDLOG_ASSERT(*leftp >= namesize);
323         memcpy(ptr, name, namesize);
324         ptr += namesize;
325         *leftp -= namesize;
326
327         return (ptr);
328 }
329
330 unsigned char *
331 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
332     size_t *leftp)
333 {
334         int64_t value;
335
336         NVPAIR_ASSERT(nvp);
337         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
338
339         value = (int64_t)nvp->nvp_data;
340         if (value != -1) {
341                 /*
342                  * If there is a real descriptor here, we change its number
343                  * to position in the array of descriptors send via control
344                  * message.
345                  */
346                 PJDLOG_ASSERT(fdidxp != NULL);
347
348                 value = *fdidxp;
349                 (*fdidxp)++;
350         }
351
352         PJDLOG_ASSERT(*leftp >= sizeof(value));
353         memcpy(ptr, &value, sizeof(value));
354         ptr += sizeof(value);
355         *leftp -= sizeof(value);
356
357         return (ptr);
358 }
359
360 unsigned char *
361 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
362 {
363
364         NVPAIR_ASSERT(nvp);
365         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
366
367         PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
368         memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
369         ptr += nvp->nvp_datasize;
370         *leftp -= nvp->nvp_datasize;
371
372         return (ptr);
373 }
374
375 void
376 nvpair_init_datasize(nvpair_t *nvp)
377 {
378
379         NVPAIR_ASSERT(nvp);
380
381         if (nvp->nvp_type == NV_TYPE_NVLIST) {
382                 if (nvp->nvp_data == 0) {
383                         nvp->nvp_datasize = 0;
384                 } else {
385                         nvp->nvp_datasize =
386                             nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
387                 }
388         }
389 }
390
391 const unsigned char *
392 nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr,
393     size_t *leftp)
394 {
395         struct nvpair_header nvphdr;
396
397         if (*leftp < sizeof(nvphdr))
398                 goto failed;
399
400         memcpy(&nvphdr, ptr, sizeof(nvphdr));
401         ptr += sizeof(nvphdr);
402         *leftp -= sizeof(nvphdr);
403
404 #if NV_TYPE_FIRST > 0
405         if (nvphdr.nvph_type < NV_TYPE_FIRST)
406                 goto failed;
407 #endif
408         if (nvphdr.nvph_type > NV_TYPE_LAST &&
409             nvphdr.nvph_type != NV_TYPE_NVLIST_UP) {
410                 goto failed;
411         }
412
413 #if BYTE_ORDER == BIG_ENDIAN
414         if ((flags & NV_FLAG_BIG_ENDIAN) == 0) {
415                 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
416                 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
417         }
418 #else
419         if ((flags & NV_FLAG_BIG_ENDIAN) != 0) {
420                 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
421                 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
422         }
423 #endif
424
425         if (nvphdr.nvph_namesize > NV_NAME_MAX)
426                 goto failed;
427         if (*leftp < nvphdr.nvph_namesize)
428                 goto failed;
429         if (nvphdr.nvph_namesize < 1)
430                 goto failed;
431         if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
432             (size_t)(nvphdr.nvph_namesize - 1)) {
433                 goto failed;
434         }
435
436         memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
437         ptr += nvphdr.nvph_namesize;
438         *leftp -= nvphdr.nvph_namesize;
439
440         if (*leftp < nvphdr.nvph_datasize)
441                 goto failed;
442
443         nvp->nvp_type = nvphdr.nvph_type;
444         nvp->nvp_data = 0;
445         nvp->nvp_datasize = nvphdr.nvph_datasize;
446
447         return (ptr);
448 failed:
449         errno = EINVAL;
450         return (NULL);
451 }
452
453 const unsigned char *
454 nvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
455     size_t *leftp __unused)
456 {
457
458         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
459
460         if (nvp->nvp_datasize != 0) {
461                 errno = EINVAL;
462                 return (NULL);
463         }
464
465         return (ptr);
466 }
467
468 const unsigned char *
469 nvpair_unpack_bool(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
470     size_t *leftp)
471 {
472         uint8_t value;
473
474         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
475
476         if (nvp->nvp_datasize != sizeof(value)) {
477                 errno = EINVAL;
478                 return (NULL);
479         }
480         if (*leftp < sizeof(value)) {
481                 errno = EINVAL;
482                 return (NULL);
483         }
484
485         memcpy(&value, ptr, sizeof(value));
486         ptr += sizeof(value);
487         *leftp -= sizeof(value);
488
489         if (value != 0 && value != 1) {
490                 errno = EINVAL;
491                 return (NULL);
492         }
493
494         nvp->nvp_data = (uint64_t)value;
495
496         return (ptr);
497 }
498
499 const unsigned char *
500 nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr,
501      size_t *leftp)
502 {
503
504         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
505
506         if (nvp->nvp_datasize != sizeof(uint64_t)) {
507                 errno = EINVAL;
508                 return (NULL);
509         }
510         if (*leftp < sizeof(uint64_t)) {
511                 errno = EINVAL;
512                 return (NULL);
513         }
514
515         if ((flags & NV_FLAG_BIG_ENDIAN) != 0)
516                 nvp->nvp_data = be64dec(ptr);
517         else
518                 nvp->nvp_data = le64dec(ptr);
519         ptr += sizeof(uint64_t);
520         *leftp -= sizeof(uint64_t);
521
522         return (ptr);
523 }
524
525 const unsigned char *
526 nvpair_unpack_string(int flags __unused, nvpair_t *nvp,
527     const unsigned char *ptr, size_t *leftp)
528 {
529
530         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
531
532         if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
533                 errno = EINVAL;
534                 return (NULL);
535         }
536
537         if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
538             nvp->nvp_datasize - 1) {
539                 errno = EINVAL;
540                 return (NULL);
541         }
542
543         nvp->nvp_data = (uint64_t)(uintptr_t)strdup((const char *)ptr);
544         if (nvp->nvp_data == 0)
545                 return (NULL);
546
547         ptr += nvp->nvp_datasize;
548         *leftp -= nvp->nvp_datasize;
549
550         return (ptr);
551 }
552
553 const unsigned char *
554 nvpair_unpack_nvlist(int *flagsp, nvpair_t *nvp, const unsigned char *ptr,
555     size_t *leftp, size_t nfds, nvlist_t **child)
556 {
557         nvlist_t *value;
558
559         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
560
561         if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
562                 errno = EINVAL;
563                 return (NULL);
564         }
565
566         value = nvlist_create(0);
567         if (value == NULL)
568                 return (NULL);
569
570         ptr = nvlist_unpack_header(value, ptr, nfds, flagsp, leftp);
571         if (ptr == NULL)
572                 return (NULL);
573
574         nvp->nvp_data = (uint64_t)(uintptr_t)value;
575         *child = value;
576
577         return (ptr);
578 }
579
580 const unsigned char *
581 nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr,
582     size_t *leftp, const int *fds, size_t nfds)
583 {
584         int64_t idx;
585
586         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
587
588         if (nvp->nvp_datasize != sizeof(idx)) {
589                 errno = EINVAL;
590                 return (NULL);
591         }
592         if (*leftp < sizeof(idx)) {
593                 errno = EINVAL;
594                 return (NULL);
595         }
596
597         if ((flags & NV_FLAG_BIG_ENDIAN) != 0)
598                 idx = be64dec(ptr);
599         else
600                 idx = le64dec(ptr);
601
602         if (idx < 0) {
603                 errno = EINVAL;
604                 return (NULL);
605         }
606
607         if ((size_t)idx >= nfds) {
608                 errno = EINVAL;
609                 return (NULL);
610         }
611
612         nvp->nvp_data = (uint64_t)fds[idx];
613
614         ptr += sizeof(idx);
615         *leftp -= sizeof(idx);
616
617         return (ptr);
618 }
619
620 const unsigned char *
621 nvpair_unpack_binary(int flags __unused, nvpair_t *nvp,
622     const unsigned char *ptr, size_t *leftp)
623 {
624         void *value;
625
626         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
627
628         if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
629                 errno = EINVAL;
630                 return (NULL);
631         }
632
633         value = malloc(nvp->nvp_datasize);
634         if (value == NULL)
635                 return (NULL);
636
637         memcpy(value, ptr, nvp->nvp_datasize);
638         ptr += nvp->nvp_datasize;
639         *leftp -= nvp->nvp_datasize;
640
641         nvp->nvp_data = (uint64_t)(uintptr_t)value;
642
643         return (ptr);
644 }
645
646 const unsigned char *
647 nvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp,
648     nvpair_t **nvpp)
649 {
650         nvpair_t *nvp, *tmp;
651
652         nvp = calloc(1, sizeof(*nvp) + NV_NAME_MAX);
653         if (nvp == NULL)
654                 return (NULL);
655         nvp->nvp_name = (char *)(nvp + 1);
656
657         ptr = nvpair_unpack_header(flags, nvp, ptr, leftp);
658         if (ptr == NULL)
659                 goto failed;
660         tmp = realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
661         if (tmp == NULL)
662                 goto failed;
663         nvp = tmp;
664
665         /* Update nvp_name after realloc(). */
666         nvp->nvp_name = (char *)(nvp + 1);
667         nvp->nvp_data = 0x00;
668         nvp->nvp_magic = NVPAIR_MAGIC;
669         *nvpp = nvp;
670         return (ptr);
671 failed:
672         free(nvp);
673         return (NULL);
674 }
675
676 int
677 nvpair_type(const nvpair_t *nvp)
678 {
679
680         NVPAIR_ASSERT(nvp);
681
682         return (nvp->nvp_type);
683 }
684
685 const char *
686 nvpair_name(const nvpair_t *nvp)
687 {
688
689         NVPAIR_ASSERT(nvp);
690
691         return (nvp->nvp_name);
692 }
693
694 static nvpair_t *
695 nvpair_allocv(int type, uint64_t data, size_t datasize, const char *namefmt,
696     va_list nameap)
697 {
698         nvpair_t *nvp;
699         char *name;
700         int namelen;
701
702         PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
703
704         namelen = vasprintf(&name, namefmt, nameap);
705         if (namelen < 0)
706                 return (NULL);
707
708         PJDLOG_ASSERT(namelen > 0);
709         if (namelen >= NV_NAME_MAX) {
710                 free(name);
711                 errno = ENAMETOOLONG;
712                 return (NULL);
713         }
714
715         nvp = calloc(1, sizeof(*nvp) + namelen + 1);
716         if (nvp != NULL) {
717                 nvp->nvp_name = (char *)(nvp + 1);
718                 memcpy(nvp->nvp_name, name, namelen + 1);
719                 nvp->nvp_type = type;
720                 nvp->nvp_data = data;
721                 nvp->nvp_datasize = datasize;
722                 nvp->nvp_magic = NVPAIR_MAGIC;
723         }
724         free(name);
725
726         return (nvp);
727 };
728
729 nvpair_t *
730 nvpair_create_null(const char *name)
731 {
732
733         return (nvpair_createf_null("%s", name));
734 }
735
736 nvpair_t *
737 nvpair_create_bool(const char *name, bool value)
738 {
739
740         return (nvpair_createf_bool(value, "%s", name));
741 }
742
743 nvpair_t *
744 nvpair_create_number(const char *name, uint64_t value)
745 {
746
747         return (nvpair_createf_number(value, "%s", name));
748 }
749
750 nvpair_t *
751 nvpair_create_string(const char *name, const char *value)
752 {
753
754         return (nvpair_createf_string(value, "%s", name));
755 }
756
757 nvpair_t *
758 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
759 {
760         va_list valueap;
761         nvpair_t *nvp;
762
763         va_start(valueap, valuefmt);
764         nvp = nvpair_create_stringv(name, valuefmt, valueap);
765         va_end(valueap);
766
767         return (nvp);
768 }
769
770 nvpair_t *
771 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
772 {
773         nvpair_t *nvp;
774         char *str;
775         int len;
776
777         len = vasprintf(&str, valuefmt, valueap);
778         if (len < 0)
779                 return (NULL);
780         nvp = nvpair_create_string(name, str);
781         if (nvp == NULL)
782                 free(str);
783         return (nvp);
784 }
785
786 nvpair_t *
787 nvpair_create_nvlist(const char *name, const nvlist_t *value)
788 {
789
790         return (nvpair_createf_nvlist(value, "%s", name));
791 }
792
793 nvpair_t *
794 nvpair_create_descriptor(const char *name, int value)
795 {
796
797         return (nvpair_createf_descriptor(value, "%s", name));
798 }
799
800 nvpair_t *
801 nvpair_create_binary(const char *name, const void *value, size_t size)
802 {
803
804         return (nvpair_createf_binary(value, size, "%s", name));
805 }
806
807 nvpair_t *
808 nvpair_createf_null(const char *namefmt, ...)
809 {
810         va_list nameap;
811         nvpair_t *nvp;
812
813         va_start(nameap, namefmt);
814         nvp = nvpair_createv_null(namefmt, nameap);
815         va_end(nameap);
816
817         return (nvp);
818 }
819
820 nvpair_t *
821 nvpair_createf_bool(bool value, const char *namefmt, ...)
822 {
823         va_list nameap;
824         nvpair_t *nvp;
825
826         va_start(nameap, namefmt);
827         nvp = nvpair_createv_bool(value, namefmt, nameap);
828         va_end(nameap);
829
830         return (nvp);
831 }
832
833 nvpair_t *
834 nvpair_createf_number(uint64_t value, const char *namefmt, ...)
835 {
836         va_list nameap;
837         nvpair_t *nvp;
838
839         va_start(nameap, namefmt);
840         nvp = nvpair_createv_number(value, namefmt, nameap);
841         va_end(nameap);
842
843         return (nvp);
844 }
845
846 nvpair_t *
847 nvpair_createf_string(const char *value, const char *namefmt, ...)
848 {
849         va_list nameap;
850         nvpair_t *nvp;
851
852         va_start(nameap, namefmt);
853         nvp = nvpair_createv_string(value, namefmt, nameap);
854         va_end(nameap);
855
856         return (nvp);
857 }
858
859 nvpair_t *
860 nvpair_createf_nvlist(const nvlist_t *value, const char *namefmt, ...)
861 {
862         va_list nameap;
863         nvpair_t *nvp;
864
865         va_start(nameap, namefmt);
866         nvp = nvpair_createv_nvlist(value, namefmt, nameap);
867         va_end(nameap);
868
869         return (nvp);
870 }
871
872 nvpair_t *
873 nvpair_createf_descriptor(int value, const char *namefmt, ...)
874 {
875         va_list nameap;
876         nvpair_t *nvp;
877
878         va_start(nameap, namefmt);
879         nvp = nvpair_createv_descriptor(value, namefmt, nameap);
880         va_end(nameap);
881
882         return (nvp);
883 }
884
885 nvpair_t *
886 nvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...)
887 {
888         va_list nameap;
889         nvpair_t *nvp;
890
891         va_start(nameap, namefmt);
892         nvp = nvpair_createv_binary(value, size, namefmt, nameap);
893         va_end(nameap);
894
895         return (nvp);
896 }
897
898 nvpair_t *
899 nvpair_createv_null(const char *namefmt, va_list nameap)
900 {
901
902         return (nvpair_allocv(NV_TYPE_NULL, 0, 0, namefmt, nameap));
903 }
904
905 nvpair_t *
906 nvpair_createv_bool(bool value, const char *namefmt, va_list nameap)
907 {
908
909         return (nvpair_allocv(NV_TYPE_BOOL, value ? 1 : 0, sizeof(uint8_t),
910             namefmt, nameap));
911 }
912
913 nvpair_t *
914 nvpair_createv_number(uint64_t value, const char *namefmt, va_list nameap)
915 {
916
917         return (nvpair_allocv(NV_TYPE_NUMBER, value, sizeof(value), namefmt,
918             nameap));
919 }
920
921 nvpair_t *
922 nvpair_createv_string(const char *value, const char *namefmt, va_list nameap)
923 {
924         nvpair_t *nvp;
925         size_t size;
926         char *data;
927
928         if (value == NULL) {
929                 errno = EINVAL;
930                 return (NULL);
931         }
932
933         data = strdup(value);
934         if (data == NULL)
935                 return (NULL);
936         size = strlen(value) + 1;
937
938         nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)data, size,
939             namefmt, nameap);
940         if (nvp == NULL)
941                 free(data);
942
943         return (nvp);
944 }
945
946 nvpair_t *
947 nvpair_createv_nvlist(const nvlist_t *value, const char *namefmt,
948     va_list nameap)
949 {
950         nvlist_t *nvl;
951         nvpair_t *nvp;
952
953         if (value == NULL) {
954                 errno = EINVAL;
955                 return (NULL);
956         }
957
958         nvl = nvlist_clone(value);
959         if (nvl == NULL)
960                 return (NULL);
961
962         nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
963             namefmt, nameap);
964         if (nvp == NULL)
965                 nvlist_destroy(nvl);
966         else
967                 nvlist_set_parent(nvl, nvp);
968
969         return (nvp);
970 }
971
972 nvpair_t *
973 nvpair_createv_descriptor(int value, const char *namefmt, va_list nameap)
974 {
975         nvpair_t *nvp;
976
977         if (value < 0 || !fd_is_valid(value)) {
978                 errno = EBADF;
979                 return (NULL);
980         }
981
982         value = fcntl(value, F_DUPFD_CLOEXEC, 0);
983         if (value < 0)
984                 return (NULL);
985
986         nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value,
987             sizeof(int64_t), namefmt, nameap);
988         if (nvp == NULL)
989                 close(value);
990
991         return (nvp);
992 }
993
994 nvpair_t *
995 nvpair_createv_binary(const void *value, size_t size, const char *namefmt,
996     va_list nameap)
997 {
998         nvpair_t *nvp;
999         void *data;
1000
1001         if (value == NULL || size == 0) {
1002                 errno = EINVAL;
1003                 return (NULL);
1004         }
1005
1006         data = malloc(size);
1007         if (data == NULL)
1008                 return (NULL);
1009         memcpy(data, value, size);
1010
1011         nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, size,
1012             namefmt, nameap);
1013         if (nvp == NULL)
1014                 free(data);
1015
1016         return (nvp);
1017 }
1018
1019 nvpair_t *
1020 nvpair_move_string(const char *name, char *value)
1021 {
1022
1023         return (nvpair_movef_string(value, "%s", name));
1024 }
1025
1026 nvpair_t *
1027 nvpair_move_nvlist(const char *name, nvlist_t *value)
1028 {
1029
1030         return (nvpair_movef_nvlist(value, "%s", name));
1031 }
1032
1033 nvpair_t *
1034 nvpair_move_descriptor(const char *name, int value)
1035 {
1036
1037         return (nvpair_movef_descriptor(value, "%s", name));
1038 }
1039
1040 nvpair_t *
1041 nvpair_move_binary(const char *name, void *value, size_t size)
1042 {
1043
1044         return (nvpair_movef_binary(value, size, "%s", name));
1045 }
1046
1047 nvpair_t *
1048 nvpair_movef_string(char *value, const char *namefmt, ...)
1049 {
1050         va_list nameap;
1051         nvpair_t *nvp;
1052
1053         va_start(nameap, namefmt);
1054         nvp = nvpair_movev_string(value, namefmt, nameap);
1055         va_end(nameap);
1056
1057         return (nvp);
1058 }
1059
1060 nvpair_t *
1061 nvpair_movef_nvlist(nvlist_t *value, const char *namefmt, ...)
1062 {
1063         va_list nameap;
1064         nvpair_t *nvp;
1065
1066         va_start(nameap, namefmt);
1067         nvp = nvpair_movev_nvlist(value, namefmt, nameap);
1068         va_end(nameap);
1069
1070         return (nvp);
1071 }
1072
1073 nvpair_t *
1074 nvpair_movef_descriptor(int value, const char *namefmt, ...)
1075 {
1076         va_list nameap;
1077         nvpair_t *nvp;
1078
1079         va_start(nameap, namefmt);
1080         nvp = nvpair_movev_descriptor(value, namefmt, nameap);
1081         va_end(nameap);
1082
1083         return (nvp);
1084 }
1085
1086 nvpair_t *
1087 nvpair_movef_binary(void *value, size_t size, const char *namefmt, ...)
1088 {
1089         va_list nameap;
1090         nvpair_t *nvp;
1091
1092         va_start(nameap, namefmt);
1093         nvp = nvpair_movev_binary(value, size, namefmt, nameap);
1094         va_end(nameap);
1095
1096         return (nvp);
1097 }
1098
1099 nvpair_t *
1100 nvpair_movev_string(char *value, const char *namefmt, va_list nameap)
1101 {
1102         nvpair_t *nvp;
1103
1104         if (value == NULL) {
1105                 errno = EINVAL;
1106                 return (NULL);
1107         }
1108
1109         nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1110             strlen(value) + 1, namefmt, nameap);
1111         if (nvp == NULL)
1112                 free(value);
1113
1114         return (nvp);
1115 }
1116
1117 nvpair_t *
1118 nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap)
1119 {
1120         nvpair_t *nvp;
1121
1122         if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1123                 errno = EINVAL;
1124                 return (NULL);
1125         }
1126
1127         nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 0,
1128             namefmt, nameap);
1129         if (nvp == NULL)
1130                 nvlist_destroy(value);
1131         else
1132                 nvlist_set_parent(value, nvp);
1133
1134         return (nvp);
1135 }
1136
1137 nvpair_t *
1138 nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap)
1139 {
1140
1141         if (value < 0 || !fd_is_valid(value)) {
1142                 errno = EBADF;
1143                 return (NULL);
1144         }
1145
1146         return (nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value,
1147             sizeof(int64_t), namefmt, nameap));
1148 }
1149
1150 nvpair_t *
1151 nvpair_movev_binary(void *value, size_t size, const char *namefmt,
1152     va_list nameap)
1153 {
1154
1155         if (value == NULL || size == 0) {
1156                 errno = EINVAL;
1157                 return (NULL);
1158         }
1159
1160         return (nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size,
1161             namefmt, nameap));
1162 }
1163
1164 bool
1165 nvpair_get_bool(const nvpair_t *nvp)
1166 {
1167
1168         NVPAIR_ASSERT(nvp);
1169
1170         return (nvp->nvp_data == 1);
1171 }
1172
1173 uint64_t
1174 nvpair_get_number(const nvpair_t *nvp)
1175 {
1176
1177         NVPAIR_ASSERT(nvp);
1178
1179         return (nvp->nvp_data);
1180 }
1181
1182 const char *
1183 nvpair_get_string(const nvpair_t *nvp)
1184 {
1185
1186         NVPAIR_ASSERT(nvp);
1187         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1188
1189         return ((const char *)(intptr_t)nvp->nvp_data);
1190 }
1191
1192 const nvlist_t *
1193 nvpair_get_nvlist(const nvpair_t *nvp)
1194 {
1195
1196         NVPAIR_ASSERT(nvp);
1197         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1198
1199         return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1200 }
1201
1202 int
1203 nvpair_get_descriptor(const nvpair_t *nvp)
1204 {
1205
1206         NVPAIR_ASSERT(nvp);
1207         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1208
1209         return ((int)nvp->nvp_data);
1210 }
1211
1212 const void *
1213 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1214 {
1215
1216         NVPAIR_ASSERT(nvp);
1217         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1218
1219         if (sizep != NULL)
1220                 *sizep = nvp->nvp_datasize;
1221         return ((const void *)(intptr_t)nvp->nvp_data);
1222 }
1223
1224 void
1225 nvpair_free(nvpair_t *nvp)
1226 {
1227
1228         NVPAIR_ASSERT(nvp);
1229         PJDLOG_ASSERT(nvp->nvp_list == NULL);
1230
1231         nvp->nvp_magic = 0;
1232         switch (nvp->nvp_type) {
1233         case NV_TYPE_DESCRIPTOR:
1234                 close((int)nvp->nvp_data);
1235                 break;
1236         case NV_TYPE_NVLIST:
1237                 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
1238                 break;
1239         case NV_TYPE_STRING:
1240                 free((char *)(intptr_t)nvp->nvp_data);
1241                 break;
1242         case NV_TYPE_BINARY:
1243                 free((void *)(intptr_t)nvp->nvp_data);
1244                 break;
1245         }
1246         free(nvp);
1247 }
1248
1249 void
1250 nvpair_free_structure(nvpair_t *nvp)
1251 {
1252
1253         NVPAIR_ASSERT(nvp);
1254         PJDLOG_ASSERT(nvp->nvp_list == NULL);
1255
1256         nvp->nvp_magic = 0;
1257         free(nvp);
1258 }
1259
1260 const char *
1261 nvpair_type_string(int type)
1262 {
1263
1264         switch (type) {
1265         case NV_TYPE_NULL:
1266                 return ("NULL");
1267         case NV_TYPE_BOOL:
1268                 return ("BOOL");
1269         case NV_TYPE_NUMBER:
1270                 return ("NUMBER");
1271         case NV_TYPE_STRING:
1272                 return ("STRING");
1273         case NV_TYPE_NVLIST:
1274                 return ("NVLIST");
1275         case NV_TYPE_DESCRIPTOR:
1276                 return ("DESCRIPTOR");
1277         case NV_TYPE_BINARY:
1278                 return ("BINARY");
1279         default:
1280                 return ("<UNKNOWN>");
1281         }
1282 }