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