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