156e5ad5fSMatt Macy /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
356e5ad5fSMatt Macy *
456e5ad5fSMatt Macy * Copyright (c) 2009-2013 The FreeBSD Foundation
556e5ad5fSMatt Macy * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
656e5ad5fSMatt Macy * All rights reserved.
756e5ad5fSMatt Macy *
856e5ad5fSMatt Macy * This software was developed by Pawel Jakub Dawidek under sponsorship from
956e5ad5fSMatt Macy * the FreeBSD Foundation.
1056e5ad5fSMatt Macy *
1156e5ad5fSMatt Macy * Redistribution and use in source and binary forms, with or without
1256e5ad5fSMatt Macy * modification, are permitted provided that the following conditions
1356e5ad5fSMatt Macy * are met:
1456e5ad5fSMatt Macy * 1. Redistributions of source code must retain the above copyright
1556e5ad5fSMatt Macy * notice, this list of conditions and the following disclaimer.
1656e5ad5fSMatt Macy * 2. Redistributions in binary form must reproduce the above copyright
1756e5ad5fSMatt Macy * notice, this list of conditions and the following disclaimer in the
1856e5ad5fSMatt Macy * documentation and/or other materials provided with the distribution.
1956e5ad5fSMatt Macy *
2056e5ad5fSMatt Macy * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
2156e5ad5fSMatt Macy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2256e5ad5fSMatt Macy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2356e5ad5fSMatt Macy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
2456e5ad5fSMatt Macy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2556e5ad5fSMatt Macy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2656e5ad5fSMatt Macy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2756e5ad5fSMatt Macy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2856e5ad5fSMatt Macy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2956e5ad5fSMatt Macy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3056e5ad5fSMatt Macy * SUCH DAMAGE.
3156e5ad5fSMatt Macy */
3256e5ad5fSMatt Macy
3356e5ad5fSMatt Macy #include <sys/cdefs.h>
3456e5ad5fSMatt Macy __FBSDID("$FreeBSD$");
3556e5ad5fSMatt Macy
3656e5ad5fSMatt Macy #include <sys/param.h>
3756e5ad5fSMatt Macy #include <sys/endian.h>
3856e5ad5fSMatt Macy #include <sys/queue.h>
3956e5ad5fSMatt Macy
4056e5ad5fSMatt Macy #ifdef _KERNEL
4156e5ad5fSMatt Macy
4256e5ad5fSMatt Macy #include <sys/errno.h>
4356e5ad5fSMatt Macy #include <sys/lock.h>
4456e5ad5fSMatt Macy #include <sys/malloc.h>
4556e5ad5fSMatt Macy #include <sys/systm.h>
4656e5ad5fSMatt Macy
4756e5ad5fSMatt Macy #include <machine/stdarg.h>
4856e5ad5fSMatt Macy
4956e5ad5fSMatt Macy #else
5056e5ad5fSMatt Macy #include <errno.h>
5156e5ad5fSMatt Macy #include <fcntl.h>
5256e5ad5fSMatt Macy #include <stdarg.h>
5356e5ad5fSMatt Macy #include <stdbool.h>
5456e5ad5fSMatt Macy #include <stdint.h>
5556e5ad5fSMatt Macy #include <stdlib.h>
5656e5ad5fSMatt Macy #include <string.h>
5756e5ad5fSMatt Macy #include <unistd.h>
5856e5ad5fSMatt Macy
5956e5ad5fSMatt Macy #include "common_impl.h"
6056e5ad5fSMatt Macy #endif
6156e5ad5fSMatt Macy
6256e5ad5fSMatt Macy #ifdef HAVE_PJDLOG
6356e5ad5fSMatt Macy #include <pjdlog.h>
6456e5ad5fSMatt Macy #endif
6556e5ad5fSMatt Macy
6656e5ad5fSMatt Macy #include <sys/nv.h>
6756e5ad5fSMatt Macy
6856e5ad5fSMatt Macy #include "nv_impl.h"
6956e5ad5fSMatt Macy #include "nvlist_impl.h"
7056e5ad5fSMatt Macy #include "nvpair_impl.h"
7156e5ad5fSMatt Macy
7256e5ad5fSMatt Macy #ifndef HAVE_PJDLOG
7356e5ad5fSMatt Macy #ifdef _KERNEL
7456e5ad5fSMatt Macy #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__)
7556e5ad5fSMatt Macy #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__))
7656e5ad5fSMatt Macy #define PJDLOG_ABORT(...) panic(__VA_ARGS__)
7756e5ad5fSMatt Macy #else
7856e5ad5fSMatt Macy #include <assert.h>
7956e5ad5fSMatt Macy #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
8056e5ad5fSMatt Macy #define PJDLOG_RASSERT(expr, ...) assert(expr)
8156e5ad5fSMatt Macy #define PJDLOG_ABORT(...) abort()
8256e5ad5fSMatt Macy #endif
8356e5ad5fSMatt Macy #endif
8456e5ad5fSMatt Macy
8556e5ad5fSMatt Macy #define NVPAIR_MAGIC 0x6e7670 /* "nvp" */
8656e5ad5fSMatt Macy struct nvpair {
8756e5ad5fSMatt Macy int nvp_magic;
8856e5ad5fSMatt Macy char *nvp_name;
8956e5ad5fSMatt Macy int nvp_type;
9056e5ad5fSMatt Macy uint64_t nvp_data;
9156e5ad5fSMatt Macy size_t nvp_datasize;
9256e5ad5fSMatt Macy size_t nvp_nitems; /* Used only for array types. */
9356e5ad5fSMatt Macy nvlist_t *nvp_list;
9456e5ad5fSMatt Macy TAILQ_ENTRY(nvpair) nvp_next;
9556e5ad5fSMatt Macy };
9656e5ad5fSMatt Macy
9756e5ad5fSMatt Macy #define NVPAIR_ASSERT(nvp) do { \
9856e5ad5fSMatt Macy PJDLOG_ASSERT((nvp) != NULL); \
9956e5ad5fSMatt Macy PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \
10056e5ad5fSMatt Macy } while (0)
10156e5ad5fSMatt Macy
10256e5ad5fSMatt Macy struct nvpair_header {
10356e5ad5fSMatt Macy uint8_t nvph_type;
10456e5ad5fSMatt Macy uint16_t nvph_namesize;
10556e5ad5fSMatt Macy uint64_t nvph_datasize;
10656e5ad5fSMatt Macy uint64_t nvph_nitems;
10756e5ad5fSMatt Macy } __packed;
10856e5ad5fSMatt Macy
10956e5ad5fSMatt Macy
11056e5ad5fSMatt Macy void
nvpair_assert(const nvpair_t * nvp __unused)11156e5ad5fSMatt Macy nvpair_assert(const nvpair_t *nvp __unused)
11256e5ad5fSMatt Macy {
11356e5ad5fSMatt Macy
11456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
11556e5ad5fSMatt Macy }
11656e5ad5fSMatt Macy
11756e5ad5fSMatt Macy static nvpair_t *
nvpair_allocv(const char * name,int type,uint64_t data,size_t datasize,size_t nitems)11856e5ad5fSMatt Macy nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize,
11956e5ad5fSMatt Macy size_t nitems)
12056e5ad5fSMatt Macy {
12156e5ad5fSMatt Macy nvpair_t *nvp;
12256e5ad5fSMatt Macy size_t namelen;
12356e5ad5fSMatt Macy
12456e5ad5fSMatt Macy PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
12556e5ad5fSMatt Macy
12656e5ad5fSMatt Macy namelen = strlen(name);
12756e5ad5fSMatt Macy if (namelen >= NV_NAME_MAX) {
12856e5ad5fSMatt Macy ERRNO_SET(ENAMETOOLONG);
12956e5ad5fSMatt Macy return (NULL);
13056e5ad5fSMatt Macy }
13156e5ad5fSMatt Macy
13256e5ad5fSMatt Macy nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
13356e5ad5fSMatt Macy if (nvp != NULL) {
13456e5ad5fSMatt Macy nvp->nvp_name = (char *)(nvp + 1);
13556e5ad5fSMatt Macy memcpy(nvp->nvp_name, name, namelen);
13656e5ad5fSMatt Macy nvp->nvp_name[namelen] = '\0';
13756e5ad5fSMatt Macy nvp->nvp_type = type;
13856e5ad5fSMatt Macy nvp->nvp_data = data;
13956e5ad5fSMatt Macy nvp->nvp_datasize = datasize;
14056e5ad5fSMatt Macy nvp->nvp_nitems = nitems;
14156e5ad5fSMatt Macy nvp->nvp_magic = NVPAIR_MAGIC;
14256e5ad5fSMatt Macy }
14356e5ad5fSMatt Macy
14456e5ad5fSMatt Macy return (nvp);
14556e5ad5fSMatt Macy }
14656e5ad5fSMatt Macy
14756e5ad5fSMatt Macy static int
nvpair_append(nvpair_t * nvp,const void * value,size_t valsize,size_t datasize)14856e5ad5fSMatt Macy nvpair_append(nvpair_t *nvp, const void *value, size_t valsize, size_t datasize)
14956e5ad5fSMatt Macy {
15056e5ad5fSMatt Macy void *olddata, *data, *valp;
15156e5ad5fSMatt Macy size_t oldlen;
15256e5ad5fSMatt Macy
15356e5ad5fSMatt Macy oldlen = nvp->nvp_nitems * valsize;
15456e5ad5fSMatt Macy olddata = (void *)(uintptr_t)nvp->nvp_data;
15556e5ad5fSMatt Macy data = nv_realloc(olddata, oldlen + valsize);
15656e5ad5fSMatt Macy if (data == NULL) {
15756e5ad5fSMatt Macy ERRNO_SET(ENOMEM);
15856e5ad5fSMatt Macy return (-1);
15956e5ad5fSMatt Macy }
16056e5ad5fSMatt Macy valp = (unsigned char *)data + oldlen;
16156e5ad5fSMatt Macy memcpy(valp, value, valsize);
16256e5ad5fSMatt Macy
16356e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)data;
16456e5ad5fSMatt Macy nvp->nvp_datasize += datasize;
16556e5ad5fSMatt Macy nvp->nvp_nitems++;
16656e5ad5fSMatt Macy return (0);
16756e5ad5fSMatt Macy }
16856e5ad5fSMatt Macy
16956e5ad5fSMatt Macy nvlist_t *
nvpair_nvlist(const nvpair_t * nvp)17056e5ad5fSMatt Macy nvpair_nvlist(const nvpair_t *nvp)
17156e5ad5fSMatt Macy {
17256e5ad5fSMatt Macy
17356e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
17456e5ad5fSMatt Macy
17556e5ad5fSMatt Macy return (nvp->nvp_list);
17656e5ad5fSMatt Macy }
17756e5ad5fSMatt Macy
17856e5ad5fSMatt Macy nvpair_t *
nvpair_next(const nvpair_t * nvp)17956e5ad5fSMatt Macy nvpair_next(const nvpair_t *nvp)
18056e5ad5fSMatt Macy {
18156e5ad5fSMatt Macy
18256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
18356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list != NULL);
18456e5ad5fSMatt Macy
18556e5ad5fSMatt Macy return (TAILQ_NEXT(nvp, nvp_next));
18656e5ad5fSMatt Macy }
18756e5ad5fSMatt Macy
18856e5ad5fSMatt Macy nvpair_t *
nvpair_prev(const nvpair_t * nvp)18956e5ad5fSMatt Macy nvpair_prev(const nvpair_t *nvp)
19056e5ad5fSMatt Macy {
19156e5ad5fSMatt Macy
19256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
19356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list != NULL);
19456e5ad5fSMatt Macy
19556e5ad5fSMatt Macy return (TAILQ_PREV(nvp, nvl_head, nvp_next));
19656e5ad5fSMatt Macy }
19756e5ad5fSMatt Macy
19856e5ad5fSMatt Macy void
nvpair_insert(struct nvl_head * head,nvpair_t * nvp,nvlist_t * nvl)19956e5ad5fSMatt Macy nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
20056e5ad5fSMatt Macy {
20156e5ad5fSMatt Macy
20256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
20356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list == NULL);
20456e5ad5fSMatt Macy PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 ||
20556e5ad5fSMatt Macy !nvlist_exists(nvl, nvpair_name(nvp)));
20656e5ad5fSMatt Macy
20756e5ad5fSMatt Macy TAILQ_INSERT_TAIL(head, nvp, nvp_next);
20856e5ad5fSMatt Macy nvp->nvp_list = nvl;
20956e5ad5fSMatt Macy }
21056e5ad5fSMatt Macy
21156e5ad5fSMatt Macy static void
nvpair_remove_nvlist(nvpair_t * nvp)21256e5ad5fSMatt Macy nvpair_remove_nvlist(nvpair_t *nvp)
21356e5ad5fSMatt Macy {
21456e5ad5fSMatt Macy nvlist_t *nvl;
21556e5ad5fSMatt Macy
21656e5ad5fSMatt Macy /* XXX: DECONST is bad, mkay? */
21756e5ad5fSMatt Macy nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
21856e5ad5fSMatt Macy PJDLOG_ASSERT(nvl != NULL);
21956e5ad5fSMatt Macy nvlist_set_parent(nvl, NULL);
22056e5ad5fSMatt Macy }
22156e5ad5fSMatt Macy
22256e5ad5fSMatt Macy static void
nvpair_remove_nvlist_array(nvpair_t * nvp)22356e5ad5fSMatt Macy nvpair_remove_nvlist_array(nvpair_t *nvp)
22456e5ad5fSMatt Macy {
22556e5ad5fSMatt Macy nvlist_t **nvlarray;
22656e5ad5fSMatt Macy size_t count, i;
22756e5ad5fSMatt Macy
22856e5ad5fSMatt Macy /* XXX: DECONST is bad, mkay? */
22956e5ad5fSMatt Macy nvlarray = __DECONST(nvlist_t **,
23056e5ad5fSMatt Macy nvpair_get_nvlist_array(nvp, &count));
23156e5ad5fSMatt Macy for (i = 0; i < count; i++) {
23256e5ad5fSMatt Macy nvlist_set_array_next(nvlarray[i], NULL);
23356e5ad5fSMatt Macy nvlist_set_parent(nvlarray[i], NULL);
23456e5ad5fSMatt Macy }
23556e5ad5fSMatt Macy }
23656e5ad5fSMatt Macy
23756e5ad5fSMatt Macy void
nvpair_remove(struct nvl_head * head,nvpair_t * nvp,const nvlist_t * nvl __unused)23856e5ad5fSMatt Macy nvpair_remove(struct nvl_head *head, nvpair_t *nvp,
23956e5ad5fSMatt Macy const nvlist_t *nvl __unused)
24056e5ad5fSMatt Macy {
24156e5ad5fSMatt Macy
24256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
24356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list == nvl);
24456e5ad5fSMatt Macy
24556e5ad5fSMatt Macy if (nvpair_type(nvp) == NV_TYPE_NVLIST)
24656e5ad5fSMatt Macy nvpair_remove_nvlist(nvp);
24756e5ad5fSMatt Macy else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY)
24856e5ad5fSMatt Macy nvpair_remove_nvlist_array(nvp);
24956e5ad5fSMatt Macy
25056e5ad5fSMatt Macy TAILQ_REMOVE(head, nvp, nvp_next);
25156e5ad5fSMatt Macy nvp->nvp_list = NULL;
25256e5ad5fSMatt Macy }
25356e5ad5fSMatt Macy
25456e5ad5fSMatt Macy nvpair_t *
nvpair_clone(const nvpair_t * nvp)25556e5ad5fSMatt Macy nvpair_clone(const nvpair_t *nvp)
25656e5ad5fSMatt Macy {
25756e5ad5fSMatt Macy nvpair_t *newnvp;
25856e5ad5fSMatt Macy const char *name;
25956e5ad5fSMatt Macy const void *data;
26056e5ad5fSMatt Macy size_t datasize;
26156e5ad5fSMatt Macy
26256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
26356e5ad5fSMatt Macy
26456e5ad5fSMatt Macy name = nvpair_name(nvp);
26556e5ad5fSMatt Macy
26656e5ad5fSMatt Macy switch (nvpair_type(nvp)) {
26756e5ad5fSMatt Macy case NV_TYPE_NULL:
26856e5ad5fSMatt Macy newnvp = nvpair_create_null(name);
26956e5ad5fSMatt Macy break;
27056e5ad5fSMatt Macy case NV_TYPE_BOOL:
27156e5ad5fSMatt Macy newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
27256e5ad5fSMatt Macy break;
27356e5ad5fSMatt Macy case NV_TYPE_NUMBER:
27456e5ad5fSMatt Macy newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
27556e5ad5fSMatt Macy break;
27656e5ad5fSMatt Macy case NV_TYPE_STRING:
27756e5ad5fSMatt Macy newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
27856e5ad5fSMatt Macy break;
27956e5ad5fSMatt Macy case NV_TYPE_NVLIST:
28056e5ad5fSMatt Macy newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
28156e5ad5fSMatt Macy break;
28256e5ad5fSMatt Macy case NV_TYPE_BINARY:
28356e5ad5fSMatt Macy data = nvpair_get_binary(nvp, &datasize);
28456e5ad5fSMatt Macy newnvp = nvpair_create_binary(name, data, datasize);
28556e5ad5fSMatt Macy break;
28656e5ad5fSMatt Macy case NV_TYPE_BOOL_ARRAY:
28756e5ad5fSMatt Macy data = nvpair_get_bool_array(nvp, &datasize);
28856e5ad5fSMatt Macy newnvp = nvpair_create_bool_array(name, data, datasize);
28956e5ad5fSMatt Macy break;
29056e5ad5fSMatt Macy case NV_TYPE_NUMBER_ARRAY:
29156e5ad5fSMatt Macy data = nvpair_get_number_array(nvp, &datasize);
29256e5ad5fSMatt Macy newnvp = nvpair_create_number_array(name, data, datasize);
29356e5ad5fSMatt Macy break;
29456e5ad5fSMatt Macy case NV_TYPE_STRING_ARRAY:
29556e5ad5fSMatt Macy data = nvpair_get_string_array(nvp, &datasize);
29656e5ad5fSMatt Macy newnvp = nvpair_create_string_array(name, data, datasize);
29756e5ad5fSMatt Macy break;
29856e5ad5fSMatt Macy case NV_TYPE_NVLIST_ARRAY:
29956e5ad5fSMatt Macy data = nvpair_get_nvlist_array(nvp, &datasize);
30056e5ad5fSMatt Macy newnvp = nvpair_create_nvlist_array(name, data, datasize);
30156e5ad5fSMatt Macy break;
30256e5ad5fSMatt Macy #ifndef _KERNEL
30356e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR:
30456e5ad5fSMatt Macy newnvp = nvpair_create_descriptor(name,
30556e5ad5fSMatt Macy nvpair_get_descriptor(nvp));
30656e5ad5fSMatt Macy break;
30756e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR_ARRAY:
30856e5ad5fSMatt Macy data = nvpair_get_descriptor_array(nvp, &datasize);
30956e5ad5fSMatt Macy newnvp = nvpair_create_descriptor_array(name, data, datasize);
31056e5ad5fSMatt Macy break;
31156e5ad5fSMatt Macy #endif
31256e5ad5fSMatt Macy default:
31356e5ad5fSMatt Macy PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
31456e5ad5fSMatt Macy }
31556e5ad5fSMatt Macy
31656e5ad5fSMatt Macy return (newnvp);
31756e5ad5fSMatt Macy }
31856e5ad5fSMatt Macy
31956e5ad5fSMatt Macy size_t
nvpair_header_size(void)32056e5ad5fSMatt Macy nvpair_header_size(void)
32156e5ad5fSMatt Macy {
32256e5ad5fSMatt Macy
32356e5ad5fSMatt Macy return (sizeof(struct nvpair_header));
32456e5ad5fSMatt Macy }
32556e5ad5fSMatt Macy
32656e5ad5fSMatt Macy size_t
nvpair_size(const nvpair_t * nvp)32756e5ad5fSMatt Macy nvpair_size(const nvpair_t *nvp)
32856e5ad5fSMatt Macy {
32956e5ad5fSMatt Macy
33056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
33156e5ad5fSMatt Macy
33256e5ad5fSMatt Macy return (nvp->nvp_datasize);
33356e5ad5fSMatt Macy }
33456e5ad5fSMatt Macy
33556e5ad5fSMatt Macy unsigned char *
nvpair_pack_header(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)33656e5ad5fSMatt Macy nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
33756e5ad5fSMatt Macy {
33856e5ad5fSMatt Macy struct nvpair_header nvphdr;
33956e5ad5fSMatt Macy size_t namesize;
34056e5ad5fSMatt Macy
34156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
34256e5ad5fSMatt Macy
34356e5ad5fSMatt Macy nvphdr.nvph_type = nvp->nvp_type;
34456e5ad5fSMatt Macy namesize = strlen(nvp->nvp_name) + 1;
34556e5ad5fSMatt Macy PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
34656e5ad5fSMatt Macy nvphdr.nvph_namesize = namesize;
34756e5ad5fSMatt Macy nvphdr.nvph_datasize = nvp->nvp_datasize;
34856e5ad5fSMatt Macy nvphdr.nvph_nitems = nvp->nvp_nitems;
34956e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
35056e5ad5fSMatt Macy memcpy(ptr, &nvphdr, sizeof(nvphdr));
35156e5ad5fSMatt Macy ptr += sizeof(nvphdr);
35256e5ad5fSMatt Macy *leftp -= sizeof(nvphdr);
35356e5ad5fSMatt Macy
35456e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= namesize);
35556e5ad5fSMatt Macy memcpy(ptr, nvp->nvp_name, namesize);
35656e5ad5fSMatt Macy ptr += namesize;
35756e5ad5fSMatt Macy *leftp -= namesize;
35856e5ad5fSMatt Macy
35956e5ad5fSMatt Macy return (ptr);
36056e5ad5fSMatt Macy }
36156e5ad5fSMatt Macy
36256e5ad5fSMatt Macy unsigned char *
nvpair_pack_null(const nvpair_t * nvp __unused,unsigned char * ptr,size_t * leftp __unused)36356e5ad5fSMatt Macy nvpair_pack_null(const nvpair_t *nvp __unused, unsigned char *ptr,
36456e5ad5fSMatt Macy size_t *leftp __unused)
36556e5ad5fSMatt Macy {
36656e5ad5fSMatt Macy
36756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
36856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
36956e5ad5fSMatt Macy
37056e5ad5fSMatt Macy return (ptr);
37156e5ad5fSMatt Macy }
37256e5ad5fSMatt Macy
37356e5ad5fSMatt Macy unsigned char *
nvpair_pack_bool(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)37456e5ad5fSMatt Macy nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
37556e5ad5fSMatt Macy {
37656e5ad5fSMatt Macy uint8_t value;
37756e5ad5fSMatt Macy
37856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
37956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
38056e5ad5fSMatt Macy
38156e5ad5fSMatt Macy value = (uint8_t)nvp->nvp_data;
38256e5ad5fSMatt Macy
38356e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(value));
38456e5ad5fSMatt Macy memcpy(ptr, &value, sizeof(value));
38556e5ad5fSMatt Macy ptr += sizeof(value);
38656e5ad5fSMatt Macy *leftp -= sizeof(value);
38756e5ad5fSMatt Macy
38856e5ad5fSMatt Macy return (ptr);
38956e5ad5fSMatt Macy }
39056e5ad5fSMatt Macy
39156e5ad5fSMatt Macy unsigned char *
nvpair_pack_number(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)39256e5ad5fSMatt Macy nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
39356e5ad5fSMatt Macy {
39456e5ad5fSMatt Macy uint64_t value;
39556e5ad5fSMatt Macy
39656e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
39756e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
39856e5ad5fSMatt Macy
39956e5ad5fSMatt Macy value = (uint64_t)nvp->nvp_data;
40056e5ad5fSMatt Macy
40156e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(value));
40256e5ad5fSMatt Macy memcpy(ptr, &value, sizeof(value));
40356e5ad5fSMatt Macy ptr += sizeof(value);
40456e5ad5fSMatt Macy *leftp -= sizeof(value);
40556e5ad5fSMatt Macy
40656e5ad5fSMatt Macy return (ptr);
40756e5ad5fSMatt Macy }
40856e5ad5fSMatt Macy
40956e5ad5fSMatt Macy unsigned char *
nvpair_pack_string(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)41056e5ad5fSMatt Macy nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
41156e5ad5fSMatt Macy {
41256e5ad5fSMatt Macy
41356e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
41456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
41556e5ad5fSMatt Macy
41656e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
41756e5ad5fSMatt Macy memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
41856e5ad5fSMatt Macy ptr += nvp->nvp_datasize;
41956e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize;
42056e5ad5fSMatt Macy
42156e5ad5fSMatt Macy return (ptr);
42256e5ad5fSMatt Macy }
42356e5ad5fSMatt Macy
42456e5ad5fSMatt Macy unsigned char *
nvpair_pack_nvlist_up(unsigned char * ptr,size_t * leftp)42556e5ad5fSMatt Macy nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
42656e5ad5fSMatt Macy {
42756e5ad5fSMatt Macy struct nvpair_header nvphdr;
42856e5ad5fSMatt Macy size_t namesize;
42956e5ad5fSMatt Macy const char *name = "";
43056e5ad5fSMatt Macy
43156e5ad5fSMatt Macy namesize = 1;
43256e5ad5fSMatt Macy nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
43356e5ad5fSMatt Macy nvphdr.nvph_namesize = namesize;
43456e5ad5fSMatt Macy nvphdr.nvph_datasize = 0;
43556e5ad5fSMatt Macy nvphdr.nvph_nitems = 0;
43656e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
43756e5ad5fSMatt Macy memcpy(ptr, &nvphdr, sizeof(nvphdr));
43856e5ad5fSMatt Macy ptr += sizeof(nvphdr);
43956e5ad5fSMatt Macy *leftp -= sizeof(nvphdr);
44056e5ad5fSMatt Macy
44156e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= namesize);
44256e5ad5fSMatt Macy memcpy(ptr, name, namesize);
44356e5ad5fSMatt Macy ptr += namesize;
44456e5ad5fSMatt Macy *leftp -= namesize;
44556e5ad5fSMatt Macy
44656e5ad5fSMatt Macy return (ptr);
44756e5ad5fSMatt Macy }
44856e5ad5fSMatt Macy
44956e5ad5fSMatt Macy unsigned char *
nvpair_pack_nvlist_array_next(unsigned char * ptr,size_t * leftp)45056e5ad5fSMatt Macy nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp)
45156e5ad5fSMatt Macy {
45256e5ad5fSMatt Macy struct nvpair_header nvphdr;
45356e5ad5fSMatt Macy size_t namesize;
45456e5ad5fSMatt Macy const char *name = "";
45556e5ad5fSMatt Macy
45656e5ad5fSMatt Macy namesize = 1;
45756e5ad5fSMatt Macy nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT;
45856e5ad5fSMatt Macy nvphdr.nvph_namesize = namesize;
45956e5ad5fSMatt Macy nvphdr.nvph_datasize = 0;
46056e5ad5fSMatt Macy nvphdr.nvph_nitems = 0;
46156e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
46256e5ad5fSMatt Macy memcpy(ptr, &nvphdr, sizeof(nvphdr));
46356e5ad5fSMatt Macy ptr += sizeof(nvphdr);
46456e5ad5fSMatt Macy *leftp -= sizeof(nvphdr);
46556e5ad5fSMatt Macy
46656e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= namesize);
46756e5ad5fSMatt Macy memcpy(ptr, name, namesize);
46856e5ad5fSMatt Macy ptr += namesize;
46956e5ad5fSMatt Macy *leftp -= namesize;
47056e5ad5fSMatt Macy
47156e5ad5fSMatt Macy return (ptr);
47256e5ad5fSMatt Macy }
47356e5ad5fSMatt Macy
47456e5ad5fSMatt Macy #ifndef _KERNEL
47556e5ad5fSMatt Macy unsigned char *
nvpair_pack_descriptor(const nvpair_t * nvp,unsigned char * ptr,int64_t * fdidxp,size_t * leftp)47656e5ad5fSMatt Macy nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
47756e5ad5fSMatt Macy size_t *leftp)
47856e5ad5fSMatt Macy {
47956e5ad5fSMatt Macy int64_t value;
48056e5ad5fSMatt Macy
48156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
48256e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
48356e5ad5fSMatt Macy
48456e5ad5fSMatt Macy value = (int64_t)nvp->nvp_data;
48556e5ad5fSMatt Macy if (value != -1) {
48656e5ad5fSMatt Macy /*
48756e5ad5fSMatt Macy * If there is a real descriptor here, we change its number
48856e5ad5fSMatt Macy * to position in the array of descriptors send via control
48956e5ad5fSMatt Macy * message.
49056e5ad5fSMatt Macy */
49156e5ad5fSMatt Macy PJDLOG_ASSERT(fdidxp != NULL);
49256e5ad5fSMatt Macy
49356e5ad5fSMatt Macy value = *fdidxp;
49456e5ad5fSMatt Macy (*fdidxp)++;
49556e5ad5fSMatt Macy }
49656e5ad5fSMatt Macy
49756e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(value));
49856e5ad5fSMatt Macy memcpy(ptr, &value, sizeof(value));
49956e5ad5fSMatt Macy ptr += sizeof(value);
50056e5ad5fSMatt Macy *leftp -= sizeof(value);
50156e5ad5fSMatt Macy
50256e5ad5fSMatt Macy return (ptr);
50356e5ad5fSMatt Macy }
50456e5ad5fSMatt Macy #endif
50556e5ad5fSMatt Macy
50656e5ad5fSMatt Macy unsigned char *
nvpair_pack_binary(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)50756e5ad5fSMatt Macy nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
50856e5ad5fSMatt Macy {
50956e5ad5fSMatt Macy
51056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
51156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
51256e5ad5fSMatt Macy
51356e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
51456e5ad5fSMatt Macy memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
51556e5ad5fSMatt Macy ptr += nvp->nvp_datasize;
51656e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize;
51756e5ad5fSMatt Macy
51856e5ad5fSMatt Macy return (ptr);
51956e5ad5fSMatt Macy }
52056e5ad5fSMatt Macy
52156e5ad5fSMatt Macy unsigned char *
nvpair_pack_bool_array(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)52256e5ad5fSMatt Macy nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
52356e5ad5fSMatt Macy {
52456e5ad5fSMatt Macy
52556e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
52656e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
52756e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
52856e5ad5fSMatt Macy
52956e5ad5fSMatt Macy memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
53056e5ad5fSMatt Macy ptr += nvp->nvp_datasize;
53156e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize;
53256e5ad5fSMatt Macy
53356e5ad5fSMatt Macy return (ptr);
53456e5ad5fSMatt Macy }
53556e5ad5fSMatt Macy
53656e5ad5fSMatt Macy unsigned char *
nvpair_pack_number_array(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)53756e5ad5fSMatt Macy nvpair_pack_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
53856e5ad5fSMatt Macy {
53956e5ad5fSMatt Macy
54056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
54156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
54256e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
54356e5ad5fSMatt Macy
54456e5ad5fSMatt Macy memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
54556e5ad5fSMatt Macy ptr += nvp->nvp_datasize;
54656e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize;
54756e5ad5fSMatt Macy
54856e5ad5fSMatt Macy return (ptr);
54956e5ad5fSMatt Macy }
55056e5ad5fSMatt Macy
55156e5ad5fSMatt Macy unsigned char *
nvpair_pack_string_array(const nvpair_t * nvp,unsigned char * ptr,size_t * leftp)55256e5ad5fSMatt Macy nvpair_pack_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
55356e5ad5fSMatt Macy {
55456e5ad5fSMatt Macy unsigned int ii;
5553fbf4ca6SJohn Baldwin size_t size __unused, len;
55656e5ad5fSMatt Macy const char * const *array;
55756e5ad5fSMatt Macy
55856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
55956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
56056e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
56156e5ad5fSMatt Macy
56256e5ad5fSMatt Macy size = 0;
56356e5ad5fSMatt Macy array = nvpair_get_string_array(nvp, NULL);
56456e5ad5fSMatt Macy PJDLOG_ASSERT(array != NULL);
56556e5ad5fSMatt Macy
56656e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) {
56756e5ad5fSMatt Macy len = strlen(array[ii]) + 1;
56856e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= len);
56956e5ad5fSMatt Macy
57056e5ad5fSMatt Macy memcpy(ptr, (const void *)array[ii], len);
57156e5ad5fSMatt Macy size += len;
57256e5ad5fSMatt Macy ptr += len;
57356e5ad5fSMatt Macy *leftp -= len;
57456e5ad5fSMatt Macy }
57556e5ad5fSMatt Macy
57656e5ad5fSMatt Macy PJDLOG_ASSERT(size == nvp->nvp_datasize);
57756e5ad5fSMatt Macy
57856e5ad5fSMatt Macy return (ptr);
57956e5ad5fSMatt Macy }
58056e5ad5fSMatt Macy
58156e5ad5fSMatt Macy #ifndef _KERNEL
58256e5ad5fSMatt Macy unsigned char *
nvpair_pack_descriptor_array(const nvpair_t * nvp,unsigned char * ptr,int64_t * fdidxp,size_t * leftp)58356e5ad5fSMatt Macy nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr,
58456e5ad5fSMatt Macy int64_t *fdidxp, size_t *leftp)
58556e5ad5fSMatt Macy {
58656e5ad5fSMatt Macy int64_t value;
58756e5ad5fSMatt Macy const int *array;
58856e5ad5fSMatt Macy unsigned int ii;
58956e5ad5fSMatt Macy
59056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
59156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
59256e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
59356e5ad5fSMatt Macy
59456e5ad5fSMatt Macy array = nvpair_get_descriptor_array(nvp, NULL);
59556e5ad5fSMatt Macy PJDLOG_ASSERT(array != NULL);
59656e5ad5fSMatt Macy
59756e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) {
59856e5ad5fSMatt Macy PJDLOG_ASSERT(*leftp >= sizeof(value));
59956e5ad5fSMatt Macy
60056e5ad5fSMatt Macy value = array[ii];
60156e5ad5fSMatt Macy if (value != -1) {
60256e5ad5fSMatt Macy /*
60356e5ad5fSMatt Macy * If there is a real descriptor here, we change its
60456e5ad5fSMatt Macy * number to position in the array of descriptors send
60556e5ad5fSMatt Macy * via control message.
60656e5ad5fSMatt Macy */
60756e5ad5fSMatt Macy PJDLOG_ASSERT(fdidxp != NULL);
60856e5ad5fSMatt Macy
60956e5ad5fSMatt Macy value = *fdidxp;
61056e5ad5fSMatt Macy (*fdidxp)++;
61156e5ad5fSMatt Macy }
61256e5ad5fSMatt Macy memcpy(ptr, &value, sizeof(value));
61356e5ad5fSMatt Macy ptr += sizeof(value);
61456e5ad5fSMatt Macy *leftp -= sizeof(value);
61556e5ad5fSMatt Macy }
61656e5ad5fSMatt Macy
61756e5ad5fSMatt Macy return (ptr);
61856e5ad5fSMatt Macy }
61956e5ad5fSMatt Macy #endif
62056e5ad5fSMatt Macy
62156e5ad5fSMatt Macy void
nvpair_init_datasize(nvpair_t * nvp)62256e5ad5fSMatt Macy nvpair_init_datasize(nvpair_t *nvp)
62356e5ad5fSMatt Macy {
62456e5ad5fSMatt Macy
62556e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
62656e5ad5fSMatt Macy
62756e5ad5fSMatt Macy if (nvp->nvp_type == NV_TYPE_NVLIST) {
62856e5ad5fSMatt Macy if (nvp->nvp_data == 0) {
62956e5ad5fSMatt Macy nvp->nvp_datasize = 0;
63056e5ad5fSMatt Macy } else {
63156e5ad5fSMatt Macy nvp->nvp_datasize =
63256e5ad5fSMatt Macy nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
63356e5ad5fSMatt Macy }
63456e5ad5fSMatt Macy }
63556e5ad5fSMatt Macy }
63656e5ad5fSMatt Macy
63756e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_header(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)63856e5ad5fSMatt Macy nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
63956e5ad5fSMatt Macy size_t *leftp)
64056e5ad5fSMatt Macy {
64156e5ad5fSMatt Macy struct nvpair_header nvphdr;
64256e5ad5fSMatt Macy
64356e5ad5fSMatt Macy if (*leftp < sizeof(nvphdr))
64456e5ad5fSMatt Macy goto fail;
64556e5ad5fSMatt Macy
64656e5ad5fSMatt Macy memcpy(&nvphdr, ptr, sizeof(nvphdr));
64756e5ad5fSMatt Macy ptr += sizeof(nvphdr);
64856e5ad5fSMatt Macy *leftp -= sizeof(nvphdr);
64956e5ad5fSMatt Macy
65056e5ad5fSMatt Macy #if NV_TYPE_FIRST > 0
65156e5ad5fSMatt Macy if (nvphdr.nvph_type < NV_TYPE_FIRST)
65256e5ad5fSMatt Macy goto fail;
65356e5ad5fSMatt Macy #endif
65456e5ad5fSMatt Macy if (nvphdr.nvph_type > NV_TYPE_LAST &&
65556e5ad5fSMatt Macy nvphdr.nvph_type != NV_TYPE_NVLIST_UP &&
65656e5ad5fSMatt Macy nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) {
65756e5ad5fSMatt Macy goto fail;
65856e5ad5fSMatt Macy }
65956e5ad5fSMatt Macy
66056e5ad5fSMatt Macy #if BYTE_ORDER == BIG_ENDIAN
66156e5ad5fSMatt Macy if (!isbe) {
66256e5ad5fSMatt Macy nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
66356e5ad5fSMatt Macy nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
664e673ac3fSStefan Grundmann nvphdr.nvph_nitems = le64toh(nvphdr.nvph_nitems);
66556e5ad5fSMatt Macy }
66656e5ad5fSMatt Macy #else
66756e5ad5fSMatt Macy if (isbe) {
66856e5ad5fSMatt Macy nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
66956e5ad5fSMatt Macy nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
670e673ac3fSStefan Grundmann nvphdr.nvph_nitems = be64toh(nvphdr.nvph_nitems);
67156e5ad5fSMatt Macy }
67256e5ad5fSMatt Macy #endif
67356e5ad5fSMatt Macy
67456e5ad5fSMatt Macy if (nvphdr.nvph_namesize > NV_NAME_MAX)
67556e5ad5fSMatt Macy goto fail;
67656e5ad5fSMatt Macy if (*leftp < nvphdr.nvph_namesize)
67756e5ad5fSMatt Macy goto fail;
67856e5ad5fSMatt Macy if (nvphdr.nvph_namesize < 1)
67956e5ad5fSMatt Macy goto fail;
68056e5ad5fSMatt Macy if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
68156e5ad5fSMatt Macy (size_t)(nvphdr.nvph_namesize - 1)) {
68256e5ad5fSMatt Macy goto fail;
68356e5ad5fSMatt Macy }
68456e5ad5fSMatt Macy
68556e5ad5fSMatt Macy memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
68656e5ad5fSMatt Macy ptr += nvphdr.nvph_namesize;
68756e5ad5fSMatt Macy *leftp -= nvphdr.nvph_namesize;
68856e5ad5fSMatt Macy
68956e5ad5fSMatt Macy if (*leftp < nvphdr.nvph_datasize)
69056e5ad5fSMatt Macy goto fail;
69156e5ad5fSMatt Macy
69256e5ad5fSMatt Macy nvp->nvp_type = nvphdr.nvph_type;
69356e5ad5fSMatt Macy nvp->nvp_data = 0;
69456e5ad5fSMatt Macy nvp->nvp_datasize = nvphdr.nvph_datasize;
69556e5ad5fSMatt Macy nvp->nvp_nitems = nvphdr.nvph_nitems;
69656e5ad5fSMatt Macy
69756e5ad5fSMatt Macy return (ptr);
69856e5ad5fSMatt Macy fail:
69956e5ad5fSMatt Macy ERRNO_SET(EINVAL);
70056e5ad5fSMatt Macy return (NULL);
70156e5ad5fSMatt Macy }
70256e5ad5fSMatt Macy
70356e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_null(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp __unused)70456e5ad5fSMatt Macy nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
70556e5ad5fSMatt Macy size_t *leftp __unused)
70656e5ad5fSMatt Macy {
70756e5ad5fSMatt Macy
70856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
70956e5ad5fSMatt Macy
71056e5ad5fSMatt Macy if (nvp->nvp_datasize != 0) {
71156e5ad5fSMatt Macy ERRNO_SET(EINVAL);
71256e5ad5fSMatt Macy return (NULL);
71356e5ad5fSMatt Macy }
71456e5ad5fSMatt Macy
71556e5ad5fSMatt Macy return (ptr);
71656e5ad5fSMatt Macy }
71756e5ad5fSMatt Macy
71856e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_bool(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)71956e5ad5fSMatt Macy nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
72056e5ad5fSMatt Macy size_t *leftp)
72156e5ad5fSMatt Macy {
72256e5ad5fSMatt Macy uint8_t value;
72356e5ad5fSMatt Macy
72456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
72556e5ad5fSMatt Macy
72656e5ad5fSMatt Macy if (nvp->nvp_datasize != sizeof(value)) {
72756e5ad5fSMatt Macy ERRNO_SET(EINVAL);
72856e5ad5fSMatt Macy return (NULL);
72956e5ad5fSMatt Macy }
73056e5ad5fSMatt Macy if (*leftp < sizeof(value)) {
73156e5ad5fSMatt Macy ERRNO_SET(EINVAL);
73256e5ad5fSMatt Macy return (NULL);
73356e5ad5fSMatt Macy }
73456e5ad5fSMatt Macy
73556e5ad5fSMatt Macy memcpy(&value, ptr, sizeof(value));
73656e5ad5fSMatt Macy ptr += sizeof(value);
73756e5ad5fSMatt Macy *leftp -= sizeof(value);
73856e5ad5fSMatt Macy
73956e5ad5fSMatt Macy if (value != 0 && value != 1) {
74056e5ad5fSMatt Macy ERRNO_SET(EINVAL);
74156e5ad5fSMatt Macy return (NULL);
74256e5ad5fSMatt Macy }
74356e5ad5fSMatt Macy
74456e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)value;
74556e5ad5fSMatt Macy
74656e5ad5fSMatt Macy return (ptr);
74756e5ad5fSMatt Macy }
74856e5ad5fSMatt Macy
74956e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_number(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)75056e5ad5fSMatt Macy nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
75156e5ad5fSMatt Macy size_t *leftp)
75256e5ad5fSMatt Macy {
75356e5ad5fSMatt Macy
75456e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
75556e5ad5fSMatt Macy
75656e5ad5fSMatt Macy if (nvp->nvp_datasize != sizeof(uint64_t)) {
75756e5ad5fSMatt Macy ERRNO_SET(EINVAL);
75856e5ad5fSMatt Macy return (NULL);
75956e5ad5fSMatt Macy }
76056e5ad5fSMatt Macy if (*leftp < sizeof(uint64_t)) {
76156e5ad5fSMatt Macy ERRNO_SET(EINVAL);
76256e5ad5fSMatt Macy return (NULL);
76356e5ad5fSMatt Macy }
76456e5ad5fSMatt Macy
76556e5ad5fSMatt Macy if (isbe)
76656e5ad5fSMatt Macy nvp->nvp_data = be64dec(ptr);
76756e5ad5fSMatt Macy else
76856e5ad5fSMatt Macy nvp->nvp_data = le64dec(ptr);
76956e5ad5fSMatt Macy
77056e5ad5fSMatt Macy ptr += sizeof(uint64_t);
77156e5ad5fSMatt Macy *leftp -= sizeof(uint64_t);
77256e5ad5fSMatt Macy
77356e5ad5fSMatt Macy return (ptr);
77456e5ad5fSMatt Macy }
77556e5ad5fSMatt Macy
77656e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_string(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)77756e5ad5fSMatt Macy nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
77856e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp)
77956e5ad5fSMatt Macy {
78056e5ad5fSMatt Macy
78156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
78256e5ad5fSMatt Macy
78356e5ad5fSMatt Macy if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
78456e5ad5fSMatt Macy ERRNO_SET(EINVAL);
78556e5ad5fSMatt Macy return (NULL);
78656e5ad5fSMatt Macy }
78756e5ad5fSMatt Macy
78856e5ad5fSMatt Macy if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
78956e5ad5fSMatt Macy nvp->nvp_datasize - 1) {
79056e5ad5fSMatt Macy ERRNO_SET(EINVAL);
79156e5ad5fSMatt Macy return (NULL);
79256e5ad5fSMatt Macy }
79356e5ad5fSMatt Macy
79456e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
79556e5ad5fSMatt Macy if (nvp->nvp_data == 0)
79656e5ad5fSMatt Macy return (NULL);
79756e5ad5fSMatt Macy
79856e5ad5fSMatt Macy ptr += nvp->nvp_datasize;
79956e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize;
80056e5ad5fSMatt Macy
80156e5ad5fSMatt Macy return (ptr);
80256e5ad5fSMatt Macy }
80356e5ad5fSMatt Macy
80456e5ad5fSMatt Macy 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)80556e5ad5fSMatt Macy nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
80656e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
80756e5ad5fSMatt Macy {
80856e5ad5fSMatt Macy nvlist_t *value;
80956e5ad5fSMatt Macy
81056e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
81156e5ad5fSMatt Macy
81256e5ad5fSMatt Macy if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
81356e5ad5fSMatt Macy ERRNO_SET(EINVAL);
81456e5ad5fSMatt Macy return (NULL);
81556e5ad5fSMatt Macy }
81656e5ad5fSMatt Macy
81756e5ad5fSMatt Macy value = nvlist_create(0);
81856e5ad5fSMatt Macy if (value == NULL)
81956e5ad5fSMatt Macy return (NULL);
82056e5ad5fSMatt Macy
82156e5ad5fSMatt Macy ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
82256e5ad5fSMatt Macy if (ptr == NULL)
82356e5ad5fSMatt Macy return (NULL);
82456e5ad5fSMatt Macy
82556e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value;
82656e5ad5fSMatt Macy *child = value;
82756e5ad5fSMatt Macy
82856e5ad5fSMatt Macy return (ptr);
82956e5ad5fSMatt Macy }
83056e5ad5fSMatt Macy
83156e5ad5fSMatt Macy #ifndef _KERNEL
83256e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_descriptor(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,const int * fds,size_t nfds)83356e5ad5fSMatt Macy nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
83456e5ad5fSMatt Macy size_t *leftp, const int *fds, size_t nfds)
83556e5ad5fSMatt Macy {
83656e5ad5fSMatt Macy int64_t idx;
83756e5ad5fSMatt Macy
83856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
83956e5ad5fSMatt Macy
84056e5ad5fSMatt Macy if (nvp->nvp_datasize != sizeof(idx)) {
84156e5ad5fSMatt Macy ERRNO_SET(EINVAL);
84256e5ad5fSMatt Macy return (NULL);
84356e5ad5fSMatt Macy }
84456e5ad5fSMatt Macy if (*leftp < sizeof(idx)) {
84556e5ad5fSMatt Macy ERRNO_SET(EINVAL);
84656e5ad5fSMatt Macy return (NULL);
84756e5ad5fSMatt Macy }
84856e5ad5fSMatt Macy
84956e5ad5fSMatt Macy if (isbe)
85056e5ad5fSMatt Macy idx = be64dec(ptr);
85156e5ad5fSMatt Macy else
85256e5ad5fSMatt Macy idx = le64dec(ptr);
85356e5ad5fSMatt Macy
85456e5ad5fSMatt Macy if (idx < 0) {
85556e5ad5fSMatt Macy ERRNO_SET(EINVAL);
85656e5ad5fSMatt Macy return (NULL);
85756e5ad5fSMatt Macy }
85856e5ad5fSMatt Macy
85956e5ad5fSMatt Macy if ((size_t)idx >= nfds) {
86056e5ad5fSMatt Macy ERRNO_SET(EINVAL);
86156e5ad5fSMatt Macy return (NULL);
86256e5ad5fSMatt Macy }
86356e5ad5fSMatt Macy
86456e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)fds[idx];
86556e5ad5fSMatt Macy
86656e5ad5fSMatt Macy ptr += sizeof(idx);
86756e5ad5fSMatt Macy *leftp -= sizeof(idx);
86856e5ad5fSMatt Macy
86956e5ad5fSMatt Macy return (ptr);
87056e5ad5fSMatt Macy }
87156e5ad5fSMatt Macy #endif
87256e5ad5fSMatt Macy
87356e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_binary(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)87456e5ad5fSMatt Macy nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
87556e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp)
87656e5ad5fSMatt Macy {
87756e5ad5fSMatt Macy void *value;
87856e5ad5fSMatt Macy
87956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
88056e5ad5fSMatt Macy
88156e5ad5fSMatt Macy if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
88256e5ad5fSMatt Macy ERRNO_SET(EINVAL);
88356e5ad5fSMatt Macy return (NULL);
88456e5ad5fSMatt Macy }
88556e5ad5fSMatt Macy
88656e5ad5fSMatt Macy value = nv_malloc(nvp->nvp_datasize);
88756e5ad5fSMatt Macy if (value == NULL)
88856e5ad5fSMatt Macy return (NULL);
88956e5ad5fSMatt Macy
89056e5ad5fSMatt Macy memcpy(value, ptr, nvp->nvp_datasize);
89156e5ad5fSMatt Macy ptr += nvp->nvp_datasize;
89256e5ad5fSMatt Macy *leftp -= nvp->nvp_datasize;
89356e5ad5fSMatt Macy
89456e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value;
89556e5ad5fSMatt Macy
89656e5ad5fSMatt Macy return (ptr);
89756e5ad5fSMatt Macy }
89856e5ad5fSMatt Macy
89956e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_bool_array(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)90056e5ad5fSMatt Macy nvpair_unpack_bool_array(bool isbe __unused, nvpair_t *nvp,
90156e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp)
90256e5ad5fSMatt Macy {
90356e5ad5fSMatt Macy uint8_t *value;
90456e5ad5fSMatt Macy size_t size;
90556e5ad5fSMatt Macy unsigned int i;
90656e5ad5fSMatt Macy
90756e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
90856e5ad5fSMatt Macy
90956e5ad5fSMatt Macy size = sizeof(*value) * nvp->nvp_nitems;
91056e5ad5fSMatt Macy if (nvp->nvp_datasize != size || *leftp < size ||
91156e5ad5fSMatt Macy nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
91256e5ad5fSMatt Macy ERRNO_SET(EINVAL);
91356e5ad5fSMatt Macy return (NULL);
91456e5ad5fSMatt Macy }
91556e5ad5fSMatt Macy
91656e5ad5fSMatt Macy value = nv_malloc(size);
91756e5ad5fSMatt Macy if (value == NULL)
91856e5ad5fSMatt Macy return (NULL);
91956e5ad5fSMatt Macy
92056e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) {
92156e5ad5fSMatt Macy value[i] = *(const uint8_t *)ptr;
92256e5ad5fSMatt Macy
92356e5ad5fSMatt Macy ptr += sizeof(*value);
92456e5ad5fSMatt Macy *leftp -= sizeof(*value);
92556e5ad5fSMatt Macy }
92656e5ad5fSMatt Macy
92756e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value;
92856e5ad5fSMatt Macy
92956e5ad5fSMatt Macy return (ptr);
93056e5ad5fSMatt Macy }
93156e5ad5fSMatt Macy
93256e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_number_array(bool isbe,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)93356e5ad5fSMatt Macy nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
93456e5ad5fSMatt Macy size_t *leftp)
93556e5ad5fSMatt Macy {
93656e5ad5fSMatt Macy uint64_t *value;
93756e5ad5fSMatt Macy size_t size;
93856e5ad5fSMatt Macy unsigned int i;
93956e5ad5fSMatt Macy
94056e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
94156e5ad5fSMatt Macy
94256e5ad5fSMatt Macy size = sizeof(*value) * nvp->nvp_nitems;
94356e5ad5fSMatt Macy if (nvp->nvp_datasize != size || *leftp < size ||
94456e5ad5fSMatt Macy nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
94556e5ad5fSMatt Macy ERRNO_SET(EINVAL);
94656e5ad5fSMatt Macy return (NULL);
94756e5ad5fSMatt Macy }
94856e5ad5fSMatt Macy
94956e5ad5fSMatt Macy value = nv_malloc(size);
95056e5ad5fSMatt Macy if (value == NULL)
95156e5ad5fSMatt Macy return (NULL);
95256e5ad5fSMatt Macy
95356e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) {
95456e5ad5fSMatt Macy if (isbe)
95556e5ad5fSMatt Macy value[i] = be64dec(ptr);
95656e5ad5fSMatt Macy else
95756e5ad5fSMatt Macy value[i] = le64dec(ptr);
95856e5ad5fSMatt Macy
95956e5ad5fSMatt Macy ptr += sizeof(*value);
96056e5ad5fSMatt Macy *leftp -= sizeof(*value);
96156e5ad5fSMatt Macy }
96256e5ad5fSMatt Macy
96356e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value;
96456e5ad5fSMatt Macy
96556e5ad5fSMatt Macy return (ptr);
96656e5ad5fSMatt Macy }
96756e5ad5fSMatt Macy
96856e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_string_array(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp)96956e5ad5fSMatt Macy nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp,
97056e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp)
97156e5ad5fSMatt Macy {
97256e5ad5fSMatt Macy ssize_t size;
97356e5ad5fSMatt Macy size_t len;
97456e5ad5fSMatt Macy const char *tmp;
97556e5ad5fSMatt Macy char **value;
97656e5ad5fSMatt Macy unsigned int ii, j;
97756e5ad5fSMatt Macy
97856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
97956e5ad5fSMatt Macy
98056e5ad5fSMatt Macy if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 ||
98156e5ad5fSMatt Macy nvp->nvp_nitems == 0) {
98256e5ad5fSMatt Macy ERRNO_SET(EINVAL);
98356e5ad5fSMatt Macy return (NULL);
98456e5ad5fSMatt Macy }
98556e5ad5fSMatt Macy
98656e5ad5fSMatt Macy size = nvp->nvp_datasize;
98756e5ad5fSMatt Macy tmp = (const char *)ptr;
98856e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) {
98956e5ad5fSMatt Macy len = strnlen(tmp, size - 1) + 1;
99056e5ad5fSMatt Macy size -= len;
991*3aaaca1bSMariusz Zaborski if (tmp[len - 1] != '\0') {
992*3aaaca1bSMariusz Zaborski ERRNO_SET(EINVAL);
993*3aaaca1bSMariusz Zaborski return (NULL);
994*3aaaca1bSMariusz Zaborski }
99556e5ad5fSMatt Macy if (size < 0) {
99656e5ad5fSMatt Macy ERRNO_SET(EINVAL);
99756e5ad5fSMatt Macy return (NULL);
99856e5ad5fSMatt Macy }
99956e5ad5fSMatt Macy tmp += len;
100056e5ad5fSMatt Macy }
100156e5ad5fSMatt Macy if (size != 0) {
100256e5ad5fSMatt Macy ERRNO_SET(EINVAL);
100356e5ad5fSMatt Macy return (NULL);
100456e5ad5fSMatt Macy }
100556e5ad5fSMatt Macy
100636fa90dbSMariusz Zaborski value = nv_calloc(nvp->nvp_nitems, sizeof(*value));
100756e5ad5fSMatt Macy if (value == NULL)
100856e5ad5fSMatt Macy return (NULL);
100956e5ad5fSMatt Macy
101056e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) {
101156e5ad5fSMatt Macy value[ii] = nv_strdup((const char *)ptr);
101256e5ad5fSMatt Macy if (value[ii] == NULL)
101356e5ad5fSMatt Macy goto out;
101456e5ad5fSMatt Macy len = strlen(value[ii]) + 1;
101556e5ad5fSMatt Macy ptr += len;
101656e5ad5fSMatt Macy *leftp -= len;
101756e5ad5fSMatt Macy }
101856e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value;
101956e5ad5fSMatt Macy
102056e5ad5fSMatt Macy return (ptr);
102156e5ad5fSMatt Macy out:
102256e5ad5fSMatt Macy for (j = 0; j < ii; j++)
102356e5ad5fSMatt Macy nv_free(value[j]);
102456e5ad5fSMatt Macy nv_free(value);
102556e5ad5fSMatt Macy return (NULL);
102656e5ad5fSMatt Macy }
102756e5ad5fSMatt Macy
102856e5ad5fSMatt Macy #ifndef _KERNEL
102956e5ad5fSMatt Macy 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)103056e5ad5fSMatt Macy nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp,
103156e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
103256e5ad5fSMatt Macy {
103356e5ad5fSMatt Macy int64_t idx;
103456e5ad5fSMatt Macy size_t size;
103556e5ad5fSMatt Macy unsigned int ii;
103656e5ad5fSMatt Macy int *array;
103756e5ad5fSMatt Macy
103856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
103956e5ad5fSMatt Macy
104056e5ad5fSMatt Macy size = sizeof(idx) * nvp->nvp_nitems;
104156e5ad5fSMatt Macy if (nvp->nvp_datasize != size || *leftp < size ||
104256e5ad5fSMatt Macy nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) {
104356e5ad5fSMatt Macy ERRNO_SET(EINVAL);
104456e5ad5fSMatt Macy return (NULL);
104556e5ad5fSMatt Macy }
104656e5ad5fSMatt Macy
104756e5ad5fSMatt Macy array = (int *)nv_malloc(size);
104856e5ad5fSMatt Macy if (array == NULL)
104956e5ad5fSMatt Macy return (NULL);
105056e5ad5fSMatt Macy
105156e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) {
105256e5ad5fSMatt Macy if (isbe)
105356e5ad5fSMatt Macy idx = be64dec(ptr);
105456e5ad5fSMatt Macy else
105556e5ad5fSMatt Macy idx = le64dec(ptr);
105656e5ad5fSMatt Macy
105756e5ad5fSMatt Macy if (idx < 0) {
105856e5ad5fSMatt Macy ERRNO_SET(EINVAL);
105956e5ad5fSMatt Macy nv_free(array);
106056e5ad5fSMatt Macy return (NULL);
106156e5ad5fSMatt Macy }
106256e5ad5fSMatt Macy
106356e5ad5fSMatt Macy if ((size_t)idx >= nfds) {
106456e5ad5fSMatt Macy ERRNO_SET(EINVAL);
106556e5ad5fSMatt Macy nv_free(array);
106656e5ad5fSMatt Macy return (NULL);
106756e5ad5fSMatt Macy }
106856e5ad5fSMatt Macy
106956e5ad5fSMatt Macy array[ii] = (uint64_t)fds[idx];
107056e5ad5fSMatt Macy
107156e5ad5fSMatt Macy ptr += sizeof(idx);
107256e5ad5fSMatt Macy *leftp -= sizeof(idx);
107356e5ad5fSMatt Macy }
107456e5ad5fSMatt Macy
107556e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)array;
107656e5ad5fSMatt Macy
107756e5ad5fSMatt Macy return (ptr);
107856e5ad5fSMatt Macy }
107956e5ad5fSMatt Macy #endif
108056e5ad5fSMatt Macy
108156e5ad5fSMatt Macy const unsigned char *
nvpair_unpack_nvlist_array(bool isbe __unused,nvpair_t * nvp,const unsigned char * ptr,size_t * leftp,nvlist_t ** firstel)108256e5ad5fSMatt Macy nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp,
108356e5ad5fSMatt Macy const unsigned char *ptr, size_t *leftp, nvlist_t **firstel)
108456e5ad5fSMatt Macy {
108556e5ad5fSMatt Macy nvlist_t **value;
108656e5ad5fSMatt Macy nvpair_t *tmpnvp;
108756e5ad5fSMatt Macy unsigned int ii, j;
108856e5ad5fSMatt Macy size_t sizeup;
108956e5ad5fSMatt Macy
109056e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
109156e5ad5fSMatt Macy
109256e5ad5fSMatt Macy sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems;
109356e5ad5fSMatt Macy if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems ||
109456e5ad5fSMatt Macy sizeup > *leftp) {
109556e5ad5fSMatt Macy ERRNO_SET(EINVAL);
109656e5ad5fSMatt Macy return (NULL);
109756e5ad5fSMatt Macy }
109856e5ad5fSMatt Macy
109936fa90dbSMariusz Zaborski value = nv_calloc(nvp->nvp_nitems, sizeof(*value));
110056e5ad5fSMatt Macy if (value == NULL)
110156e5ad5fSMatt Macy return (NULL);
110256e5ad5fSMatt Macy
110356e5ad5fSMatt Macy for (ii = 0; ii < nvp->nvp_nitems; ii++) {
110456e5ad5fSMatt Macy value[ii] = nvlist_create(0);
110556e5ad5fSMatt Macy if (value[ii] == NULL)
110656e5ad5fSMatt Macy goto fail;
110756e5ad5fSMatt Macy if (ii > 0) {
110856e5ad5fSMatt Macy tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
110956e5ad5fSMatt Macy (uint64_t)(uintptr_t)value[ii], 0, 0);
111056e5ad5fSMatt Macy if (tmpnvp == NULL)
111156e5ad5fSMatt Macy goto fail;
111256e5ad5fSMatt Macy nvlist_set_array_next(value[ii - 1], tmpnvp);
111356e5ad5fSMatt Macy }
111456e5ad5fSMatt Macy }
111556e5ad5fSMatt Macy nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY);
111656e5ad5fSMatt Macy
111756e5ad5fSMatt Macy nvp->nvp_data = (uint64_t)(uintptr_t)value;
111856e5ad5fSMatt Macy *firstel = value[0];
111956e5ad5fSMatt Macy
112056e5ad5fSMatt Macy return (ptr);
112156e5ad5fSMatt Macy fail:
112256e5ad5fSMatt Macy ERRNO_SAVE();
112356e5ad5fSMatt Macy for (j = 0; j <= ii; j++)
112456e5ad5fSMatt Macy nvlist_destroy(value[j]);
112556e5ad5fSMatt Macy nv_free(value);
112656e5ad5fSMatt Macy ERRNO_RESTORE();
112756e5ad5fSMatt Macy
112856e5ad5fSMatt Macy return (NULL);
112956e5ad5fSMatt Macy }
113056e5ad5fSMatt Macy
113156e5ad5fSMatt Macy const unsigned char *
nvpair_unpack(bool isbe,const unsigned char * ptr,size_t * leftp,nvpair_t ** nvpp)113256e5ad5fSMatt Macy nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
113356e5ad5fSMatt Macy nvpair_t **nvpp)
113456e5ad5fSMatt Macy {
113556e5ad5fSMatt Macy nvpair_t *nvp, *tmp;
113656e5ad5fSMatt Macy
113756e5ad5fSMatt Macy nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
113856e5ad5fSMatt Macy if (nvp == NULL)
113956e5ad5fSMatt Macy return (NULL);
114056e5ad5fSMatt Macy nvp->nvp_name = (char *)(nvp + 1);
114156e5ad5fSMatt Macy
114256e5ad5fSMatt Macy ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
114356e5ad5fSMatt Macy if (ptr == NULL)
114456e5ad5fSMatt Macy goto fail;
114556e5ad5fSMatt Macy tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
114656e5ad5fSMatt Macy if (tmp == NULL)
114756e5ad5fSMatt Macy goto fail;
114856e5ad5fSMatt Macy nvp = tmp;
114956e5ad5fSMatt Macy
115056e5ad5fSMatt Macy /* Update nvp_name after realloc(). */
115156e5ad5fSMatt Macy nvp->nvp_name = (char *)(nvp + 1);
115256e5ad5fSMatt Macy nvp->nvp_data = 0x00;
115356e5ad5fSMatt Macy nvp->nvp_magic = NVPAIR_MAGIC;
115456e5ad5fSMatt Macy *nvpp = nvp;
115556e5ad5fSMatt Macy return (ptr);
115656e5ad5fSMatt Macy fail:
115756e5ad5fSMatt Macy nv_free(nvp);
115856e5ad5fSMatt Macy return (NULL);
115956e5ad5fSMatt Macy }
116056e5ad5fSMatt Macy
116156e5ad5fSMatt Macy int
nvpair_type(const nvpair_t * nvp)116256e5ad5fSMatt Macy nvpair_type(const nvpair_t *nvp)
116356e5ad5fSMatt Macy {
116456e5ad5fSMatt Macy
116556e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
116656e5ad5fSMatt Macy
116756e5ad5fSMatt Macy return (nvp->nvp_type);
116856e5ad5fSMatt Macy }
116956e5ad5fSMatt Macy
117056e5ad5fSMatt Macy const char *
nvpair_name(const nvpair_t * nvp)117156e5ad5fSMatt Macy nvpair_name(const nvpair_t *nvp)
117256e5ad5fSMatt Macy {
117356e5ad5fSMatt Macy
117456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
117556e5ad5fSMatt Macy
117656e5ad5fSMatt Macy return (nvp->nvp_name);
117756e5ad5fSMatt Macy }
117856e5ad5fSMatt Macy
117956e5ad5fSMatt Macy nvpair_t *
nvpair_create_stringf(const char * name,const char * valuefmt,...)118056e5ad5fSMatt Macy nvpair_create_stringf(const char *name, const char *valuefmt, ...)
118156e5ad5fSMatt Macy {
118256e5ad5fSMatt Macy va_list valueap;
118356e5ad5fSMatt Macy nvpair_t *nvp;
118456e5ad5fSMatt Macy
118556e5ad5fSMatt Macy va_start(valueap, valuefmt);
118656e5ad5fSMatt Macy nvp = nvpair_create_stringv(name, valuefmt, valueap);
118756e5ad5fSMatt Macy va_end(valueap);
118856e5ad5fSMatt Macy
118956e5ad5fSMatt Macy return (nvp);
119056e5ad5fSMatt Macy }
119156e5ad5fSMatt Macy
119256e5ad5fSMatt Macy nvpair_t *
nvpair_create_stringv(const char * name,const char * valuefmt,va_list valueap)119356e5ad5fSMatt Macy nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
119456e5ad5fSMatt Macy {
119556e5ad5fSMatt Macy nvpair_t *nvp;
119656e5ad5fSMatt Macy char *str;
119756e5ad5fSMatt Macy int len;
119856e5ad5fSMatt Macy
119956e5ad5fSMatt Macy len = nv_vasprintf(&str, valuefmt, valueap);
120056e5ad5fSMatt Macy if (len < 0)
120156e5ad5fSMatt Macy return (NULL);
120256e5ad5fSMatt Macy nvp = nvpair_create_string(name, str);
120356e5ad5fSMatt Macy nv_free(str);
120456e5ad5fSMatt Macy return (nvp);
120556e5ad5fSMatt Macy }
120656e5ad5fSMatt Macy
120756e5ad5fSMatt Macy nvpair_t *
nvpair_create_null(const char * name)120856e5ad5fSMatt Macy nvpair_create_null(const char *name)
120956e5ad5fSMatt Macy {
121056e5ad5fSMatt Macy
121156e5ad5fSMatt Macy return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0));
121256e5ad5fSMatt Macy }
121356e5ad5fSMatt Macy
121456e5ad5fSMatt Macy nvpair_t *
nvpair_create_bool(const char * name,bool value)121556e5ad5fSMatt Macy nvpair_create_bool(const char *name, bool value)
121656e5ad5fSMatt Macy {
121756e5ad5fSMatt Macy
121856e5ad5fSMatt Macy return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
121956e5ad5fSMatt Macy sizeof(uint8_t), 0));
122056e5ad5fSMatt Macy }
122156e5ad5fSMatt Macy
122256e5ad5fSMatt Macy nvpair_t *
nvpair_create_number(const char * name,uint64_t value)122356e5ad5fSMatt Macy nvpair_create_number(const char *name, uint64_t value)
122456e5ad5fSMatt Macy {
122556e5ad5fSMatt Macy
122656e5ad5fSMatt Macy return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0));
122756e5ad5fSMatt Macy }
122856e5ad5fSMatt Macy
122956e5ad5fSMatt Macy nvpair_t *
nvpair_create_string(const char * name,const char * value)123056e5ad5fSMatt Macy nvpair_create_string(const char *name, const char *value)
123156e5ad5fSMatt Macy {
123256e5ad5fSMatt Macy nvpair_t *nvp;
123356e5ad5fSMatt Macy size_t size;
123456e5ad5fSMatt Macy char *data;
123556e5ad5fSMatt Macy
123656e5ad5fSMatt Macy if (value == NULL) {
123756e5ad5fSMatt Macy ERRNO_SET(EINVAL);
123856e5ad5fSMatt Macy return (NULL);
123956e5ad5fSMatt Macy }
124056e5ad5fSMatt Macy
124156e5ad5fSMatt Macy data = nv_strdup(value);
124256e5ad5fSMatt Macy if (data == NULL)
124356e5ad5fSMatt Macy return (NULL);
124456e5ad5fSMatt Macy size = strlen(value) + 1;
124556e5ad5fSMatt Macy
124656e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
124756e5ad5fSMatt Macy size, 0);
124856e5ad5fSMatt Macy if (nvp == NULL)
124956e5ad5fSMatt Macy nv_free(data);
125056e5ad5fSMatt Macy
125156e5ad5fSMatt Macy return (nvp);
125256e5ad5fSMatt Macy }
125356e5ad5fSMatt Macy
125456e5ad5fSMatt Macy nvpair_t *
nvpair_create_nvlist(const char * name,const nvlist_t * value)125556e5ad5fSMatt Macy nvpair_create_nvlist(const char *name, const nvlist_t *value)
125656e5ad5fSMatt Macy {
125756e5ad5fSMatt Macy nvlist_t *nvl;
125856e5ad5fSMatt Macy nvpair_t *nvp;
125956e5ad5fSMatt Macy
126056e5ad5fSMatt Macy if (value == NULL) {
126156e5ad5fSMatt Macy ERRNO_SET(EINVAL);
126256e5ad5fSMatt Macy return (NULL);
126356e5ad5fSMatt Macy }
126456e5ad5fSMatt Macy
126556e5ad5fSMatt Macy nvl = nvlist_clone(value);
126656e5ad5fSMatt Macy if (nvl == NULL)
126756e5ad5fSMatt Macy return (NULL);
126856e5ad5fSMatt Macy
126956e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0,
127056e5ad5fSMatt Macy 0);
127156e5ad5fSMatt Macy if (nvp == NULL)
127256e5ad5fSMatt Macy nvlist_destroy(nvl);
127356e5ad5fSMatt Macy else
127456e5ad5fSMatt Macy nvlist_set_parent(nvl, nvp);
127556e5ad5fSMatt Macy
127656e5ad5fSMatt Macy return (nvp);
127756e5ad5fSMatt Macy }
127856e5ad5fSMatt Macy
127956e5ad5fSMatt Macy #ifndef _KERNEL
128056e5ad5fSMatt Macy nvpair_t *
nvpair_create_descriptor(const char * name,int value)128156e5ad5fSMatt Macy nvpair_create_descriptor(const char *name, int value)
128256e5ad5fSMatt Macy {
128356e5ad5fSMatt Macy nvpair_t *nvp;
128456e5ad5fSMatt Macy
128556e5ad5fSMatt Macy value = fcntl(value, F_DUPFD_CLOEXEC, 0);
128656e5ad5fSMatt Macy if (value < 0)
128756e5ad5fSMatt Macy return (NULL);
128856e5ad5fSMatt Macy
128956e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
129056e5ad5fSMatt Macy sizeof(int64_t), 0);
129156e5ad5fSMatt Macy if (nvp == NULL) {
129256e5ad5fSMatt Macy ERRNO_SAVE();
129356e5ad5fSMatt Macy close(value);
129456e5ad5fSMatt Macy ERRNO_RESTORE();
129556e5ad5fSMatt Macy }
129656e5ad5fSMatt Macy
129756e5ad5fSMatt Macy return (nvp);
129856e5ad5fSMatt Macy }
129956e5ad5fSMatt Macy #endif
130056e5ad5fSMatt Macy
130156e5ad5fSMatt Macy nvpair_t *
nvpair_create_binary(const char * name,const void * value,size_t size)130256e5ad5fSMatt Macy nvpair_create_binary(const char *name, const void *value, size_t size)
130356e5ad5fSMatt Macy {
130456e5ad5fSMatt Macy nvpair_t *nvp;
130556e5ad5fSMatt Macy void *data;
130656e5ad5fSMatt Macy
130756e5ad5fSMatt Macy if (value == NULL || size == 0) {
130856e5ad5fSMatt Macy ERRNO_SET(EINVAL);
130956e5ad5fSMatt Macy return (NULL);
131056e5ad5fSMatt Macy }
131156e5ad5fSMatt Macy
131256e5ad5fSMatt Macy data = nv_malloc(size);
131356e5ad5fSMatt Macy if (data == NULL)
131456e5ad5fSMatt Macy return (NULL);
131556e5ad5fSMatt Macy memcpy(data, value, size);
131656e5ad5fSMatt Macy
131756e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
131856e5ad5fSMatt Macy size, 0);
131956e5ad5fSMatt Macy if (nvp == NULL)
132056e5ad5fSMatt Macy nv_free(data);
132156e5ad5fSMatt Macy
132256e5ad5fSMatt Macy return (nvp);
132356e5ad5fSMatt Macy }
132456e5ad5fSMatt Macy
132556e5ad5fSMatt Macy nvpair_t *
nvpair_create_bool_array(const char * name,const bool * value,size_t nitems)132656e5ad5fSMatt Macy nvpair_create_bool_array(const char *name, const bool *value, size_t nitems)
132756e5ad5fSMatt Macy {
132856e5ad5fSMatt Macy nvpair_t *nvp;
132956e5ad5fSMatt Macy size_t size;
133056e5ad5fSMatt Macy void *data;
133156e5ad5fSMatt Macy
133256e5ad5fSMatt Macy if (value == NULL || nitems == 0) {
133356e5ad5fSMatt Macy ERRNO_SET(EINVAL);
133456e5ad5fSMatt Macy return (NULL);
133556e5ad5fSMatt Macy }
133656e5ad5fSMatt Macy
133736fa90dbSMariusz Zaborski data = nv_calloc(nitems, sizeof(value[0]));
133856e5ad5fSMatt Macy if (data == NULL)
133956e5ad5fSMatt Macy return (NULL);
134036fa90dbSMariusz Zaborski size = sizeof(value[0]) * nitems;
134156e5ad5fSMatt Macy
134256e5ad5fSMatt Macy memcpy(data, value, size);
134356e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data,
134456e5ad5fSMatt Macy size, nitems);
134556e5ad5fSMatt Macy if (nvp == NULL) {
134656e5ad5fSMatt Macy ERRNO_SAVE();
134756e5ad5fSMatt Macy nv_free(data);
134856e5ad5fSMatt Macy ERRNO_RESTORE();
134956e5ad5fSMatt Macy }
135056e5ad5fSMatt Macy
135156e5ad5fSMatt Macy return (nvp);
135256e5ad5fSMatt Macy }
135356e5ad5fSMatt Macy
135456e5ad5fSMatt Macy nvpair_t *
nvpair_create_number_array(const char * name,const uint64_t * value,size_t nitems)135556e5ad5fSMatt Macy nvpair_create_number_array(const char *name, const uint64_t *value,
135656e5ad5fSMatt Macy size_t nitems)
135756e5ad5fSMatt Macy {
135856e5ad5fSMatt Macy nvpair_t *nvp;
135956e5ad5fSMatt Macy size_t size;
136056e5ad5fSMatt Macy void *data;
136156e5ad5fSMatt Macy
136256e5ad5fSMatt Macy if (value == NULL || nitems == 0) {
136356e5ad5fSMatt Macy ERRNO_SET(EINVAL);
136456e5ad5fSMatt Macy return (NULL);
136556e5ad5fSMatt Macy }
136656e5ad5fSMatt Macy
136736fa90dbSMariusz Zaborski data = nv_calloc(nitems, sizeof(value[0]));
136856e5ad5fSMatt Macy if (data == NULL)
136956e5ad5fSMatt Macy return (NULL);
137036fa90dbSMariusz Zaborski size = sizeof(value[0]) * nitems;
137156e5ad5fSMatt Macy
137256e5ad5fSMatt Macy memcpy(data, value, size);
137356e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
137456e5ad5fSMatt Macy (uint64_t)(uintptr_t)data, size, nitems);
137556e5ad5fSMatt Macy if (nvp == NULL) {
137656e5ad5fSMatt Macy ERRNO_SAVE();
137756e5ad5fSMatt Macy nv_free(data);
137856e5ad5fSMatt Macy ERRNO_RESTORE();
137956e5ad5fSMatt Macy }
138056e5ad5fSMatt Macy
138156e5ad5fSMatt Macy return (nvp);
138256e5ad5fSMatt Macy }
138356e5ad5fSMatt Macy
138456e5ad5fSMatt Macy nvpair_t *
nvpair_create_string_array(const char * name,const char * const * value,size_t nitems)138556e5ad5fSMatt Macy nvpair_create_string_array(const char *name, const char * const *value,
138656e5ad5fSMatt Macy size_t nitems)
138756e5ad5fSMatt Macy {
138856e5ad5fSMatt Macy nvpair_t *nvp;
138956e5ad5fSMatt Macy unsigned int ii;
139056e5ad5fSMatt Macy size_t datasize, size;
139156e5ad5fSMatt Macy char **data;
139256e5ad5fSMatt Macy
139356e5ad5fSMatt Macy if (value == NULL || nitems == 0) {
139456e5ad5fSMatt Macy ERRNO_SET(EINVAL);
139556e5ad5fSMatt Macy return (NULL);
139656e5ad5fSMatt Macy }
139756e5ad5fSMatt Macy
139856e5ad5fSMatt Macy nvp = NULL;
139956e5ad5fSMatt Macy datasize = 0;
140036fa90dbSMariusz Zaborski data = nv_calloc(nitems, sizeof(value[0]));
140156e5ad5fSMatt Macy if (data == NULL)
140256e5ad5fSMatt Macy return (NULL);
140356e5ad5fSMatt Macy
140456e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) {
140556e5ad5fSMatt Macy if (value[ii] == NULL) {
140656e5ad5fSMatt Macy ERRNO_SET(EINVAL);
140756e5ad5fSMatt Macy goto fail;
140856e5ad5fSMatt Macy }
140956e5ad5fSMatt Macy
141056e5ad5fSMatt Macy size = strlen(value[ii]) + 1;
141156e5ad5fSMatt Macy datasize += size;
141256e5ad5fSMatt Macy data[ii] = nv_strdup(value[ii]);
141356e5ad5fSMatt Macy if (data[ii] == NULL)
141456e5ad5fSMatt Macy goto fail;
141556e5ad5fSMatt Macy }
141656e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
141756e5ad5fSMatt Macy (uint64_t)(uintptr_t)data, datasize, nitems);
141856e5ad5fSMatt Macy
141956e5ad5fSMatt Macy fail:
142056e5ad5fSMatt Macy if (nvp == NULL) {
142156e5ad5fSMatt Macy ERRNO_SAVE();
142256e5ad5fSMatt Macy for (; ii > 0; ii--)
142356e5ad5fSMatt Macy nv_free(data[ii - 1]);
142456e5ad5fSMatt Macy nv_free(data);
142556e5ad5fSMatt Macy ERRNO_RESTORE();
142656e5ad5fSMatt Macy }
142756e5ad5fSMatt Macy
142856e5ad5fSMatt Macy return (nvp);
142956e5ad5fSMatt Macy }
143056e5ad5fSMatt Macy
143156e5ad5fSMatt Macy nvpair_t *
nvpair_create_nvlist_array(const char * name,const nvlist_t * const * value,size_t nitems)143256e5ad5fSMatt Macy nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value,
143356e5ad5fSMatt Macy size_t nitems)
143456e5ad5fSMatt Macy {
143556e5ad5fSMatt Macy unsigned int ii;
143656e5ad5fSMatt Macy nvlist_t **nvls;
143756e5ad5fSMatt Macy nvpair_t *parent;
143856e5ad5fSMatt Macy int flags;
143956e5ad5fSMatt Macy
144056e5ad5fSMatt Macy nvls = NULL;
144156e5ad5fSMatt Macy
144256e5ad5fSMatt Macy if (value == NULL || nitems == 0) {
144356e5ad5fSMatt Macy ERRNO_SET(EINVAL);
144456e5ad5fSMatt Macy return (NULL);
144556e5ad5fSMatt Macy }
144656e5ad5fSMatt Macy
144736fa90dbSMariusz Zaborski nvls = nv_calloc(nitems, sizeof(value[0]));
144856e5ad5fSMatt Macy if (nvls == NULL)
144956e5ad5fSMatt Macy return (NULL);
145056e5ad5fSMatt Macy
145156e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) {
145256e5ad5fSMatt Macy if (value[ii] == NULL) {
145356e5ad5fSMatt Macy ERRNO_SET(EINVAL);
145456e5ad5fSMatt Macy goto fail;
145556e5ad5fSMatt Macy }
145656e5ad5fSMatt Macy
145756e5ad5fSMatt Macy nvls[ii] = nvlist_clone(value[ii]);
145856e5ad5fSMatt Macy if (nvls[ii] == NULL)
145956e5ad5fSMatt Macy goto fail;
146056e5ad5fSMatt Macy
146156e5ad5fSMatt Macy if (ii > 0) {
146256e5ad5fSMatt Macy nvpair_t *nvp;
146356e5ad5fSMatt Macy
146456e5ad5fSMatt Macy nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
146556e5ad5fSMatt Macy (uint64_t)(uintptr_t)nvls[ii], 0, 0);
146656e5ad5fSMatt Macy if (nvp == NULL) {
146756e5ad5fSMatt Macy ERRNO_SAVE();
146856e5ad5fSMatt Macy nvlist_destroy(nvls[ii]);
146956e5ad5fSMatt Macy ERRNO_RESTORE();
147056e5ad5fSMatt Macy goto fail;
147156e5ad5fSMatt Macy }
147256e5ad5fSMatt Macy nvlist_set_array_next(nvls[ii - 1], nvp);
147356e5ad5fSMatt Macy }
147456e5ad5fSMatt Macy }
147556e5ad5fSMatt Macy flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY;
147656e5ad5fSMatt Macy nvlist_set_flags(nvls[nitems - 1], flags);
147756e5ad5fSMatt Macy
147856e5ad5fSMatt Macy parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
147956e5ad5fSMatt Macy (uint64_t)(uintptr_t)nvls, 0, nitems);
148056e5ad5fSMatt Macy if (parent == NULL)
148156e5ad5fSMatt Macy goto fail;
148256e5ad5fSMatt Macy
148356e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++)
148456e5ad5fSMatt Macy nvlist_set_parent(nvls[ii], parent);
148556e5ad5fSMatt Macy
148656e5ad5fSMatt Macy return (parent);
148756e5ad5fSMatt Macy
148856e5ad5fSMatt Macy fail:
148956e5ad5fSMatt Macy ERRNO_SAVE();
149056e5ad5fSMatt Macy for (; ii > 0; ii--)
149156e5ad5fSMatt Macy nvlist_destroy(nvls[ii - 1]);
149256e5ad5fSMatt Macy nv_free(nvls);
149356e5ad5fSMatt Macy ERRNO_RESTORE();
149456e5ad5fSMatt Macy
149556e5ad5fSMatt Macy return (NULL);
149656e5ad5fSMatt Macy }
149756e5ad5fSMatt Macy
149856e5ad5fSMatt Macy #ifndef _KERNEL
149956e5ad5fSMatt Macy nvpair_t *
nvpair_create_descriptor_array(const char * name,const int * value,size_t nitems)150056e5ad5fSMatt Macy nvpair_create_descriptor_array(const char *name, const int *value,
150156e5ad5fSMatt Macy size_t nitems)
150256e5ad5fSMatt Macy {
150356e5ad5fSMatt Macy unsigned int ii;
150456e5ad5fSMatt Macy nvpair_t *nvp;
150556e5ad5fSMatt Macy int *fds;
150656e5ad5fSMatt Macy
150756e5ad5fSMatt Macy if (value == NULL) {
150856e5ad5fSMatt Macy ERRNO_SET(EINVAL);
150956e5ad5fSMatt Macy return (NULL);
151056e5ad5fSMatt Macy }
151156e5ad5fSMatt Macy
151256e5ad5fSMatt Macy nvp = NULL;
151356e5ad5fSMatt Macy
151436fa90dbSMariusz Zaborski fds = nv_calloc(nitems, sizeof(value[0]));
151556e5ad5fSMatt Macy if (fds == NULL)
151656e5ad5fSMatt Macy return (NULL);
151756e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) {
151856e5ad5fSMatt Macy if (value[ii] == -1) {
151956e5ad5fSMatt Macy fds[ii] = -1;
152056e5ad5fSMatt Macy } else {
152156e5ad5fSMatt Macy fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
152256e5ad5fSMatt Macy if (fds[ii] == -1)
152356e5ad5fSMatt Macy goto fail;
152456e5ad5fSMatt Macy }
152556e5ad5fSMatt Macy }
152656e5ad5fSMatt Macy
152756e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
152856e5ad5fSMatt Macy (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems);
152956e5ad5fSMatt Macy
153056e5ad5fSMatt Macy fail:
153156e5ad5fSMatt Macy if (nvp == NULL) {
153256e5ad5fSMatt Macy ERRNO_SAVE();
153356e5ad5fSMatt Macy for (; ii > 0; ii--) {
153456e5ad5fSMatt Macy if (fds[ii - 1] != -1)
153556e5ad5fSMatt Macy close(fds[ii - 1]);
153656e5ad5fSMatt Macy }
153756e5ad5fSMatt Macy nv_free(fds);
153856e5ad5fSMatt Macy ERRNO_RESTORE();
153956e5ad5fSMatt Macy }
154056e5ad5fSMatt Macy
154156e5ad5fSMatt Macy return (nvp);
154256e5ad5fSMatt Macy }
154356e5ad5fSMatt Macy #endif
154456e5ad5fSMatt Macy
154556e5ad5fSMatt Macy nvpair_t *
nvpair_move_string(const char * name,char * value)154656e5ad5fSMatt Macy nvpair_move_string(const char *name, char *value)
154756e5ad5fSMatt Macy {
154856e5ad5fSMatt Macy nvpair_t *nvp;
154956e5ad5fSMatt Macy
155056e5ad5fSMatt Macy if (value == NULL) {
155156e5ad5fSMatt Macy ERRNO_SET(EINVAL);
155256e5ad5fSMatt Macy return (NULL);
155356e5ad5fSMatt Macy }
155456e5ad5fSMatt Macy
155556e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
155656e5ad5fSMatt Macy strlen(value) + 1, 0);
155756e5ad5fSMatt Macy if (nvp == NULL) {
155856e5ad5fSMatt Macy ERRNO_SAVE();
155956e5ad5fSMatt Macy nv_free(value);
156056e5ad5fSMatt Macy ERRNO_RESTORE();
156156e5ad5fSMatt Macy }
156256e5ad5fSMatt Macy
156356e5ad5fSMatt Macy return (nvp);
156456e5ad5fSMatt Macy }
156556e5ad5fSMatt Macy
156656e5ad5fSMatt Macy nvpair_t *
nvpair_move_nvlist(const char * name,nvlist_t * value)156756e5ad5fSMatt Macy nvpair_move_nvlist(const char *name, nvlist_t *value)
156856e5ad5fSMatt Macy {
156956e5ad5fSMatt Macy nvpair_t *nvp;
157056e5ad5fSMatt Macy
157156e5ad5fSMatt Macy if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
157256e5ad5fSMatt Macy ERRNO_SET(EINVAL);
157356e5ad5fSMatt Macy return (NULL);
157456e5ad5fSMatt Macy }
157556e5ad5fSMatt Macy
157656e5ad5fSMatt Macy if (nvlist_error(value) != 0) {
157756e5ad5fSMatt Macy ERRNO_SET(nvlist_error(value));
157856e5ad5fSMatt Macy nvlist_destroy(value);
157956e5ad5fSMatt Macy return (NULL);
158056e5ad5fSMatt Macy }
158156e5ad5fSMatt Macy
158256e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
158356e5ad5fSMatt Macy 0, 0);
158456e5ad5fSMatt Macy if (nvp == NULL)
158556e5ad5fSMatt Macy nvlist_destroy(value);
158656e5ad5fSMatt Macy else
158756e5ad5fSMatt Macy nvlist_set_parent(value, nvp);
158856e5ad5fSMatt Macy
158956e5ad5fSMatt Macy return (nvp);
159056e5ad5fSMatt Macy }
159156e5ad5fSMatt Macy
159256e5ad5fSMatt Macy #ifndef _KERNEL
159356e5ad5fSMatt Macy nvpair_t *
nvpair_move_descriptor(const char * name,int value)159456e5ad5fSMatt Macy nvpair_move_descriptor(const char *name, int value)
159556e5ad5fSMatt Macy {
159656e5ad5fSMatt Macy nvpair_t *nvp;
159756e5ad5fSMatt Macy
159856e5ad5fSMatt Macy if (value < 0 || !fd_is_valid(value)) {
159956e5ad5fSMatt Macy ERRNO_SET(EBADF);
160056e5ad5fSMatt Macy return (NULL);
160156e5ad5fSMatt Macy }
160256e5ad5fSMatt Macy
160356e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
160456e5ad5fSMatt Macy sizeof(int64_t), 0);
160556e5ad5fSMatt Macy if (nvp == NULL) {
160656e5ad5fSMatt Macy ERRNO_SAVE();
160756e5ad5fSMatt Macy close(value);
160856e5ad5fSMatt Macy ERRNO_RESTORE();
160956e5ad5fSMatt Macy }
161056e5ad5fSMatt Macy
161156e5ad5fSMatt Macy return (nvp);
161256e5ad5fSMatt Macy }
161356e5ad5fSMatt Macy #endif
161456e5ad5fSMatt Macy
161556e5ad5fSMatt Macy nvpair_t *
nvpair_move_binary(const char * name,void * value,size_t size)161656e5ad5fSMatt Macy nvpair_move_binary(const char *name, void *value, size_t size)
161756e5ad5fSMatt Macy {
161856e5ad5fSMatt Macy nvpair_t *nvp;
161956e5ad5fSMatt Macy
162056e5ad5fSMatt Macy if (value == NULL || size == 0) {
162156e5ad5fSMatt Macy ERRNO_SET(EINVAL);
162256e5ad5fSMatt Macy return (NULL);
162356e5ad5fSMatt Macy }
162456e5ad5fSMatt Macy
162556e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
162656e5ad5fSMatt Macy size, 0);
162756e5ad5fSMatt Macy if (nvp == NULL) {
162856e5ad5fSMatt Macy ERRNO_SAVE();
162956e5ad5fSMatt Macy nv_free(value);
163056e5ad5fSMatt Macy ERRNO_RESTORE();
163156e5ad5fSMatt Macy }
163256e5ad5fSMatt Macy
163356e5ad5fSMatt Macy return (nvp);
163456e5ad5fSMatt Macy }
163556e5ad5fSMatt Macy
163656e5ad5fSMatt Macy nvpair_t *
nvpair_move_bool_array(const char * name,bool * value,size_t nitems)163756e5ad5fSMatt Macy nvpair_move_bool_array(const char *name, bool *value, size_t nitems)
163856e5ad5fSMatt Macy {
163956e5ad5fSMatt Macy nvpair_t *nvp;
164056e5ad5fSMatt Macy
164156e5ad5fSMatt Macy if (value == NULL || nitems == 0) {
164256e5ad5fSMatt Macy ERRNO_SET(EINVAL);
164356e5ad5fSMatt Macy return (NULL);
164456e5ad5fSMatt Macy }
164556e5ad5fSMatt Macy
164656e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY,
164756e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
164856e5ad5fSMatt Macy if (nvp == NULL) {
164956e5ad5fSMatt Macy ERRNO_SAVE();
165056e5ad5fSMatt Macy nv_free(value);
165156e5ad5fSMatt Macy ERRNO_RESTORE();
165256e5ad5fSMatt Macy }
165356e5ad5fSMatt Macy
165456e5ad5fSMatt Macy return (nvp);
165556e5ad5fSMatt Macy }
165656e5ad5fSMatt Macy
165756e5ad5fSMatt Macy nvpair_t *
nvpair_move_string_array(const char * name,char ** value,size_t nitems)165856e5ad5fSMatt Macy nvpair_move_string_array(const char *name, char **value, size_t nitems)
165956e5ad5fSMatt Macy {
166056e5ad5fSMatt Macy nvpair_t *nvp;
166156e5ad5fSMatt Macy size_t i, size;
166256e5ad5fSMatt Macy
166356e5ad5fSMatt Macy if (value == NULL || nitems == 0) {
166456e5ad5fSMatt Macy ERRNO_SET(EINVAL);
166556e5ad5fSMatt Macy return (NULL);
166656e5ad5fSMatt Macy }
166756e5ad5fSMatt Macy
166856e5ad5fSMatt Macy size = 0;
166956e5ad5fSMatt Macy for (i = 0; i < nitems; i++) {
167056e5ad5fSMatt Macy if (value[i] == NULL) {
167156e5ad5fSMatt Macy ERRNO_SET(EINVAL);
167256e5ad5fSMatt Macy return (NULL);
167356e5ad5fSMatt Macy }
167456e5ad5fSMatt Macy
167556e5ad5fSMatt Macy size += strlen(value[i]) + 1;
167656e5ad5fSMatt Macy }
167756e5ad5fSMatt Macy
167856e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY,
167956e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, size, nitems);
168056e5ad5fSMatt Macy if (nvp == NULL) {
168156e5ad5fSMatt Macy ERRNO_SAVE();
168256e5ad5fSMatt Macy for (i = 0; i < nitems; i++)
168356e5ad5fSMatt Macy nv_free(value[i]);
168456e5ad5fSMatt Macy nv_free(value);
168556e5ad5fSMatt Macy ERRNO_RESTORE();
168656e5ad5fSMatt Macy }
168756e5ad5fSMatt Macy
168856e5ad5fSMatt Macy return (nvp);
168956e5ad5fSMatt Macy }
169056e5ad5fSMatt Macy
169156e5ad5fSMatt Macy nvpair_t *
nvpair_move_number_array(const char * name,uint64_t * value,size_t nitems)169256e5ad5fSMatt Macy nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems)
169356e5ad5fSMatt Macy {
169456e5ad5fSMatt Macy nvpair_t *nvp;
169556e5ad5fSMatt Macy
169656e5ad5fSMatt Macy if (value == NULL || nitems == 0) {
169756e5ad5fSMatt Macy ERRNO_SET(EINVAL);
169856e5ad5fSMatt Macy return (NULL);
169956e5ad5fSMatt Macy }
170056e5ad5fSMatt Macy
170156e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY,
170256e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
170356e5ad5fSMatt Macy if (nvp == NULL) {
170456e5ad5fSMatt Macy ERRNO_SAVE();
170556e5ad5fSMatt Macy nv_free(value);
170656e5ad5fSMatt Macy ERRNO_RESTORE();
170756e5ad5fSMatt Macy }
170856e5ad5fSMatt Macy
170956e5ad5fSMatt Macy return (nvp);
171056e5ad5fSMatt Macy }
171156e5ad5fSMatt Macy
171256e5ad5fSMatt Macy nvpair_t *
nvpair_move_nvlist_array(const char * name,nvlist_t ** value,size_t nitems)171356e5ad5fSMatt Macy nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems)
171456e5ad5fSMatt Macy {
171556e5ad5fSMatt Macy nvpair_t *parent;
171656e5ad5fSMatt Macy unsigned int ii;
171756e5ad5fSMatt Macy int flags;
171856e5ad5fSMatt Macy
171956e5ad5fSMatt Macy if (value == NULL || nitems == 0) {
172056e5ad5fSMatt Macy ERRNO_SET(EINVAL);
172156e5ad5fSMatt Macy return (NULL);
172256e5ad5fSMatt Macy }
172356e5ad5fSMatt Macy
172456e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) {
172556e5ad5fSMatt Macy if (value == NULL || nvlist_error(value[ii]) != 0 ||
172656e5ad5fSMatt Macy nvlist_get_pararr(value[ii], NULL) != NULL) {
172756e5ad5fSMatt Macy ERRNO_SET(EINVAL);
172856e5ad5fSMatt Macy goto fail;
172956e5ad5fSMatt Macy }
173056e5ad5fSMatt Macy if (ii > 0) {
173156e5ad5fSMatt Macy nvpair_t *nvp;
173256e5ad5fSMatt Macy
173356e5ad5fSMatt Macy nvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
173456e5ad5fSMatt Macy (uint64_t)(uintptr_t)value[ii], 0, 0);
173556e5ad5fSMatt Macy if (nvp == NULL)
173656e5ad5fSMatt Macy goto fail;
173756e5ad5fSMatt Macy nvlist_set_array_next(value[ii - 1], nvp);
173856e5ad5fSMatt Macy }
173956e5ad5fSMatt Macy }
174056e5ad5fSMatt Macy flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY;
174156e5ad5fSMatt Macy nvlist_set_flags(value[nitems - 1], flags);
174256e5ad5fSMatt Macy
174356e5ad5fSMatt Macy parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY,
174456e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, 0, nitems);
174556e5ad5fSMatt Macy if (parent == NULL)
174656e5ad5fSMatt Macy goto fail;
174756e5ad5fSMatt Macy
174856e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++)
174956e5ad5fSMatt Macy nvlist_set_parent(value[ii], parent);
175056e5ad5fSMatt Macy
175156e5ad5fSMatt Macy return (parent);
175256e5ad5fSMatt Macy fail:
175356e5ad5fSMatt Macy ERRNO_SAVE();
175456e5ad5fSMatt Macy for (ii = 0; ii < nitems; ii++) {
175556e5ad5fSMatt Macy if (value[ii] != NULL &&
175656e5ad5fSMatt Macy nvlist_get_pararr(value[ii], NULL) != NULL) {
175756e5ad5fSMatt Macy nvlist_destroy(value[ii]);
175856e5ad5fSMatt Macy }
175956e5ad5fSMatt Macy }
176056e5ad5fSMatt Macy nv_free(value);
176156e5ad5fSMatt Macy ERRNO_RESTORE();
176256e5ad5fSMatt Macy
176356e5ad5fSMatt Macy return (NULL);
176456e5ad5fSMatt Macy }
176556e5ad5fSMatt Macy
176656e5ad5fSMatt Macy #ifndef _KERNEL
176756e5ad5fSMatt Macy nvpair_t *
nvpair_move_descriptor_array(const char * name,int * value,size_t nitems)176856e5ad5fSMatt Macy nvpair_move_descriptor_array(const char *name, int *value, size_t nitems)
176956e5ad5fSMatt Macy {
177056e5ad5fSMatt Macy nvpair_t *nvp;
177156e5ad5fSMatt Macy size_t i;
177256e5ad5fSMatt Macy
177356e5ad5fSMatt Macy if (value == NULL || nitems == 0) {
177456e5ad5fSMatt Macy ERRNO_SET(EINVAL);
177556e5ad5fSMatt Macy return (NULL);
177656e5ad5fSMatt Macy }
177756e5ad5fSMatt Macy
177856e5ad5fSMatt Macy for (i = 0; i < nitems; i++) {
177956e5ad5fSMatt Macy if (value[i] != -1 && !fd_is_valid(value[i])) {
178056e5ad5fSMatt Macy ERRNO_SET(EBADF);
178156e5ad5fSMatt Macy goto fail;
178256e5ad5fSMatt Macy }
178356e5ad5fSMatt Macy }
178456e5ad5fSMatt Macy
178556e5ad5fSMatt Macy nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY,
178656e5ad5fSMatt Macy (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems);
178756e5ad5fSMatt Macy if (nvp == NULL)
178856e5ad5fSMatt Macy goto fail;
178956e5ad5fSMatt Macy
179056e5ad5fSMatt Macy return (nvp);
179156e5ad5fSMatt Macy fail:
179256e5ad5fSMatt Macy ERRNO_SAVE();
179356e5ad5fSMatt Macy for (i = 0; i < nitems; i++) {
179456e5ad5fSMatt Macy if (fd_is_valid(value[i]))
179556e5ad5fSMatt Macy close(value[i]);
179656e5ad5fSMatt Macy }
179756e5ad5fSMatt Macy nv_free(value);
179856e5ad5fSMatt Macy ERRNO_RESTORE();
179956e5ad5fSMatt Macy
180056e5ad5fSMatt Macy return (NULL);
180156e5ad5fSMatt Macy }
180256e5ad5fSMatt Macy #endif
180356e5ad5fSMatt Macy
180456e5ad5fSMatt Macy bool
nvpair_get_bool(const nvpair_t * nvp)180556e5ad5fSMatt Macy nvpair_get_bool(const nvpair_t *nvp)
180656e5ad5fSMatt Macy {
180756e5ad5fSMatt Macy
180856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
180956e5ad5fSMatt Macy
181056e5ad5fSMatt Macy return (nvp->nvp_data == 1);
181156e5ad5fSMatt Macy }
181256e5ad5fSMatt Macy
181356e5ad5fSMatt Macy uint64_t
nvpair_get_number(const nvpair_t * nvp)181456e5ad5fSMatt Macy nvpair_get_number(const nvpair_t *nvp)
181556e5ad5fSMatt Macy {
181656e5ad5fSMatt Macy
181756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
181856e5ad5fSMatt Macy
181956e5ad5fSMatt Macy return (nvp->nvp_data);
182056e5ad5fSMatt Macy }
182156e5ad5fSMatt Macy
182256e5ad5fSMatt Macy const char *
nvpair_get_string(const nvpair_t * nvp)182356e5ad5fSMatt Macy nvpair_get_string(const nvpair_t *nvp)
182456e5ad5fSMatt Macy {
182556e5ad5fSMatt Macy
182656e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
182756e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
182856e5ad5fSMatt Macy
182956e5ad5fSMatt Macy return ((const char *)(intptr_t)nvp->nvp_data);
183056e5ad5fSMatt Macy }
183156e5ad5fSMatt Macy
183256e5ad5fSMatt Macy const nvlist_t *
nvpair_get_nvlist(const nvpair_t * nvp)183356e5ad5fSMatt Macy nvpair_get_nvlist(const nvpair_t *nvp)
183456e5ad5fSMatt Macy {
183556e5ad5fSMatt Macy
183656e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
183756e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
183856e5ad5fSMatt Macy
183956e5ad5fSMatt Macy return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
184056e5ad5fSMatt Macy }
184156e5ad5fSMatt Macy
184256e5ad5fSMatt Macy #ifndef _KERNEL
184356e5ad5fSMatt Macy int
nvpair_get_descriptor(const nvpair_t * nvp)184456e5ad5fSMatt Macy nvpair_get_descriptor(const nvpair_t *nvp)
184556e5ad5fSMatt Macy {
184656e5ad5fSMatt Macy
184756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
184856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
184956e5ad5fSMatt Macy
185056e5ad5fSMatt Macy return ((int)nvp->nvp_data);
185156e5ad5fSMatt Macy }
185256e5ad5fSMatt Macy #endif
185356e5ad5fSMatt Macy
185456e5ad5fSMatt Macy const void *
nvpair_get_binary(const nvpair_t * nvp,size_t * sizep)185556e5ad5fSMatt Macy nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
185656e5ad5fSMatt Macy {
185756e5ad5fSMatt Macy
185856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
185956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
186056e5ad5fSMatt Macy
186156e5ad5fSMatt Macy if (sizep != NULL)
186256e5ad5fSMatt Macy *sizep = nvp->nvp_datasize;
186356e5ad5fSMatt Macy
186456e5ad5fSMatt Macy return ((const void *)(intptr_t)nvp->nvp_data);
186556e5ad5fSMatt Macy }
186656e5ad5fSMatt Macy
186756e5ad5fSMatt Macy const bool *
nvpair_get_bool_array(const nvpair_t * nvp,size_t * nitems)186856e5ad5fSMatt Macy nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems)
186956e5ad5fSMatt Macy {
187056e5ad5fSMatt Macy
187156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
187256e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
187356e5ad5fSMatt Macy
187456e5ad5fSMatt Macy if (nitems != NULL)
187556e5ad5fSMatt Macy *nitems = nvp->nvp_nitems;
187656e5ad5fSMatt Macy
187756e5ad5fSMatt Macy return ((const bool *)(intptr_t)nvp->nvp_data);
187856e5ad5fSMatt Macy }
187956e5ad5fSMatt Macy
188056e5ad5fSMatt Macy const uint64_t *
nvpair_get_number_array(const nvpair_t * nvp,size_t * nitems)188156e5ad5fSMatt Macy nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems)
188256e5ad5fSMatt Macy {
188356e5ad5fSMatt Macy
188456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
188556e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
188656e5ad5fSMatt Macy
188756e5ad5fSMatt Macy if (nitems != NULL)
188856e5ad5fSMatt Macy *nitems = nvp->nvp_nitems;
188956e5ad5fSMatt Macy
189056e5ad5fSMatt Macy return ((const uint64_t *)(intptr_t)nvp->nvp_data);
189156e5ad5fSMatt Macy }
189256e5ad5fSMatt Macy
189356e5ad5fSMatt Macy const char * const *
nvpair_get_string_array(const nvpair_t * nvp,size_t * nitems)189456e5ad5fSMatt Macy nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems)
189556e5ad5fSMatt Macy {
189656e5ad5fSMatt Macy
189756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
189856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
189956e5ad5fSMatt Macy
190056e5ad5fSMatt Macy if (nitems != NULL)
190156e5ad5fSMatt Macy *nitems = nvp->nvp_nitems;
190256e5ad5fSMatt Macy
190356e5ad5fSMatt Macy return ((const char * const *)(intptr_t)nvp->nvp_data);
190456e5ad5fSMatt Macy }
190556e5ad5fSMatt Macy
190656e5ad5fSMatt Macy const nvlist_t * const *
nvpair_get_nvlist_array(const nvpair_t * nvp,size_t * nitems)190756e5ad5fSMatt Macy nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems)
190856e5ad5fSMatt Macy {
190956e5ad5fSMatt Macy
191056e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
191156e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
191256e5ad5fSMatt Macy
191356e5ad5fSMatt Macy if (nitems != NULL)
191456e5ad5fSMatt Macy *nitems = nvp->nvp_nitems;
191556e5ad5fSMatt Macy
191656e5ad5fSMatt Macy return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data));
191756e5ad5fSMatt Macy }
191856e5ad5fSMatt Macy
191956e5ad5fSMatt Macy #ifndef _KERNEL
192056e5ad5fSMatt Macy const int *
nvpair_get_descriptor_array(const nvpair_t * nvp,size_t * nitems)192156e5ad5fSMatt Macy nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems)
192256e5ad5fSMatt Macy {
192356e5ad5fSMatt Macy
192456e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
192556e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
192656e5ad5fSMatt Macy
192756e5ad5fSMatt Macy if (nitems != NULL)
192856e5ad5fSMatt Macy *nitems = nvp->nvp_nitems;
192956e5ad5fSMatt Macy
193056e5ad5fSMatt Macy return ((const int *)(intptr_t)nvp->nvp_data);
193156e5ad5fSMatt Macy }
193256e5ad5fSMatt Macy #endif
193356e5ad5fSMatt Macy
193456e5ad5fSMatt Macy int
nvpair_append_bool_array(nvpair_t * nvp,const bool value)193556e5ad5fSMatt Macy nvpair_append_bool_array(nvpair_t *nvp, const bool value)
193656e5ad5fSMatt Macy {
193756e5ad5fSMatt Macy
193856e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
193956e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY);
194056e5ad5fSMatt Macy return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
194156e5ad5fSMatt Macy }
194256e5ad5fSMatt Macy
194356e5ad5fSMatt Macy int
nvpair_append_number_array(nvpair_t * nvp,const uint64_t value)194456e5ad5fSMatt Macy nvpair_append_number_array(nvpair_t *nvp, const uint64_t value)
194556e5ad5fSMatt Macy {
194656e5ad5fSMatt Macy
194756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
194856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY);
194956e5ad5fSMatt Macy return (nvpair_append(nvp, &value, sizeof(value), sizeof(value)));
195056e5ad5fSMatt Macy }
195156e5ad5fSMatt Macy
195256e5ad5fSMatt Macy int
nvpair_append_string_array(nvpair_t * nvp,const char * value)195356e5ad5fSMatt Macy nvpair_append_string_array(nvpair_t *nvp, const char *value)
195456e5ad5fSMatt Macy {
195556e5ad5fSMatt Macy char *str;
195656e5ad5fSMatt Macy
195756e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
195856e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY);
195956e5ad5fSMatt Macy if (value == NULL) {
196056e5ad5fSMatt Macy ERRNO_SET(EINVAL);
196156e5ad5fSMatt Macy return (-1);
196256e5ad5fSMatt Macy }
196356e5ad5fSMatt Macy str = nv_strdup(value);
196456e5ad5fSMatt Macy if (str == NULL) {
196556e5ad5fSMatt Macy return (-1);
196656e5ad5fSMatt Macy }
196756e5ad5fSMatt Macy if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) {
196856e5ad5fSMatt Macy nv_free(str);
196956e5ad5fSMatt Macy return (-1);
197056e5ad5fSMatt Macy }
197156e5ad5fSMatt Macy return (0);
197256e5ad5fSMatt Macy }
197356e5ad5fSMatt Macy
197456e5ad5fSMatt Macy int
nvpair_append_nvlist_array(nvpair_t * nvp,const nvlist_t * value)197556e5ad5fSMatt Macy nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value)
197656e5ad5fSMatt Macy {
197756e5ad5fSMatt Macy nvpair_t *tmpnvp;
197856e5ad5fSMatt Macy nvlist_t *nvl, *prev;
197956e5ad5fSMatt Macy int flags;
198056e5ad5fSMatt Macy
198156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
198256e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY);
198356e5ad5fSMatt Macy if (value == NULL || nvlist_error(value) != 0 ||
198456e5ad5fSMatt Macy nvlist_get_pararr(value, NULL) != NULL) {
198556e5ad5fSMatt Macy ERRNO_SET(EINVAL);
198656e5ad5fSMatt Macy return (-1);
198756e5ad5fSMatt Macy }
198856e5ad5fSMatt Macy nvl = nvlist_clone(value);
198956e5ad5fSMatt Macy if (nvl == NULL) {
199056e5ad5fSMatt Macy return (-1);
199156e5ad5fSMatt Macy }
199256e5ad5fSMatt Macy flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY;
199356e5ad5fSMatt Macy nvlist_set_flags(nvl, flags);
199456e5ad5fSMatt Macy
199556e5ad5fSMatt Macy tmpnvp = NULL;
199656e5ad5fSMatt Macy prev = NULL;
199756e5ad5fSMatt Macy if (nvp->nvp_nitems > 0) {
199856e5ad5fSMatt Macy nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data;
199956e5ad5fSMatt Macy
200056e5ad5fSMatt Macy prev = nvls[nvp->nvp_nitems - 1];
200156e5ad5fSMatt Macy PJDLOG_ASSERT(prev != NULL);
200256e5ad5fSMatt Macy
200356e5ad5fSMatt Macy tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST,
200456e5ad5fSMatt Macy (uint64_t)(uintptr_t)nvl, 0, 0);
200556e5ad5fSMatt Macy if (tmpnvp == NULL) {
200656e5ad5fSMatt Macy goto fail;
200756e5ad5fSMatt Macy }
200856e5ad5fSMatt Macy }
200956e5ad5fSMatt Macy if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) {
201056e5ad5fSMatt Macy goto fail;
201156e5ad5fSMatt Macy }
201256e5ad5fSMatt Macy if (tmpnvp) {
201356e5ad5fSMatt Macy NVPAIR_ASSERT(tmpnvp);
201456e5ad5fSMatt Macy nvlist_set_array_next(prev, tmpnvp);
201556e5ad5fSMatt Macy }
201656e5ad5fSMatt Macy nvlist_set_parent(nvl, nvp);
201756e5ad5fSMatt Macy return (0);
201856e5ad5fSMatt Macy fail:
201956e5ad5fSMatt Macy if (tmpnvp) {
202056e5ad5fSMatt Macy nvpair_free(tmpnvp);
202156e5ad5fSMatt Macy }
202256e5ad5fSMatt Macy nvlist_destroy(nvl);
202356e5ad5fSMatt Macy return (-1);
202456e5ad5fSMatt Macy }
202556e5ad5fSMatt Macy
202656e5ad5fSMatt Macy #ifndef _KERNEL
202756e5ad5fSMatt Macy int
nvpair_append_descriptor_array(nvpair_t * nvp,const int value)202856e5ad5fSMatt Macy nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
202956e5ad5fSMatt Macy {
203056e5ad5fSMatt Macy int fd;
203156e5ad5fSMatt Macy
203256e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
203356e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
203456e5ad5fSMatt Macy fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
203556e5ad5fSMatt Macy if (fd == -1) {
203656e5ad5fSMatt Macy return (-1);
203756e5ad5fSMatt Macy }
203856e5ad5fSMatt Macy if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) {
203956e5ad5fSMatt Macy close(fd);
204056e5ad5fSMatt Macy return (-1);
204156e5ad5fSMatt Macy }
204256e5ad5fSMatt Macy return (0);
204356e5ad5fSMatt Macy }
204456e5ad5fSMatt Macy #endif
204556e5ad5fSMatt Macy
204656e5ad5fSMatt Macy void
nvpair_free(nvpair_t * nvp)204756e5ad5fSMatt Macy nvpair_free(nvpair_t *nvp)
204856e5ad5fSMatt Macy {
204956e5ad5fSMatt Macy size_t i;
205056e5ad5fSMatt Macy
205156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
205256e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list == NULL);
205356e5ad5fSMatt Macy
205456e5ad5fSMatt Macy nvp->nvp_magic = 0;
205556e5ad5fSMatt Macy switch (nvp->nvp_type) {
205656e5ad5fSMatt Macy #ifndef _KERNEL
205756e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR:
205856e5ad5fSMatt Macy close((int)nvp->nvp_data);
205956e5ad5fSMatt Macy break;
206056e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR_ARRAY:
206156e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++)
206256e5ad5fSMatt Macy close(((int *)(intptr_t)nvp->nvp_data)[i]);
206356e5ad5fSMatt Macy nv_free((int *)(intptr_t)nvp->nvp_data);
206456e5ad5fSMatt Macy break;
206556e5ad5fSMatt Macy #endif
206656e5ad5fSMatt Macy case NV_TYPE_NVLIST:
206756e5ad5fSMatt Macy nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
206856e5ad5fSMatt Macy break;
206956e5ad5fSMatt Macy case NV_TYPE_STRING:
207056e5ad5fSMatt Macy nv_free((char *)(intptr_t)nvp->nvp_data);
207156e5ad5fSMatt Macy break;
207256e5ad5fSMatt Macy case NV_TYPE_BINARY:
207356e5ad5fSMatt Macy nv_free((void *)(intptr_t)nvp->nvp_data);
207456e5ad5fSMatt Macy break;
207556e5ad5fSMatt Macy case NV_TYPE_NVLIST_ARRAY:
207656e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++) {
207756e5ad5fSMatt Macy nvlist_destroy(
207856e5ad5fSMatt Macy ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]);
207956e5ad5fSMatt Macy }
208056e5ad5fSMatt Macy nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data));
208156e5ad5fSMatt Macy break;
208256e5ad5fSMatt Macy case NV_TYPE_NUMBER_ARRAY:
208356e5ad5fSMatt Macy nv_free((uint64_t *)(intptr_t)nvp->nvp_data);
208456e5ad5fSMatt Macy break;
208556e5ad5fSMatt Macy case NV_TYPE_BOOL_ARRAY:
208656e5ad5fSMatt Macy nv_free((bool *)(intptr_t)nvp->nvp_data);
208756e5ad5fSMatt Macy break;
208856e5ad5fSMatt Macy case NV_TYPE_STRING_ARRAY:
208956e5ad5fSMatt Macy for (i = 0; i < nvp->nvp_nitems; i++)
209056e5ad5fSMatt Macy nv_free(((char **)(intptr_t)nvp->nvp_data)[i]);
209156e5ad5fSMatt Macy nv_free((char **)(intptr_t)nvp->nvp_data);
209256e5ad5fSMatt Macy break;
209356e5ad5fSMatt Macy }
209456e5ad5fSMatt Macy nv_free(nvp);
209556e5ad5fSMatt Macy }
209656e5ad5fSMatt Macy
209756e5ad5fSMatt Macy void
nvpair_free_structure(nvpair_t * nvp)209856e5ad5fSMatt Macy nvpair_free_structure(nvpair_t *nvp)
209956e5ad5fSMatt Macy {
210056e5ad5fSMatt Macy
210156e5ad5fSMatt Macy NVPAIR_ASSERT(nvp);
210256e5ad5fSMatt Macy PJDLOG_ASSERT(nvp->nvp_list == NULL);
210356e5ad5fSMatt Macy
210456e5ad5fSMatt Macy nvp->nvp_magic = 0;
210556e5ad5fSMatt Macy nv_free(nvp);
210656e5ad5fSMatt Macy }
210756e5ad5fSMatt Macy
210856e5ad5fSMatt Macy const char *
nvpair_type_string(int type)210956e5ad5fSMatt Macy nvpair_type_string(int type)
211056e5ad5fSMatt Macy {
211156e5ad5fSMatt Macy
211256e5ad5fSMatt Macy switch (type) {
211356e5ad5fSMatt Macy case NV_TYPE_NULL:
211456e5ad5fSMatt Macy return ("NULL");
211556e5ad5fSMatt Macy case NV_TYPE_BOOL:
211656e5ad5fSMatt Macy return ("BOOL");
211756e5ad5fSMatt Macy case NV_TYPE_NUMBER:
211856e5ad5fSMatt Macy return ("NUMBER");
211956e5ad5fSMatt Macy case NV_TYPE_STRING:
212056e5ad5fSMatt Macy return ("STRING");
212156e5ad5fSMatt Macy case NV_TYPE_NVLIST:
212256e5ad5fSMatt Macy return ("NVLIST");
212356e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR:
212456e5ad5fSMatt Macy return ("DESCRIPTOR");
212556e5ad5fSMatt Macy case NV_TYPE_BINARY:
212656e5ad5fSMatt Macy return ("BINARY");
212756e5ad5fSMatt Macy case NV_TYPE_BOOL_ARRAY:
212856e5ad5fSMatt Macy return ("BOOL ARRAY");
212956e5ad5fSMatt Macy case NV_TYPE_NUMBER_ARRAY:
213056e5ad5fSMatt Macy return ("NUMBER ARRAY");
213156e5ad5fSMatt Macy case NV_TYPE_STRING_ARRAY:
213256e5ad5fSMatt Macy return ("STRING ARRAY");
213356e5ad5fSMatt Macy case NV_TYPE_NVLIST_ARRAY:
213456e5ad5fSMatt Macy return ("NVLIST ARRAY");
213556e5ad5fSMatt Macy case NV_TYPE_DESCRIPTOR_ARRAY:
213656e5ad5fSMatt Macy return ("DESCRIPTOR ARRAY");
213756e5ad5fSMatt Macy default:
213856e5ad5fSMatt Macy return ("<UNKNOWN>");
213956e5ad5fSMatt Macy }
214056e5ad5fSMatt Macy }
214156e5ad5fSMatt Macy
2142