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