Date: Sun, 14 Sep 2014 09:30:10 +0000 (UTC) From: Pawel Jakub Dawidek <pjd@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r271579 - head/lib/libnv Message-ID: <201409140930.s8E9UAFd097184@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: pjd Date: Sun Sep 14 09:30:09 2014 New Revision: 271579 URL: http://svnweb.freebsd.org/changeset/base/271579 Log: Use non-recursive algorithm for traversing nvlists. This also removes the limit on number of nested nvlists. Submitted by: Mariusz Zaborski Modified: head/lib/libnv/nv.h head/lib/libnv/nv_impl.h head/lib/libnv/nvlist.c head/lib/libnv/nvlist_impl.h head/lib/libnv/nvpair.c head/lib/libnv/nvpair_impl.h Modified: head/lib/libnv/nv.h ============================================================================== --- head/lib/libnv/nv.h Sun Sep 14 09:27:12 2014 (r271578) +++ head/lib/libnv/nv.h Sun Sep 14 09:30:09 2014 (r271579) @@ -83,6 +83,8 @@ nvlist_t *nvlist_xfer(int sock, nvlist_t 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. Modified: head/lib/libnv/nv_impl.h ============================================================================== --- head/lib/libnv/nv_impl.h Sun Sep 14 09:27:12 2014 (r271578) +++ head/lib/libnv/nv_impl.h Sun Sep 14 09:30:09 2014 (r271579) @@ -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, co 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); Modified: head/lib/libnv/nvlist.c ============================================================================== --- head/lib/libnv/nvlist.c Sun Sep 14 09:27:12 2014 (r271578) +++ head/lib/libnv/nvlist.c Sun Sep 14 09:30:09 2014 (r271579) @@ -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); } +static bool +nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level) +{ + + if (nvlist_error(nvl) != 0) { + dprintf(fd, "%*serror: %d\n", level * 4, "", + nvlist_error(nvl)); + return (true); + } + + return (false); +} + /* * Dump content of nvlist. */ -static void -nvlist_xdump(const nvlist_t *nvl, int fd, int level) +void +nvlist_dump(const nvlist_t *nvl, int fd) { nvpair_t *nvp; + int level; - PJDLOG_ASSERT(level < 3); - - if (nvlist_error(nvl) != 0) { - dprintf(fd, "%*serror: %d\n", level * 4, "", - nvlist_error(nvl)); + level = 0; + if (nvlist_dump_error_check(nvl, fd, level)) return; - } - for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; - nvp = nvlist_next_nvpair(nvl, nvp)) { + 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 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,14 +409,15 @@ nvlist_xdump(const nvlist_t *nvl, int fd default: PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); } - } -} - -void -nvlist_dump(const nvlist_t *nvl, int fd) -{ - nvlist_xdump(nvl, fd, 0); + 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 @@ -381,41 +430,44 @@ nvlist_fdump(const nvlist_t *nvl, FILE * /* * 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_ 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 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 s 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 s 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, nvlis 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; } Modified: head/lib/libnv/nvlist_impl.h ============================================================================== --- head/lib/libnv/nvlist_impl.h Sun Sep 14 09:27:12 2014 (r271578) +++ head/lib/libnv/nvlist_impl.h Sun Sep 14 09:30:09 2014 (r271579) @@ -40,4 +40,8 @@ void *nvlist_xpack(const nvlist_t *nvl, 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_ */ Modified: head/lib/libnv/nvpair.c ============================================================================== --- head/lib/libnv/nvpair.c Sun Sep 14 09:27:12 2014 (r271578) +++ head/lib/libnv/nvpair.c Sun Sep 14 09:30:09 2014 (r271579) @@ -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, nvp 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, nvp 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, 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, un 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, un 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, 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, 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; - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); - - 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); + struct nvpair_header nvphdr; + size_t namesize; + const char *name = ""; - memcpy(ptr, data, nvp->nvp_datasize); - free(data); + 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); - 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 *n 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, 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 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 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 @@ failed: 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, n 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, n 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 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, 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, 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, nvpa 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, 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 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 *va 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, con { 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, con namefmt, nameap); if (nvp == NULL) nvlist_destroy(value); + else + nvlist_set_parent(value, nvp); return (nvp); } Modified: head/lib/libnv/nvpair_impl.h ============================================================================== --- head/lib/libnv/nvpair_impl.h Sun Sep 14 09:27:12 2014 (r271578) +++ head/lib/libnv/nvpair_impl.h Sun Sep 14 09:30:09 2014 (r271579) @@ -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_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409140930.s8E9UAFd097184>