Use non-recursive algorithm for traversing nvlists. This also removes
the limit on number of nested nvlists. Submitted by: Mariusz Zaborski
This commit is contained in:
parent
ac34a053f0
commit
4093472823
@ -83,6 +83,8 @@ nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl);
|
||||
|
||||
const char *nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep);
|
||||
|
||||
const nvlist_t *nvlist_get_parent(const nvlist_t *nvl);
|
||||
|
||||
/*
|
||||
* The nvlist_exists functions check if the given name (optionally of the given
|
||||
* type) exists on nvlist.
|
||||
|
@ -39,6 +39,8 @@ struct nvpair;
|
||||
typedef struct nvpair nvpair_t;
|
||||
#endif
|
||||
|
||||
#define NV_TYPE_NVLIST_UP 255
|
||||
|
||||
#define NV_TYPE_FIRST NV_TYPE_NULL
|
||||
#define NV_TYPE_LAST NV_TYPE_BINARY
|
||||
|
||||
@ -55,6 +57,8 @@ void nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp);
|
||||
|
||||
void nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp);
|
||||
|
||||
void nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent);
|
||||
|
||||
const nvpair_t *nvlist_get_nvpair(const nvlist_t *nvl, const char *name);
|
||||
|
||||
nvpair_t *nvlist_take_nvpair(nvlist_t *nvl, const char *name);
|
||||
|
@ -73,10 +73,11 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define NVLIST_MAGIC 0x6e766c /* "nvl" */
|
||||
struct nvlist {
|
||||
int nvl_magic;
|
||||
int nvl_error;
|
||||
int nvl_flags;
|
||||
struct nvl_head nvl_head;
|
||||
int nvl_magic;
|
||||
int nvl_error;
|
||||
int nvl_flags;
|
||||
nvpair_t *nvl_parent;
|
||||
struct nvl_head nvl_head;
|
||||
};
|
||||
|
||||
#define NVLIST_ASSERT(nvl) do { \
|
||||
@ -106,6 +107,7 @@ nvlist_create(int flags)
|
||||
nvl = malloc(sizeof(*nvl));
|
||||
nvl->nvl_error = 0;
|
||||
nvl->nvl_flags = flags;
|
||||
nvl->nvl_parent = NULL;
|
||||
TAILQ_INIT(&nvl->nvl_head);
|
||||
nvl->nvl_magic = NVLIST_MAGIC;
|
||||
|
||||
@ -147,6 +149,36 @@ nvlist_error(const nvlist_t *nvl)
|
||||
return (nvl->nvl_error);
|
||||
}
|
||||
|
||||
nvpair_t *
|
||||
nvlist_get_nvpair_parent(const nvlist_t *nvl)
|
||||
{
|
||||
|
||||
NVLIST_ASSERT(nvl);
|
||||
|
||||
return (nvl->nvl_parent);
|
||||
}
|
||||
|
||||
const nvlist_t *
|
||||
nvlist_get_parent(const nvlist_t *nvl)
|
||||
{
|
||||
|
||||
NVLIST_ASSERT(nvl);
|
||||
|
||||
if (nvl->nvl_parent == NULL)
|
||||
return (NULL);
|
||||
|
||||
return (nvpair_nvlist(nvl->nvl_parent));
|
||||
}
|
||||
|
||||
void
|
||||
nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
|
||||
{
|
||||
|
||||
NVLIST_ASSERT(nvl);
|
||||
|
||||
nvl->nvl_parent = parent;
|
||||
}
|
||||
|
||||
bool
|
||||
nvlist_empty(const nvlist_t *nvl)
|
||||
{
|
||||
@ -301,24 +333,34 @@ nvlist_clone(const nvlist_t *nvl)
|
||||
return (newnvl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump content of nvlist.
|
||||
*/
|
||||
static void
|
||||
nvlist_xdump(const nvlist_t *nvl, int fd, int level)
|
||||
static bool
|
||||
nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
|
||||
{
|
||||
nvpair_t *nvp;
|
||||
|
||||
PJDLOG_ASSERT(level < 3);
|
||||
|
||||
if (nvlist_error(nvl) != 0) {
|
||||
dprintf(fd, "%*serror: %d\n", level * 4, "",
|
||||
nvlist_error(nvl));
|
||||
return;
|
||||
return (true);
|
||||
}
|
||||
|
||||
for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
|
||||
nvp = nvlist_next_nvpair(nvl, nvp)) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump content of nvlist.
|
||||
*/
|
||||
void
|
||||
nvlist_dump(const nvlist_t *nvl, int fd)
|
||||
{
|
||||
nvpair_t *nvp;
|
||||
int level;
|
||||
|
||||
level = 0;
|
||||
if (nvlist_dump_error_check(nvl, fd, level))
|
||||
return;
|
||||
|
||||
nvp = nvlist_first_nvpair(nvl);
|
||||
while (nvp != NULL) {
|
||||
dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
|
||||
nvpair_type_string(nvpair_type(nvp)));
|
||||
switch (nvpair_type(nvp)) {
|
||||
@ -340,8 +382,14 @@ nvlist_xdump(const nvlist_t *nvl, int fd, int level)
|
||||
break;
|
||||
case NV_TYPE_NVLIST:
|
||||
dprintf(fd, "\n");
|
||||
nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1);
|
||||
break;
|
||||
nvl = nvpair_get_nvlist(nvp);
|
||||
if (nvlist_dump_error_check(nvl, fd, level + 1)) {
|
||||
nvl = nvlist_get_parent(nvl);
|
||||
break;
|
||||
}
|
||||
level += 1;
|
||||
nvp = nvlist_first_nvpair(nvl);
|
||||
continue;
|
||||
case NV_TYPE_DESCRIPTOR:
|
||||
dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
|
||||
break;
|
||||
@ -361,16 +409,17 @@ nvlist_xdump(const nvlist_t *nvl, int fd, int level)
|
||||
default:
|
||||
PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
|
||||
}
|
||||
|
||||
while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
|
||||
nvp = nvlist_get_nvpair_parent(nvl);
|
||||
if (nvp == NULL)
|
||||
return;
|
||||
nvl = nvlist_get_parent(nvl);
|
||||
level --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nvlist_dump(const nvlist_t *nvl, int fd)
|
||||
{
|
||||
|
||||
nvlist_xdump(nvl, fd, 0);
|
||||
}
|
||||
|
||||
void
|
||||
nvlist_fdump(const nvlist_t *nvl, FILE *fp)
|
||||
{
|
||||
@ -381,41 +430,44 @@ nvlist_fdump(const nvlist_t *nvl, FILE *fp)
|
||||
|
||||
/*
|
||||
* The function obtains size of the nvlist after nvlist_pack().
|
||||
* Additional argument 'level' allows to track how deep are we as we obtain
|
||||
* size of the NV_TYPE_NVLIST elements using recursion. We allow at most
|
||||
* three levels of recursion.
|
||||
*/
|
||||
static size_t
|
||||
nvlist_xsize(const nvlist_t *nvl, int level)
|
||||
size_t
|
||||
nvlist_size(const nvlist_t *nvl)
|
||||
{
|
||||
const nvpair_t *nvp;
|
||||
size_t size;
|
||||
|
||||
NVLIST_ASSERT(nvl);
|
||||
PJDLOG_ASSERT(nvl->nvl_error == 0);
|
||||
PJDLOG_ASSERT(level < 3);
|
||||
|
||||
size = sizeof(struct nvlist_header);
|
||||
for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
|
||||
nvp = nvlist_next_nvpair(nvl, nvp)) {
|
||||
nvp = nvlist_first_nvpair(nvl);
|
||||
while (nvp != NULL) {
|
||||
size += nvpair_header_size();
|
||||
size += strlen(nvpair_name(nvp)) + 1;
|
||||
if (nvpair_type(nvp) == NV_TYPE_NVLIST)
|
||||
size += nvlist_xsize(nvpair_get_nvlist(nvp), level + 1);
|
||||
else
|
||||
if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
|
||||
size += sizeof(struct nvlist_header);
|
||||
size += nvpair_header_size() + 1;
|
||||
nvl = nvpair_get_nvlist(nvp);
|
||||
PJDLOG_ASSERT(nvl->nvl_error == 0);
|
||||
nvp = nvlist_first_nvpair(nvl);
|
||||
continue;
|
||||
} else {
|
||||
size += nvpair_size(nvp);
|
||||
}
|
||||
|
||||
while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
|
||||
nvp = nvlist_get_nvpair_parent(nvl);
|
||||
if (nvp == NULL)
|
||||
goto out;
|
||||
nvl = nvlist_get_parent(nvl);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return (size);
|
||||
}
|
||||
|
||||
size_t
|
||||
nvlist_size(const nvlist_t *nvl)
|
||||
{
|
||||
|
||||
return (nvlist_xsize(nvl, 0));
|
||||
}
|
||||
|
||||
static int *
|
||||
nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
|
||||
{
|
||||
@ -541,15 +593,59 @@ nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
|
||||
|
||||
ptr = nvlist_pack_header(nvl, ptr, &left);
|
||||
|
||||
for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
|
||||
nvp = nvlist_next_nvpair(nvl, nvp)) {
|
||||
ptr = nvpair_pack(nvp, ptr, fdidxp, &left);
|
||||
nvp = nvlist_first_nvpair(nvl);
|
||||
while (nvp != NULL) {
|
||||
NVPAIR_ASSERT(nvp);
|
||||
|
||||
nvpair_init_datasize(nvp);
|
||||
ptr = nvpair_pack_header(nvp, ptr, &left);
|
||||
if (ptr == NULL) {
|
||||
free(buf);
|
||||
return (NULL);
|
||||
}
|
||||
switch (nvpair_type(nvp)) {
|
||||
case NV_TYPE_NULL:
|
||||
ptr = nvpair_pack_null(nvp, ptr, &left);
|
||||
break;
|
||||
case NV_TYPE_BOOL:
|
||||
ptr = nvpair_pack_bool(nvp, ptr, &left);
|
||||
break;
|
||||
case NV_TYPE_NUMBER:
|
||||
ptr = nvpair_pack_number(nvp, ptr, &left);
|
||||
break;
|
||||
case NV_TYPE_STRING:
|
||||
ptr = nvpair_pack_string(nvp, ptr, &left);
|
||||
break;
|
||||
case NV_TYPE_NVLIST:
|
||||
nvl = nvpair_get_nvlist(nvp);
|
||||
nvp = nvlist_first_nvpair(nvl);
|
||||
ptr = nvlist_pack_header(nvl, ptr, &left);
|
||||
continue;
|
||||
case NV_TYPE_DESCRIPTOR:
|
||||
ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
|
||||
break;
|
||||
case NV_TYPE_BINARY:
|
||||
ptr = nvpair_pack_binary(nvp, ptr, &left);
|
||||
break;
|
||||
default:
|
||||
PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
free(buf);
|
||||
return (NULL);
|
||||
}
|
||||
while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
|
||||
nvp = nvlist_get_nvpair_parent(nvl);
|
||||
if (nvp == NULL)
|
||||
goto out;
|
||||
ptr = nvpair_pack_nvlist_up(ptr, &left);
|
||||
if (ptr == NULL)
|
||||
goto out;
|
||||
nvl = nvlist_get_parent(nvl);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (sizep != NULL)
|
||||
*sizep = size;
|
||||
return (buf);
|
||||
@ -600,7 +696,7 @@ nvlist_check_header(struct nvlist_header *nvlhdrp)
|
||||
return (true);
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
const unsigned char *
|
||||
nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
|
||||
int *flagsp, size_t *leftp)
|
||||
{
|
||||
@ -642,7 +738,7 @@ nvlist_t *
|
||||
nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
|
||||
{
|
||||
const unsigned char *ptr;
|
||||
nvlist_t *nvl;
|
||||
nvlist_t *nvl, *retnvl, *tmpnvl;
|
||||
nvpair_t *nvp;
|
||||
size_t left;
|
||||
int flags;
|
||||
@ -650,7 +746,8 @@ nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
|
||||
left = size;
|
||||
ptr = buf;
|
||||
|
||||
nvl = nvlist_create(0);
|
||||
tmpnvl = NULL;
|
||||
nvl = retnvl = nvlist_create(0);
|
||||
if (nvl == NULL)
|
||||
goto failed;
|
||||
|
||||
@ -659,15 +756,55 @@ nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
|
||||
goto failed;
|
||||
|
||||
while (left > 0) {
|
||||
ptr = nvpair_unpack(flags, ptr, &left, fds, nfds, &nvp);
|
||||
ptr = nvpair_unpack(flags, ptr, &left, &nvp);
|
||||
if (ptr == NULL)
|
||||
goto failed;
|
||||
switch (nvpair_type(nvp)) {
|
||||
case NV_TYPE_NULL:
|
||||
ptr = nvpair_unpack_null(flags, nvp, ptr, &left);
|
||||
break;
|
||||
case NV_TYPE_BOOL:
|
||||
ptr = nvpair_unpack_bool(flags, nvp, ptr, &left);
|
||||
break;
|
||||
case NV_TYPE_NUMBER:
|
||||
ptr = nvpair_unpack_number(flags, nvp, ptr, &left);
|
||||
break;
|
||||
case NV_TYPE_STRING:
|
||||
ptr = nvpair_unpack_string(flags, nvp, ptr, &left);
|
||||
break;
|
||||
case NV_TYPE_NVLIST:
|
||||
ptr = nvpair_unpack_nvlist(&flags, nvp, ptr, &left,
|
||||
nfds, &tmpnvl);
|
||||
nvlist_set_parent(tmpnvl, nvp);
|
||||
break;
|
||||
case NV_TYPE_DESCRIPTOR:
|
||||
ptr = nvpair_unpack_descriptor(flags, nvp, ptr, &left,
|
||||
fds, nfds);
|
||||
break;
|
||||
case NV_TYPE_BINARY:
|
||||
ptr = nvpair_unpack_binary(flags, nvp, ptr, &left);
|
||||
break;
|
||||
case NV_TYPE_NVLIST_UP:
|
||||
if (nvl->nvl_parent == NULL)
|
||||
goto failed;
|
||||
nvl = nvpair_nvlist(nvl->nvl_parent);
|
||||
flags = nvl->nvl_flags;
|
||||
continue;
|
||||
default:
|
||||
PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
|
||||
}
|
||||
if (ptr == NULL)
|
||||
goto failed;
|
||||
nvlist_move_nvpair(nvl, nvp);
|
||||
if (tmpnvl != NULL) {
|
||||
nvl = tmpnvl;
|
||||
tmpnvl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (nvl);
|
||||
return (retnvl);
|
||||
failed:
|
||||
nvlist_destroy(nvl);
|
||||
nvlist_destroy(retnvl);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -1331,7 +1468,8 @@ nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
|
||||
nvpair_t *nvp;
|
||||
|
||||
if (nvlist_error(nvl) != 0) {
|
||||
nvlist_destroy(value);
|
||||
if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
|
||||
nvlist_destroy(value);
|
||||
errno = nvlist_error(nvl);
|
||||
return;
|
||||
}
|
||||
|
@ -40,4 +40,8 @@ void *nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep);
|
||||
nvlist_t *nvlist_xunpack(const void *buf, size_t size, const int *fds,
|
||||
size_t nfds);
|
||||
|
||||
nvpair_t *nvlist_get_nvpair_parent(const nvlist_t *nvl);
|
||||
const unsigned char *nvlist_unpack_header(nvlist_t *nvl,
|
||||
const unsigned char *ptr, size_t nfds, int *flagsp, size_t *leftp);
|
||||
|
||||
#endif /* !_NVLIST_IMPL_H_ */
|
||||
|
@ -67,7 +67,7 @@ struct nvpair {
|
||||
int nvp_type;
|
||||
uint64_t nvp_data;
|
||||
size_t nvp_datasize;
|
||||
nvlist_t *nvp_list; /* Used for sanity checks. */
|
||||
nvlist_t *nvp_list;
|
||||
TAILQ_ENTRY(nvpair) nvp_next;
|
||||
};
|
||||
|
||||
@ -90,7 +90,7 @@ nvpair_assert(const nvpair_t *nvp)
|
||||
NVPAIR_ASSERT(nvp);
|
||||
}
|
||||
|
||||
const nvlist_t *
|
||||
nvlist_t *
|
||||
nvpair_nvlist(const nvpair_t *nvp)
|
||||
{
|
||||
|
||||
@ -131,6 +131,17 @@ nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
|
||||
nvp->nvp_list = nvl;
|
||||
}
|
||||
|
||||
static void
|
||||
nvpair_remove_nvlist(nvpair_t *nvp)
|
||||
{
|
||||
nvlist_t *nvl;
|
||||
|
||||
/* XXX: DECONST is bad, mkay? */
|
||||
nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
|
||||
PJDLOG_ASSERT(nvl != NULL);
|
||||
nvlist_set_parent(nvl, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
|
||||
{
|
||||
@ -138,6 +149,9 @@ nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
|
||||
NVPAIR_ASSERT(nvp);
|
||||
PJDLOG_ASSERT(nvp->nvp_list == nvl);
|
||||
|
||||
if (nvpair_type(nvp) == NV_TYPE_NVLIST)
|
||||
nvpair_remove_nvlist(nvp);
|
||||
|
||||
TAILQ_REMOVE(head, nvp, nvp_next);
|
||||
nvp->nvp_list = NULL;
|
||||
}
|
||||
@ -201,7 +215,7 @@ nvpair_size(const nvpair_t *nvp)
|
||||
return (nvp->nvp_datasize);
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unsigned char *
|
||||
nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
|
||||
{
|
||||
struct nvpair_header nvphdr;
|
||||
@ -227,7 +241,7 @@ nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unsigned char *
|
||||
nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
|
||||
size_t *leftp __unused)
|
||||
{
|
||||
@ -238,7 +252,7 @@ nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unsigned char *
|
||||
nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
|
||||
{
|
||||
uint8_t value;
|
||||
@ -256,7 +270,7 @@ nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unsigned char *
|
||||
nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
|
||||
{
|
||||
uint64_t value;
|
||||
@ -274,7 +288,7 @@ nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unsigned char *
|
||||
nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
|
||||
{
|
||||
|
||||
@ -289,37 +303,31 @@ nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
nvpair_pack_nvlist(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
|
||||
size_t *leftp)
|
||||
unsigned char *
|
||||
nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
|
||||
{
|
||||
unsigned char *data;
|
||||
size_t size;
|
||||
struct nvpair_header nvphdr;
|
||||
size_t namesize;
|
||||
const char *name = "";
|
||||
|
||||
NVPAIR_ASSERT(nvp);
|
||||
PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
|
||||
namesize = 1;
|
||||
nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
|
||||
nvphdr.nvph_namesize = namesize;
|
||||
nvphdr.nvph_datasize = 0;
|
||||
PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
|
||||
memcpy(ptr, &nvphdr, sizeof(nvphdr));
|
||||
ptr += sizeof(nvphdr);
|
||||
*leftp -= sizeof(nvphdr);
|
||||
|
||||
if (nvp->nvp_datasize == 0)
|
||||
return (ptr);
|
||||
|
||||
data = nvlist_xpack((const nvlist_t *)(intptr_t)nvp->nvp_data, fdidxp,
|
||||
&size);
|
||||
if (data == NULL)
|
||||
return (NULL);
|
||||
|
||||
PJDLOG_ASSERT(size == nvp->nvp_datasize);
|
||||
PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
|
||||
|
||||
memcpy(ptr, data, nvp->nvp_datasize);
|
||||
free(data);
|
||||
|
||||
ptr += nvp->nvp_datasize;
|
||||
*leftp -= nvp->nvp_datasize;
|
||||
PJDLOG_ASSERT(*leftp >= namesize);
|
||||
memcpy(ptr, name, namesize);
|
||||
ptr += namesize;
|
||||
*leftp -= namesize;
|
||||
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unsigned char *
|
||||
nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
|
||||
size_t *leftp)
|
||||
{
|
||||
@ -349,7 +357,7 @@ nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unsigned char *
|
||||
nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
|
||||
{
|
||||
|
||||
@ -364,17 +372,12 @@ nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
nvpair_pack(nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, size_t *leftp)
|
||||
void
|
||||
nvpair_init_datasize(nvpair_t *nvp)
|
||||
{
|
||||
|
||||
NVPAIR_ASSERT(nvp);
|
||||
|
||||
/*
|
||||
* We have to update datasize for NV_TYPE_NVLIST on every pack,
|
||||
* so that proper datasize is placed into nvpair_header
|
||||
* during the nvpair_pack_header() call below.
|
||||
*/
|
||||
if (nvp->nvp_type == NV_TYPE_NVLIST) {
|
||||
if (nvp->nvp_data == 0) {
|
||||
nvp->nvp_datasize = 0;
|
||||
@ -383,41 +386,9 @@ nvpair_pack(nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, size_t *leftp)
|
||||
nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
|
||||
}
|
||||
}
|
||||
|
||||
ptr = nvpair_pack_header(nvp, ptr, leftp);
|
||||
if (ptr == NULL)
|
||||
return (NULL);
|
||||
|
||||
switch (nvp->nvp_type) {
|
||||
case NV_TYPE_NULL:
|
||||
ptr = nvpair_pack_null(nvp, ptr, leftp);
|
||||
break;
|
||||
case NV_TYPE_BOOL:
|
||||
ptr = nvpair_pack_bool(nvp, ptr, leftp);
|
||||
break;
|
||||
case NV_TYPE_NUMBER:
|
||||
ptr = nvpair_pack_number(nvp, ptr, leftp);
|
||||
break;
|
||||
case NV_TYPE_STRING:
|
||||
ptr = nvpair_pack_string(nvp, ptr, leftp);
|
||||
break;
|
||||
case NV_TYPE_NVLIST:
|
||||
ptr = nvpair_pack_nvlist(nvp, ptr, fdidxp, leftp);
|
||||
break;
|
||||
case NV_TYPE_DESCRIPTOR:
|
||||
ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, leftp);
|
||||
break;
|
||||
case NV_TYPE_BINARY:
|
||||
ptr = nvpair_pack_binary(nvp, ptr, leftp);
|
||||
break;
|
||||
default:
|
||||
PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type);
|
||||
}
|
||||
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
const unsigned char *
|
||||
nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr,
|
||||
size_t *leftp)
|
||||
{
|
||||
@ -434,8 +405,10 @@ nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr,
|
||||
if (nvphdr.nvph_type < NV_TYPE_FIRST)
|
||||
goto failed;
|
||||
#endif
|
||||
if (nvphdr.nvph_type > NV_TYPE_LAST)
|
||||
if (nvphdr.nvph_type > NV_TYPE_LAST &&
|
||||
nvphdr.nvph_type != NV_TYPE_NVLIST_UP) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
if ((flags & NV_FLAG_BIG_ENDIAN) == 0) {
|
||||
@ -477,7 +450,7 @@ nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
const unsigned char *
|
||||
nvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
|
||||
size_t *leftp __unused)
|
||||
{
|
||||
@ -492,7 +465,7 @@ nvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
const unsigned char *
|
||||
nvpair_unpack_bool(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
|
||||
size_t *leftp)
|
||||
{
|
||||
@ -523,9 +496,9 @@ nvpair_unpack_bool(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
const unsigned char *
|
||||
nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr,
|
||||
size_t *leftp)
|
||||
size_t *leftp)
|
||||
{
|
||||
|
||||
PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
|
||||
@ -549,7 +522,7 @@ nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr,
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
const unsigned char *
|
||||
nvpair_unpack_string(int flags __unused, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp)
|
||||
{
|
||||
@ -577,9 +550,9 @@ nvpair_unpack_string(int flags __unused, nvpair_t *nvp,
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
nvpair_unpack_nvlist(int flags __unused, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
|
||||
const unsigned char *
|
||||
nvpair_unpack_nvlist(int *flagsp, nvpair_t *nvp, const unsigned char *ptr,
|
||||
size_t *leftp, size_t nfds, nvlist_t **child)
|
||||
{
|
||||
nvlist_t *value;
|
||||
|
||||
@ -590,19 +563,21 @@ nvpair_unpack_nvlist(int flags __unused, nvpair_t *nvp,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
value = nvlist_xunpack(ptr, nvp->nvp_datasize, fds, nfds);
|
||||
value = nvlist_create(0);
|
||||
if (value == NULL)
|
||||
return (NULL);
|
||||
|
||||
nvp->nvp_data = (uint64_t)(uintptr_t)value;
|
||||
ptr = nvlist_unpack_header(value, ptr, nfds, flagsp, leftp);
|
||||
if (ptr == NULL)
|
||||
return (NULL);
|
||||
|
||||
ptr += nvp->nvp_datasize;
|
||||
*leftp -= nvp->nvp_datasize;
|
||||
nvp->nvp_data = (uint64_t)(uintptr_t)value;
|
||||
*child = value;
|
||||
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
const unsigned char *
|
||||
nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr,
|
||||
size_t *leftp, const int *fds, size_t nfds)
|
||||
{
|
||||
@ -642,7 +617,7 @@ nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr,
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
const unsigned char *
|
||||
nvpair_unpack_binary(int flags __unused, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp)
|
||||
{
|
||||
@ -670,7 +645,7 @@ nvpair_unpack_binary(int flags __unused, nvpair_t *nvp,
|
||||
|
||||
const unsigned char *
|
||||
nvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp,
|
||||
const int *fds, size_t nfds, nvpair_t **nvpp)
|
||||
nvpair_t **nvpp)
|
||||
{
|
||||
nvpair_t *nvp, *tmp;
|
||||
|
||||
@ -686,40 +661,10 @@ nvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp,
|
||||
if (tmp == NULL)
|
||||
goto failed;
|
||||
nvp = tmp;
|
||||
|
||||
/* Update nvp_name after realloc(). */
|
||||
nvp->nvp_name = (char *)(nvp + 1);
|
||||
|
||||
switch (nvp->nvp_type) {
|
||||
case NV_TYPE_NULL:
|
||||
ptr = nvpair_unpack_null(flags, nvp, ptr, leftp);
|
||||
break;
|
||||
case NV_TYPE_BOOL:
|
||||
ptr = nvpair_unpack_bool(flags, nvp, ptr, leftp);
|
||||
break;
|
||||
case NV_TYPE_NUMBER:
|
||||
ptr = nvpair_unpack_number(flags, nvp, ptr, leftp);
|
||||
break;
|
||||
case NV_TYPE_STRING:
|
||||
ptr = nvpair_unpack_string(flags, nvp, ptr, leftp);
|
||||
break;
|
||||
case NV_TYPE_NVLIST:
|
||||
ptr = nvpair_unpack_nvlist(flags, nvp, ptr, leftp, fds,
|
||||
nfds);
|
||||
break;
|
||||
case NV_TYPE_DESCRIPTOR:
|
||||
ptr = nvpair_unpack_descriptor(flags, nvp, ptr, leftp, fds,
|
||||
nfds);
|
||||
break;
|
||||
case NV_TYPE_BINARY:
|
||||
ptr = nvpair_unpack_binary(flags, nvp, ptr, leftp);
|
||||
break;
|
||||
default:
|
||||
PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type);
|
||||
}
|
||||
|
||||
if (ptr == NULL)
|
||||
goto failed;
|
||||
|
||||
nvp->nvp_data = 0x00;
|
||||
nvp->nvp_magic = NVPAIR_MAGIC;
|
||||
*nvpp = nvp;
|
||||
return (ptr);
|
||||
@ -1018,6 +963,7 @@ nvpair_createv_nvlist(const nvlist_t *value, const char *namefmt,
|
||||
namefmt, nameap);
|
||||
if (nvp == NULL)
|
||||
nvlist_destroy(nvl);
|
||||
nvlist_set_parent(nvl, nvp);
|
||||
|
||||
return (nvp);
|
||||
}
|
||||
@ -1172,7 +1118,7 @@ nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap)
|
||||
{
|
||||
nvpair_t *nvp;
|
||||
|
||||
if (value == NULL) {
|
||||
if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
@ -1181,6 +1127,8 @@ nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap)
|
||||
namefmt, nameap);
|
||||
if (nvp == NULL)
|
||||
nvlist_destroy(value);
|
||||
else
|
||||
nvlist_set_parent(value, nvp);
|
||||
|
||||
return (nvp);
|
||||
}
|
||||
|
@ -41,18 +41,52 @@
|
||||
TAILQ_HEAD(nvl_head, nvpair);
|
||||
|
||||
void nvpair_assert(const nvpair_t *nvp);
|
||||
const nvlist_t *nvpair_nvlist(const nvpair_t *nvp);
|
||||
nvlist_t *nvpair_nvlist(const nvpair_t *nvp);
|
||||
nvpair_t *nvpair_next(const nvpair_t *nvp);
|
||||
nvpair_t *nvpair_prev(const nvpair_t *nvp);
|
||||
void nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl);
|
||||
void nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl);
|
||||
size_t nvpair_header_size(void);
|
||||
size_t nvpair_size(const nvpair_t *nvp);
|
||||
unsigned char *nvpair_pack(nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
|
||||
size_t *leftp);
|
||||
const unsigned char *nvpair_unpack(int flags, const unsigned char *ptr,
|
||||
size_t *leftp, const int *fds, size_t nfds, nvpair_t **nvpp);
|
||||
size_t *leftp, nvpair_t **nvpp);
|
||||
void nvpair_free_structure(nvpair_t *nvp);
|
||||
void nvpair_init_datasize(nvpair_t *nvp);
|
||||
const char *nvpair_type_string(int type);
|
||||
|
||||
/* Pack functions. */
|
||||
unsigned char *nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr,
|
||||
size_t *leftp);
|
||||
unsigned char *nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
|
||||
size_t *leftp);
|
||||
unsigned char *nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr,
|
||||
size_t *leftp);
|
||||
unsigned char *nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr,
|
||||
size_t *leftp);
|
||||
unsigned char *nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr,
|
||||
size_t *leftp);
|
||||
unsigned char *nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr,
|
||||
int64_t *fdidxp, size_t *leftp);
|
||||
unsigned char *nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr,
|
||||
size_t *leftp);
|
||||
unsigned char *nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp);
|
||||
|
||||
/* Unpack data functions. */
|
||||
const unsigned char *nvpair_unpack_header(int flags, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp);
|
||||
const unsigned char *nvpair_unpack_null(int flags, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp);
|
||||
const unsigned char *nvpair_unpack_bool(int flags, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp);
|
||||
const unsigned char *nvpair_unpack_number(int flags, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp);
|
||||
const unsigned char *nvpair_unpack_string(int flags, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp);
|
||||
const unsigned char *nvpair_unpack_nvlist(int *flagsp, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp, size_t nvlist, nvlist_t **child);
|
||||
const unsigned char *nvpair_unpack_descriptor(int flags, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds);
|
||||
const unsigned char *nvpair_unpack_binary(int flags, nvpair_t *nvp,
|
||||
const unsigned char *ptr, size_t *leftp);
|
||||
|
||||
#endif /* !_NVPAIR_IMPL_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user