From ed2711702a8f454a940514d9f30fb67d174e4df7 Mon Sep 17 00:00:00 2001 From: Ryan Stone Date: Sat, 17 May 2014 17:33:17 -0400 Subject: [PATCH 12/17] Split userland-specific stuff into its own file Refactor libnv so that all functions that deal solely with userland-specific data like file descriptors or sockets into a separate file. Some more generic functions have been untouched; those functions will have the userland-specific parts #ifdef'ed out ina subsequent commit. --- lib/libnv/Makefile | 1 + lib/libnv/dnvlist.c | 99 +-------- lib/libnv/nv_impl.h | 5 + lib/libnv/nv_user.c | 487 +++++++++++++++++++++++++++++++++++++++++++++ lib/libnv/nvlist.c | 462 +----------------------------------------- lib/libnv/nvlist_getters.h | 276 +++++++++++++++++++++++++ lib/libnv/nvlist_impl.h | 21 ++ lib/libnv/nvpair.c | 182 +---------------- lib/libnv/nvpair_impl.h | 24 ++- 9 files changed, 819 insertions(+), 738 deletions(-) create mode 100644 lib/libnv/nv_user.c create mode 100644 lib/libnv/nvlist_getters.h diff --git a/lib/libnv/Makefile b/lib/libnv/Makefile index 36e70e8..523c46a 100644 --- a/lib/libnv/Makefile +++ b/lib/libnv/Makefile @@ -8,6 +8,7 @@ SRCS= dnvlist.c SRCS+= msgio.c SRCS+= nvlist.c SRCS+= nvpair.c +SRCS+= nv_user.c INCS= dnv.h INCS+= nv.h diff --git a/lib/libnv/dnvlist.c b/lib/libnv/dnvlist.c index b758bbf..a0344a0 100644 --- a/lib/libnv/dnvlist.c +++ b/lib/libnv/dnvlist.c @@ -36,24 +36,14 @@ __FBSDID("$FreeBSD$"); #include "nv.h" #include "nv_impl.h" +#include "nvlist_getters.h" #include "dnv.h" -#define DNVLIST_GET(ftype, type) \ -ftype \ -dnvlist_get_##type(const nvlist_t *nvl, const char *name, ftype defval) \ -{ \ - \ - return (dnvlist_getf_##type(nvl, defval, "%s", name)); \ -} - DNVLIST_GET(bool, bool) DNVLIST_GET(uint64_t, number) DNVLIST_GET(const char *, string) DNVLIST_GET(const nvlist_t *, nvlist) -DNVLIST_GET(int, descriptor) - -#undef DNVLIST_GET const void * dnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep, @@ -63,28 +53,10 @@ dnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep, return (dnvlist_getf_binary(nvl, sizep, defval, defsize, "%s", name)); } -#define DNVLIST_GETF(ftype, type) \ -ftype \ -dnvlist_getf_##type(const nvlist_t *nvl, ftype defval, \ - const char *namefmt, ...) \ -{ \ - va_list nameap; \ - ftype value; \ - \ - va_start(nameap, namefmt); \ - value = dnvlist_getv_##type(nvl, defval, namefmt, nameap); \ - va_end(nameap); \ - \ - return (value); \ -} - DNVLIST_GETF(bool, bool) DNVLIST_GETF(uint64_t, number) DNVLIST_GETF(const char *, string) DNVLIST_GETF(const nvlist_t *, nvlist) -DNVLIST_GETF(int, descriptor) - -#undef DNVLIST_GETF const void * dnvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const void *defval, @@ -101,30 +73,10 @@ dnvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const void *defval, return (value); } -#define DNVLIST_GETV(ftype, type) \ -ftype \ -dnvlist_getv_##type(const nvlist_t *nvl, ftype defval, \ - const char *namefmt, va_list nameap) \ -{ \ - va_list cnameap; \ - ftype value; \ - \ - va_copy(cnameap, nameap); \ - if (nvlist_existsv_##type(nvl, namefmt, cnameap)) \ - value = nvlist_getv_##type(nvl, namefmt, nameap); \ - else \ - value = defval; \ - va_end(cnameap); \ - return (value); \ -} - DNVLIST_GETV(bool, bool) DNVLIST_GETV(uint64_t, number) DNVLIST_GETV(const char *, string) DNVLIST_GETV(const nvlist_t *, nvlist) -DNVLIST_GETV(int, descriptor) - -#undef DNVLIST_GETV const void * dnvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const void *defval, @@ -145,21 +97,10 @@ dnvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const void *defval, return (value); } -#define DNVLIST_TAKE(ftype, type) \ -ftype \ -dnvlist_take_##type(nvlist_t *nvl, const char *name, ftype defval) \ -{ \ - \ - return (dnvlist_takef_##type(nvl, defval, "%s", name)); \ -} - DNVLIST_TAKE(bool, bool) DNVLIST_TAKE(uint64_t, number) DNVLIST_TAKE(char *, string) DNVLIST_TAKE(nvlist_t *, nvlist) -DNVLIST_TAKE(int, descriptor) - -#undef DNVLIST_TAKE void * dnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep, @@ -169,28 +110,10 @@ dnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep, return (dnvlist_takef_binary(nvl, sizep, defval, defsize, "%s", name)); } -#define DNVLIST_TAKEF(ftype, type) \ -ftype \ -dnvlist_takef_##type(nvlist_t *nvl, ftype defval, \ - const char *namefmt, ...) \ -{ \ - va_list nameap; \ - ftype value; \ - \ - va_start(nameap, namefmt); \ - value = dnvlist_takev_##type(nvl, defval, namefmt, nameap); \ - va_end(nameap); \ - \ - return (value); \ -} - DNVLIST_TAKEF(bool, bool) DNVLIST_TAKEF(uint64_t, number) DNVLIST_TAKEF(char *, string) DNVLIST_TAKEF(nvlist_t *, nvlist) -DNVLIST_TAKEF(int, descriptor) - -#undef DNVLIST_TAKEF void * dnvlist_takef_binary(nvlist_t *nvl, size_t *sizep, void *defval, @@ -207,30 +130,10 @@ dnvlist_takef_binary(nvlist_t *nvl, size_t *sizep, void *defval, return (value); } -#define DNVLIST_TAKEV(ftype, type) \ -ftype \ -dnvlist_takev_##type(nvlist_t *nvl, ftype defval, const char *namefmt, \ - va_list nameap) \ -{ \ - va_list cnameap; \ - ftype value; \ - \ - va_copy(cnameap, nameap); \ - if (nvlist_existsv_##type(nvl, namefmt, cnameap)) \ - value = nvlist_takev_##type(nvl, namefmt, nameap); \ - else \ - value = defval; \ - va_end(cnameap); \ - return (value); \ -} - DNVLIST_TAKEV(bool, bool) DNVLIST_TAKEV(uint64_t, number) DNVLIST_TAKEV(char *, string) DNVLIST_TAKEV(nvlist_t *, nvlist) -DNVLIST_TAKEV(int, descriptor) - -#undef DNVLIST_TAKEV void * dnvlist_takev_binary(nvlist_t *nvl, size_t *sizep, void *defval, diff --git a/lib/libnv/nv_impl.h b/lib/libnv/nv_impl.h index 3206006..0e580fe 100644 --- a/lib/libnv/nv_impl.h +++ b/lib/libnv/nv_impl.h @@ -127,4 +127,9 @@ nvpair_t *nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list name nvpair_t *nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap) __printflike(2, 0); nvpair_t *nvpair_movev_binary(void *value, size_t size, const char *namefmt, va_list nameap) __printflike(3, 0); +unsigned char *nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, + int64_t *fdidxp, size_t *leftp); +const unsigned char *nvpair_unpack_descriptor(int flags, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds); + #endif /* !_NV_IMPL_H_ */ diff --git a/lib/libnv/nv_user.c b/lib/libnv/nv_user.c new file mode 100644 index 0000000..0993aff --- /dev/null +++ b/lib/libnv/nv_user.c @@ -0,0 +1,487 @@ +/*- + * Copyright (c) 2009-2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#define _WITH_DPRINTF +#include +#include +#include +#include + +#ifdef HAVE_PJDLOG +#include +#endif + +#include "common_impl.h" +#include "dnv.h" +#include "msgio.h" +#include "nv.h" +#include "nv_impl.h" +#include "nvlist_getters.h" +#include "nvlist_impl.h" +#include "nvpair_impl.h" + +#ifndef HAVE_PJDLOG +#include +#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) +#define PJDLOG_RASSERT(expr, ...) assert(expr) +#define PJDLOG_ABORT(...) do { \ + fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + abort(); \ +} while (0) +#endif + +/* + * Dump content of nvlist. + */ +static void +nvlist_xdump(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; + } + + for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; + nvp = nvlist_next_nvpair(nvl, nvp)) { + dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), + nvpair_type_string(nvpair_type(nvp))); + switch (nvpair_type(nvp)) { + case NV_TYPE_NULL: + dprintf(fd, " null\n"); + break; + case NV_TYPE_BOOL: + dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? + "TRUE" : "FALSE"); + break; + case NV_TYPE_NUMBER: + dprintf(fd, " %ju (%jd) (0x%jx)\n", + (uintmax_t)nvpair_get_number(nvp), + (intmax_t)nvpair_get_number(nvp), + (uintmax_t)nvpair_get_number(nvp)); + break; + case NV_TYPE_STRING: + dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); + break; + case NV_TYPE_NVLIST: + dprintf(fd, "\n"); + nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1); + break; + case NV_TYPE_DESCRIPTOR: + dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); + break; + case NV_TYPE_BINARY: + { + const unsigned char *binary; + unsigned int ii; + size_t size; + + binary = nvpair_get_binary(nvp, &size); + dprintf(fd, " %zu ", size); + for (ii = 0; ii < size; ii++) + dprintf(fd, "%02hhx", binary[ii]); + dprintf(fd, "\n"); + break; + } + default: + PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); + } + } +} + +void +nvlist_dump(const nvlist_t *nvl, int fd) +{ + + nvlist_xdump(nvl, fd, 0); +} + +void +nvlist_fdump(const nvlist_t *nvl, FILE *fp) +{ + + fflush(fp); + nvlist_dump(nvl, fileno(fp)); +} + +NVLIST_EXISTS(descriptor) +NVLIST_EXISTSF(descriptor) +NVLIST_EXISTSV(descriptor, DESCRIPTOR) + +void +nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value) +{ + + nvlist_addf_descriptor(nvl, value, "%s", name); +} + +void +nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...) +{ + va_list nameap; + + va_start(nameap, namefmt); + nvlist_addv_descriptor(nvl, value, namefmt, nameap); + va_end(nameap); +} + +void +nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt, + va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + errno = nvlist_error(nvl); + return; + } + + nvp = nvpair_createv_descriptor(value, namefmt, nameap); + if (nvp == NULL) + nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); + else + nvlist_move_nvpair(nvl, nvp); +} + +void +nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt, + va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + close(value); + errno = nvlist_error(nvl); + return; + } + + nvp = nvpair_movev_descriptor(value, namefmt, nameap); + if (nvp == NULL) + nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); + else + nvlist_move_nvpair(nvl, nvp); +} + +NVLIST_MOVE(int, descriptor) +NVLIST_MOVEF(int, descriptor) +NVLIST_GET(int, descriptor) +NVLIST_GETF(int, descriptor) +NVLIST_GETV(int, descriptor, DESCRIPTOR) +NVLIST_TAKE(int, descriptor) +NVLIST_TAKEF(int, descriptor) +NVLIST_TAKEV(int, descriptor, DESCRIPTOR) +NVLIST_FREE(descriptor) +NVLIST_FREEF(descriptor) +NVLIST_FREEV(descriptor, DESCRIPTOR) + +int +nvlist_send(int sock, const nvlist_t *nvl) +{ + size_t datasize, nfds; + int *fds; + void *data; + int64_t fdidx; + int serrno, ret; + + if (nvlist_error(nvl) != 0) { + errno = nvlist_error(nvl); + return (-1); + } + + fds = nvlist_descriptors(nvl, &nfds); + if (fds == NULL) + return (-1); + + ret = -1; + data = NULL; + fdidx = 0; + + data = nvlist_xpack(nvl, &fdidx, &datasize); + if (data == NULL) + goto out; + + if (buf_send(sock, data, datasize) == -1) + goto out; + + if (nfds > 0) { + if (fd_send(sock, fds, nfds) == -1) + goto out; + } + + ret = 0; +out: + serrno = errno; + free(fds); + free(data); + errno = serrno; + return (ret); +} + +nvlist_t * +nvlist_recv(int sock) +{ + struct nvlist_header nvlhdr; + nvlist_t *nvl, *ret; + unsigned char *buf; + size_t nfds, size; + int serrno, *fds; + + if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1) + return (NULL); + + if (!nvlist_check_header(&nvlhdr)) + return (NULL); + + nfds = (size_t)nvlhdr.nvlh_descriptors; + size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size; + + buf = malloc(size); + if (buf == NULL) + return (NULL); + + memcpy(buf, &nvlhdr, sizeof(nvlhdr)); + + ret = NULL; + fds = NULL; + + if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1) + goto out; + + if (nfds > 0) { + fds = malloc(nfds * sizeof(fds[0])); + if (fds == NULL) + goto out; + if (fd_recv(sock, fds, nfds) == -1) + goto out; + } + + nvl = nvlist_xunpack(buf, size, fds, nfds); + if (nvl == NULL) + goto out; + + ret = nvl; +out: + serrno = errno; + free(buf); + free(fds); + errno = serrno; + + return (ret); +} + +nvlist_t * +nvlist_xfer(int sock, nvlist_t *nvl) +{ + + if (nvlist_send(sock, nvl) < 0) { + nvlist_destroy(nvl); + return (NULL); + } + nvlist_destroy(nvl); + return (nvlist_recv(sock)); +} + +nvpair_t * +nvpair_createv_descriptor(int value, const char *namefmt, va_list nameap) +{ + nvpair_t *nvp; + + if (value < 0 || !fd_is_valid(value)) { + errno = EBADF; + return (NULL); + } + + value = fcntl(value, F_DUPFD_CLOEXEC, 0); + if (value < 0) + return (NULL); + + nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, + sizeof(int64_t), namefmt, nameap); + if (nvp == NULL) + close(value); + + return (nvp); +} + +unsigned char * +nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, + size_t *leftp) +{ + int64_t value; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); + + value = (int64_t)nvp->nvp_data; + if (value != -1) { + /* + * If there is a real descriptor here, we change its number + * to position in the array of descriptors send via control + * message. + */ + PJDLOG_ASSERT(fdidxp != NULL); + + value = *fdidxp; + (*fdidxp)++; + } + + PJDLOG_ASSERT(*leftp >= sizeof(value)); + memcpy(ptr, &value, sizeof(value)); + ptr += sizeof(value); + *leftp -= sizeof(value); + + return (ptr); +} + +const unsigned char * +nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp, const int *fds, size_t nfds) +{ + int64_t idx; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); + + if (nvp->nvp_datasize != sizeof(idx)) { + errno = EINVAL; + return (NULL); + } + if (*leftp < sizeof(idx)) { + errno = EINVAL; + return (NULL); + } + + if ((flags & NV_FLAG_BIG_ENDIAN) != 0) + idx = be64dec(ptr); + else + idx = le64dec(ptr); + + if (idx < 0) { + errno = EINVAL; + return (NULL); + } + + if ((size_t)idx >= nfds) { + errno = EINVAL; + return (NULL); + } + + nvp->nvp_data = (uint64_t)fds[idx]; + + ptr += sizeof(idx); + *leftp -= sizeof(idx); + + return (ptr); +} + +nvpair_t * +nvpair_create_descriptor(const char *name, int value) +{ + + return (nvpair_createf_descriptor(value, "%s", name)); +} + +nvpair_t * +nvpair_createf_descriptor(int value, const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_createv_descriptor(value, namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +nvpair_t * +nvpair_move_descriptor(const char *name, int value) +{ + + return (nvpair_movef_descriptor(value, "%s", name)); +} + +nvpair_t * +nvpair_movef_descriptor(int value, const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_movev_descriptor(value, namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +nvpair_t * +nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap) +{ + + if (value < 0 || !fd_is_valid(value)) { + errno = EBADF; + return (NULL); + } + + return (nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, + sizeof(int64_t), namefmt, nameap)); +} + +int +nvpair_get_descriptor(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); + + return ((int)nvp->nvp_data); +} + + +DNVLIST_GET(int, descriptor) +DNVLIST_GETF(int, descriptor) +DNVLIST_GETV(int, descriptor) +DNVLIST_TAKE(int, descriptor) +DNVLIST_TAKEF(int, descriptor) +DNVLIST_TAKEV(int, descriptor) diff --git a/lib/libnv/nvlist.c b/lib/libnv/nvlist.c index 6b17a3d..fcecfaf 100644 --- a/lib/libnv/nvlist.c +++ b/lib/libnv/nvlist.c @@ -49,9 +49,9 @@ __FBSDID("$FreeBSD$"); #include #endif -#include "msgio.h" #include "nv.h" #include "nv_impl.h" +#include "nvlist_getters.h" #include "nvlist_impl.h" #include "nvpair_impl.h" @@ -71,30 +71,11 @@ __FBSDID("$FreeBSD$"); #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE) #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK) -#define NVLIST_MAGIC 0x6e766c /* "nvl" */ -struct nvlist { - int nvl_magic; - int nvl_error; - int nvl_flags; - struct nvl_head nvl_head; -}; - #define NVLIST_ASSERT(nvl) do { \ PJDLOG_ASSERT((nvl) != NULL); \ PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \ } while (0) -#define NVPAIR_ASSERT(nvp) nvpair_assert(nvp) - -#define NVLIST_HEADER_MAGIC 0x6c -#define NVLIST_HEADER_VERSION 0x00 -struct nvlist_header { - uint8_t nvlh_magic; - uint8_t nvlh_version; - uint8_t nvlh_flags; - uint64_t nvlh_descriptors; - uint64_t nvlh_size; -} __packed; nvlist_t * nvlist_create(int flags) @@ -165,7 +146,7 @@ nvlist_empty(const nvlist_t *nvl) return (nvlist_first_nvpair(nvl) == NULL); } -static void +void nvlist_report_missing(int type, const char *namefmt, va_list nameap) { char *name; @@ -175,7 +156,7 @@ nvlist_report_missing(int type, const char *namefmt, va_list nameap) name != NULL ? name : "N/A", nvpair_type_string(type)); } -static nvpair_t * +nvpair_t * nvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap) { nvpair_t *nvp; @@ -310,84 +291,6 @@ nvlist_clone(const nvlist_t *nvl) } /* - * Dump content of nvlist. - */ -static void -nvlist_xdump(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; - } - - for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; - nvp = nvlist_next_nvpair(nvl, nvp)) { - dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), - nvpair_type_string(nvpair_type(nvp))); - switch (nvpair_type(nvp)) { - case NV_TYPE_NULL: - dprintf(fd, " null\n"); - break; - case NV_TYPE_BOOL: - dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? - "TRUE" : "FALSE"); - break; - case NV_TYPE_NUMBER: - dprintf(fd, " %ju (%jd) (0x%jx)\n", - (uintmax_t)nvpair_get_number(nvp), - (intmax_t)nvpair_get_number(nvp), - (uintmax_t)nvpair_get_number(nvp)); - break; - case NV_TYPE_STRING: - dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); - break; - case NV_TYPE_NVLIST: - dprintf(fd, "\n"); - nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1); - break; - case NV_TYPE_DESCRIPTOR: - dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); - break; - case NV_TYPE_BINARY: - { - const unsigned char *binary; - unsigned int ii; - size_t size; - - binary = nvpair_get_binary(nvp, &size); - dprintf(fd, " %zu ", size); - for (ii = 0; ii < size; ii++) - dprintf(fd, "%02hhx", binary[ii]); - dprintf(fd, "\n"); - break; - } - default: - PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); - } - } -} - -void -nvlist_dump(const nvlist_t *nvl, int fd) -{ - - nvlist_xdump(nvl, fd, 0); -} - -void -nvlist_fdump(const nvlist_t *nvl, FILE *fp) -{ - - fflush(fp); - nvlist_dump(nvl, fileno(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 @@ -582,7 +485,7 @@ nvlist_pack(const nvlist_t *nvl, size_t *sizep) return (nvlist_xpack(nvl, NULL, sizep)); } -static bool +bool nvlist_check_header(struct nvlist_header *nvlhdrp) { @@ -686,113 +589,6 @@ nvlist_unpack(const void *buf, size_t size) return (nvlist_xunpack(buf, size, NULL, 0)); } -int -nvlist_send(int sock, const nvlist_t *nvl) -{ - size_t datasize, nfds; - int *fds; - void *data; - int64_t fdidx; - int serrno, ret; - - if (nvlist_error(nvl) != 0) { - errno = nvlist_error(nvl); - return (-1); - } - - fds = nvlist_descriptors(nvl, &nfds); - if (fds == NULL) - return (-1); - - ret = -1; - data = NULL; - fdidx = 0; - - data = nvlist_xpack(nvl, &fdidx, &datasize); - if (data == NULL) - goto out; - - if (buf_send(sock, data, datasize) == -1) - goto out; - - if (nfds > 0) { - if (fd_send(sock, fds, nfds) == -1) - goto out; - } - - ret = 0; -out: - serrno = errno; - free(fds); - free(data); - errno = serrno; - return (ret); -} - -nvlist_t * -nvlist_recv(int sock) -{ - struct nvlist_header nvlhdr; - nvlist_t *nvl, *ret; - unsigned char *buf; - size_t nfds, size; - int serrno, *fds; - - if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1) - return (NULL); - - if (!nvlist_check_header(&nvlhdr)) - return (NULL); - - nfds = (size_t)nvlhdr.nvlh_descriptors; - size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size; - - buf = malloc(size); - if (buf == NULL) - return (NULL); - - memcpy(buf, &nvlhdr, sizeof(nvlhdr)); - - ret = NULL; - fds = NULL; - - if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1) - goto out; - - if (nfds > 0) { - fds = malloc(nfds * sizeof(fds[0])); - if (fds == NULL) - goto out; - if (fd_recv(sock, fds, nfds) == -1) - goto out; - } - - nvl = nvlist_xunpack(buf, size, fds, nfds); - if (nvl == NULL) - goto out; - - ret = nvl; -out: - serrno = errno; - free(buf); - free(fds); - errno = serrno; - - return (ret); -} - -nvlist_t * -nvlist_xfer(int sock, nvlist_t *nvl) -{ - - if (nvlist_send(sock, nvl) < 0) { - nvlist_destroy(nvl); - return (NULL); - } - nvlist_destroy(nvl); - return (nvlist_recv(sock)); -} - nvpair_t * nvlist_first_nvpair(const nvlist_t *nvl) { @@ -860,24 +656,13 @@ nvlist_exists(const nvlist_t *nvl, const char *name) return (nvlist_existsf(nvl, "%s", name)); } -#define NVLIST_EXISTS(type) \ -bool \ -nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ -{ \ - \ - return (nvlist_existsf_##type(nvl, "%s", name)); \ -} - NVLIST_EXISTS(null) NVLIST_EXISTS(bool) NVLIST_EXISTS(number) NVLIST_EXISTS(string) NVLIST_EXISTS(nvlist) -NVLIST_EXISTS(descriptor) NVLIST_EXISTS(binary) -#undef NVLIST_EXISTS - bool nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...) { @@ -890,29 +675,13 @@ nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...) return (ret); } -#define NVLIST_EXISTSF(type) \ -bool \ -nvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...) \ -{ \ - va_list nameap; \ - bool ret; \ - \ - va_start(nameap, namefmt); \ - ret = nvlist_existsv_##type(nvl, namefmt, nameap); \ - va_end(nameap); \ - return (ret); \ -} - NVLIST_EXISTSF(null) NVLIST_EXISTSF(bool) NVLIST_EXISTSF(number) NVLIST_EXISTSF(string) NVLIST_EXISTSF(nvlist) -NVLIST_EXISTSF(descriptor) NVLIST_EXISTSF(binary) -#undef NVLIST_EXISTSF - bool nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap) { @@ -920,26 +689,13 @@ nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap) return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap) != NULL); } -#define NVLIST_EXISTSV(type, TYPE) \ -bool \ -nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \ - va_list nameap) \ -{ \ - \ - return (nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, nameap) != \ - NULL); \ -} - NVLIST_EXISTSV(null, NULL) NVLIST_EXISTSV(bool, BOOL) NVLIST_EXISTSV(number, NUMBER) NVLIST_EXISTSV(string, STRING) NVLIST_EXISTSV(nvlist, NVLIST) -NVLIST_EXISTSV(descriptor, DESCRIPTOR) NVLIST_EXISTSV(binary, BINARY) -#undef NVLIST_EXISTSV - void nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) { @@ -1029,13 +785,6 @@ nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value) } void -nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value) -{ - - nvlist_addf_descriptor(nvl, value, "%s", name); -} - -void nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, size_t size) { @@ -1095,16 +844,6 @@ nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, } void -nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_descriptor(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size, const char *namefmt, ...) { @@ -1203,23 +942,6 @@ nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, nvlist_move_nvpair(nvl, nvp); } -void -nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - errno = nvlist_error(nvl); - return; - } - - nvp = nvpair_createv_descriptor(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else - nvlist_move_nvpair(nvl, nvp); -} void nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size, @@ -1260,19 +982,8 @@ nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) nvpair_insert(&nvl->nvl_head, nvp, nvl); } -#define NVLIST_MOVE(vtype, type) \ -void \ -nvlist_move_##type(nvlist_t *nvl, const char *name, vtype value) \ -{ \ - \ - nvlist_movef_##type(nvl, value, "%s", name); \ -} - NVLIST_MOVE(char *, string) NVLIST_MOVE(nvlist_t *, nvlist) -NVLIST_MOVE(int, descriptor) - -#undef NVLIST_MOVE void nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size) @@ -1281,23 +992,8 @@ nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size) nvlist_movef_binary(nvl, value, size, "%s", name); } -#define NVLIST_MOVEF(vtype, type) \ -void \ -nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt, \ - ...) \ -{ \ - va_list nameap; \ - \ - va_start(nameap, namefmt); \ - nvlist_movev_##type(nvl, value, namefmt, nameap); \ - va_end(nameap); \ -} - NVLIST_MOVEF(char *, string) NVLIST_MOVEF(nvlist_t *, nvlist) -NVLIST_MOVEF(int, descriptor) - -#undef NVLIST_MOVEF void nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size, @@ -1348,24 +1044,6 @@ nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt, nvlist_move_nvpair(nvl, nvp); } -void -nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - close(value); - errno = nvlist_error(nvl); - return; - } - - nvp = nvpair_movev_descriptor(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else - nvlist_move_nvpair(nvl, nvp); -} void nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, @@ -1386,22 +1064,11 @@ nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, nvlist_move_nvpair(nvl, nvp); } -#define NVLIST_GET(ftype, type) \ -ftype \ -nvlist_get_##type(const nvlist_t *nvl, const char *name) \ -{ \ - \ - return (nvlist_getf_##type(nvl, "%s", name)); \ -} - NVLIST_GET(const nvpair_t *, nvpair) NVLIST_GET(bool, bool) NVLIST_GET(uint64_t, number) NVLIST_GET(const char *, string) NVLIST_GET(const nvlist_t *, nvlist) -NVLIST_GET(int, descriptor) - -#undef NVLIST_GET const void * nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) @@ -1410,28 +1077,11 @@ nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) return (nvlist_getf_binary(nvl, sizep, "%s", name)); } -#define NVLIST_GETF(ftype, type) \ -ftype \ -nvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...) \ -{ \ - va_list nameap; \ - ftype value; \ - \ - va_start(nameap, namefmt); \ - value = nvlist_getv_##type(nvl, namefmt, nameap); \ - va_end(nameap); \ - \ - return (value); \ -} - NVLIST_GETF(const nvpair_t *, nvpair) NVLIST_GETF(bool, bool) NVLIST_GETF(uint64_t, number) NVLIST_GETF(const char *, string) NVLIST_GETF(const nvlist_t *, nvlist) -NVLIST_GETF(int, descriptor) - -#undef NVLIST_GETF const void * nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) @@ -1453,29 +1103,10 @@ nvlist_getv_nvpair(const nvlist_t *nvl, const char *namefmt, va_list nameap) return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap)); } -#define NVLIST_GETV(ftype, type, TYPE) \ -ftype \ -nvlist_getv_##type(const nvlist_t *nvl, const char *namefmt, \ - va_list nameap) \ -{ \ - va_list cnameap; \ - const nvpair_t *nvp; \ - \ - va_copy(cnameap, nameap); \ - nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \ - va_end(cnameap); \ - if (nvp == NULL) \ - nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \ - return (nvpair_get_##type(nvp)); \ -} - NVLIST_GETV(bool, bool, BOOL) NVLIST_GETV(uint64_t, number, NUMBER) NVLIST_GETV(const char *, string, STRING) NVLIST_GETV(const nvlist_t *, nvlist, NVLIST) -NVLIST_GETV(int, descriptor, DESCRIPTOR) - -#undef NVLIST_GETV const void * nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, @@ -1493,22 +1124,11 @@ nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, return (nvpair_get_binary(nvp, sizep)); } -#define NVLIST_TAKE(ftype, type) \ -ftype \ -nvlist_take_##type(nvlist_t *nvl, const char *name) \ -{ \ - \ - return (nvlist_takef_##type(nvl, "%s", name)); \ -} - NVLIST_TAKE(nvpair_t *, nvpair) NVLIST_TAKE(bool, bool) NVLIST_TAKE(uint64_t, number) NVLIST_TAKE(char *, string) NVLIST_TAKE(nvlist_t *, nvlist) -NVLIST_TAKE(int, descriptor) - -#undef NVLIST_TAKE void * nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) @@ -1517,28 +1137,11 @@ nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) return (nvlist_takef_binary(nvl, sizep, "%s", name)); } -#define NVLIST_TAKEF(ftype, type) \ -ftype \ -nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...) \ -{ \ - va_list nameap; \ - ftype value; \ - \ - va_start(nameap, namefmt); \ - value = nvlist_takev_##type(nvl, namefmt, nameap); \ - va_end(nameap); \ - \ - return (value); \ -} - NVLIST_TAKEF(nvpair_t *, nvpair) NVLIST_TAKEF(bool, bool) NVLIST_TAKEF(uint64_t, number) NVLIST_TAKEF(char *, string) NVLIST_TAKEF(nvlist_t *, nvlist) -NVLIST_TAKEF(int, descriptor) - -#undef NVLIST_TAKEF void * nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) @@ -1564,32 +1167,10 @@ nvlist_takev_nvpair(nvlist_t *nvl, const char *namefmt, va_list nameap) return (nvp); } -#define NVLIST_TAKEV(ftype, type, TYPE) \ -ftype \ -nvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \ -{ \ - va_list cnameap; \ - nvpair_t *nvp; \ - ftype value; \ - \ - va_copy(cnameap, nameap); \ - nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \ - va_end(cnameap); \ - if (nvp == NULL) \ - nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \ - value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ - nvlist_remove_nvpair(nvl, nvp); \ - nvpair_free_structure(nvp); \ - return (value); \ -} - NVLIST_TAKEV(bool, bool, BOOL) NVLIST_TAKEV(uint64_t, number, NUMBER) NVLIST_TAKEV(char *, string, STRING) NVLIST_TAKEV(nvlist_t *, nvlist, NVLIST) -NVLIST_TAKEV(int, descriptor, DESCRIPTOR) - -#undef NVLIST_TAKEV void * nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, @@ -1629,24 +1210,13 @@ nvlist_free(nvlist_t *nvl, const char *name) nvlist_freef(nvl, "%s", name); } -#define NVLIST_FREE(type) \ -void \ -nvlist_free_##type(nvlist_t *nvl, const char *name) \ -{ \ - \ - nvlist_freef_##type(nvl, "%s", name); \ -} - NVLIST_FREE(null) NVLIST_FREE(bool) NVLIST_FREE(number) NVLIST_FREE(string) NVLIST_FREE(nvlist) -NVLIST_FREE(descriptor) NVLIST_FREE(binary) -#undef NVLIST_FREE - void nvlist_freef(nvlist_t *nvl, const char *namefmt, ...) { @@ -1657,27 +1227,13 @@ nvlist_freef(nvlist_t *nvl, const char *namefmt, ...) va_end(nameap); } -#define NVLIST_FREEF(type) \ -void \ -nvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...) \ -{ \ - va_list nameap; \ - \ - va_start(nameap, namefmt); \ - nvlist_freev_##type(nvl, namefmt, nameap); \ - va_end(nameap); \ -} - NVLIST_FREEF(null) NVLIST_FREEF(bool) NVLIST_FREEF(number) NVLIST_FREEF(string) NVLIST_FREEF(nvlist) -NVLIST_FREEF(descriptor) NVLIST_FREEF(binary) -#undef NVLIST_FREEF - void nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap) { @@ -1685,22 +1241,12 @@ nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap) nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap); } -#define NVLIST_FREEV(type, TYPE) \ -void \ -nvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \ -{ \ - \ - nvlist_freev_type(nvl, NV_TYPE_##TYPE, namefmt, nameap); \ -} - NVLIST_FREEV(null, NULL) NVLIST_FREEV(bool, BOOL) NVLIST_FREEV(number, NUMBER) NVLIST_FREEV(string, STRING) NVLIST_FREEV(nvlist, NVLIST) -NVLIST_FREEV(descriptor, DESCRIPTOR) NVLIST_FREEV(binary, BINARY) -#undef NVLIST_FREEV void nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) diff --git a/lib/libnv/nvlist_getters.h b/lib/libnv/nvlist_getters.h new file mode 100644 index 0000000..7c00b64 --- /dev/null +++ b/lib/libnv/nvlist_getters.h @@ -0,0 +1,276 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NVLIST_GETTERS_H +#define _NVLIST_GETTERS_H + +nvpair_t * nvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, + va_list nameap); +void nvlist_report_missing(int type, const char *namefmt, va_list nameap); + +#define DNVLIST_GET(ftype, type) \ +ftype \ +dnvlist_get_##type(const nvlist_t *nvl, const char *name, ftype defval) \ +{ \ + \ + return (dnvlist_getf_##type(nvl, defval, "%s", name)); \ +} + +#define DNVLIST_GETF(ftype, type) \ +ftype \ +dnvlist_getf_##type(const nvlist_t *nvl, ftype defval, \ + const char *namefmt, ...) \ +{ \ + va_list nameap; \ + ftype value; \ + \ + va_start(nameap, namefmt); \ + value = dnvlist_getv_##type(nvl, defval, namefmt, nameap); \ + va_end(nameap); \ + \ + return (value); \ +} + +#define DNVLIST_GETV(ftype, type) \ +ftype \ +dnvlist_getv_##type(const nvlist_t *nvl, ftype defval, \ + const char *namefmt, va_list nameap) \ +{ \ + va_list cnameap; \ + ftype value; \ + \ + va_copy(cnameap, nameap); \ + if (nvlist_existsv_##type(nvl, namefmt, cnameap)) \ + value = nvlist_getv_##type(nvl, namefmt, nameap); \ + else \ + value = defval; \ + va_end(cnameap); \ + return (value); \ +} + +#define DNVLIST_TAKE(ftype, type) \ +ftype \ +dnvlist_take_##type(nvlist_t *nvl, const char *name, ftype defval) \ +{ \ + \ + return (dnvlist_takef_##type(nvl, defval, "%s", name)); \ +} + +#define DNVLIST_TAKEF(ftype, type) \ +ftype \ +dnvlist_takef_##type(nvlist_t *nvl, ftype defval, \ + const char *namefmt, ...) \ +{ \ + va_list nameap; \ + ftype value; \ + \ + va_start(nameap, namefmt); \ + value = dnvlist_takev_##type(nvl, defval, namefmt, nameap); \ + va_end(nameap); \ + \ + return (value); \ +} + +#define DNVLIST_TAKEV(ftype, type) \ +ftype \ +dnvlist_takev_##type(nvlist_t *nvl, ftype defval, const char *namefmt, \ + va_list nameap) \ +{ \ + va_list cnameap; \ + ftype value; \ + \ + va_copy(cnameap, nameap); \ + if (nvlist_existsv_##type(nvl, namefmt, cnameap)) \ + value = nvlist_takev_##type(nvl, namefmt, nameap); \ + else \ + value = defval; \ + va_end(cnameap); \ + return (value); \ +} + +#define NVLIST_EXISTS(type) \ +bool \ +nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ +{ \ + \ + return (nvlist_existsf_##type(nvl, "%s", name)); \ +} + +#define NVLIST_EXISTSF(type) \ +bool \ +nvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...) \ +{ \ + va_list nameap; \ + bool ret; \ + \ + va_start(nameap, namefmt); \ + ret = nvlist_existsv_##type(nvl, namefmt, nameap); \ + va_end(nameap); \ + return (ret); \ +} + +#define NVLIST_EXISTSV(type, TYPE) \ +bool \ +nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \ + va_list nameap) \ +{ \ + \ + return (nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, nameap) != \ + NULL); \ +} + +#define NVLIST_MOVE(vtype, type) \ +void \ +nvlist_move_##type(nvlist_t *nvl, const char *name, vtype value) \ +{ \ + \ + nvlist_movef_##type(nvl, value, "%s", name); \ +} + +#define NVLIST_MOVEF(vtype, type) \ +void \ +nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt, \ + ...) \ +{ \ + va_list nameap; \ + \ + va_start(nameap, namefmt); \ + nvlist_movev_##type(nvl, value, namefmt, nameap); \ + va_end(nameap); \ +} + +#define NVLIST_GET(ftype, type) \ +ftype \ +nvlist_get_##type(const nvlist_t *nvl, const char *name) \ +{ \ + \ + return (nvlist_getf_##type(nvl, "%s", name)); \ +} + +#define NVLIST_GETF(ftype, type) \ +ftype \ +nvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...) \ +{ \ + va_list nameap; \ + ftype value; \ + \ + va_start(nameap, namefmt); \ + value = nvlist_getv_##type(nvl, namefmt, nameap); \ + va_end(nameap); \ + \ + return (value); \ +} + +#define NVLIST_GETV(ftype, type, TYPE) \ +ftype \ +nvlist_getv_##type(const nvlist_t *nvl, const char *namefmt, \ + va_list nameap) \ +{ \ + va_list cnameap; \ + const nvpair_t *nvp; \ + \ + va_copy(cnameap, nameap); \ + nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \ + va_end(cnameap); \ + if (nvp == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \ + return (nvpair_get_##type(nvp)); \ +} + +#define NVLIST_TAKE(ftype, type) \ +ftype \ +nvlist_take_##type(nvlist_t *nvl, const char *name) \ +{ \ + \ + return (nvlist_takef_##type(nvl, "%s", name)); \ +} + +#define NVLIST_TAKEF(ftype, type) \ +ftype \ +nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...) \ +{ \ + va_list nameap; \ + ftype value; \ + \ + va_start(nameap, namefmt); \ + value = nvlist_takev_##type(nvl, namefmt, nameap); \ + va_end(nameap); \ + \ + return (value); \ +} + +#define NVLIST_TAKEV(ftype, type, TYPE) \ +ftype \ +nvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \ +{ \ + va_list cnameap; \ + nvpair_t *nvp; \ + ftype value; \ + \ + va_copy(cnameap, nameap); \ + nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \ + va_end(cnameap); \ + if (nvp == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \ + value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ + nvlist_remove_nvpair(nvl, nvp); \ + nvpair_free_structure(nvp); \ + return (value); \ +} + +#define NVLIST_FREE(type) \ +void \ +nvlist_free_##type(nvlist_t *nvl, const char *name) \ +{ \ + \ + nvlist_freef_##type(nvl, "%s", name); \ +} + +#define NVLIST_FREEF(type) \ +void \ +nvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...) \ +{ \ + va_list nameap; \ + \ + va_start(nameap, namefmt); \ + nvlist_freev_##type(nvl, namefmt, nameap); \ + va_end(nameap); \ +} + +#define NVLIST_FREEV(type, TYPE) \ +void \ +nvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \ +{ \ + \ + nvlist_freev_type(nvl, NV_TYPE_##TYPE, namefmt, nameap); \ +} + +#endif diff --git a/lib/libnv/nvlist_impl.h b/lib/libnv/nvlist_impl.h index 43a7bb0..73223e6 100644 --- a/lib/libnv/nvlist_impl.h +++ b/lib/libnv/nvlist_impl.h @@ -36,8 +36,29 @@ #include "nv.h" +TAILQ_HEAD(nvl_head, nvpair); + +#define NVLIST_MAGIC 0x6e766c /* "nvl" */ +struct nvlist { + int nvl_magic; + int nvl_error; + int nvl_flags; + struct nvl_head nvl_head; +}; + +#define NVLIST_HEADER_MAGIC 0x6c +#define NVLIST_HEADER_VERSION 0x00 +struct nvlist_header { + uint8_t nvlh_magic; + uint8_t nvlh_version; + uint8_t nvlh_flags; + uint64_t nvlh_descriptors; + uint64_t nvlh_size; +} __packed; + 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); +bool nvlist_check_header(struct nvlist_header *nvlhdrp); #endif /* !_NVLIST_IMPL_H_ */ diff --git a/lib/libnv/nvpair.c b/lib/libnv/nvpair.c index 916444f..9db9933 100644 --- a/lib/libnv/nvpair.c +++ b/lib/libnv/nvpair.c @@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -60,29 +59,6 @@ __FBSDID("$FreeBSD$"); #define PJDLOG_ABORT(...) abort() #endif -#define NVPAIR_MAGIC 0x6e7670 /* "nvp" */ -struct nvpair { - int nvp_magic; - char *nvp_name; - int nvp_type; - uint64_t nvp_data; - size_t nvp_datasize; - nvlist_t *nvp_list; /* Used for sanity checks. */ - TAILQ_ENTRY(nvpair) nvp_next; -}; - -#define NVPAIR_ASSERT(nvp) do { \ - PJDLOG_ASSERT((nvp) != NULL); \ - PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \ -} while (0) - -struct nvpair_header { - uint8_t nvph_type; - uint16_t nvph_namesize; - uint64_t nvph_datasize; -} __packed; - - void nvpair_assert(const nvpair_t *nvp) { @@ -320,36 +296,6 @@ nvpair_pack_nvlist(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, } static unsigned char * -nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, - size_t *leftp) -{ - int64_t value; - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); - - value = (int64_t)nvp->nvp_data; - if (value != -1) { - /* - * If there is a real descriptor here, we change its number - * to position in the array of descriptors send via control - * message. - */ - PJDLOG_ASSERT(fdidxp != NULL); - - value = *fdidxp; - (*fdidxp)++; - } - - PJDLOG_ASSERT(*leftp >= sizeof(value)); - memcpy(ptr, &value, sizeof(value)); - ptr += sizeof(value); - *leftp -= sizeof(value); - - return (ptr); -} - -static unsigned char * nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) { @@ -603,46 +549,6 @@ nvpair_unpack_nvlist(int flags __unused, nvpair_t *nvp, } static const unsigned char * -nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr, - size_t *leftp, const int *fds, size_t nfds) -{ - int64_t idx; - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); - - if (nvp->nvp_datasize != sizeof(idx)) { - errno = EINVAL; - return (NULL); - } - if (*leftp < sizeof(idx)) { - errno = EINVAL; - return (NULL); - } - - if ((flags & NV_FLAG_BIG_ENDIAN) != 0) - idx = be64dec(ptr); - else - idx = le64dec(ptr); - - if (idx < 0) { - errno = EINVAL; - return (NULL); - } - - if ((size_t)idx >= nfds) { - errno = EINVAL; - return (NULL); - } - - nvp->nvp_data = (uint64_t)fds[idx]; - - ptr += sizeof(idx); - *leftp -= sizeof(idx); - - return (ptr); -} - -static const unsigned char * nvpair_unpack_binary(int flags __unused, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp) { @@ -746,7 +652,7 @@ nvpair_name(const nvpair_t *nvp) return (nvp->nvp_name); } -static nvpair_t * +nvpair_t * nvpair_allocv(int type, uint64_t data, size_t datasize, const char *namefmt, va_list nameap) { @@ -846,13 +752,6 @@ nvpair_create_nvlist(const char *name, const nvlist_t *value) } nvpair_t * -nvpair_create_descriptor(const char *name, int value) -{ - - return (nvpair_createf_descriptor(value, "%s", name)); -} - -nvpair_t * nvpair_create_binary(const char *name, const void *value, size_t size) { @@ -925,19 +824,6 @@ nvpair_createf_nvlist(const nvlist_t *value, const char *namefmt, ...) } nvpair_t * -nvpair_createf_descriptor(int value, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_createv_descriptor(value, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -nvpair_t * nvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...) { va_list nameap; @@ -1023,28 +909,6 @@ nvpair_createv_nvlist(const nvlist_t *value, const char *namefmt, } nvpair_t * -nvpair_createv_descriptor(int value, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (value < 0 || !fd_is_valid(value)) { - errno = EBADF; - return (NULL); - } - - value = fcntl(value, F_DUPFD_CLOEXEC, 0); - if (value < 0) - return (NULL); - - nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, - sizeof(int64_t), namefmt, nameap); - if (nvp == NULL) - close(value); - - return (nvp); -} - -nvpair_t * nvpair_createv_binary(const void *value, size_t size, const char *namefmt, va_list nameap) { @@ -1084,13 +948,6 @@ nvpair_move_nvlist(const char *name, nvlist_t *value) } nvpair_t * -nvpair_move_descriptor(const char *name, int value) -{ - - return (nvpair_movef_descriptor(value, "%s", name)); -} - -nvpair_t * nvpair_move_binary(const char *name, void *value, size_t size) { @@ -1124,19 +981,6 @@ nvpair_movef_nvlist(nvlist_t *value, const char *namefmt, ...) } nvpair_t * -nvpair_movef_descriptor(int value, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_movev_descriptor(value, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -nvpair_t * nvpair_movef_binary(void *value, size_t size, const char *namefmt, ...) { va_list nameap; @@ -1186,19 +1030,6 @@ nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap) } nvpair_t * -nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap) -{ - - if (value < 0 || !fd_is_valid(value)) { - errno = EBADF; - return (NULL); - } - - return (nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, - sizeof(int64_t), namefmt, nameap)); -} - -nvpair_t * nvpair_movev_binary(void *value, size_t size, const char *namefmt, va_list nameap) { @@ -1249,17 +1080,6 @@ nvpair_get_nvlist(const nvpair_t *nvp) return ((const nvlist_t *)(intptr_t)nvp->nvp_data); } - -int -nvpair_get_descriptor(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); - - return ((int)nvp->nvp_data); -} - const void * nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) { diff --git a/lib/libnv/nvpair_impl.h b/lib/libnv/nvpair_impl.h index aa4046c..58159be 100644 --- a/lib/libnv/nvpair_impl.h +++ b/lib/libnv/nvpair_impl.h @@ -38,7 +38,27 @@ #include "nv.h" -TAILQ_HEAD(nvl_head, nvpair); +#define NVPAIR_MAGIC 0x6e7670 /* "nvp" */ +struct nvpair { + int nvp_magic; + char *nvp_name; + int nvp_type; + uint64_t nvp_data; + size_t nvp_datasize; + nvlist_t *nvp_list; /* Used for sanity checks. */ + TAILQ_ENTRY(nvpair) nvp_next; +}; + +#define NVPAIR_ASSERT(nvp) do { \ + PJDLOG_ASSERT((nvp) != NULL); \ + PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC); \ +} while (0) + +struct nvpair_header { + uint8_t nvph_type; + uint16_t nvph_namesize; + uint64_t nvph_datasize; +} __packed; void nvpair_assert(const nvpair_t *nvp); const nvlist_t *nvpair_nvlist(const nvpair_t *nvp); @@ -54,5 +74,7 @@ const unsigned char *nvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds, nvpair_t **nvpp); void nvpair_free_structure(nvpair_t *nvp); const char *nvpair_type_string(int type); +nvpair_t *nvpair_allocv(int type, uint64_t data, size_t datasize, + const char *namefmt, va_list nameap); #endif /* !_NVPAIR_IMPL_H_ */ -- 1.9.2