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 if (nvp == NULL)
1198 nv_free(str);
1199 return (nvp);
1200 }
1201
1202 nvpair_t *
nvpair_create_null(const char * name)1203 nvpair_create_null(const char *name)
1204 {
1205
1206 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1207 }
1208
1209 nvpair_t *
nvpair_create_bool(const char * name,bool value)1210 nvpair_create_bool(const char *name, bool value)
1211 {
1212
1213 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1214 sizeof(uint8_t), 0));
1215 }
1216
1217 nvpair_t *
nvpair_create_number(const char * name,uint64_t value)1218 nvpair_create_number(const char *name, uint64_t value)
1219 {
1220
1221 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1222 }
1223
1224 nvpair_t *
nvpair_create_string(const char * name,const char * value)1225 nvpair_create_string(const char *name, const char *value)
1226 {
1227 nvpair_t *nvp;
1228 size_t size;
1229 char *data;
1230
1231 if (value == NULL) {
1232 ERRNO_SET(EINVAL);
1233 return (NULL);
1234 }
1235
1236 data = nv_strdup(value);
1237 if (data == NULL)
1238 return (NULL);
1239 size = strlen(value) + 1;
1240
1241 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1242 size, 0);
1243 if (nvp == NULL)
1244 nv_free(data);
1245
1246 return (nvp);
1247 }
1248
1249 nvpair_t *
nvpair_create_nvlist(const char * name,const nvlist_t * value)1250 nvpair_create_nvlist(const char *name, const nvlist_t *value)
1251 {
1252 nvlist_t *nvl;
1253 nvpair_t *nvp;
1254
1255 if (value == NULL) {
1256 ERRNO_SET(EINVAL);
1257 return (NULL);
1258 }
1259
1260 nvl = nvlist_clone(value);
1261 if (nvl == NULL)
1262 return (NULL);
1263
1264 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1265 0);
1266 if (nvp == NULL)
1267 nvlist_destroy(nvl);
1268 else
1269 nvlist_set_parent(nvl, nvp);
1270
1271 return (nvp);
1272 }
1273
1274 #ifndef _KERNEL
1275 nvpair_t *
nvpair_create_descriptor(const char * name,int value)1276 nvpair_create_descriptor(const char *name, int value)
1277 {
1278 nvpair_t *nvp;
1279
1280 value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1281 if (value < 0)
1282 return (NULL);
1283
1284 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1285 sizeof(int64_t), 0);
1286 if (nvp == NULL) {
1287 ERRNO_SAVE();
1288 close(value);
1289 ERRNO_RESTORE();
1290 }
1291
1292 return (nvp);
1293 }
1294 #endif
1295
1296 nvpair_t *
nvpair_create_binary(const char * name,const void * value,size_t size)1297 nvpair_create_binary(const char *name, const void *value, size_t size)
1298 {
1299 nvpair_t *nvp;
1300 void *data;
1301
1302 if (value == NULL || size == 0) {
1303 ERRNO_SET(EINVAL);
1304 return (NULL);
1305 }
1306
1307 data = nv_malloc(size);
1308 if (data == NULL)
1309 return (NULL);
1310 memcpy(data, value, size);
1311
1312 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1313 size, 0);
1314 if (nvp == NULL)
1315 nv_free(data);
1316
1317 return (nvp);
1318 }
1319
1320 nvpair_t *
nvpair_create_bool_array(const char * name,const bool * value,size_t nitems)1321 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1322 {
1323 nvpair_t *nvp;
1324 size_t size;
1325 void *data;
1326
1327 if (value == NULL || nitems == 0) {
1328 ERRNO_SET(EINVAL);
1329 return (NULL);
1330 }
1331
1332 size = sizeof(value[0]) * nitems;
1333 data = nv_malloc(size);
1334 if (data == NULL)
1335 return (NULL);
1336
1337 memcpy(data, value, size);
1338 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1339 size, nitems);
1340 if (nvp == NULL) {
1341 ERRNO_SAVE();
1342 nv_free(data);
1343 ERRNO_RESTORE();
1344 }
1345
1346 return (nvp);
1347 }
1348
1349 nvpair_t *
nvpair_create_number_array(const char * name,const uint64_t * value,size_t nitems)1350 nvpair_create_number_array(const char *name, const uint64_t *value,
1351 size_t nitems)
1352 {
1353 nvpair_t *nvp;
1354 size_t size;
1355 void *data;
1356
1357 if (value == NULL || nitems == 0) {
1358 ERRNO_SET(EINVAL);
1359 return (NULL);
1360 }
1361
1362 size = sizeof(value[0]) * nitems;
1363 data = nv_malloc(size);
1364 if (data == NULL)
1365 return (NULL);
1366
1367 memcpy(data, value, size);
1368 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1369 (uint64_t)(uintptr_t)data, size, nitems);
1370 if (nvp == NULL) {
1371 ERRNO_SAVE();
1372 nv_free(data);
1373 ERRNO_RESTORE();
1374 }
1375
1376 return (nvp);
1377 }
1378
1379 nvpair_t *
nvpair_create_string_array(const char * name,const char * const * value,size_t nitems)1380 nvpair_create_string_array(const char *name, const char * const *value,
1381 size_t nitems)
1382 {
1383 nvpair_t *nvp;
1384 unsigned int ii;
1385 size_t datasize, size;
1386 char **data;
1387
1388 if (value == NULL || nitems == 0) {
1389 ERRNO_SET(EINVAL);
1390 return (NULL);
1391 }
1392
1393 nvp = NULL;
1394 datasize = 0;
1395 data = nv_malloc(sizeof(value[0]) * nitems);
1396 if (data == NULL)
1397 return (NULL);
1398
1399 for (ii = 0; ii < nitems; ii++) {
1400 if (value[ii] == NULL) {
1401 ERRNO_SET(EINVAL);
1402 goto fail;
1403 }
1404
1405 size = strlen(value[ii]) + 1;
1406 datasize += size;
1407 data[ii] = nv_strdup(value[ii]);
1408 if (data[ii] == NULL)
1409 goto fail;
1410 }
1411 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1412 (uint64_t)(uintptr_t)data, datasize, nitems);
1413
1414 fail:
1415 if (nvp == NULL) {
1416 ERRNO_SAVE();
1417 for (; ii > 0; ii--)
1418 nv_free(data[ii - 1]);
1419 nv_free(data);
1420 ERRNO_RESTORE();
1421 }
1422
1423 return (nvp);
1424 }
1425
1426 nvpair_t *
nvpair_create_nvlist_array(const char * name,const nvlist_t * const * value,size_t nitems)1427 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1428 size_t nitems)
1429 {
1430 unsigned int ii;
1431 nvlist_t **nvls;
1432 nvpair_t *parent;
1433 int flags;
1434
1435 nvls = NULL;
1436
1437 if (value == NULL || nitems == 0) {
1438 ERRNO_SET(EINVAL);
1439 return (NULL);
1440 }
1441
1442 nvls = nv_malloc(sizeof(value[0]) * nitems);
1443 if (nvls == NULL)
1444 return (NULL);
1445
1446 for (ii = 0; ii < nitems; ii++) {
1447 if (value[ii] == NULL) {
1448 ERRNO_SET(EINVAL);
1449 goto fail;
1450 }
1451
1452 nvls[ii] = nvlist_clone(value[ii]);
1453 if (nvls[ii] == NULL)
1454 goto fail;
1455
1456 if (ii > 0) {
1457 nvpair_t *nvp;
1458
1459 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1460 (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1461 if (nvp == NULL) {
1462 ERRNO_SAVE();
1463 nvlist_destroy(nvls[ii]);
1464 ERRNO_RESTORE();
1465 goto fail;
1466 }
1467 nvlist_set_array_next(nvls[ii - 1], nvp);
1468 }
1469 }
1470 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1471 nvlist_set_flags(nvls[nitems - 1], flags);
1472
1473 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1474 (uint64_t)(uintptr_t)nvls, 0, nitems);
1475 if (parent == NULL)
1476 goto fail;
1477
1478 for (ii = 0; ii < nitems; ii++)
1479 nvlist_set_parent(nvls[ii], parent);
1480
1481 return (parent);
1482
1483 fail:
1484 ERRNO_SAVE();
1485 for (; ii > 0; ii--)
1486 nvlist_destroy(nvls[ii - 1]);
1487 nv_free(nvls);
1488 ERRNO_RESTORE();
1489
1490 return (NULL);
1491 }
1492
1493 #ifndef _KERNEL
1494 nvpair_t *
nvpair_create_descriptor_array(const char * name,const int * value,size_t nitems)1495 nvpair_create_descriptor_array(const char *name, const int *value,
1496 size_t nitems)
1497 {
1498 unsigned int ii;
1499 nvpair_t *nvp;
1500 int *fds;
1501
1502 if (value == NULL) {
1503 ERRNO_SET(EINVAL);
1504 return (NULL);
1505 }
1506
1507 nvp = NULL;
1508
1509 fds = nv_malloc(sizeof(value[0]) * nitems);
1510 if (fds == NULL)
1511 return (NULL);
1512 for (ii = 0; ii < nitems; ii++) {
1513 if (value[ii] == -1) {
1514 fds[ii] = -1;
1515 } else {
1516 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1517 if (fds[ii] == -1)
1518 goto fail;
1519 }
1520 }
1521
1522 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1523 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1524
1525 fail:
1526 if (nvp == NULL) {
1527 ERRNO_SAVE();
1528 for (; ii > 0; ii--) {
1529 if (fds[ii - 1] != -1)
1530 close(fds[ii - 1]);
1531 }
1532 nv_free(fds);
1533 ERRNO_RESTORE();
1534 }
1535
1536 return (nvp);
1537 }
1538 #endif
1539
1540 nvpair_t *
nvpair_move_string(const char * name,char * value)1541 nvpair_move_string(const char *name, char *value)
1542 {
1543 nvpair_t *nvp;
1544
1545 if (value == NULL) {
1546 ERRNO_SET(EINVAL);
1547 return (NULL);
1548 }
1549
1550 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1551 strlen(value) + 1, 0);
1552 if (nvp == NULL) {
1553 ERRNO_SAVE();
1554 nv_free(value);
1555 ERRNO_RESTORE();
1556 }
1557
1558 return (nvp);
1559 }
1560
1561 nvpair_t *
nvpair_move_nvlist(const char * name,nvlist_t * value)1562 nvpair_move_nvlist(const char *name, nvlist_t *value)
1563 {
1564 nvpair_t *nvp;
1565
1566 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1567 ERRNO_SET(EINVAL);
1568 return (NULL);
1569 }
1570
1571 if (nvlist_error(value) != 0) {
1572 ERRNO_SET(nvlist_error(value));
1573 nvlist_destroy(value);
1574 return (NULL);
1575 }
1576
1577 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1578 0, 0);
1579 if (nvp == NULL)
1580 nvlist_destroy(value);
1581 else
1582 nvlist_set_parent(value, nvp);
1583
1584 return (nvp);
1585 }
1586
1587 #ifndef _KERNEL
1588 nvpair_t *
nvpair_move_descriptor(const char * name,int value)1589 nvpair_move_descriptor(const char *name, int value)
1590 {
1591 nvpair_t *nvp;
1592
1593 if (value < 0 || !fd_is_valid(value)) {
1594 ERRNO_SET(EBADF);
1595 return (NULL);
1596 }
1597
1598 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1599 sizeof(int64_t), 0);
1600 if (nvp == NULL) {
1601 ERRNO_SAVE();
1602 close(value);
1603 ERRNO_RESTORE();
1604 }
1605
1606 return (nvp);
1607 }
1608 #endif
1609
1610 nvpair_t *
nvpair_move_binary(const char * name,void * value,size_t size)1611 nvpair_move_binary(const char *name, void *value, size_t size)
1612 {
1613 nvpair_t *nvp;
1614
1615 if (value == NULL || size == 0) {
1616 ERRNO_SET(EINVAL);
1617 return (NULL);
1618 }
1619
1620 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1621 size, 0);
1622 if (nvp == NULL) {
1623 ERRNO_SAVE();
1624 nv_free(value);
1625 ERRNO_RESTORE();
1626 }
1627
1628 return (nvp);
1629 }
1630
1631 nvpair_t *
nvpair_move_bool_array(const char * name,bool * value,size_t nitems)1632 nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1633 {
1634 nvpair_t *nvp;
1635
1636 if (value == NULL || nitems == 0) {
1637 ERRNO_SET(EINVAL);
1638 return (NULL);
1639 }
1640
1641 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1642 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1643 if (nvp == NULL) {
1644 ERRNO_SAVE();
1645 nv_free(value);
1646 ERRNO_RESTORE();
1647 }
1648
1649 return (nvp);
1650 }
1651
1652 nvpair_t *
nvpair_move_string_array(const char * name,char ** value,size_t nitems)1653 nvpair_move_string_array(const char *name, char **value, size_t nitems)
1654 {
1655 nvpair_t *nvp;
1656 size_t i, size;
1657
1658 if (value == NULL || nitems == 0) {
1659 ERRNO_SET(EINVAL);
1660 return (NULL);
1661 }
1662
1663 size = 0;
1664 for (i = 0; i < nitems; i++) {
1665 if (value[i] == NULL) {
1666 ERRNO_SET(EINVAL);
1667 return (NULL);
1668 }
1669
1670 size += strlen(value[i]) + 1;
1671 }
1672
1673 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1674 (uint64_t)(uintptr_t)value, size, nitems);
1675 if (nvp == NULL) {
1676 ERRNO_SAVE();
1677 for (i = 0; i < nitems; i++)
1678 nv_free(value[i]);
1679 nv_free(value);
1680 ERRNO_RESTORE();
1681 }
1682
1683 return (nvp);
1684 }
1685
1686 nvpair_t *
nvpair_move_number_array(const char * name,uint64_t * value,size_t nitems)1687 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1688 {
1689 nvpair_t *nvp;
1690
1691 if (value == NULL || nitems == 0) {
1692 ERRNO_SET(EINVAL);
1693 return (NULL);
1694 }
1695
1696 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1697 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1698 if (nvp == NULL) {
1699 ERRNO_SAVE();
1700 nv_free(value);
1701 ERRNO_RESTORE();
1702 }
1703
1704 return (nvp);
1705 }
1706
1707 nvpair_t *
nvpair_move_nvlist_array(const char * name,nvlist_t ** value,size_t nitems)1708 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1709 {
1710 nvpair_t *parent;
1711 unsigned int ii;
1712 int flags;
1713
1714 if (value == NULL || nitems == 0) {
1715 ERRNO_SET(EINVAL);
1716 return (NULL);
1717 }
1718
1719 for (ii = 0; ii < nitems; ii++) {
1720 if (value == NULL || nvlist_error(value[ii]) != 0 ||
1721 nvlist_get_pararr(value[ii], NULL) != NULL) {
1722 ERRNO_SET(EINVAL);
1723 goto fail;
1724 }
1725 if (ii > 0) {
1726 nvpair_t *nvp;
1727
1728 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1729 (uint64_t)(uintptr_t)value[ii], 0, 0);
1730 if (nvp == NULL)
1731 goto fail;
1732 nvlist_set_array_next(value[ii - 1], nvp);
1733 }
1734 }
1735 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1736 nvlist_set_flags(value[nitems - 1], flags);
1737
1738 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1739 (uint64_t)(uintptr_t)value, 0, nitems);
1740 if (parent == NULL)
1741 goto fail;
1742
1743 for (ii = 0; ii < nitems; ii++)
1744 nvlist_set_parent(value[ii], parent);
1745
1746 return (parent);
1747 fail:
1748 ERRNO_SAVE();
1749 for (ii = 0; ii < nitems; ii++) {
1750 if (value[ii] != NULL &&
1751 nvlist_get_pararr(value[ii], NULL) != NULL) {
1752 nvlist_destroy(value[ii]);
1753 }
1754 }
1755 nv_free(value);
1756 ERRNO_RESTORE();
1757
1758 return (NULL);
1759 }
1760
1761 #ifndef _KERNEL
1762 nvpair_t *
nvpair_move_descriptor_array(const char * name,int * value,size_t nitems)1763 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1764 {
1765 nvpair_t *nvp;
1766 size_t i;
1767
1768 if (value == NULL || nitems == 0) {
1769 ERRNO_SET(EINVAL);
1770 return (NULL);
1771 }
1772
1773 for (i = 0; i < nitems; i++) {
1774 if (value[i] != -1 && !fd_is_valid(value[i])) {
1775 ERRNO_SET(EBADF);
1776 goto fail;
1777 }
1778 }
1779
1780 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1781 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1782 if (nvp == NULL)
1783 goto fail;
1784
1785 return (nvp);
1786 fail:
1787 ERRNO_SAVE();
1788 for (i = 0; i < nitems; i++) {
1789 if (fd_is_valid(value[i]))
1790 close(value[i]);
1791 }
1792 nv_free(value);
1793 ERRNO_RESTORE();
1794
1795 return (NULL);
1796 }
1797 #endif
1798
1799 bool
nvpair_get_bool(const nvpair_t * nvp)1800 nvpair_get_bool(const nvpair_t *nvp)
1801 {
1802
1803 NVPAIR_ASSERT(nvp);
1804
1805 return (nvp->nvp_data == 1);
1806 }
1807
1808 uint64_t
nvpair_get_number(const nvpair_t * nvp)1809 nvpair_get_number(const nvpair_t *nvp)
1810 {
1811
1812 NVPAIR_ASSERT(nvp);
1813
1814 return (nvp->nvp_data);
1815 }
1816
1817 const char *
nvpair_get_string(const nvpair_t * nvp)1818 nvpair_get_string(const nvpair_t *nvp)
1819 {
1820
1821 NVPAIR_ASSERT(nvp);
1822 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1823
1824 return ((const char *)(intptr_t)nvp->nvp_data);
1825 }
1826
1827 const nvlist_t *
nvpair_get_nvlist(const nvpair_t * nvp)1828 nvpair_get_nvlist(const nvpair_t *nvp)
1829 {
1830
1831 NVPAIR_ASSERT(nvp);
1832 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1833
1834 return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1835 }
1836
1837 #ifndef _KERNEL
1838 int
nvpair_get_descriptor(const nvpair_t * nvp)1839 nvpair_get_descriptor(const nvpair_t *nvp)
1840 {
1841
1842 NVPAIR_ASSERT(nvp);
1843 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1844
1845 return ((int)nvp->nvp_data);
1846 }
1847 #endif
1848
1849 const void *
nvpair_get_binary(const nvpair_t * nvp,size_t * sizep)1850 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1851 {
1852
1853 NVPAIR_ASSERT(nvp);
1854 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1855
1856 if (sizep != NULL)
1857 *sizep = nvp->nvp_datasize;
1858
1859 return ((const void *)(intptr_t)nvp->nvp_data);
1860 }
1861
1862 const bool *
nvpair_get_bool_array(const nvpair_t * nvp,size_t * nitems)1863 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1864 {
1865
1866 NVPAIR_ASSERT(nvp);
1867 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1868
1869 if (nitems != NULL)
1870 *nitems = nvp->nvp_nitems;
1871
1872 return ((const bool *)(intptr_t)nvp->nvp_data);
1873 }
1874
1875 const uint64_t *
nvpair_get_number_array(const nvpair_t * nvp,size_t * nitems)1876 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1877 {
1878
1879 NVPAIR_ASSERT(nvp);
1880 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1881
1882 if (nitems != NULL)
1883 *nitems = nvp->nvp_nitems;
1884
1885 return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1886 }
1887
1888 const char * const *
nvpair_get_string_array(const nvpair_t * nvp,size_t * nitems)1889 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1890 {
1891
1892 NVPAIR_ASSERT(nvp);
1893 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1894
1895 if (nitems != NULL)
1896 *nitems = nvp->nvp_nitems;
1897
1898 return ((const char * const *)(intptr_t)nvp->nvp_data);
1899 }
1900
1901 const nvlist_t * const *
nvpair_get_nvlist_array(const nvpair_t * nvp,size_t * nitems)1902 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1903 {
1904
1905 NVPAIR_ASSERT(nvp);
1906 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1907
1908 if (nitems != NULL)
1909 *nitems = nvp->nvp_nitems;
1910
1911 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1912 }
1913
1914 #ifndef _KERNEL
1915 const int *
nvpair_get_descriptor_array(const nvpair_t * nvp,size_t * nitems)1916 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1917 {
1918
1919 NVPAIR_ASSERT(nvp);
1920 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1921
1922 if (nitems != NULL)
1923 *nitems = nvp->nvp_nitems;
1924
1925 return ((const int *)(intptr_t)nvp->nvp_data);
1926 }
1927 #endif
1928
1929 int
nvpair_append_bool_array(nvpair_t * nvp,const bool value)1930 nvpair_append_bool_array(nvpair_t *nvp, const bool value)
1931 {
1932
1933 NVPAIR_ASSERT(nvp);
1934 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1935 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1936 }
1937
1938 int
nvpair_append_number_array(nvpair_t * nvp,const uint64_t value)1939 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
1940 {
1941
1942 NVPAIR_ASSERT(nvp);
1943 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1944 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1945 }
1946
1947 int
nvpair_append_string_array(nvpair_t * nvp,const char * value)1948 nvpair_append_string_array(nvpair_t *nvp, const char *value)
1949 {
1950 char *str;
1951
1952 NVPAIR_ASSERT(nvp);
1953 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1954 if (value == NULL) {
1955 ERRNO_SET(EINVAL);
1956 return (-1);
1957 }
1958 str = nv_strdup(value);
1959 if (str == NULL) {
1960 return (-1);
1961 }
1962 if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
1963 nv_free(str);
1964 return (-1);
1965 }
1966 return (0);
1967 }
1968
1969 int
nvpair_append_nvlist_array(nvpair_t * nvp,const nvlist_t * value)1970 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
1971 {
1972 nvpair_t *tmpnvp;
1973 nvlist_t *nvl, *prev;
1974 int flags;
1975
1976 NVPAIR_ASSERT(nvp);
1977 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1978 if (value == NULL || nvlist_error(value) != 0 ||
1979 nvlist_get_pararr(value, NULL) != NULL) {
1980 ERRNO_SET(EINVAL);
1981 return (-1);
1982 }
1983 nvl = nvlist_clone(value);
1984 if (nvl == NULL) {
1985 return (-1);
1986 }
1987 flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
1988 nvlist_set_flags(nvl, flags);
1989
1990 tmpnvp = NULL;
1991 prev = NULL;
1992 if (nvp->nvp_nitems > 0) {
1993 nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
1994
1995 prev = nvls[nvp->nvp_nitems - 1];
1996 PJDLOG_ASSERT(prev != NULL);
1997
1998 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1999 (uint64_t)(uintptr_t)nvl, 0, 0);
2000 if (tmpnvp == NULL) {
2001 goto fail;
2002 }
2003 }
2004 if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
2005 goto fail;
2006 }
2007 if (tmpnvp) {
2008 NVPAIR_ASSERT(tmpnvp);
2009 nvlist_set_array_next(prev, tmpnvp);
2010 }
2011 nvlist_set_parent(nvl, nvp);
2012 return (0);
2013 fail:
2014 if (tmpnvp) {
2015 nvpair_free(tmpnvp);
2016 }
2017 nvlist_destroy(nvl);
2018 return (-1);
2019 }
2020
2021 #ifndef _KERNEL
2022 int
nvpair_append_descriptor_array(nvpair_t * nvp,const int value)2023 nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
2024 {
2025 int fd;
2026
2027 NVPAIR_ASSERT(nvp);
2028 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
2029 fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
2030 if (fd == -1) {
2031 return (-1);
2032 }
2033 if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
2034 close(fd);
2035 return (-1);
2036 }
2037 return (0);
2038 }
2039 #endif
2040
2041 void
nvpair_free(nvpair_t * nvp)2042 nvpair_free(nvpair_t *nvp)
2043 {
2044 size_t i;
2045
2046 NVPAIR_ASSERT(nvp);
2047 PJDLOG_ASSERT(nvp->nvp_list == NULL);
2048
2049 nvp->nvp_magic = 0;
2050 switch (nvp->nvp_type) {
2051 #ifndef _KERNEL
2052 case NV_TYPE_DESCRIPTOR:
2053 close((int)nvp->nvp_data);
2054 break;
2055 case NV_TYPE_DESCRIPTOR_ARRAY:
2056 for (i = 0; i < nvp->nvp_nitems; i++)
2057 close(((int *)(intptr_t)nvp->nvp_data)[i]);
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