1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2009-2013 The FreeBSD Foundation
5 * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
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 (tmp[len - 1] != '\0') {
990 ERRNO_SET(EINVAL);
991 return (NULL);
992 }
993 if (size < 0) {
994 ERRNO_SET(EINVAL);
995 return (NULL);
996 }
997 tmp += len;
998 }
999 if (size != 0) {
1000 ERRNO_SET(EINVAL);
1001 return (NULL);
1002 }
1003
1004 value = nv_calloc(nvp->nvp_nitems, sizeof(*value));
1005 if (value == NULL)
1006 return (NULL);
1007
1008 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1009 value[ii] = nv_strdup((const char *)ptr);
1010 if (value[ii] == NULL)
1011 goto out;
1012 len = strlen(value[ii]) + 1;
1013 ptr += len;
1014 *leftp -= len;
1015 }
1016 nvp->nvp_data = (uint64_t)(uintptr_t)value;
1017
1018 return (ptr);
1019 out:
1020 for (j = 0; j < ii; j++)
1021 nv_free(value[j]);
1022 nv_free(value);
1023 return (NULL);
1024 }
1025
1026 #ifndef _KERNEL
1027 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)1028 nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
1029 const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
1030 {
1031 int64_t idx;
1032 size_t size;
1033 unsigned int ii;
1034 int *array;
1035
1036 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1037
1038 size = sizeof(idx) * nvp->nvp_nitems;
1039 if (nvp->nvp_datasize != size || *leftp < size ||
1040 nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
1041 ERRNO_SET(EINVAL);
1042 return (NULL);
1043 }
1044
1045 array = (int *)nv_malloc(size);
1046 if (array == NULL)
1047 return (NULL);
1048
1049 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1050 if (isbe)
1051 idx = be64dec(ptr);
1052 else
1053 idx = le64dec(ptr);
1054
1055 if (idx < 0) {
1056 ERRNO_SET(EINVAL);
1057 nv_free(array);
1058 return (NULL);
1059 }
1060
1061 if ((size_t)idx >= nfds) {
1062 ERRNO_SET(EINVAL);
1063 nv_free(array);
1064 return (NULL);
1065 }
1066
1067 array[ii] = (uint64_t)fds[idx];
1068
1069 ptr += sizeof(idx);
1070 *leftp -= sizeof(idx);
1071 }
1072
1073 nvp->nvp_data = (uint64_t)(uintptr_t)array;
1074
1075 return (ptr);
1076 }
1077 #endif
1078
1079 const unsigned char *
nvpair_unpack_nvlist_array(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,nvlist_t ** firstel)1080 nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
1081 const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
1082 {
1083 nvlist_t **value;
1084 nvpair_t *tmpnvp;
1085 unsigned int ii, j;
1086 size_t sizeup;
1087
1088 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1089
1090 sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
1091 if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
1092 sizeup > *leftp) {
1093 ERRNO_SET(EINVAL);
1094 return (NULL);
1095 }
1096
1097 value = nv_calloc(nvp->nvp_nitems, sizeof(*value));
1098 if (value == NULL)
1099 return (NULL);
1100
1101 for (ii = 0; ii < nvp->nvp_nitems; ii++) {
1102 value[ii] = nvlist_create(0);
1103 if (value[ii] == NULL)
1104 goto fail;
1105 if (ii > 0) {
1106 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1107 (uint64_t)(uintptr_t)value[ii], 0, 0);
1108 if (tmpnvp == NULL)
1109 goto fail;
1110 nvlist_set_array_next(value[ii - 1], tmpnvp);
1111 }
1112 }
1113 nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
1114
1115 nvp->nvp_data = (uint64_t)(uintptr_t)value;
1116 *firstel = value[0];
1117
1118 return (ptr);
1119 fail:
1120 ERRNO_SAVE();
1121 for (j = 0; j <= ii; j++)
1122 nvlist_destroy(value[j]);
1123 nv_free(value);
1124 ERRNO_RESTORE();
1125
1126 return (NULL);
1127 }
1128
1129 const unsigned char *
nvpair_unpack(bool isbe,const unsigned char * ptr,size_t * leftp,nvpair_t ** nvpp)1130 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
1131 nvpair_t **nvpp)
1132 {
1133 nvpair_t *nvp, *tmp;
1134
1135 nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
1136 if (nvp == NULL)
1137 return (NULL);
1138 nvp->nvp_name = (char *)(nvp + 1);
1139
1140 ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
1141 if (ptr == NULL)
1142 goto fail;
1143 tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
1144 if (tmp == NULL)
1145 goto fail;
1146 nvp = tmp;
1147
1148 /* Update nvp_name after realloc(). */
1149 nvp->nvp_name = (char *)(nvp + 1);
1150 nvp->nvp_data = 0x00;
1151 nvp->nvp_magic = NVPAIR_MAGIC;
1152 *nvpp = nvp;
1153 return (ptr);
1154 fail:
1155 nv_free(nvp);
1156 return (NULL);
1157 }
1158
1159 int
nvpair_type(const nvpair_t * nvp)1160 nvpair_type(const nvpair_t *nvp)
1161 {
1162
1163 NVPAIR_ASSERT(nvp);
1164
1165 return (nvp->nvp_type);
1166 }
1167
1168 const char *
nvpair_name(const nvpair_t * nvp)1169 nvpair_name(const nvpair_t *nvp)
1170 {
1171
1172 NVPAIR_ASSERT(nvp);
1173
1174 return (nvp->nvp_name);
1175 }
1176
1177 nvpair_t *
nvpair_create_stringf(const char * name,const char * valuefmt,...)1178 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
1179 {
1180 va_list valueap;
1181 nvpair_t *nvp;
1182
1183 va_start(valueap, valuefmt);
1184 nvp = nvpair_create_stringv(name, valuefmt, valueap);
1185 va_end(valueap);
1186
1187 return (nvp);
1188 }
1189
1190 nvpair_t *
nvpair_create_stringv(const char * name,const char * valuefmt,va_list valueap)1191 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
1192 {
1193 nvpair_t *nvp;
1194 char *str;
1195 int len;
1196
1197 len = nv_vasprintf(&str, valuefmt, valueap);
1198 if (len < 0)
1199 return (NULL);
1200 nvp = nvpair_create_string(name, str);
1201 nv_free(str);
1202 return (nvp);
1203 }
1204
1205 nvpair_t *
nvpair_create_null(const char * name)1206 nvpair_create_null(const char *name)
1207 {
1208
1209 return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
1210 }
1211
1212 nvpair_t *
nvpair_create_bool(const char * name,bool value)1213 nvpair_create_bool(const char *name, bool value)
1214 {
1215
1216 return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
1217 sizeof(uint8_t), 0));
1218 }
1219
1220 nvpair_t *
nvpair_create_number(const char * name,uint64_t value)1221 nvpair_create_number(const char *name, uint64_t value)
1222 {
1223
1224 return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
1225 }
1226
1227 nvpair_t *
nvpair_create_string(const char * name,const char * value)1228 nvpair_create_string(const char *name, const char *value)
1229 {
1230 nvpair_t *nvp;
1231 size_t size;
1232 char *data;
1233
1234 if (value == NULL) {
1235 ERRNO_SET(EINVAL);
1236 return (NULL);
1237 }
1238
1239 data = nv_strdup(value);
1240 if (data == NULL)
1241 return (NULL);
1242 size = strlen(value) + 1;
1243
1244 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
1245 size, 0);
1246 if (nvp == NULL)
1247 nv_free(data);
1248
1249 return (nvp);
1250 }
1251
1252 nvpair_t *
nvpair_create_nvlist(const char * name,const nvlist_t * value)1253 nvpair_create_nvlist(const char *name, const nvlist_t *value)
1254 {
1255 nvlist_t *nvl;
1256 nvpair_t *nvp;
1257
1258 if (value == NULL) {
1259 ERRNO_SET(EINVAL);
1260 return (NULL);
1261 }
1262
1263 nvl = nvlist_clone(value);
1264 if (nvl == NULL)
1265 return (NULL);
1266
1267 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
1268 0);
1269 if (nvp == NULL)
1270 nvlist_destroy(nvl);
1271 else
1272 nvlist_set_parent(nvl, nvp);
1273
1274 return (nvp);
1275 }
1276
1277 #ifndef _KERNEL
1278 nvpair_t *
nvpair_create_descriptor(const char * name,int value)1279 nvpair_create_descriptor(const char *name, int value)
1280 {
1281 nvpair_t *nvp;
1282
1283 value = fcntl(value, F_DUPFD_CLOEXEC, 0);
1284 if (value < 0)
1285 return (NULL);
1286
1287 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1288 sizeof(int64_t), 0);
1289 if (nvp == NULL) {
1290 ERRNO_SAVE();
1291 close(value);
1292 ERRNO_RESTORE();
1293 }
1294
1295 return (nvp);
1296 }
1297 #endif
1298
1299 nvpair_t *
nvpair_create_binary(const char * name,const void * value,size_t size)1300 nvpair_create_binary(const char *name, const void *value, size_t size)
1301 {
1302 nvpair_t *nvp;
1303 void *data;
1304
1305 if (value == NULL || size == 0) {
1306 ERRNO_SET(EINVAL);
1307 return (NULL);
1308 }
1309
1310 data = nv_malloc(size);
1311 if (data == NULL)
1312 return (NULL);
1313 memcpy(data, value, size);
1314
1315 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
1316 size, 0);
1317 if (nvp == NULL)
1318 nv_free(data);
1319
1320 return (nvp);
1321 }
1322
1323 nvpair_t *
nvpair_create_bool_array(const char * name,const bool * value,size_t nitems)1324 nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
1325 {
1326 nvpair_t *nvp;
1327 size_t size;
1328 void *data;
1329
1330 if (value == NULL || nitems == 0) {
1331 ERRNO_SET(EINVAL);
1332 return (NULL);
1333 }
1334
1335 data = nv_calloc(nitems, sizeof(value[0]));
1336 if (data == NULL)
1337 return (NULL);
1338 size = sizeof(value[0]) * nitems;
1339
1340 memcpy(data, value, size);
1341 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
1342 size, nitems);
1343 if (nvp == NULL) {
1344 ERRNO_SAVE();
1345 nv_free(data);
1346 ERRNO_RESTORE();
1347 }
1348
1349 return (nvp);
1350 }
1351
1352 nvpair_t *
nvpair_create_number_array(const char * name,const uint64_t * value,size_t nitems)1353 nvpair_create_number_array(const char *name, const uint64_t *value,
1354 size_t nitems)
1355 {
1356 nvpair_t *nvp;
1357 size_t size;
1358 void *data;
1359
1360 if (value == NULL || nitems == 0) {
1361 ERRNO_SET(EINVAL);
1362 return (NULL);
1363 }
1364
1365 data = nv_calloc(nitems, sizeof(value[0]));
1366 if (data == NULL)
1367 return (NULL);
1368 size = sizeof(value[0]) * nitems;
1369
1370 memcpy(data, value, size);
1371 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1372 (uint64_t)(uintptr_t)data, size, nitems);
1373 if (nvp == NULL) {
1374 ERRNO_SAVE();
1375 nv_free(data);
1376 ERRNO_RESTORE();
1377 }
1378
1379 return (nvp);
1380 }
1381
1382 nvpair_t *
nvpair_create_string_array(const char * name,const char * const * value,size_t nitems)1383 nvpair_create_string_array(const char *name, const char * const *value,
1384 size_t nitems)
1385 {
1386 nvpair_t *nvp;
1387 unsigned int ii;
1388 size_t datasize, size;
1389 char **data;
1390
1391 if (value == NULL || nitems == 0) {
1392 ERRNO_SET(EINVAL);
1393 return (NULL);
1394 }
1395
1396 nvp = NULL;
1397 datasize = 0;
1398 data = nv_calloc(nitems, sizeof(value[0]));
1399 if (data == NULL)
1400 return (NULL);
1401
1402 for (ii = 0; ii < nitems; ii++) {
1403 if (value[ii] == NULL) {
1404 ERRNO_SET(EINVAL);
1405 goto fail;
1406 }
1407
1408 size = strlen(value[ii]) + 1;
1409 datasize += size;
1410 data[ii] = nv_strdup(value[ii]);
1411 if (data[ii] == NULL)
1412 goto fail;
1413 }
1414 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1415 (uint64_t)(uintptr_t)data, datasize, nitems);
1416
1417 fail:
1418 if (nvp == NULL) {
1419 ERRNO_SAVE();
1420 for (; ii > 0; ii--)
1421 nv_free(data[ii - 1]);
1422 nv_free(data);
1423 ERRNO_RESTORE();
1424 }
1425
1426 return (nvp);
1427 }
1428
1429 nvpair_t *
nvpair_create_nvlist_array(const char * name,const nvlist_t * const * value,size_t nitems)1430 nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
1431 size_t nitems)
1432 {
1433 unsigned int ii;
1434 nvlist_t **nvls;
1435 nvpair_t *parent;
1436 int flags;
1437
1438 nvls = NULL;
1439
1440 if (value == NULL || nitems == 0) {
1441 ERRNO_SET(EINVAL);
1442 return (NULL);
1443 }
1444
1445 nvls = nv_calloc(nitems, sizeof(value[0]));
1446 if (nvls == NULL)
1447 return (NULL);
1448
1449 for (ii = 0; ii < nitems; ii++) {
1450 if (value[ii] == NULL) {
1451 ERRNO_SET(EINVAL);
1452 goto fail;
1453 }
1454
1455 nvls[ii] = nvlist_clone(value[ii]);
1456 if (nvls[ii] == NULL)
1457 goto fail;
1458
1459 if (ii > 0) {
1460 nvpair_t *nvp;
1461
1462 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1463 (uint64_t)(uintptr_t)nvls[ii], 0, 0);
1464 if (nvp == NULL) {
1465 ERRNO_SAVE();
1466 nvlist_destroy(nvls[ii]);
1467 ERRNO_RESTORE();
1468 goto fail;
1469 }
1470 nvlist_set_array_next(nvls[ii - 1], nvp);
1471 }
1472 }
1473 flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
1474 nvlist_set_flags(nvls[nitems - 1], flags);
1475
1476 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1477 (uint64_t)(uintptr_t)nvls, 0, nitems);
1478 if (parent == NULL)
1479 goto fail;
1480
1481 for (ii = 0; ii < nitems; ii++)
1482 nvlist_set_parent(nvls[ii], parent);
1483
1484 return (parent);
1485
1486 fail:
1487 ERRNO_SAVE();
1488 for (; ii > 0; ii--)
1489 nvlist_destroy(nvls[ii - 1]);
1490 nv_free(nvls);
1491 ERRNO_RESTORE();
1492
1493 return (NULL);
1494 }
1495
1496 #ifndef _KERNEL
1497 nvpair_t *
nvpair_create_descriptor_array(const char * name,const int * value,size_t nitems)1498 nvpair_create_descriptor_array(const char *name, const int *value,
1499 size_t nitems)
1500 {
1501 unsigned int ii;
1502 nvpair_t *nvp;
1503 int *fds;
1504
1505 if (value == NULL) {
1506 ERRNO_SET(EINVAL);
1507 return (NULL);
1508 }
1509
1510 nvp = NULL;
1511
1512 fds = nv_calloc(nitems, sizeof(value[0]));
1513 if (fds == NULL)
1514 return (NULL);
1515 for (ii = 0; ii < nitems; ii++) {
1516 if (value[ii] == -1) {
1517 fds[ii] = -1;
1518 } else {
1519 fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
1520 if (fds[ii] == -1)
1521 goto fail;
1522 }
1523 }
1524
1525 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1526 (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
1527
1528 fail:
1529 if (nvp == NULL) {
1530 ERRNO_SAVE();
1531 for (; ii > 0; ii--) {
1532 if (fds[ii - 1] != -1)
1533 close(fds[ii - 1]);
1534 }
1535 nv_free(fds);
1536 ERRNO_RESTORE();
1537 }
1538
1539 return (nvp);
1540 }
1541 #endif
1542
1543 nvpair_t *
nvpair_move_string(const char * name,char * value)1544 nvpair_move_string(const char *name, char *value)
1545 {
1546 nvpair_t *nvp;
1547
1548 if (value == NULL) {
1549 ERRNO_SET(EINVAL);
1550 return (NULL);
1551 }
1552
1553 nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
1554 strlen(value) + 1, 0);
1555 if (nvp == NULL) {
1556 ERRNO_SAVE();
1557 nv_free(value);
1558 ERRNO_RESTORE();
1559 }
1560
1561 return (nvp);
1562 }
1563
1564 nvpair_t *
nvpair_move_nvlist(const char * name,nvlist_t * value)1565 nvpair_move_nvlist(const char *name, nvlist_t *value)
1566 {
1567 nvpair_t *nvp;
1568
1569 if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
1570 ERRNO_SET(EINVAL);
1571 return (NULL);
1572 }
1573
1574 if (nvlist_error(value) != 0) {
1575 ERRNO_SET(nvlist_error(value));
1576 nvlist_destroy(value);
1577 return (NULL);
1578 }
1579
1580 nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
1581 0, 0);
1582 if (nvp == NULL)
1583 nvlist_destroy(value);
1584 else
1585 nvlist_set_parent(value, nvp);
1586
1587 return (nvp);
1588 }
1589
1590 #ifndef _KERNEL
1591 nvpair_t *
nvpair_move_descriptor(const char * name,int value)1592 nvpair_move_descriptor(const char *name, int value)
1593 {
1594 nvpair_t *nvp;
1595
1596 if (value < 0 || !fd_is_valid(value)) {
1597 ERRNO_SET(EBADF);
1598 return (NULL);
1599 }
1600
1601 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
1602 sizeof(int64_t), 0);
1603 if (nvp == NULL) {
1604 ERRNO_SAVE();
1605 close(value);
1606 ERRNO_RESTORE();
1607 }
1608
1609 return (nvp);
1610 }
1611 #endif
1612
1613 nvpair_t *
nvpair_move_binary(const char * name,void * value,size_t size)1614 nvpair_move_binary(const char *name, void *value, size_t size)
1615 {
1616 nvpair_t *nvp;
1617
1618 if (value == NULL || size == 0) {
1619 ERRNO_SET(EINVAL);
1620 return (NULL);
1621 }
1622
1623 nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
1624 size, 0);
1625 if (nvp == NULL) {
1626 ERRNO_SAVE();
1627 nv_free(value);
1628 ERRNO_RESTORE();
1629 }
1630
1631 return (nvp);
1632 }
1633
1634 nvpair_t *
nvpair_move_bool_array(const char * name,bool * value,size_t nitems)1635 nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
1636 {
1637 nvpair_t *nvp;
1638
1639 if (value == NULL || nitems == 0) {
1640 ERRNO_SET(EINVAL);
1641 return (NULL);
1642 }
1643
1644 nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
1645 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1646 if (nvp == NULL) {
1647 ERRNO_SAVE();
1648 nv_free(value);
1649 ERRNO_RESTORE();
1650 }
1651
1652 return (nvp);
1653 }
1654
1655 nvpair_t *
nvpair_move_string_array(const char * name,char ** value,size_t nitems)1656 nvpair_move_string_array(const char *name, char **value, size_t nitems)
1657 {
1658 nvpair_t *nvp;
1659 size_t i, size;
1660
1661 if (value == NULL || nitems == 0) {
1662 ERRNO_SET(EINVAL);
1663 return (NULL);
1664 }
1665
1666 size = 0;
1667 for (i = 0; i < nitems; i++) {
1668 if (value[i] == NULL) {
1669 ERRNO_SET(EINVAL);
1670 return (NULL);
1671 }
1672
1673 size += strlen(value[i]) + 1;
1674 }
1675
1676 nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
1677 (uint64_t)(uintptr_t)value, size, nitems);
1678 if (nvp == NULL) {
1679 ERRNO_SAVE();
1680 for (i = 0; i < nitems; i++)
1681 nv_free(value[i]);
1682 nv_free(value);
1683 ERRNO_RESTORE();
1684 }
1685
1686 return (nvp);
1687 }
1688
1689 nvpair_t *
nvpair_move_number_array(const char * name,uint64_t * value,size_t nitems)1690 nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
1691 {
1692 nvpair_t *nvp;
1693
1694 if (value == NULL || nitems == 0) {
1695 ERRNO_SET(EINVAL);
1696 return (NULL);
1697 }
1698
1699 nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
1700 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1701 if (nvp == NULL) {
1702 ERRNO_SAVE();
1703 nv_free(value);
1704 ERRNO_RESTORE();
1705 }
1706
1707 return (nvp);
1708 }
1709
1710 nvpair_t *
nvpair_move_nvlist_array(const char * name,nvlist_t ** value,size_t nitems)1711 nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
1712 {
1713 nvpair_t *parent;
1714 unsigned int ii;
1715 int flags;
1716
1717 if (value == NULL || nitems == 0) {
1718 ERRNO_SET(EINVAL);
1719 return (NULL);
1720 }
1721
1722 for (ii = 0; ii < nitems; ii++) {
1723 if (value == NULL || nvlist_error(value[ii]) != 0 ||
1724 nvlist_get_pararr(value[ii], NULL) != NULL) {
1725 ERRNO_SET(EINVAL);
1726 goto fail;
1727 }
1728 if (ii > 0) {
1729 nvpair_t *nvp;
1730
1731 nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
1732 (uint64_t)(uintptr_t)value[ii], 0, 0);
1733 if (nvp == NULL)
1734 goto fail;
1735 nvlist_set_array_next(value[ii - 1], nvp);
1736 }
1737 }
1738 flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
1739 nvlist_set_flags(value[nitems - 1], flags);
1740
1741 parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
1742 (uint64_t)(uintptr_t)value, 0, nitems);
1743 if (parent == NULL)
1744 goto fail;
1745
1746 for (ii = 0; ii < nitems; ii++)
1747 nvlist_set_parent(value[ii], parent);
1748
1749 return (parent);
1750 fail:
1751 ERRNO_SAVE();
1752 for (ii = 0; ii < nitems; ii++) {
1753 if (value[ii] != NULL &&
1754 nvlist_get_pararr(value[ii], NULL) != NULL) {
1755 nvlist_destroy(value[ii]);
1756 }
1757 }
1758 nv_free(value);
1759 ERRNO_RESTORE();
1760
1761 return (NULL);
1762 }
1763
1764 #ifndef _KERNEL
1765 nvpair_t *
nvpair_move_descriptor_array(const char * name,int * value,size_t nitems)1766 nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
1767 {
1768 nvpair_t *nvp;
1769 size_t i;
1770
1771 if (value == NULL || nitems == 0) {
1772 ERRNO_SET(EINVAL);
1773 return (NULL);
1774 }
1775
1776 for (i = 0; i < nitems; i++) {
1777 if (value[i] != -1 && !fd_is_valid(value[i])) {
1778 ERRNO_SET(EBADF);
1779 goto fail;
1780 }
1781 }
1782
1783 nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
1784 (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
1785 if (nvp == NULL)
1786 goto fail;
1787
1788 return (nvp);
1789 fail:
1790 ERRNO_SAVE();
1791 for (i = 0; i < nitems; i++) {
1792 if (fd_is_valid(value[i]))
1793 close(value[i]);
1794 }
1795 nv_free(value);
1796 ERRNO_RESTORE();
1797
1798 return (NULL);
1799 }
1800 #endif
1801
1802 bool
nvpair_get_bool(const nvpair_t * nvp)1803 nvpair_get_bool(const nvpair_t *nvp)
1804 {
1805
1806 NVPAIR_ASSERT(nvp);
1807
1808 return (nvp->nvp_data == 1);
1809 }
1810
1811 uint64_t
nvpair_get_number(const nvpair_t * nvp)1812 nvpair_get_number(const nvpair_t *nvp)
1813 {
1814
1815 NVPAIR_ASSERT(nvp);
1816
1817 return (nvp->nvp_data);
1818 }
1819
1820 const char *
nvpair_get_string(const nvpair_t * nvp)1821 nvpair_get_string(const nvpair_t *nvp)
1822 {
1823
1824 NVPAIR_ASSERT(nvp);
1825 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
1826
1827 return ((const char *)(intptr_t)nvp->nvp_data);
1828 }
1829
1830 const nvlist_t *
nvpair_get_nvlist(const nvpair_t * nvp)1831 nvpair_get_nvlist(const nvpair_t *nvp)
1832 {
1833
1834 NVPAIR_ASSERT(nvp);
1835 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
1836
1837 return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
1838 }
1839
1840 #ifndef _KERNEL
1841 int
nvpair_get_descriptor(const nvpair_t * nvp)1842 nvpair_get_descriptor(const nvpair_t *nvp)
1843 {
1844
1845 NVPAIR_ASSERT(nvp);
1846 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
1847
1848 return ((int)nvp->nvp_data);
1849 }
1850 #endif
1851
1852 const void *
nvpair_get_binary(const nvpair_t * nvp,size_t * sizep)1853 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
1854 {
1855
1856 NVPAIR_ASSERT(nvp);
1857 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
1858
1859 if (sizep != NULL)
1860 *sizep = nvp->nvp_datasize;
1861
1862 return ((const void *)(intptr_t)nvp->nvp_data);
1863 }
1864
1865 const bool *
nvpair_get_bool_array(const nvpair_t * nvp,size_t * nitems)1866 nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
1867 {
1868
1869 NVPAIR_ASSERT(nvp);
1870 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1871
1872 if (nitems != NULL)
1873 *nitems = nvp->nvp_nitems;
1874
1875 return ((const bool *)(intptr_t)nvp->nvp_data);
1876 }
1877
1878 const uint64_t *
nvpair_get_number_array(const nvpair_t * nvp,size_t * nitems)1879 nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
1880 {
1881
1882 NVPAIR_ASSERT(nvp);
1883 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1884
1885 if (nitems != NULL)
1886 *nitems = nvp->nvp_nitems;
1887
1888 return ((const uint64_t *)(intptr_t)nvp->nvp_data);
1889 }
1890
1891 const char * const *
nvpair_get_string_array(const nvpair_t * nvp,size_t * nitems)1892 nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
1893 {
1894
1895 NVPAIR_ASSERT(nvp);
1896 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1897
1898 if (nitems != NULL)
1899 *nitems = nvp->nvp_nitems;
1900
1901 return ((const char * const *)(intptr_t)nvp->nvp_data);
1902 }
1903
1904 const nvlist_t * const *
nvpair_get_nvlist_array(const nvpair_t * nvp,size_t * nitems)1905 nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
1906 {
1907
1908 NVPAIR_ASSERT(nvp);
1909 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1910
1911 if (nitems != NULL)
1912 *nitems = nvp->nvp_nitems;
1913
1914 return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
1915 }
1916
1917 #ifndef _KERNEL
1918 const int *
nvpair_get_descriptor_array(const nvpair_t * nvp,size_t * nitems)1919 nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
1920 {
1921
1922 NVPAIR_ASSERT(nvp);
1923 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
1924
1925 if (nitems != NULL)
1926 *nitems = nvp->nvp_nitems;
1927
1928 return ((const int *)(intptr_t)nvp->nvp_data);
1929 }
1930 #endif
1931
1932 int
nvpair_append_bool_array(nvpair_t * nvp,const bool value)1933 nvpair_append_bool_array(nvpair_t *nvp, const bool value)
1934 {
1935
1936 NVPAIR_ASSERT(nvp);
1937 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
1938 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1939 }
1940
1941 int
nvpair_append_number_array(nvpair_t * nvp,const uint64_t value)1942 nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
1943 {
1944
1945 NVPAIR_ASSERT(nvp);
1946 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
1947 return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
1948 }
1949
1950 int
nvpair_append_string_array(nvpair_t * nvp,const char * value)1951 nvpair_append_string_array(nvpair_t *nvp, const char *value)
1952 {
1953 char *str;
1954
1955 NVPAIR_ASSERT(nvp);
1956 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
1957 if (value == NULL) {
1958 ERRNO_SET(EINVAL);
1959 return (-1);
1960 }
1961 str = nv_strdup(value);
1962 if (str == NULL) {
1963 return (-1);
1964 }
1965 if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
1966 nv_free(str);
1967 return (-1);
1968 }
1969 return (0);
1970 }
1971
1972 int
nvpair_append_nvlist_array(nvpair_t * nvp,const nvlist_t * value)1973 nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
1974 {
1975 nvpair_t *tmpnvp;
1976 nvlist_t *nvl, *prev;
1977 int flags;
1978
1979 NVPAIR_ASSERT(nvp);
1980 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
1981 if (value == NULL || nvlist_error(value) != 0 ||
1982 nvlist_get_pararr(value, NULL) != NULL) {
1983 ERRNO_SET(EINVAL);
1984 return (-1);
1985 }
1986 nvl = nvlist_clone(value);
1987 if (nvl == NULL) {
1988 return (-1);
1989 }
1990 flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
1991 nvlist_set_flags(nvl, flags);
1992
1993 tmpnvp = NULL;
1994 prev = NULL;
1995 if (nvp->nvp_nitems > 0) {
1996 nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
1997
1998 prev = nvls[nvp->nvp_nitems - 1];
1999 PJDLOG_ASSERT(prev != NULL);
2000
2001 tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
2002 (uint64_t)(uintptr_t)nvl, 0, 0);
2003 if (tmpnvp == NULL) {
2004 goto fail;
2005 }
2006 }
2007 if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
2008 goto fail;
2009 }
2010 if (tmpnvp) {
2011 NVPAIR_ASSERT(tmpnvp);
2012 nvlist_set_array_next(prev, tmpnvp);
2013 }
2014 nvlist_set_parent(nvl, nvp);
2015 return (0);
2016 fail:
2017 if (tmpnvp) {
2018 nvpair_free(tmpnvp);
2019 }
2020 nvlist_destroy(nvl);
2021 return (-1);
2022 }
2023
2024 #ifndef _KERNEL
2025 int
nvpair_append_descriptor_array(nvpair_t * nvp,const int value)2026 nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
2027 {
2028 int fd;
2029
2030 NVPAIR_ASSERT(nvp);
2031 PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
2032 fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
2033 if (fd == -1) {
2034 return (-1);
2035 }
2036 if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
2037 close(fd);
2038 return (-1);
2039 }
2040 return (0);
2041 }
2042 #endif
2043
2044 void
nvpair_free(nvpair_t * nvp)2045 nvpair_free(nvpair_t *nvp)
2046 {
2047 size_t i;
2048
2049 NVPAIR_ASSERT(nvp);
2050 PJDLOG_ASSERT(nvp->nvp_list == NULL);
2051
2052 nvp->nvp_magic = 0;
2053 switch (nvp->nvp_type) {
2054 #ifndef _KERNEL
2055 case NV_TYPE_DESCRIPTOR:
2056 close((int)nvp->nvp_data);
2057 break;
2058 case NV_TYPE_DESCRIPTOR_ARRAY:
2059 for (i = 0; i < nvp->nvp_nitems; i++)
2060 close(((int *)(intptr_t)nvp->nvp_data)[i]);
2061 nv_free((int *)(intptr_t)nvp->nvp_data);
2062 break;
2063 #endif
2064 case NV_TYPE_NVLIST:
2065 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
2066 break;
2067 case NV_TYPE_STRING:
2068 nv_free((char *)(intptr_t)nvp->nvp_data);
2069 break;
2070 case NV_TYPE_BINARY:
2071 nv_free((void *)(intptr_t)nvp->nvp_data);
2072 break;
2073 case NV_TYPE_NVLIST_ARRAY:
2074 for (i = 0; i < nvp->nvp_nitems; i++) {
2075 nvlist_destroy(
2076 ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
2077 }
2078 nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
2079 break;
2080 case NV_TYPE_NUMBER_ARRAY:
2081 nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
2082 break;
2083 case NV_TYPE_BOOL_ARRAY:
2084 nv_free((bool *)(intptr_t)nvp->nvp_data);
2085 break;
2086 case NV_TYPE_STRING_ARRAY:
2087 for (i = 0; i < nvp->nvp_nitems; i++)
2088 nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
2089 nv_free((char **)(intptr_t)nvp->nvp_data);
2090 break;
2091 }
2092 nv_free(nvp);
2093 }
2094
2095 void
nvpair_free_structure(nvpair_t * nvp)2096 nvpair_free_structure(nvpair_t *nvp)
2097 {
2098
2099 NVPAIR_ASSERT(nvp);
2100 PJDLOG_ASSERT(nvp->nvp_list == NULL);
2101
2102 nvp->nvp_magic = 0;
2103 nv_free(nvp);
2104 }
2105
2106 const char *
nvpair_type_string(int type)2107 nvpair_type_string(int type)
2108 {
2109
2110 switch (type) {
2111 case NV_TYPE_NULL:
2112 return ("NULL");
2113 case NV_TYPE_BOOL:
2114 return ("BOOL");
2115 case NV_TYPE_NUMBER:
2116 return ("NUMBER");
2117 case NV_TYPE_STRING:
2118 return ("STRING");
2119 case NV_TYPE_NVLIST:
2120 return ("NVLIST");
2121 case NV_TYPE_DESCRIPTOR:
2122 return ("DESCRIPTOR");
2123 case NV_TYPE_BINARY:
2124 return ("BINARY");
2125 case NV_TYPE_BOOL_ARRAY:
2126 return ("BOOL ARRAY");
2127 case NV_TYPE_NUMBER_ARRAY:
2128 return ("NUMBER ARRAY");
2129 case NV_TYPE_STRING_ARRAY:
2130 return ("STRING ARRAY");
2131 case NV_TYPE_NVLIST_ARRAY:
2132 return ("NVLIST ARRAY");
2133 case NV_TYPE_DESCRIPTOR_ARRAY:
2134 return ("DESCRIPTOR ARRAY");
2135 default:
2136 return ("<UNKNOWN>");
2137 }
2138 }
2139
2140