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