svn commit: r292632 - user/ngie/stable-10-libnv/lib/libnv
Garrett Cooper
ngie at FreeBSD.org
Tue Dec 22 23:05:45 UTC 2015
Author: ngie
Date: Tue Dec 22 23:05:43 2015
New Revision: 292632
URL: https://svnweb.freebsd.org/changeset/base/292632
Log:
MFC r271578,r271579,r271847,r272102,r272843,r273752,r277920,r277921,r277925,r277926,r277927,r279421,r279422,r279423:
r271578 (by pjd):
Remove the limit on descriptors that can be send in one nvlist.
Submitted by: Mariusz Zaborski
r271579 (by pjd):
Use non-recursive algorithm for traversing nvlists. This also removes
the limit on number of nested nvlists.
Submitted by: Mariusz Zaborski
r271847 (by pjd):
Don't use nvl in case of a failure.
Reported by: Coverity
CID: 1238922
r272102 (by pjd):
Document the new nvlist_get_parent() function.
Submitted by: Mariusz Zaborski
r272843 (by pjd):
Fix problem on big endian systems introduced in r271579 - when we were
returning from handling a nested nvlist we were resetting big-endian flag.
Reported by: Kuleshov Aleksey @ yandex.ru
Tested by: Kuleshov Aleksey @ yandex.ru
r273752 (by jmg):
fix typo, properly install a link to nv for nvlist_freev...
r277920 (by pjd):
If moving descriptor or binary data to an nvlist fails, we need to close the
descriptor or free the memory before returning.
Submitted by: Mariusz Zaborski <oshogbo at FreeBSD.org>
While here, protect errno, so it won't be overwritted by close(2) or free(3).
r277921 (by pjd):
Modify nvlist_get_parent() API to take additional cookie argument.
This allow for non-recursive iteration over nested nvlists, as in documented
example.
Submitted by: Mariusz Zaborski <oshogbo at FreeBSD.org>
r277925 (by pjd):
Handle empty nvlists correctly.
Submitted by: Mariusz Zaborski <oshogbo at FreeBSD.org>
r277926 (by pjd):
Add missing nvlist_get_parent(3) link.
Submitted by: Mariusz Zaborski <oshogbo at FreeBSD.org>
r277927 (by pjd):
Make gcc happy.
Reported by: bz
r279421 (by rstone):
Make libnv headers includable from C++
Differential Revision: https://reviews.freebsd.org/D1868
Reviewed by: jfv, pjd
Sponsored by: Sandvine Inc.
r279422 (by rstone):
Tests of basic nvlist add functions
Differential Revision: https://reviews.freebsd.org/D1869
Reviewed by: jfv, pjd
Sponsored by: Sandvine Inc.
r279423 (by rstone):
Revert r279422. My "apply patch and commit" script wasn't adding
new files properly.
Pointy hat to: rstone
Modified:
user/ngie/stable-10-libnv/lib/libnv/Makefile
user/ngie/stable-10-libnv/lib/libnv/dnv.h
user/ngie/stable-10-libnv/lib/libnv/msgio.c
user/ngie/stable-10-libnv/lib/libnv/nv.3
user/ngie/stable-10-libnv/lib/libnv/nv.h
user/ngie/stable-10-libnv/lib/libnv/nv_impl.h
user/ngie/stable-10-libnv/lib/libnv/nvlist.c
user/ngie/stable-10-libnv/lib/libnv/nvlist_impl.h
user/ngie/stable-10-libnv/lib/libnv/nvpair.c
user/ngie/stable-10-libnv/lib/libnv/nvpair_impl.h
Directory Properties:
user/ngie/stable-10-libnv/ (props changed)
Modified: user/ngie/stable-10-libnv/lib/libnv/Makefile
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/Makefile Tue Dec 22 23:02:12 2015 (r292631)
+++ user/ngie/stable-10-libnv/lib/libnv/Makefile Tue Dec 22 23:05:43 2015 (r292632)
@@ -60,6 +60,7 @@ MLINKS+=nv.3 nvlist_create.3 \
nv.3 nvlist_get_nvlist.3 \
nv.3 nvlist_get_descriptor.3 \
nv.3 nvlist_get_binary.3 \
+ nv.3 nvlist_get_parent.3 \
nv.3 nvlist_take_bool.3 \
nv.3 nvlist_take_number.3 \
nv.3 nvlist_take_string.3 \
@@ -148,7 +149,7 @@ MLINKS+=nv.3 nvlist_existsv.3 \
nv.3 nvlist_takev_nvlist.3 \
nv.3 nvlist_takev_descriptor.3 \
nv.3 nvlist_takev_binary.3 \
- nv.3 nvlist_freef.3 \
+ nv.3 nvlist_freev.3 \
nv.3 nvlist_freev_type.3 \
nv.3 nvlist_freev_null.3 \
nv.3 nvlist_freev_bool.3 \
Modified: user/ngie/stable-10-libnv/lib/libnv/dnv.h
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/dnv.h Tue Dec 22 23:02:12 2015 (r292631)
+++ user/ngie/stable-10-libnv/lib/libnv/dnv.h Tue Dec 22 23:05:43 2015 (r292632)
@@ -45,6 +45,8 @@ struct nvlist;
typedef struct nvlist nvlist_t;
#endif
+__BEGIN_DECLS
+
/*
* The dnvlist_get functions returns value associated with the given name.
* If it returns a pointer, the pointer represents internal buffer and should
@@ -103,4 +105,6 @@ nvlist_t *dnvlist_takev_nvlist(nvlist_t
int dnvlist_takev_descriptor(nvlist_t *nvl, int defval, const char *namefmt, va_list nameap) __printflike(3, 0);
void *dnvlist_takev_binary(nvlist_t *nvl, size_t *sizep, void *defval, size_t defsize, const char *namefmt, va_list nameap) __printflike(5, 0);
+__END_DECLS
+
#endif /* !_DNV_H_ */
Modified: user/ngie/stable-10-libnv/lib/libnv/msgio.c
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/msgio.c Tue Dec 22 23:02:12 2015 (r292631)
+++ user/ngie/stable-10-libnv/lib/libnv/msgio.c Tue Dec 22 23:05:43 2015 (r292632)
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/socket.h>
#include <errno.h>
@@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$");
#define PJDLOG_ABORT(...) abort()
#endif
+#define PKG_MAX_SIZE (MCLBYTES / CMSG_SPACE(sizeof(int)) - 1)
+
static int
msghdr_add_fd(struct cmsghdr *cmsg, int fd)
{
@@ -234,22 +236,31 @@ cred_recv(int sock, struct cmsgcred *cre
return (0);
}
-int
-fd_send(int sock, const int *fds, size_t nfds)
+static int
+fd_package_send(int sock, const int *fds, size_t nfds)
{
struct msghdr msg;
struct cmsghdr *cmsg;
+ struct iovec iov;
unsigned int i;
int serrno, ret;
+ uint8_t dummy;
- if (nfds == 0 || fds == NULL) {
- errno = EINVAL;
- return (-1);
- }
+ PJDLOG_ASSERT(sock >= 0);
+ PJDLOG_ASSERT(fds != NULL);
+ PJDLOG_ASSERT(nfds > 0);
bzero(&msg, sizeof(msg));
- msg.msg_iov = NULL;
- msg.msg_iovlen = 0;
+
+ /*
+ * XXX: Look into cred_send function for more details.
+ */
+ dummy = 0;
+ iov.iov_base = &dummy;
+ iov.iov_len = sizeof(dummy);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int));
msg.msg_control = calloc(1, msg.msg_controllen);
if (msg.msg_control == NULL)
@@ -274,22 +285,32 @@ end:
return (ret);
}
-int
-fd_recv(int sock, int *fds, size_t nfds)
+static int
+fd_package_recv(int sock, int *fds, size_t nfds)
{
struct msghdr msg;
struct cmsghdr *cmsg;
unsigned int i;
int serrno, ret;
+ struct iovec iov;
+ uint8_t dummy;
- if (nfds == 0 || fds == NULL) {
- errno = EINVAL;
- return (-1);
- }
+ PJDLOG_ASSERT(sock >= 0);
+ PJDLOG_ASSERT(nfds > 0);
+ PJDLOG_ASSERT(fds != NULL);
+ i = 0;
bzero(&msg, sizeof(msg));
- msg.msg_iov = NULL;
- msg.msg_iovlen = 0;
+ bzero(&iov, sizeof(iov));
+
+ /*
+ * XXX: Look into cred_send function for more details.
+ */
+ iov.iov_base = &dummy;
+ iov.iov_len = sizeof(dummy);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int));
msg.msg_control = calloc(1, msg.msg_controllen);
if (msg.msg_control == NULL)
@@ -333,6 +354,64 @@ end:
}
int
+fd_recv(int sock, int *fds, size_t nfds)
+{
+ unsigned int i, step, j;
+ int ret, serrno;
+
+ if (nfds == 0 || fds == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ret = i = step = 0;
+ while (i < nfds) {
+ if (PKG_MAX_SIZE < nfds - i)
+ step = PKG_MAX_SIZE;
+ else
+ step = nfds - i;
+ ret = fd_package_recv(sock, fds + i, step);
+ if (ret != 0) {
+ /* Close all received descriptors. */
+ serrno = errno;
+ for (j = 0; j < i; j++)
+ close(fds[j]);
+ errno = serrno;
+ break;
+ }
+ i += step;
+ }
+
+ return (ret);
+}
+
+int
+fd_send(int sock, const int *fds, size_t nfds)
+{
+ unsigned int i, step;
+ int ret;
+
+ if (nfds == 0 || fds == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ret = i = step = 0;
+ while (i < nfds) {
+ if (PKG_MAX_SIZE < nfds - i)
+ step = PKG_MAX_SIZE;
+ else
+ step = nfds - i;
+ ret = fd_package_send(sock, fds + i, step);
+ if (ret != 0)
+ break;
+ i += step;
+ }
+
+ return (ret);
+}
+
+int
buf_send(int sock, void *buf, size_t size)
{
ssize_t done;
Modified: user/ngie/stable-10-libnv/lib/libnv/nv.3
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/nv.3 Tue Dec 22 23:02:12 2015 (r292631)
+++ user/ngie/stable-10-libnv/lib/libnv/nv.3 Tue Dec 22 23:05:43 2015 (r292632)
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 21, 2014
+.Dd January 30, 2015
.Dt NV 3
.Os
.Sh NAME
@@ -150,6 +150,8 @@
.Fn nvlist_get_descriptor "const nvlist_t *nvl" "const char *name"
.Ft "const void *"
.Fn nvlist_get_binary "const nvlist_t *nvl" "const char *name" "size_t *sizep"
+.Ft "const nvlist_t *"
+.Fn nvlist_get_parent "const nvlist_t *nvl" "void **cookiep"
.\"
.Ft bool
.Fn nvlist_take_bool "nvlist_t *nvl" "const char *name"
@@ -437,6 +439,10 @@ extension, which allows to provide defau
The nvlist must not be in error state.
.Pp
The
+.Fn nvlist_get_parent
+function allows to obtain the parent nvlist from the nested nvlist.
+.Pp
+The
.Fn nvlist_take_bool ,
.Fn nvlist_take_number ,
.Fn nvlist_take_string ,
@@ -582,6 +588,28 @@ while ((name = nvlist_next(nvl, &type, &
printf("\\n");
}
.Ed
+.Pp
+Iterating over every nested nvlist:
+.Bd -literal
+nvlist_t *nvl;
+const char *name;
+void *cookie;
+int type;
+
+nvl = nvlist_recv(sock);
+if (nvl == NULL)
+ err(1, "nvlist_recv() failed");
+
+cookie = NULL;
+do {
+ while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
+ if (type == NV_TYPE_NVLIST) {
+ nvl = nvlist_get_nvlist(nvl, name);
+ cookie = NULL;
+ }
+ }
+} while ((nvl = nvlist_get_parent(nvl, &cookie)) != NULL);
+.Ed
.Sh SEE ALSO
.Xr close 2 ,
.Xr dup 2 ,
Modified: user/ngie/stable-10-libnv/lib/libnv/nv.h
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/nv.h Tue Dec 22 23:02:12 2015 (r292631)
+++ user/ngie/stable-10-libnv/lib/libnv/nv.h Tue Dec 22 23:05:43 2015 (r292632)
@@ -63,6 +63,8 @@ typedef struct nvlist nvlist_t;
*/
#define NV_FLAG_IGNORE_CASE 0x01
+__BEGIN_DECLS
+
nvlist_t *nvlist_create(int flags);
void nvlist_destroy(nvlist_t *nvl);
int nvlist_error(const nvlist_t *nvl);
@@ -83,6 +85,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, void **cookiep);
+
/*
* The nvlist_exists functions check if the given name (optionally of the given
* type) exists on nvlist.
@@ -270,4 +274,6 @@ void nvlist_freev_nvlist(nvlist_t *nvl,
void nvlist_freev_descriptor(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0);
void nvlist_freev_binary(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0);
+__END_DECLS
+
#endif /* !_NV_H_ */
Modified: user/ngie/stable-10-libnv/lib/libnv/nv_impl.h
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/nv_impl.h Tue Dec 22 23:02:12 2015 (r292631)
+++ user/ngie/stable-10-libnv/lib/libnv/nv_impl.h Tue Dec 22 23:05:43 2015 (r292632)
@@ -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: user/ngie/stable-10-libnv/lib/libnv/nvlist.c
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/nvlist.c Tue Dec 22 23:02:12 2015 (r292631)
+++ user/ngie/stable-10-libnv/lib/libnv/nvlist.c Tue Dec 22 23:05:43 2015 (r292632)
@@ -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,40 @@ 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, void **cookiep)
+{
+ nvpair_t *nvp;
+
+ NVLIST_ASSERT(nvl);
+
+ nvp = nvl->nvl_parent;
+ if (cookiep != NULL)
+ *cookiep = nvp;
+ if (nvp == NULL)
+ return (NULL);
+
+ return (nvpair_nvlist(nvp));
+}
+
+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 +337,36 @@ 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)
+{
+ const nvlist_t *tmpnvl;
+ nvpair_t *nvp, *tmpnvp;
+ void *cookie;
+ 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,7 +388,16 @@ 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);
+ tmpnvl = nvpair_get_nvlist(nvp);
+ if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
+ break;
+ tmpnvp = nvlist_first_nvpair(tmpnvl);
+ if (tmpnvp != NULL) {
+ nvl = tmpnvl;
+ nvp = tmpnvp;
+ level++;
+ continue;
+ }
break;
case NV_TYPE_DESCRIPTOR:
dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
@@ -361,14 +418,16 @@ 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) {
+ cookie = NULL;
+ nvl = nvlist_get_parent(nvl, &cookie);
+ if (nvl == NULL)
+ return;
+ nvp = cookie;
+ level--;
+ }
+ }
}
void
@@ -381,41 +440,51 @@ 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;
+ const nvlist_t *tmpnvl;
+ const nvpair_t *nvp, *tmpnvp;
+ void *cookie;
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;
+ tmpnvl = nvpair_get_nvlist(nvp);
+ PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
+ tmpnvp = nvlist_first_nvpair(tmpnvl);
+ if (tmpnvp != NULL) {
+ nvl = tmpnvl;
+ nvp = tmpnvp;
+ continue;
+ }
+ } else {
size += nvpair_size(nvp);
+ }
+
+ while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
+ cookie = NULL;
+ nvl = nvlist_get_parent(nvl, &cookie);
+ if (nvl == NULL)
+ goto out;
+ nvp = cookie;
+ }
}
+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)
{
@@ -522,7 +591,9 @@ nvlist_xpack(const nvlist_t *nvl, int64_
{
unsigned char *buf, *ptr;
size_t left, size;
- nvpair_t *nvp;
+ const nvlist_t *tmpnvl;
+ nvpair_t *nvp, *tmpnvp;
+ void *cookie;
NVLIST_ASSERT(nvl);
@@ -541,15 +612,68 @@ 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:
+ tmpnvl = nvpair_get_nvlist(nvp);
+ ptr = nvlist_pack_header(tmpnvl, ptr, &left);
+ if (ptr == NULL)
+ goto out;
+ tmpnvp = nvlist_first_nvpair(tmpnvl);
+ if (tmpnvp != NULL) {
+ nvl = tmpnvl;
+ nvp = tmpnvp;
+ continue;
+ }
+ ptr = nvpair_pack_nvlist_up(ptr, &left);
+ break;
+ 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) {
+ cookie = NULL;
+ nvl = nvlist_get_parent(nvl, &cookie);
+ if (nvl == NULL)
+ goto out;
+ nvp = cookie;
+ ptr = nvpair_pack_nvlist_up(ptr, &left);
+ if (ptr == NULL)
+ goto out;
+ }
}
+out:
if (sizep != NULL)
*sizep = size;
return (buf);
@@ -600,9 +724,9 @@ 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)
+ bool *isbep, size_t *leftp)
{
struct nvlist_header nvlhdr;
@@ -629,7 +753,8 @@ nvlist_unpack_header(nvlist_t *nvl, cons
nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
ptr += sizeof(nvlhdr);
- *flagsp = (int)nvlhdr.nvlh_flags;
+ if (isbep != NULL)
+ *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
*leftp -= sizeof(nvlhdr);
return (ptr);
@@ -642,32 +767,72 @@ 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;
+ bool isbe;
left = size;
ptr = buf;
- nvl = nvlist_create(0);
+ tmpnvl = NULL;
+ nvl = retnvl = nvlist_create(0);
if (nvl == NULL)
goto failed;
- ptr = nvlist_unpack_header(nvl, ptr, nfds, &flags, &left);
+ ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
if (ptr == NULL)
goto failed;
while (left > 0) {
- ptr = nvpair_unpack(flags, ptr, &left, fds, nfds, &nvp);
+ ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
+ if (ptr == NULL)
+ goto failed;
+ switch (nvpair_type(nvp)) {
+ case NV_TYPE_NULL:
+ ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
+ break;
+ case NV_TYPE_BOOL:
+ ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
+ break;
+ case NV_TYPE_NUMBER:
+ ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
+ break;
+ case NV_TYPE_STRING:
+ ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
+ break;
+ case NV_TYPE_NVLIST:
+ ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
+ &tmpnvl);
+ nvlist_set_parent(tmpnvl, nvp);
+ break;
+ case NV_TYPE_DESCRIPTOR:
+ ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
+ fds, nfds);
+ break;
+ case NV_TYPE_BINARY:
+ ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
+ break;
+ case NV_TYPE_NVLIST_UP:
+ if (nvl->nvl_parent == NULL)
+ goto failed;
+ nvl = nvpair_nvlist(nvl->nvl_parent);
+ 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);
}
@@ -1328,7 +1493,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: user/ngie/stable-10-libnv/lib/libnv/nvlist_impl.h
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/nvlist_impl.h Tue Dec 22 23:02:12 2015 (r292631)
+++ user/ngie/stable-10-libnv/lib/libnv/nvlist_impl.h Tue Dec 22 23:05:43 2015 (r292632)
@@ -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, bool *isbep, size_t *leftp);
+
#endif /* !_NVLIST_IMPL_H_ */
Modified: user/ngie/stable-10-libnv/lib/libnv/nvpair.c
==============================================================================
--- user/ngie/stable-10-libnv/lib/libnv/nvpair.c Tue Dec 22 23:02:12 2015 (r292631)
+++ user/ngie/stable-10-libnv/lib/libnv/nvpair.c Tue Dec 22 23:05:43 2015 (r292632)
@@ -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,42 +386,10 @@ 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 *
-nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr,
+const unsigned char *
+nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp)
{
struct nvpair_header nvphdr;
@@ -434,16 +405,18 @@ 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) {
+ if (!isbe) {
nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
}
#else
- if ((flags & NV_FLAG_BIG_ENDIAN) != 0) {
+ if (isbe) {
nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
}
@@ -477,8 +450,8 @@ failed:
return (NULL);
}
-static const unsigned char *
-nvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
+const unsigned char *
+nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp __unused)
{
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-user
mailing list