1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2009-2013 The FreeBSD Foundation
5 * Copyright (c) 2013-2015 Mariusz Zaborski <[email protected]>
6 * All rights reserved.
7 *
8 * This software was developed by Pawel Jakub Dawidek under sponsorship from
9 * the FreeBSD Foundation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/endian.h>
38 #include <sys/queue.h>
39
40 #ifdef _KERNEL
41
42 #include <sys/errno.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/systm.h>
46
47 #include <machine/stdarg.h>
48
49 #else
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <stdarg.h>
53 #include <stdbool.h>
54 #include <stdint.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <unistd.h>
58
59 #include "common_impl.h"
60 #endif
61
62 #ifdef HAVE_PJDLOG
63 #include <pjdlog.h>
64 #endif
65
66 #include <sys/nv.h>
67
68 #include "nv_impl.h"
69 #include "nvlist_impl.h"
70 #include "nvpair_impl.h"
71
72 #ifndef HAVE_PJDLOG
73 #ifdef _KERNEL
74 #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
75 #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
76 #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
77 #else
78 #include <assert.h>
79 #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
80 #define PJDLOG_RASSERT(expr, ...) assert(expr)
81 #define PJDLOG_ABORT(...) abort()
82 #endif
83 #endif
84
85 #define NVPAIR_MAGIC 0x6e7670 /* "nvp" */
86 struct nvpair {
87 int nvp_magic;
88 char *nvp_name;
89 int nvp_type;
90 uint64_t nvp_data;
91 size_t nvp_datasize;
92 size_t nvp_nitems; /* Used only for array types. */
93 nvlist_t *nvp_list;
94 TAILQ_ENTRY(nvpair) nvp_next;
95 };
96
97 #define NVPAIR_ASSERT(nvp) do { \
98 PJDLOG_ASSERT((nvp) != NULL); \
99 PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \
100 } while (0)
101
102 struct nvpair_header {
103 uint8_t nvph_type;
104 uint16_t nvph_namesize;
105 uint64_t nvph_datasize;
106 uint64_t nvph_nitems;
107 } __packed;
108
109
110 void
nvpair_assert(const nvpair_t * nvp __unused)111 nvpair_assert(const nvpair_t *nvp __unused)
112 {
113
114 NVPAIR_ASSERT(nvp);
115 }
116
117 static nvpair_t *
nvpair_allocv(const char * name,int type,uint64_t data,size_t datasize,size_t nitems)118 nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize,
119 size_t nitems)
120 {
121 nvpair_t *nvp;
122 size_t namelen;
123
124 PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
125
126 namelen = strlen(name);
127 if (namelen >= NV_NAME_MAX) {
128 ERRNO_SET(ENAMETOOLONG);
129 return (NULL);
130 }
131
132 nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
133 if (nvp != NULL) {
134 nvp->nvp_name = (char *)(nvp + 1);
135 memcpy(nvp->nvp_name, name, namelen);
136 nvp->nvp_name[namelen] = '\0';
137 nvp->nvp_type = type;
138 nvp->nvp_data = data;
139 nvp->nvp_datasize = datasize;
140 nvp->nvp_nitems = nitems;
141 nvp->nvp_magic = NVPAIR_MAGIC;
142 }
143
144 return (nvp);
145 }
146
147 static int
nvpair_append(nvpair_t * nvp,const void * value,size_t valsize,size_t datasize)148 nvpair_append(nvpair_t *nvp, const void *value, size_t valsize, size_t datasize)
149 {
150 void *olddata, *data, *valp;
151 size_t oldlen;
152
153 oldlen = nvp->nvp_nitems * valsize;
154 olddata = (void *)(uintptr_t)nvp->nvp_data;
155 data = nv_realloc(olddata, oldlen + valsize);
156 if (data == NULL) {
157 ERRNO_SET(ENOMEM);
158 return (-1);
159 }
160 valp = (unsigned char *)data + oldlen;
161 memcpy(valp, value, valsize);
162
163 nvp->nvp_data = (uint64_t)(uintptr_t)data;
164 nvp->nvp_datasize += datasize;
165 nvp->nvp_nitems++;
166 return (0);
167 }
168
169 nvlist_t *
nvpair_nvlist(const nvpair_t * nvp)170 nvpair_nvlist(const nvpair_t *nvp)
171 {
172
173 NVPAIR_ASSERT(nvp);
174
175 return (nvp->nvp_list);
176 }
177
178 nvpair_t *
nvpair_next(const nvpair_t * nvp)179 nvpair_next(const nvpair_t *nvp)
180 {
181
182 NVPAIR_ASSERT(nvp);
183 PJDLOG_ASSERT(nvp->nvp_list != NULL);
184
185 return (TAILQ_NEXT(nvp, nvp_next));
186 }
187
188 nvpair_t *
nvpair_prev(const nvpair_t * nvp)189 nvpair_prev(const nvpair_t *nvp)
190 {
191
192 NVPAIR_ASSERT(nvp);
193 PJDLOG_ASSERT(nvp->nvp_list != NULL);
194
195 return (TAILQ_PREV(nvp, nvl_head, nvp_next));
196 }
197
198 void
nvpair_insert(struct nvl_head * head,nvpair_t * nvp,nvlist_t * nvl)199 nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
200 {
201
202 NVPAIR_ASSERT(nvp);
203 PJDLOG_ASSERT(nvp->nvp_list == NULL);
204 PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 ||
205 !nvlist_exists(nvl, nvpair_name(nvp)));
206
207 TAILQ_INSERT_TAIL(head, nvp, nvp_next);
208 nvp->nvp_list = nvl;
209 }
210
211 static void
nvpair_remove_nvlist(nvpair_t * nvp)212 nvpair_remove_nvlist(nvpair_t *nvp)
213 {
214 nvlist_t *nvl;
215
216 /* XXX: DECONST is bad, mkay? */
217 nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
218 PJDLOG_ASSERT(nvl != NULL);
219 nvlist_set_parent(nvl, NULL);
220 }
221
222 static void
nvpair_remove_nvlist_array(nvpair_t * nvp)223 nvpair_remove_nvlist_array(nvpair_t *nvp)
224 {
225 nvlist_t **nvlarray;
226 size_t count, i;
227
228 /* XXX: DECONST is bad, mkay? */
229 nvlarray = __DECONST(nvlist_t **,
230 nvpair_get_nvlist_array(nvp, &count));
231 for (i = 0; i < count; i++) {
232 nvlist_set_array_next(nvlarray[i], NULL);
233 nvlist_set_parent(nvlarray[i], NULL);
234 }
235 }
236
237 void
nvpair_remove(struct nvl_head * head,nvpair_t * nvp,const nvlist_t * nvl __unused)238 nvpair_remove(struct nvl_head *head, nvpair_t *nvp,
239 const nvlist_t *nvl __unused)
240 {
241
242 NVPAIR_ASSERT(nvp);
243 PJDLOG_ASSERT(nvp->nvp_list == nvl);
244
245 if (nvpair_type(nvp) == NV_TYPE_NVLIST)
246 nvpair_remove_nvlist(nvp);
247 else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY)
248 nvpair_remove_nvlist_array(nvp);
249
250 TAILQ_REMOVE(head, nvp, nvp_next);
251 nvp->nvp_list = NULL;
252 }
253
254 nvpair_t *
nvpair_clone(const nvpair_t * nvp)255 nvpair_clone(const nvpair_t *nvp)
256 {
257 nvpair_t *newnvp;
258 const char *name;
259 const void *data;
260 size_t datasize;
261
262 NVPAIR_ASSERT(nvp);
263
264 name = nvpair_name(nvp);
265
266 switch (nvpair_type(nvp)) {
267 case NV_TYPE_NULL:
268 newnvp = nvpair_create_null(name);
269 break;
270 case NV_TYPE_BOOL:
271 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
272 break;
273 case NV_TYPE_NUMBER:
274 newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
275 break;
276 case NV_TYPE_STRING:
277 newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
278 break;
279 case NV_TYPE_NVLIST:
280 newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
281 break;
282 case NV_TYPE_BINARY:
283 data = nvpair_get_binary(nvp, &datasize);
284 newnvp = nvpair_create_binary(name, data, datasize);
285 break;
286 case NV_TYPE_BOOL_ARRAY:
287 data = nvpair_get_bool_array(nvp, &datasize);
288 newnvp = nvpair_create_bool_array(name, data, datasize);
289 break;
290 case NV_TYPE_NUMBER_ARRAY:
291 data = nvpair_get_number_array(nvp, &datasize);
292 newnvp = nvpair_create_number_array(name, data, datasize);
293 break;
294 case NV_TYPE_STRING_ARRAY:
295 data = nvpair_get_string_array(nvp, &datasize);
296 newnvp = nvpair_create_string_array(name, data, datasize);
297 break;
298 case NV_TYPE_NVLIST_ARRAY:
299 data = nvpair_get_nvlist_array(nvp, &datasize);
300 newnvp = nvpair_create_nvlist_array(name, data, datasize);
301 break;
302 #ifndef _KERNEL
303 case NV_TYPE_DESCRIPTOR:
304 newnvp = nvpair_create_descriptor(name,
305 nvpair_get_descriptor(nvp));
306 break;
307 case NV_TYPE_DESCRIPTOR_ARRAY:
308 data = nvpair_get_descriptor_array(nvp, &datasize);
309 newnvp = nvpair_create_descriptor_array(name, data, datasize);
310 break;
311 #endif
312 default:
313 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
314 }
315
316 return (newnvp);
317 }
318
319 size_t
nvpair_header_size(void)320 nvpair_header_size(void)
321 {
322
323 return (sizeof(struct nvpair_header));
324 }
325
326 size_t
nvpair_size(const nvpair_t * nvp)327 nvpair_size(const nvpair_t *nvp)
328 {
329
330 NVPAIR_ASSERT(nvp);
331
332 return (nvp->nvp_datasize);
333 }
334
335 unsigned char *
nvpair_pack_header(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)336 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
337 {
338 struct nvpair_header nvphdr;
339 size_t namesize;
340
341 NVPAIR_ASSERT(nvp);
342
343 nvphdr.nvph_type = nvp->nvp_type;
344 namesize = strlen(nvp->nvp_name) + 1;
345 PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
346 nvphdr.nvph_namesize = namesize;
347 nvphdr.nvph_datasize = nvp->nvp_datasize;
348 nvphdr.nvph_nitems = nvp->nvp_nitems;
349 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
350 memcpy(ptr, &nvphdr, sizeof(nvphdr));
351 ptr += sizeof(nvphdr);
352 *leftp -= sizeof(nvphdr);
353
354 PJDLOG_ASSERT(*leftp >= namesize);
355 memcpy(ptr, nvp->nvp_name, namesize);
356 ptr += namesize;
357 *leftp -= namesize;
358
359 return (ptr);
360 }
361
362 unsigned char *
nvpair_pack_null(const nvpair_t * nvp __unused,unsigned char * ptr,size_t * leftp __unused)363 nvpair_pack_null(const nvpair_t *nvp __unused, unsigned char *ptr,
364 size_t *leftp __unused)
365 {
366
367 NVPAIR_ASSERT(nvp);
368 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
369
370 return (ptr);
371 }
372
373 unsigned char *
nvpair_pack_bool(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)374 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
375 {
376 uint8_t value;
377
378 NVPAIR_ASSERT(nvp);
379 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
380
381 value = (uint8_t)nvp->nvp_data;
382
383 PJDLOG_ASSERT(*leftp >= sizeof(value));
384 memcpy(ptr, &value, sizeof(value));
385 ptr += sizeof(value);
386 *leftp -= sizeof(value);
387
388 return (ptr);
389 }
390
391 unsigned char *
nvpair_pack_number(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)392 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
393 {
394 uint64_t value;
395
396 NVPAIR_ASSERT(nvp);
397 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
398
399 value = (uint64_t)nvp->nvp_data;
400
401 PJDLOG_ASSERT(*leftp >= sizeof(value));
402 memcpy(ptr, &value, sizeof(value));
403 ptr += sizeof(value);
404 *leftp -= sizeof(value);
405
406 return (ptr);
407 }
408
409 unsigned char *
nvpair_pack_string(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)410 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
411 {
412
413 NVPAIR_ASSERT(nvp);
414 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
415
416 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
417 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
418 ptr += nvp->nvp_datasize;
419 *leftp -= nvp->nvp_datasize;
420
421 return (ptr);
422 }
423
424 unsigned char *
nvpair_pack_nvlist_up(unsigned char * ptr,size_t * leftp)425 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
426 {
427 struct nvpair_header nvphdr;
428 size_t namesize;
429 const char *name = "";
430
431 namesize = 1;
432 nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
433 nvphdr.nvph_namesize = namesize;
434 nvphdr.nvph_datasize = 0;
435 nvphdr.nvph_nitems = 0;
436 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
437 memcpy(ptr, &nvphdr, sizeof(nvphdr));
438 ptr += sizeof(nvphdr);
439 *leftp -= sizeof(nvphdr);
440
441 PJDLOG_ASSERT(*leftp >= namesize);
442 memcpy(ptr, name, namesize);
443 ptr += namesize;
444 *leftp -= namesize;
445
446 return (ptr);
447 }
448
449 unsigned char *
nvpair_pack_nvlist_array_next(unsigned char * ptr,size_t * leftp)450 nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp)
451 {
452 struct nvpair_header nvphdr;
453 size_t namesize;
454 const char *name = "";
455
456 namesize = 1;
457 nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT;
458 nvphdr.nvph_namesize = namesize;
459 nvphdr.nvph_datasize = 0;
460 nvphdr.nvph_nitems = 0;
461 PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
462 memcpy(ptr, &nvphdr, sizeof(nvphdr));
463 ptr += sizeof(nvphdr);
464 *leftp -= sizeof(nvphdr);
465
466 PJDLOG_ASSERT(*leftp >= namesize);
467 memcpy(ptr, name, namesize);
468 ptr += namesize;
469 *leftp -= namesize;
470
471 return (ptr);
472 }
473
474 #ifndef _KERNEL
475 unsigned char *
nvpair_pack_descriptor(const nvpair_t * nvp,unsigned char * ptr,int64_t * fdidxp,size_t * leftp)476 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
477 size_t *leftp)
478 {
479 int64_t value;
480
481 NVPAIR_ASSERT(nvp);
482 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
483
484 value = (int64_t)nvp->nvp_data;
485 if (value != -1) {
486 /*
487 * If there is a real descriptor here, we change its number
488 * to position in the array of descriptors send via control
489 * message.
490 */
491 PJDLOG_ASSERT(fdidxp != NULL);
492
493 value = *fdidxp;
494 (*fdidxp)++;
495 }
496
497 PJDLOG_ASSERT(*leftp >= sizeof(value));
498 memcpy(ptr, &value, sizeof(value));
499 ptr += sizeof(value);
500 *leftp -= sizeof(value);
501
502 return (ptr);
503 }
504 #endif
505
506 unsigned char *
nvpair_pack_binary(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)507 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
508 {
509
510 NVPAIR_ASSERT(nvp);
511 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
512
513 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
514 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
515 ptr += nvp->nvp_datasize;
516 *leftp -= nvp->nvp_datasize;
517
518 return (ptr);
519 }
520
521 unsigned char *
nvpair_pack_bool_array(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)522 nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
523 {
524
525 NVPAIR_ASSERT(nvp);
526 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
527 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
528
529 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
530 ptr += nvp->nvp_datasize;
531 *leftp -= nvp->nvp_datasize;
532
533 return (ptr);
534 }
535
536 unsigned char *
nvpair_pack_number_array(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)537 nvpair_pack_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
538 {
539
540 NVPAIR_ASSERT(nvp);
541 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
542 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
543
544 memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
545 ptr += nvp->nvp_datasize;
546 *leftp -= nvp->nvp_datasize;
547
548 return (ptr);
549 }
550
551 unsigned char *
nvpair_pack_string_array(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)552 nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
553 {
554 unsigned int ii;
555 size_t size, len;
556 const char * const *array;
557
558 NVPAIR_ASSERT(nvp);
559 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
560 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
561
562 size = 0;
563 array = nvpair_get_string_array(nvp, NULL);
564 PJDLOG_ASSERT(array != NULL);
565
566 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
567 len = strlen(array[ii]) + 1;
568 PJDLOG_ASSERT(*leftp >= len);
569
570 memcpy(ptr, (const void *)array[ii], len);
571 size += len;
572 ptr += len;
573 *leftp -= len;
574 }
575
576 PJDLOG_ASSERT(size == nvp->nvp_datasize);
577
578 return (ptr);
579 }
580
581 #ifndef _KERNEL
582 unsigned char *
nvpair_pack_descriptor_array(const nvpair_t * nvp,unsigned char * ptr,int64_t * fdidxp,size_t * leftp)583 nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr,
584 int64_t *fdidxp, size_t *leftp)
585 {
586 int64_t value;
587 const int *array;
588 unsigned int ii;
589
590 NVPAIR_ASSERT(nvp);
591 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
592 PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
593
594 array = nvpair_get_descriptor_array(nvp, NULL);
595 PJDLOG_ASSERT(array != NULL);
596
597 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
598 PJDLOG_ASSERT(*leftp >= sizeof(value));
599
600 value = array[ii];
601 if (value != -1) {
602 /*
603 * If there is a real descriptor here, we change its
604 * number to position in the array of descriptors send
605 * via control message.
606 */
607 PJDLOG_ASSERT(fdidxp != NULL);
608
609 value = *fdidxp;
610 (*fdidxp)++;
611 }
612 memcpy(ptr, &value, sizeof(value));
613 ptr += sizeof(value);
614 *leftp -= sizeof(value);
615 }
616
617 return (ptr);
618 }
619 #endif
620
621 void
nvpair_init_datasize(nvpair_t * nvp)622 nvpair_init_datasize(nvpair_t *nvp)
623 {
624
625 NVPAIR_ASSERT(nvp);
626
627 if (nvp->nvp_type == NV_TYPE_NVLIST) {
628 if (nvp->nvp_data == 0) {
629 nvp->nvp_datasize = 0;
630 } else {
631 nvp->nvp_datasize =
632 nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
633 }
634 }
635 }
636
637 const unsigned char *
nvpair_unpack_header(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)638 nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
639 size_t *leftp)
640 {
641 struct nvpair_header nvphdr;
642
643 if (*leftp < sizeof(nvphdr))
644 goto fail;
645
646 memcpy(&nvphdr, ptr, sizeof(nvphdr));
647 ptr += sizeof(nvphdr);
648 *leftp -= sizeof(nvphdr);
649
650 #if NV_TYPE_FIRST > 0
651 if (nvphdr.nvph_type < NV_TYPE_FIRST)
652 goto fail;
653 #endif
654 if (nvphdr.nvph_type > NV_TYPE_LAST &&
655 nvphdr.nvph_type != NV_TYPE_NVLIST_UP &&
656 nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) {
657 goto fail;
658 }
659
660 #if BYTE_ORDER == BIG_ENDIAN
661 if (!isbe) {
662 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
663 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
664 }
665 #else
666 if (isbe) {
667 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
668 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
669 }
670 #endif
671
672 if (nvphdr.nvph_namesize > NV_NAME_MAX)
673 goto fail;
674 if (*leftp < nvphdr.nvph_namesize)
675 goto fail;
676 if (nvphdr.nvph_namesize < 1)
677 goto fail;
678 if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
679 (size_t)(nvphdr.nvph_namesize - 1)) {
680 goto fail;
681 }
682
683 memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
684 ptr += nvphdr.nvph_namesize;
685 *leftp -= nvphdr.nvph_namesize;
686
687 if (*leftp < nvphdr.nvph_datasize)
688 goto fail;
689
690 nvp->nvp_type = nvphdr.nvph_type;
691 nvp->nvp_data = 0;
692 nvp->nvp_datasize = nvphdr.nvph_datasize;
693 nvp->nvp_nitems = nvphdr.nvph_nitems;
694
695 return (ptr);
696 fail:
697 ERRNO_SET(EINVAL);
698 return (NULL);
699 }
700
701 const unsigned char *
nvpair_unpack_null(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp __unused)702 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
703 size_t *leftp __unused)
704 {
705
706 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
707
708 if (nvp->nvp_datasize != 0) {
709 ERRNO_SET(EINVAL);
710 return (NULL);
711 }
712
713 return (ptr);
714 }
715
716 const unsigned char *
nvpair_unpack_bool(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)717 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
718 size_t *leftp)
719 {
720 uint8_t value;
721
722 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
723
724 if (nvp->nvp_datasize != sizeof(value)) {
725 ERRNO_SET(EINVAL);
726 return (NULL);
727 }
728 if (*leftp < sizeof(value)) {
729 ERRNO_SET(EINVAL);
730 return (NULL);
731 }
732
733 memcpy(&value, ptr, sizeof(value));
734 ptr += sizeof(value);
735 *leftp -= sizeof(value);
736
737 if (value != 0 && value != 1) {
738 ERRNO_SET(EINVAL);
739 return (NULL);
740 }
741
742 nvp->nvp_data = (uint64_t)value;
743
744 return (ptr);
745 }
746
747 const unsigned char *
nvpair_unpack_number(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)748 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
749 size_t *leftp)
750 {
751
752 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
753
754 if (nvp->nvp_datasize != sizeof(uint64_t)) {
755 ERRNO_SET(EINVAL);
756 return (NULL);
757 }
758 if (*leftp < sizeof(uint64_t)) {
759 ERRNO_SET(EINVAL);
760 return (NULL);
761 }
762
763 if (isbe)
764 nvp->nvp_data = be64dec(ptr);
765 else
766 nvp->nvp_data = le64dec(ptr);
767
768 ptr += sizeof(uint64_t);
769 *leftp -= sizeof(uint64_t);
770
771 return (ptr);
772 }
773
774 const unsigned char *
nvpair_unpack_string(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)775 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
776 const unsigned char *ptr, size_t *leftp)
777 {
778
779 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
780
781 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
782 ERRNO_SET(EINVAL);
783 return (NULL);
784 }
785
786 if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
787 nvp->nvp_datasize - 1) {
788 ERRNO_SET(EINVAL);
789 return (NULL);
790 }
791
792 nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
793 if (nvp->nvp_data == 0)
794 return (NULL);
795
796 ptr += nvp->nvp_datasize;
797 *leftp -= nvp->nvp_datasize;
798
799 return (ptr);
800 }
801
802 const unsigned char *
nvpair_unpack_nvlist(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,size_t nfds,nvlist_t ** child)803 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
804 const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
805 {
806 nvlist_t *value;
807
808 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
809
810 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
811 ERRNO_SET(EINVAL);
812 return (NULL);
813 }
814
815 value = nvlist_create(0);
816 if (value == NULL)
817 return (NULL);
818
819 ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
820 if (ptr == NULL)
821 return (NULL);
822
823 nvp->nvp_data = (uint64_t)(uintptr_t)value;
824 *child = value;
825
826 return (ptr);
827 }
828
829 #ifndef _KERNEL
830 const unsigned char *
nvpair_unpack_descriptor(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,const int * fds,size_t nfds)831 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
832 size_t *leftp, const int *fds, size_t nfds)
833 {
834 int64_t idx;
835
836 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
837
838 if (nvp->nvp_datasize != sizeof(idx)) {
839 ERRNO_SET(EINVAL);
840 return (NULL);
841 }
842 if (*leftp < sizeof(idx)) {
843 ERRNO_SET(EINVAL);
844 return (NULL);
845 }
846
847 if (isbe)
848 idx = be64dec(ptr);
849 else
850 idx = le64dec(ptr);
851
852 if (idx < 0) {
853 ERRNO_SET(EINVAL);
854 return (NULL);
855 }
856
857 if ((size_t)idx >= nfds) {
858 ERRNO_SET(EINVAL);
859 return (NULL);
860 }
861
862 nvp->nvp_data = (uint64_t)fds[idx];
863
864 ptr += sizeof(idx);
865 *leftp -= sizeof(idx);
866
867 return (ptr);
868 }
869 #endif
870
871 const unsigned char *
nvpair_unpack_binary(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)872 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
873 const unsigned char *ptr, size_t *leftp)
874 {
875 void *value;
876
877 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
878
879 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
880 ERRNO_SET(EINVAL);
881 return (NULL);
882 }
883
884 value = nv_malloc(nvp->nvp_datasize);
885 if (value == NULL)
886 return (NULL);
887
888 memcpy(value, ptr, nvp->nvp_datasize);
889 ptr += nvp->nvp_datasize;
890 *leftp -= nvp->nvp_datasize;
891
892 nvp->nvp_data = (uint64_t)(uintptr_t)value;
893
894 return (ptr);
895 }
896
897 const unsigned char *
nvpair_unpack_bool_array(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)898 nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp,
899 const unsigned char *ptr, size_t *leftp)
900 {
901 uint8_t *value;
902 size_t size;
903 unsigned int i;
904
905 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
906
907 size = sizeof(*value) * nvp->nvp_nitems;
908 if (nvp->nvp_datasize != size || *leftp < size ||
909 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
910 ERRNO_SET(EINVAL);
911 return (NULL);
912 }
913
914 value = nv_malloc(size);
915 if (value == NULL)
916 return (NULL);
917
918 for (i = 0; i < nvp->nvp_nitems; i++) {
919 value[i] = *(const uint8_t *)ptr;
920
921 ptr += sizeof(*value);
922 *leftp -= sizeof(*value);
923 }
924
925 nvp->nvp_data = (uint64_t)(uintptr_t)value;
926
927 return (ptr);
928 }
929
930 const unsigned char *
nvpair_unpack_number_array(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)931 nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
932 size_t *leftp)
933 {
934 uint64_t *value;
935 size_t size;
936 unsigned int i;
937
938 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
939
940 size = sizeof(*value) * nvp->nvp_nitems;
941 if (nvp->nvp_datasize != size || *leftp < size ||
942 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
943 ERRNO_SET(EINVAL);
944 return (NULL);
945 }
946
947 value = nv_malloc(size);
948 if (value == NULL)
949 return (NULL);
950
951 for (i = 0; i < nvp->nvp_nitems; i++) {
952 if (isbe)
953 value[i] = be64dec(ptr);
954 else
955 value[i] = le64dec(ptr);
956
957 ptr += sizeof(*value);
958 *leftp -= sizeof(*value);
959 }
960
961 nvp->nvp_data = (uint64_t)(uintptr_t)value;
962
963 return (ptr);
964 }
965
966 const unsigned char *
nvpair_unpack_string_array(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)967 nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp,
968 const unsigned char *ptr, size_t *leftp)
969 {
970 ssize_t size;
971 size_t len;
972 const char *tmp;
973 char **value;
974 unsigned int ii, j;
975
976 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
977
978 if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 ||
979 nvp->nvp_nitems == 0) {
980 ERRNO_SET(EINVAL);
981 return (NULL);
982 }
983
984 size = nvp->nvp_datasize;
985 tmp = (const char *)ptr;
986 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
987 len = strnlen(tmp, size - 1) + 1;
988 size -= len;
989 if (size < 0) {
990 ERRNO_SET(EINVAL);
991 return (NULL);
992 }
993 tmp += len;
994 }
995 if (size != 0) {
996 ERRNO_SET(EINVAL);
997 return (NULL);
998 }
999
1000 value = nv_malloc(sizeof(*value) * nvp->nvp_nitems);
1001 if (value == NULL)
1002 return (NULL);
1003
1004 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1005 value[ii] = nv_strdup((const char *)ptr);
1006 if (value[ii] == NULL)
1007 goto out;
1008 len = strlen(value[ii]) + 1;
1009 ptr += len;
1010 *leftp -= len;
1011 }
1012 nvp->nvp_data = (uint64_t)(uintptr_t)value;
1013
1014 return (ptr);
1015 out:
1016 for (j = 0; j < ii; j++)
1017 nv_free(value[j]);
1018 nv_free(value);
1019 return (NULL);
1020 }
1021
1022 #ifndef _KERNEL
1023 const unsigned char *
nvpair_unpack_descriptor_array(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,const int * fds,size_t nfds)1024 nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
1025 const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
1026 {
1027 int64_t idx;
1028 size_t size;
1029 unsigned int ii;
1030 int *array;
1031
1032 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1033
1034 size = sizeof(idx) * nvp->nvp_nitems;
1035 if (nvp->nvp_datasize != size || *leftp < size ||
1036 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
1037 ERRNO_SET(EINVAL);
1038 return (NULL);
1039 }
1040
1041 array = (int *)nv_malloc(size);
1042 if (array == NULL)
1043 return (NULL);
1044
1045 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1046 if (isbe)
1047 idx = be64dec(ptr);
1048 else
1049 idx = le64dec(ptr);
1050
1051 if (idx < 0) {
1052 ERRNO_SET(EINVAL);
1053 nv_free(array);
1054 return (NULL);
1055 }
1056
1057 if ((size_t)idx >= nfds) {
1058 ERRNO_SET(EINVAL);
1059 nv_free(array);
1060 return (NULL);
1061 }
1062
1063 array[ii] = (uint64_t)fds[idx];
1064
1065 ptr += sizeof(idx);
1066 *leftp -= sizeof(idx);
1067 }
1068
1069 nvp->nvp_data = (uint64_t)(uintptr_t)array;
1070
1071 return (ptr);
1072 }
1073 #endif
1074
1075 const unsigned char *
nvpair_unpack_nvlist_array(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,nvlist_t ** firstel)1076 nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
1077 const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
1078 {
1079 nvlist_t **value;
1080 nvpair_t *tmpnvp;
1081 unsigned int ii, j;
1082 size_t sizeup;
1083
1084 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1085
1086 sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
1087 if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
1088 sizeup > *leftp) {
1089 ERRNO_SET(EINVAL);
1090 return (NULL);
1091 }
1092
1093 value = nv_malloc(nvp->nvp_nitems * sizeof(*value));
1094 if (value == NULL)
1095 return (NULL);
1096
1097 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1098 value[ii] = nvlist_create(0);
1099 if (value[ii] == NULL)
1100 goto fail;
1101 if (ii > 0) {
1102 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1103 (uint64_t)(uintptr_t)value[ii], 0, 0);
1104 if (tmpnvp == NULL)
1105 goto fail;
1106 nvlist_set_array_next(value[ii - 1], tmpnvp);
1107 }
1108 }
1109 nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
1110
1111 nvp->nvp_data = (uint64_t)(uintptr_t)value;
1112 *firstel = value[0];
1113
1114 return (ptr);
1115 fail:
1116 ERRNO_SAVE();
1117 for (j = 0; j <= ii; j++)
1118 nvlist_destroy(value[j]);
1119 nv_free(value);
1120 ERRNO_RESTORE();
1121
1122 return (NULL);
1123 }
1124
1125 const unsigned char *
nvpair_unpack(bool isbe,const unsigned char * ptr,size_t * leftp,nvpair_t ** nvpp)1126 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
1127 nvpair_t **nvpp)
1128 {
1129 nvpair_t *nvp, *tmp;
1130
1131 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
1132 if (nvp == NULL)
1133 return (NULL);
1134 nvp->nvp_name = (char *)(nvp + 1);
1135
1136 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
1137 if (ptr == NULL)
1138 goto fail;
1139 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
1140 if (tmp == NULL)
1141 goto fail;
1142 nvp = tmp;
1143
1144 /* Update nvp_name after realloc(). */
1145 nvp->nvp_name = (char *)(nvp + 1);
1146 nvp->nvp_data = 0x00;
1147 nvp->nvp_magic = NVPAIR_MAGIC;
1148 *nvpp = nvp;
1149 return (ptr);
1150 fail:
1151 nv_free(nvp);
1152 return (NULL);
1153 }
1154
1155 int
nvpair_type(const nvpair_t * nvp)1156 nvpair_type(const nvpair_t *nvp)
1157 {
1158
1159 NVPAIR_ASSERT(nvp);
1160
1161 return (nvp->nvp_type);
1162 }
1163
1164 const char *
nvpair_name(const nvpair_t * nvp)1165 nvpair_name(const nvpair_t *nvp)
1166 {
1167
1168 NVPAIR_ASSERT(nvp);
1169
1170 return (nvp->nvp_name);
1171 }
1172
1173 nvpair_t *
nvpair_create_stringf(const char * name,const char * valuefmt,...)1174 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
1175 {
1176 va_list valueap;
1177 nvpair_t *nvp;
1178
1179 va_start(valueap, valuefmt);
1180 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1181 va_end(valueap);
1182
1183 return (nvp);
1184 }
1185
1186 nvpair_t *
nvpair_create_stringv(const char * name,const char * valuefmt,va_list valueap)1187 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
1188 {
1189 nvpair_t *nvp;
1190 char *str;
1191 int len;
1192
1193 len = nv_vasprintf(&str, valuefmt, valueap);
1194 if (len < 0)
1195 return (NULL);
1196 nvp = nvpair_create_string(name, str);
1197 nv_free(str);
1198 return (nvp);
1199 }
1200
1201 nvpair_t *
nvpair_create_null(const char * name)1202 nvpair_create_null(const char *name)
1203 {
1204
1205 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1206 }
1207
1208 nvpair_t *
nvpair_create_bool(const char * name,bool value)1209 nvpair_create_bool(const char *name, bool value)
1210 {
1211
1212 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1213 sizeof(uint8_t), 0));
1214 }
1215
1216 nvpair_t *
nvpair_create_number(const char * name,uint64_t value)1217 nvpair_create_number(const char *name, uint64_t value)
1218 {
1219
1220 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1221 }
1222
1223 nvpair_t *
nvpair_create_string(const char * name,const char * value)1224 nvpair_create_string(const char *name, const char *value)
1225 {
1226 nvpair_t *nvp;
1227 size_t size;
1228 char *data;
1229
1230 if (value == NULL) {
1231 ERRNO_SET(EINVAL);
1232 return (NULL);
1233 }
1234
1235 data = nv_strdup(value);
1236 if (data == NULL)
1237 return (NULL);
1238 size = strlen(value) + 1;
1239
1240 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1241 size, 0);
1242 if (nvp == NULL)
1243 nv_free(data);
1244
1245 return (nvp);
1246 }
1247
1248 nvpair_t *
nvpair_create_nvlist(const char * name,const nvlist_t * value)1249 nvpair_create_nvlist(const char *name, const nvlist_t *value)
1250 {
1251 nvlist_t *nvl;
1252 nvpair_t *nvp;
1253
1254 if (value == NULL) {
1255 ERRNO_SET(EINVAL);
1256 return (NULL);
1257 }
1258
1259 nvl = nvlist_clone(value);
1260 if (nvl == NULL)
1261 return (NULL);
1262
1263 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1264 0);
1265 if (nvp == NULL)
1266 nvlist_destroy(nvl);
1267 else
1268 nvlist_set_parent(nvl, nvp);
1269
1270 return (nvp);
1271 }
1272
1273 #ifndef _KERNEL
1274 nvpair_t *
nvpair_create_descriptor(const char * name,int value)1275 nvpair_create_descriptor(const char *name, int value)
1276 {
1277 nvpair_t *nvp;
1278
1279 value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1280 if (value < 0)
1281 return (NULL);
1282
1283 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1284 sizeof(int64_t), 0);
1285 if (nvp == NULL) {
1286 ERRNO_SAVE();
1287 close(value);
1288 ERRNO_RESTORE();
1289 }
1290
1291 return (nvp);
1292 }
1293 #endif
1294
1295 nvpair_t *
nvpair_create_binary(const char * name,const void * value,size_t size)1296 nvpair_create_binary(const char *name, const void *value, size_t size)
1297 {
1298 nvpair_t *nvp;
1299 void *data;
1300
1301 if (value == NULL || size == 0) {
1302 ERRNO_SET(EINVAL);
1303 return (NULL);
1304 }
1305
1306 data = nv_malloc(size);
1307 if (data == NULL)
1308 return (NULL);
1309 memcpy(data, value, size);
1310
1311 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1312 size, 0);
1313 if (nvp == NULL)
1314 nv_free(data);
1315
1316 return (nvp);
1317 }
1318
1319 nvpair_t *
nvpair_create_bool_array(const char * name,const bool * value,size_t nitems)1320 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1321 {
1322 nvpair_t *nvp;
1323 size_t size;
1324 void *data;
1325
1326 if (value == NULL || nitems == 0) {
1327 ERRNO_SET(EINVAL);
1328 return (NULL);
1329 }
1330
1331 size = sizeof(value[0]) * nitems;
1332 data = nv_malloc(size);
1333 if (data == NULL)
1334 return (NULL);
1335
1336 memcpy(data, value, size);
1337 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1338 size, nitems);
1339 if (nvp == NULL) {
1340 ERRNO_SAVE();
1341 nv_free(data);
1342 ERRNO_RESTORE();
1343 }
1344
1345 return (nvp);
1346 }
1347
1348 nvpair_t *
nvpair_create_number_array(const char * name,const uint64_t * value,size_t nitems)1349 nvpair_create_number_array(const char *name, const uint64_t *value,
1350 size_t nitems)
1351 {
1352 nvpair_t *nvp;
1353 size_t size;
1354 void *data;
1355
1356 if (value == NULL || nitems == 0) {
1357 ERRNO_SET(EINVAL);
1358 return (NULL);
1359 }
1360
1361 size = sizeof(value[0]) * nitems;
1362 data = nv_malloc(size);
1363 if (data == NULL)
1364 return (NULL);
1365
1366 memcpy(data, value, size);
1367 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1368 (uint64_t)(uintptr_t)data, size, nitems);
1369 if (nvp == NULL) {
1370 ERRNO_SAVE();
1371 nv_free(data);
1372 ERRNO_RESTORE();
1373 }
1374
1375 return (nvp);
1376 }
1377
1378 nvpair_t *
nvpair_create_string_array(const char * name,const char * const * value,size_t nitems)1379 nvpair_create_string_array(const char *name, const char * const *value,
1380 size_t nitems)
1381 {
1382 nvpair_t *nvp;
1383 unsigned int ii;
1384 size_t datasize, size;
1385 char **data;
1386
1387 if (value == NULL || nitems == 0) {
1388 ERRNO_SET(EINVAL);
1389 return (NULL);
1390 }
1391
1392 nvp = NULL;
1393 datasize = 0;
1394 data = nv_malloc(sizeof(value[0]) * nitems);
1395 if (data == NULL)
1396 return (NULL);
1397
1398 for (ii = 0; ii < nitems; ii++) {
1399 if (value[ii] == NULL) {
1400 ERRNO_SET(EINVAL);
1401 goto fail;
1402 }
1403
1404 size = strlen(value[ii]) + 1;
1405 datasize += size;
1406 data[ii] = nv_strdup(value[ii]);
1407 if (data[ii] == NULL)
1408 goto fail;
1409 }
1410 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1411 (uint64_t)(uintptr_t)data, datasize, nitems);
1412
1413 fail:
1414 if (nvp == NULL) {
1415 ERRNO_SAVE();
1416 for (; ii > 0; ii--)
1417 nv_free(data[ii - 1]);
1418 nv_free(data);
1419 ERRNO_RESTORE();
1420 }
1421
1422 return (nvp);
1423 }
1424
1425 nvpair_t *
nvpair_create_nvlist_array(const char * name,const nvlist_t * const * value,size_t nitems)1426 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1427 size_t nitems)
1428 {
1429 unsigned int ii;
1430 nvlist_t **nvls;
1431 nvpair_t *parent;
1432 int flags;
1433
1434 nvls = NULL;
1435
1436 if (value == NULL || nitems == 0) {
1437 ERRNO_SET(EINVAL);
1438 return (NULL);
1439 }
1440
1441 nvls = nv_malloc(sizeof(value[0]) * nitems);
1442 if (nvls == NULL)
1443 return (NULL);
1444
1445 for (ii = 0; ii < nitems; ii++) {
1446 if (value[ii] == NULL) {
1447 ERRNO_SET(EINVAL);
1448 goto fail;
1449 }
1450
1451 nvls[ii] = nvlist_clone(value[ii]);
1452 if (nvls[ii] == NULL)
1453 goto fail;
1454
1455 if (ii > 0) {
1456 nvpair_t *nvp;
1457
1458 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1459 (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1460 if (nvp == NULL) {
1461 ERRNO_SAVE();
1462 nvlist_destroy(nvls[ii]);
1463 ERRNO_RESTORE();
1464 goto fail;
1465 }
1466 nvlist_set_array_next(nvls[ii - 1], nvp);
1467 }
1468 }
1469 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1470 nvlist_set_flags(nvls[nitems - 1], flags);
1471
1472 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1473 (uint64_t)(uintptr_t)nvls, 0, nitems);
1474 if (parent == NULL)
1475 goto fail;
1476
1477 for (ii = 0; ii < nitems; ii++)
1478 nvlist_set_parent(nvls[ii], parent);
1479
1480 return (parent);
1481
1482 fail:
1483 ERRNO_SAVE();
1484 for (; ii > 0; ii--)
1485 nvlist_destroy(nvls[ii - 1]);
1486 nv_free(nvls);
1487 ERRNO_RESTORE();
1488
1489 return (NULL);
1490 }
1491
1492 #ifndef _KERNEL
1493 nvpair_t *
nvpair_create_descriptor_array(const char * name,const int * value,size_t nitems)1494 nvpair_create_descriptor_array(const char *name, const int *value,
1495 size_t nitems)
1496 {
1497 unsigned int ii;
1498 nvpair_t *nvp;
1499 int *fds;
1500
1501 if (value == NULL) {
1502 ERRNO_SET(EINVAL);
1503 return (NULL);
1504 }
1505
1506 nvp = NULL;
1507
1508 fds = nv_malloc(sizeof(value[0]) * nitems);
1509 if (fds == NULL)
1510 return (NULL);
1511 for (ii = 0; ii < nitems; ii++) {
1512 if (value[ii] == -1) {
1513 fds[ii] = -1;
1514 } else {
1515 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1516 if (fds[ii] == -1)
1517 goto fail;
1518 }
1519 }
1520
1521 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1522 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1523
1524 fail:
1525 if (nvp == NULL) {
1526 ERRNO_SAVE();
1527 for (; ii > 0; ii--) {
1528 if (fds[ii - 1] != -1)
1529 close(fds[ii - 1]);
1530 }
1531 nv_free(fds);
1532 ERRNO_RESTORE();
1533 }
1534
1535 return (nvp);
1536 }
1537 #endif
1538
1539 nvpair_t *
nvpair_move_string(const char * name,char * value)1540 nvpair_move_string(const char *name, char *value)
1541 {
1542 nvpair_t *nvp;
1543
1544 if (value == NULL) {
1545 ERRNO_SET(EINVAL);
1546 return (NULL);
1547 }
1548
1549 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1550 strlen(value) + 1, 0);
1551 if (nvp == NULL) {
1552 ERRNO_SAVE();
1553 nv_free(value);
1554 ERRNO_RESTORE();
1555 }
1556
1557 return (nvp);
1558 }
1559
1560 nvpair_t *
nvpair_move_nvlist(const char * name,nvlist_t * value)1561 nvpair_move_nvlist(const char *name, nvlist_t *value)
1562 {
1563 nvpair_t *nvp;
1564
1565 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1566 ERRNO_SET(EINVAL);
1567 return (NULL);
1568 }
1569
1570 if (nvlist_error(value) != 0) {
1571 ERRNO_SET(nvlist_error(value));
1572 nvlist_destroy(value);
1573 return (NULL);
1574 }
1575
1576 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1577 0, 0);
1578 if (nvp == NULL)
1579 nvlist_destroy(value);
1580 else
1581 nvlist_set_parent(value, nvp);
1582
1583 return (nvp);
1584 }
1585
1586 #ifndef _KERNEL
1587 nvpair_t *
nvpair_move_descriptor(const char * name,int value)1588 nvpair_move_descriptor(const char *name, int value)
1589 {
1590 nvpair_t *nvp;
1591
1592 if (value < 0 || !fd_is_valid(value)) {
1593 ERRNO_SET(EBADF);
1594 return (NULL);
1595 }
1596
1597 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1598 sizeof(int64_t), 0);
1599 if (nvp == NULL) {
1600 ERRNO_SAVE();
1601 close(value);
1602 ERRNO_RESTORE();
1603 }
1604
1605 return (nvp);
1606 }
1607 #endif
1608
1609 nvpair_t *
nvpair_move_binary(const char * name,void * value,size_t size)1610 nvpair_move_binary(const char *name, void *value, size_t size)
1611 {
1612 nvpair_t *nvp;
1613
1614 if (value == NULL || size == 0) {
1615 ERRNO_SET(EINVAL);
1616 return (NULL);
1617 }
1618
1619 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1620 size, 0);
1621 if (nvp == NULL) {
1622 ERRNO_SAVE();
1623 nv_free(value);
1624 ERRNO_RESTORE();
1625 }
1626
1627 return (nvp);
1628 }
1629
1630 nvpair_t *
nvpair_move_bool_array(const char * name,bool * value,size_t nitems)1631 nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1632 {
1633 nvpair_t *nvp;
1634
1635 if (value == NULL || nitems == 0) {
1636 ERRNO_SET(EINVAL);
1637 return (NULL);
1638 }
1639
1640 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1641 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1642 if (nvp == NULL) {
1643 ERRNO_SAVE();
1644 nv_free(value);
1645 ERRNO_RESTORE();
1646 }
1647
1648 return (nvp);
1649 }
1650
1651 nvpair_t *
nvpair_move_string_array(const char * name,char ** value,size_t nitems)1652 nvpair_move_string_array(const char *name, char **value, size_t nitems)
1653 {
1654 nvpair_t *nvp;
1655 size_t i, size;
1656
1657 if (value == NULL || nitems == 0) {
1658 ERRNO_SET(EINVAL);
1659 return (NULL);
1660 }
1661
1662 size = 0;
1663 for (i = 0; i < nitems; i++) {
1664 if (value[i] == NULL) {
1665 ERRNO_SET(EINVAL);
1666 return (NULL);
1667 }
1668
1669 size += strlen(value[i]) + 1;
1670 }
1671
1672 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1673 (uint64_t)(uintptr_t)value, size, nitems);
1674 if (nvp == NULL) {
1675 ERRNO_SAVE();
1676 for (i = 0; i < nitems; i++)
1677 nv_free(value[i]);
1678 nv_free(value);
1679 ERRNO_RESTORE();
1680 }
1681
1682 return (nvp);
1683 }
1684
1685 nvpair_t *
nvpair_move_number_array(const char * name,uint64_t * value,size_t nitems)1686 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1687 {
1688 nvpair_t *nvp;
1689
1690 if (value == NULL || nitems == 0) {
1691 ERRNO_SET(EINVAL);
1692 return (NULL);
1693 }
1694
1695 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1696 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1697 if (nvp == NULL) {
1698 ERRNO_SAVE();
1699 nv_free(value);
1700 ERRNO_RESTORE();
1701 }
1702
1703 return (nvp);
1704 }
1705
1706 nvpair_t *
nvpair_move_nvlist_array(const char * name,nvlist_t ** value,size_t nitems)1707 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1708 {
1709 nvpair_t *parent;
1710 unsigned int ii;
1711 int flags;
1712
1713 if (value == NULL || nitems == 0) {
1714 ERRNO_SET(EINVAL);
1715 return (NULL);
1716 }
1717
1718 for (ii = 0; ii < nitems; ii++) {
1719 if (value == NULL || nvlist_error(value[ii]) != 0 ||
1720 nvlist_get_pararr(value[ii], NULL) != NULL) {
1721 ERRNO_SET(EINVAL);
1722 goto fail;
1723 }
1724 if (ii > 0) {
1725 nvpair_t *nvp;
1726
1727 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1728 (uint64_t)(uintptr_t)value[ii], 0, 0);
1729 if (nvp == NULL)
1730 goto fail;
1731 nvlist_set_array_next(value[ii - 1], nvp);
1732 }
1733 }
1734 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1735 nvlist_set_flags(value[nitems - 1], flags);
1736
1737 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1738 (uint64_t)(uintptr_t)value, 0, nitems);
1739 if (parent == NULL)
1740 goto fail;
1741
1742 for (ii = 0; ii < nitems; ii++)
1743 nvlist_set_parent(value[ii], parent);
1744
1745 return (parent);
1746 fail:
1747 ERRNO_SAVE();
1748 for (ii = 0; ii < nitems; ii++) {
1749 if (value[ii] != NULL &&
1750 nvlist_get_pararr(value[ii], NULL) != NULL) {
1751 nvlist_destroy(value[ii]);
1752 }
1753 }
1754 nv_free(value);
1755 ERRNO_RESTORE();
1756
1757 return (NULL);
1758 }
1759
1760 #ifndef _KERNEL
1761 nvpair_t *
nvpair_move_descriptor_array(const char * name,int * value,size_t nitems)1762 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1763 {
1764 nvpair_t *nvp;
1765 size_t i;
1766
1767 if (value == NULL || nitems == 0) {
1768 ERRNO_SET(EINVAL);
1769 return (NULL);
1770 }
1771
1772 for (i = 0; i < nitems; i++) {
1773 if (value[i] != -1 && !fd_is_valid(value[i])) {
1774 ERRNO_SET(EBADF);
1775 goto fail;
1776 }
1777 }
1778
1779 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1780 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1781 if (nvp == NULL)
1782 goto fail;
1783
1784 return (nvp);
1785 fail:
1786 ERRNO_SAVE();
1787 for (i = 0; i < nitems; i++) {
1788 if (fd_is_valid(value[i]))
1789 close(value[i]);
1790 }
1791 nv_free(value);
1792 ERRNO_RESTORE();
1793
1794 return (NULL);
1795 }
1796 #endif
1797
1798 bool
nvpair_get_bool(const nvpair_t * nvp)1799 nvpair_get_bool(const nvpair_t *nvp)
1800 {
1801
1802 NVPAIR_ASSERT(nvp);
1803
1804 return (nvp->nvp_data == 1);
1805 }
1806
1807 uint64_t
nvpair_get_number(const nvpair_t * nvp)1808 nvpair_get_number(const nvpair_t *nvp)
1809 {
1810
1811 NVPAIR_ASSERT(nvp);
1812
1813 return (nvp->nvp_data);
1814 }
1815
1816 const char *
nvpair_get_string(const nvpair_t * nvp)1817 nvpair_get_string(const nvpair_t *nvp)
1818 {
1819
1820 NVPAIR_ASSERT(nvp);
1821 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1822
1823 return ((const char *)(intptr_t)nvp->nvp_data);
1824 }
1825
1826 const nvlist_t *
nvpair_get_nvlist(const nvpair_t * nvp)1827 nvpair_get_nvlist(const nvpair_t *nvp)
1828 {
1829
1830 NVPAIR_ASSERT(nvp);
1831 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1832
1833 return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1834 }
1835
1836 #ifndef _KERNEL
1837 int
nvpair_get_descriptor(const nvpair_t * nvp)1838 nvpair_get_descriptor(const nvpair_t *nvp)
1839 {
1840
1841 NVPAIR_ASSERT(nvp);
1842 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1843
1844 return ((int)nvp->nvp_data);
1845 }
1846 #endif
1847
1848 const void *
nvpair_get_binary(const nvpair_t * nvp,size_t * sizep)1849 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1850 {
1851
1852 NVPAIR_ASSERT(nvp);
1853 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1854
1855 if (sizep != NULL)
1856 *sizep = nvp->nvp_datasize;
1857
1858 return ((const void *)(intptr_t)nvp->nvp_data);
1859 }
1860
1861 const bool *
nvpair_get_bool_array(const nvpair_t * nvp,size_t * nitems)1862 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1863 {
1864
1865 NVPAIR_ASSERT(nvp);
1866 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1867
1868 if (nitems != NULL)
1869 *nitems = nvp->nvp_nitems;
1870
1871 return ((const bool *)(intptr_t)nvp->nvp_data);
1872 }
1873
1874 const uint64_t *
nvpair_get_number_array(const nvpair_t * nvp,size_t * nitems)1875 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1876 {
1877
1878 NVPAIR_ASSERT(nvp);
1879 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1880
1881 if (nitems != NULL)
1882 *nitems = nvp->nvp_nitems;
1883
1884 return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1885 }
1886
1887 const char * const *
nvpair_get_string_array(const nvpair_t * nvp,size_t * nitems)1888 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1889 {
1890
1891 NVPAIR_ASSERT(nvp);
1892 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1893
1894 if (nitems != NULL)
1895 *nitems = nvp->nvp_nitems;
1896
1897 return ((const char * const *)(intptr_t)nvp->nvp_data);
1898 }
1899
1900 const nvlist_t * const *
nvpair_get_nvlist_array(const nvpair_t * nvp,size_t * nitems)1901 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1902 {
1903
1904 NVPAIR_ASSERT(nvp);
1905 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1906
1907 if (nitems != NULL)
1908 *nitems = nvp->nvp_nitems;
1909
1910 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1911 }
1912
1913 #ifndef _KERNEL
1914 const int *
nvpair_get_descriptor_array(const nvpair_t * nvp,size_t * nitems)1915 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1916 {
1917
1918 NVPAIR_ASSERT(nvp);
1919 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1920
1921 if (nitems != NULL)
1922 *nitems = nvp->nvp_nitems;
1923
1924 return ((const int *)(intptr_t)nvp->nvp_data);
1925 }
1926 #endif
1927
1928 int
nvpair_append_bool_array(nvpair_t * nvp,const bool value)1929 nvpair_append_bool_array(nvpair_t *nvp, const bool value)
1930 {
1931
1932 NVPAIR_ASSERT(nvp);
1933 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1934 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1935 }
1936
1937 int
nvpair_append_number_array(nvpair_t * nvp,const uint64_t value)1938 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
1939 {
1940
1941 NVPAIR_ASSERT(nvp);
1942 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1943 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1944 }
1945
1946 int
nvpair_append_string_array(nvpair_t * nvp,const char * value)1947 nvpair_append_string_array(nvpair_t *nvp, const char *value)
1948 {
1949 char *str;
1950
1951 NVPAIR_ASSERT(nvp);
1952 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1953 if (value == NULL) {
1954 ERRNO_SET(EINVAL);
1955 return (-1);
1956 }
1957 str = nv_strdup(value);
1958 if (str == NULL) {
1959 return (-1);
1960 }
1961 if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
1962 nv_free(str);
1963 return (-1);
1964 }
1965 return (0);
1966 }
1967
1968 int
nvpair_append_nvlist_array(nvpair_t * nvp,const nvlist_t * value)1969 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
1970 {
1971 nvpair_t *tmpnvp;
1972 nvlist_t *nvl, *prev;
1973 int flags;
1974
1975 NVPAIR_ASSERT(nvp);
1976 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1977 if (value == NULL || nvlist_error(value) != 0 ||
1978 nvlist_get_pararr(value, NULL) != NULL) {
1979 ERRNO_SET(EINVAL);
1980 return (-1);
1981 }
1982 nvl = nvlist_clone(value);
1983 if (nvl == NULL) {
1984 return (-1);
1985 }
1986 flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
1987 nvlist_set_flags(nvl, flags);
1988
1989 tmpnvp = NULL;
1990 prev = NULL;
1991 if (nvp->nvp_nitems > 0) {
1992 nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
1993
1994 prev = nvls[nvp->nvp_nitems - 1];
1995 PJDLOG_ASSERT(prev != NULL);
1996
1997 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1998 (uint64_t)(uintptr_t)nvl, 0, 0);
1999 if (tmpnvp == NULL) {
2000 goto fail;
2001 }
2002 }
2003 if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
2004 goto fail;
2005 }
2006 if (tmpnvp) {
2007 NVPAIR_ASSERT(tmpnvp);
2008 nvlist_set_array_next(prev, tmpnvp);
2009 }
2010 nvlist_set_parent(nvl, nvp);
2011 return (0);
2012 fail:
2013 if (tmpnvp) {
2014 nvpair_free(tmpnvp);
2015 }
2016 nvlist_destroy(nvl);
2017 return (-1);
2018 }
2019
2020 #ifndef _KERNEL
2021 int
nvpair_append_descriptor_array(nvpair_t * nvp,const int value)2022 nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
2023 {
2024 int fd;
2025
2026 NVPAIR_ASSERT(nvp);
2027 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
2028 fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
2029 if (fd == -1) {
2030 return (-1);
2031 }
2032 if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
2033 close(fd);
2034 return (-1);
2035 }
2036 return (0);
2037 }
2038 #endif
2039
2040 void
nvpair_free(nvpair_t * nvp)2041 nvpair_free(nvpair_t *nvp)
2042 {
2043 size_t i;
2044
2045 NVPAIR_ASSERT(nvp);
2046 PJDLOG_ASSERT(nvp->nvp_list == NULL);
2047
2048 nvp->nvp_magic = 0;
2049 switch (nvp->nvp_type) {
2050 #ifndef _KERNEL
2051 case NV_TYPE_DESCRIPTOR:
2052 close((int)nvp->nvp_data);
2053 break;
2054 case NV_TYPE_DESCRIPTOR_ARRAY:
2055 for (i = 0; i < nvp->nvp_nitems; i++)
2056 close(((int *)(intptr_t)nvp->nvp_data)[i]);
2057 nv_free((int *)(intptr_t)nvp->nvp_data);
2058 break;
2059 #endif
2060 case NV_TYPE_NVLIST:
2061 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
2062 break;
2063 case NV_TYPE_STRING:
2064 nv_free((char *)(intptr_t)nvp->nvp_data);
2065 break;
2066 case NV_TYPE_BINARY:
2067 nv_free((void *)(intptr_t)nvp->nvp_data);
2068 break;
2069 case NV_TYPE_NVLIST_ARRAY:
2070 for (i = 0; i < nvp->nvp_nitems; i++) {
2071 nvlist_destroy(
2072 ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
2073 }
2074 nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
2075 break;
2076 case NV_TYPE_NUMBER_ARRAY:
2077 nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
2078 break;
2079 case NV_TYPE_BOOL_ARRAY:
2080 nv_free((bool *)(intptr_t)nvp->nvp_data);
2081 break;
2082 case NV_TYPE_STRING_ARRAY:
2083 for (i = 0; i < nvp->nvp_nitems; i++)
2084 nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
2085 nv_free((char **)(intptr_t)nvp->nvp_data);
2086 break;
2087 }
2088 nv_free(nvp);
2089 }
2090
2091 void
nvpair_free_structure(nvpair_t * nvp)2092 nvpair_free_structure(nvpair_t *nvp)
2093 {
2094
2095 NVPAIR_ASSERT(nvp);
2096 PJDLOG_ASSERT(nvp->nvp_list == NULL);
2097
2098 nvp->nvp_magic = 0;
2099 nv_free(nvp);
2100 }
2101
2102 const char *
nvpair_type_string(int type)2103 nvpair_type_string(int type)
2104 {
2105
2106 switch (type) {
2107 case NV_TYPE_NULL:
2108 return ("NULL");
2109 case NV_TYPE_BOOL:
2110 return ("BOOL");
2111 case NV_TYPE_NUMBER:
2112 return ("NUMBER");
2113 case NV_TYPE_STRING:
2114 return ("STRING");
2115 case NV_TYPE_NVLIST:
2116 return ("NVLIST");
2117 case NV_TYPE_DESCRIPTOR:
2118 return ("DESCRIPTOR");
2119 case NV_TYPE_BINARY:
2120 return ("BINARY");
2121 case NV_TYPE_BOOL_ARRAY:
2122 return ("BOOL ARRAY");
2123 case NV_TYPE_NUMBER_ARRAY:
2124 return ("NUMBER ARRAY");
2125 case NV_TYPE_STRING_ARRAY:
2126 return ("STRING ARRAY");
2127 case NV_TYPE_NVLIST_ARRAY:
2128 return ("NVLIST ARRAY");
2129 case NV_TYPE_DESCRIPTOR_ARRAY:
2130 return ("DESCRIPTOR ARRAY");
2131 default:
2132 return ("<UNKNOWN>");
2133 }
2134 }
2135
2136