Index: head/lib/libnv/Makefile =================================================================== --- head/lib/libnv/Makefile +++ head/lib/libnv/Makefile @@ -7,10 +7,13 @@ LIB= nv SHLIB_MAJOR= 0 -SRCS= dnvlist.c +.PATH: ${.CURDIR}/../../sys/kern ${.CURDIR}/../../sys/sys +CFLAGS+=-I${.CURDIR}/../../sys -I${.CURDIR} + +SRCS= subr_dnvlist.c SRCS+= msgio.c -SRCS+= nvlist.c -SRCS+= nvpair.c +SRCS+= subr_nvlist.c +SRCS+= subr_nvpair.c INCS= dnv.h INCS+= nv.h Index: head/lib/libnv/dnv.h =================================================================== --- head/lib/libnv/dnv.h +++ head/lib/libnv/dnv.h @@ -1,116 +0,0 @@ -/*- - * 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 _DNV_H_ -#define _DNV_H_ - -#include - -#ifndef _KERNEL -#include -#include -#include -#endif - -#ifndef _NVLIST_T_DECLARED -#define _NVLIST_T_DECLARED -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 - * not be freed by the caller. - * If no element of the given name and type exists, the function will return - * provided default value. - */ - -bool dnvlist_get_bool(const nvlist_t *nvl, const char *name, bool defval); -uint64_t dnvlist_get_number(const nvlist_t *nvl, const char *name, uint64_t defval); -const char *dnvlist_get_string(const nvlist_t *nvl, const char *name, const char *defval); -const nvlist_t *dnvlist_get_nvlist(const nvlist_t *nvl, const char *name, const nvlist_t *defval); -int dnvlist_get_descriptor(const nvlist_t *nvl, const char *name, int defval); -const void *dnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep, const void *defval, size_t defsize); - -#ifndef _KERNEL -bool dnvlist_getf_bool(const nvlist_t *nvl, bool defval, const char *namefmt, ...) __printflike(3, 4); -uint64_t dnvlist_getf_number(const nvlist_t *nvl, uint64_t defval, const char *namefmt, ...) __printflike(3, 4); -const char *dnvlist_getf_string(const nvlist_t *nvl, const char *defval, const char *namefmt, ...) __printflike(3, 4); -const nvlist_t *dnvlist_getf_nvlist(const nvlist_t *nvl, const nvlist_t *defval, const char *namefmt, ...) __printflike(3, 4); -int dnvlist_getf_descriptor(const nvlist_t *nvl, int defval, const char *namefmt, ...) __printflike(3, 4); -const void *dnvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const void *defval, size_t defsize, const char *namefmt, ...) __printflike(5, 6); - -bool dnvlist_getv_bool(const nvlist_t *nvl, bool defval, const char *namefmt, va_list nameap) __printflike(3, 0); -uint64_t dnvlist_getv_number(const nvlist_t *nvl, uint64_t defval, const char *namefmt, va_list nameap) __printflike(3, 0); -const char *dnvlist_getv_string(const nvlist_t *nvl, const char *defval, const char *namefmt, va_list nameap) __printflike(3, 0); -const nvlist_t *dnvlist_getv_nvlist(const nvlist_t *nvl, const nvlist_t *defval, const char *namefmt, va_list nameap) __printflike(3, 0); -int dnvlist_getv_descriptor(const nvlist_t *nvl, int defval, const char *namefmt, va_list nameap) __printflike(3, 0); -const void *dnvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const void *defval, size_t defsize, const char *namefmt, va_list nameap) __printflike(5, 0); -#endif - -/* - * The dnvlist_take functions returns value associated with the given name and - * remove corresponding nvpair. - * If it returns a pointer, the caller has to free it. - * If no element of the given name and type exists, the function will return - * provided default value. - */ - -bool dnvlist_take_bool(nvlist_t *nvl, const char *name, bool defval); -uint64_t dnvlist_take_number(nvlist_t *nvl, const char *name, uint64_t defval); -char *dnvlist_take_string(nvlist_t *nvl, const char *name, char *defval); -nvlist_t *dnvlist_take_nvlist(nvlist_t *nvl, const char *name, nvlist_t *defval); -int dnvlist_take_descriptor(nvlist_t *nvl, const char *name, int defval); -void *dnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep, void *defval, size_t defsize); - -#ifndef _KERNEL -bool dnvlist_takef_bool(nvlist_t *nvl, bool defval, const char *namefmt, ...) __printflike(3, 4); -uint64_t dnvlist_takef_number(nvlist_t *nvl, uint64_t defval, const char *namefmt, ...) __printflike(3, 4); -char *dnvlist_takef_string(nvlist_t *nvl, char *defval, const char *namefmt, ...) __printflike(3, 4); -nvlist_t *dnvlist_takef_nvlist(nvlist_t *nvl, nvlist_t *defval, const char *namefmt, ...) __printflike(3, 4); -int dnvlist_takef_descriptor(nvlist_t *nvl, int defval, const char *namefmt, ...) __printflike(3, 4); -void *dnvlist_takef_binary(nvlist_t *nvl, size_t *sizep, void *defval, size_t defsize, const char *namefmt, ...) __printflike(5, 6); - -bool dnvlist_takev_bool(nvlist_t *nvl, bool defval, const char *namefmt, va_list nameap) __printflike(3, 0); -uint64_t dnvlist_takev_number(nvlist_t *nvl, uint64_t defval, const char *namefmt, va_list nameap) __printflike(3, 0); -char *dnvlist_takev_string(nvlist_t *nvl, char *defval, const char *namefmt, va_list nameap) __printflike(3, 0); -nvlist_t *dnvlist_takev_nvlist(nvlist_t *nvl, nvlist_t *defval, const char *namefmt, va_list nameap) __printflike(3, 0); -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); -#endif - -__END_DECLS - -#endif /* !_DNV_H_ */ Index: head/lib/libnv/dnvlist.c =================================================================== --- head/lib/libnv/dnvlist.c +++ head/lib/libnv/dnvlist.c @@ -1,294 +0,0 @@ -/*- - * 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. - */ - -#include -__FBSDID("$FreeBSD$"); - -#ifdef _KERNEL - -#include -#include -#include -#include -#include - -#include - -#else -#include -#include -#include -#include -#endif - -#include "nv.h" -#include "nv_impl.h" - -#include "dnv.h" - -#define DNVLIST_GET(ftype, type) \ -ftype \ -dnvlist_get_##type(const nvlist_t *nvl, const char *name, ftype defval) \ -{ \ - \ - if (nvlist_exists_##type(nvl, name)) \ - return (nvlist_get_##type(nvl, name)); \ - else \ - return (defval); \ -} - -DNVLIST_GET(bool, bool) -DNVLIST_GET(uint64_t, number) -DNVLIST_GET(const char *, string) -DNVLIST_GET(const nvlist_t *, nvlist) -#ifndef _KERNEL -DNVLIST_GET(int, descriptor) -#endif - -#undef DNVLIST_GET - -const void * -dnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep, - const void *defval, size_t defsize) -{ - const void *value; - - if (nvlist_exists_binary(nvl, name)) - value = nvlist_get_binary(nvl, name, sizep); - else { - if (sizep != NULL) - *sizep = defsize; - value = defval; - } - return (value); -} - -#ifndef _KERNEL -#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, - size_t defsize, const char *namefmt, ...) -{ - va_list nameap; - const void *value; - - va_start(nameap, namefmt); - value = dnvlist_getv_binary(nvl, sizep, defval, defsize, 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) \ -{ \ - char *name; \ - ftype value; \ - \ - vasprintf(&name, namefmt, nameap); \ - if (name == NULL) \ - return (defval); \ - value = dnvlist_get_##type(nvl, name, defval); \ - free(name); \ - 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, - size_t defsize, const char *namefmt, va_list nameap) -{ - char *name; - const void *value; - - nv_vasprintf(&name, namefmt, nameap); - if (name != NULL) { - value = dnvlist_get_binary(nvl, name, sizep, defval, defsize); - nv_free(name); - } else { - if (sizep != NULL) - *sizep = defsize; - value = defval; - } - return (value); -} -#endif - -#define DNVLIST_TAKE(ftype, type) \ -ftype \ -dnvlist_take_##type(nvlist_t *nvl, const char *name, ftype defval) \ -{ \ - \ - if (nvlist_exists_##type(nvl, name)) \ - return (nvlist_take_##type(nvl, name)); \ - else \ - return (defval); \ -} - -DNVLIST_TAKE(bool, bool) -DNVLIST_TAKE(uint64_t, number) -DNVLIST_TAKE(char *, string) -DNVLIST_TAKE(nvlist_t *, nvlist) -#ifndef _KERNEL -DNVLIST_TAKE(int, descriptor) -#endif - -#undef DNVLIST_TAKE - -void * -dnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep, - void *defval, size_t defsize) -{ - void *value; - - if (nvlist_exists_binary(nvl, name)) - value = nvlist_take_binary(nvl, name, sizep); - else { - if (sizep != NULL) - *sizep = defsize; - value = defval; - } - return (value); -} - -#ifndef _KERNEL -#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, - size_t defsize, const char *namefmt, ...) -{ - va_list nameap; - void *value; - - va_start(nameap, namefmt); - value = dnvlist_takev_binary(nvl, sizep, defval, defsize, 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) \ -{ \ - char *name; \ - ftype value; \ - \ - vasprintf(&name, namefmt, nameap); \ - if (name == NULL) \ - return (defval); \ - value = dnvlist_take_##type(nvl, name, defval); \ - free(name); \ - 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, - size_t defsize, const char *namefmt, va_list nameap) -{ - char *name; - void *value; - - nv_vasprintf(&name, namefmt, nameap); - if (name != NULL) { - value = dnvlist_take_binary(nvl, name, sizep, defval, defsize); - nv_free(name); - } else { - if (sizep != NULL) - *sizep = defsize; - value = defval; - } - - return (value); -} -#endif Index: head/lib/libnv/nv.h =================================================================== --- head/lib/libnv/nv.h +++ head/lib/libnv/nv.h @@ -1,322 +0,0 @@ -/*- - * 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. - * - * $FreeBSD$ - */ - -#ifndef _NV_H_ -#define _NV_H_ - -#include - -#ifndef _KERNEL -#include -#include -#include -#include -#endif - -#ifndef _NVLIST_T_DECLARED -#define _NVLIST_T_DECLARED -struct nvlist; - -typedef struct nvlist nvlist_t; -#endif - -#define NV_NAME_MAX 2048 - -#define NV_TYPE_NONE 0 - -#define NV_TYPE_NULL 1 -#define NV_TYPE_BOOL 2 -#define NV_TYPE_NUMBER 3 -#define NV_TYPE_STRING 4 -#define NV_TYPE_NVLIST 5 -#define NV_TYPE_DESCRIPTOR 6 -#define NV_TYPE_BINARY 7 - -/* - * Perform case-insensitive lookups of provided names. - */ -#define NV_FLAG_IGNORE_CASE 0x01 - -#if defined(_KERNEL) && defined(MALLOC_DECLARE) -MALLOC_DECLARE(M_NVLIST); -#endif - -__BEGIN_DECLS - -nvlist_t *nvlist_create(int flags); -void nvlist_destroy(nvlist_t *nvl); -int nvlist_error(const nvlist_t *nvl); -bool nvlist_empty(const nvlist_t *nvl); -void nvlist_set_error(nvlist_t *nvl, int error); - -nvlist_t *nvlist_clone(const nvlist_t *nvl); - -#ifndef _KERNEL -void nvlist_dump(const nvlist_t *nvl, int fd); -void nvlist_fdump(const nvlist_t *nvl, FILE *fp); -#endif - -size_t nvlist_size(const nvlist_t *nvl); -void *nvlist_pack(const nvlist_t *nvl, size_t *sizep); -nvlist_t *nvlist_unpack(const void *buf, size_t size); - -int nvlist_send(int sock, const nvlist_t *nvl); -nvlist_t *nvlist_recv(int sock); -nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl); - -const char *nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep); - -const nvlist_t *nvlist_get_parent(const nvlist_t *nvl, void **cookiep); - -/* - * The nvlist_exists functions check if the given name (optionally of the given - * type) exists on nvlist. - */ - -bool nvlist_exists(const nvlist_t *nvl, const char *name); -bool nvlist_exists_type(const nvlist_t *nvl, const char *name, int type); - -bool nvlist_exists_null(const nvlist_t *nvl, const char *name); -bool nvlist_exists_bool(const nvlist_t *nvl, const char *name); -bool nvlist_exists_number(const nvlist_t *nvl, const char *name); -bool nvlist_exists_string(const nvlist_t *nvl, const char *name); -bool nvlist_exists_nvlist(const nvlist_t *nvl, const char *name); -#ifndef _KERNEL -bool nvlist_exists_descriptor(const nvlist_t *nvl, const char *name); -#endif -bool nvlist_exists_binary(const nvlist_t *nvl, const char *name); - -/* - * The nvlist_add functions add the given name/value pair. - * If a pointer is provided, nvlist_add will internally allocate memory for the - * given data (in other words it won't consume provided buffer). - */ - -void nvlist_add_null(nvlist_t *nvl, const char *name); -void nvlist_add_bool(nvlist_t *nvl, const char *name, bool value); -void nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value); -void nvlist_add_string(nvlist_t *nvl, const char *name, const char *value); -void nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) __printflike(3, 4); -#ifdef _VA_LIST_DECLARED -void nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, va_list valueap) __printflike(3, 0); -#endif -void nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value); -#ifndef _KERNEL -void nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value); -#endif -void nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, size_t size); - -/* - * The nvlist_move functions add the given name/value pair. - * The functions consumes provided buffer. - */ - -void nvlist_move_string(nvlist_t *nvl, const char *name, char *value); -void nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value); -#ifndef _KERNEL -void nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value); -#endif -void nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size); - -/* - * The nvlist_get functions returns value associated with the given name. - * If it returns a pointer, the pointer represents internal buffer and should - * not be freed by the caller. - */ - -bool nvlist_get_bool(const nvlist_t *nvl, const char *name); -uint64_t nvlist_get_number(const nvlist_t *nvl, const char *name); -const char *nvlist_get_string(const nvlist_t *nvl, const char *name); -const nvlist_t *nvlist_get_nvlist(const nvlist_t *nvl, const char *name); -#ifndef _KERNEL -int nvlist_get_descriptor(const nvlist_t *nvl, const char *name); -#endif -const void *nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep); - -/* - * The nvlist_take functions returns value associated with the given name and - * remove the given entry from the nvlist. - * The caller is responsible for freeing received data. - */ - -bool nvlist_take_bool(nvlist_t *nvl, const char *name); -uint64_t nvlist_take_number(nvlist_t *nvl, const char *name); -char *nvlist_take_string(nvlist_t *nvl, const char *name); -nvlist_t *nvlist_take_nvlist(nvlist_t *nvl, const char *name); -#ifndef _KERNEL -int nvlist_take_descriptor(nvlist_t *nvl, const char *name); -#endif -void *nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep); - -/* - * The nvlist_free functions removes the given name/value pair from the nvlist - * and frees memory associated with it. - */ - -void nvlist_free(nvlist_t *nvl, const char *name); -void nvlist_free_type(nvlist_t *nvl, const char *name, int type); - -void nvlist_free_null(nvlist_t *nvl, const char *name); -void nvlist_free_bool(nvlist_t *nvl, const char *name); -void nvlist_free_number(nvlist_t *nvl, const char *name); -void nvlist_free_string(nvlist_t *nvl, const char *name); -void nvlist_free_nvlist(nvlist_t *nvl, const char *name); -#ifndef _KERNEL -void nvlist_free_descriptor(nvlist_t *nvl, const char *name); -#endif -void nvlist_free_binary(nvlist_t *nvl, const char *name); - -/* - * Below are the same functions, but which operate on format strings and - * variable argument lists. - * - * Functions that are not inserting a new pair into the nvlist cannot handle - * a failure to allocate the memory to hold the new name. Therefore these - * functions are not provided in the kernel. - */ - -#ifndef _KERNEL -bool nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...) __printflike(3, 4); - -bool nvlist_existsf_null(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_bool(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_number(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_string(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_nvlist(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_descriptor(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_binary(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); - -bool nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap) __printflike(3, 0); - -bool nvlist_existsv_null(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_bool(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_number(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_string(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_nvlist(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_descriptor(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_binary(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -#endif - -void nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...) __printflike(3, 4); -void nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...) __printflike(3, 4); -void nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...) __printflike(3, 4); -void nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, ...) __printflike(3, 4); -#ifndef _KERNEL -void nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...) __printflike(3, 4); -#endif -void nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size, const char *namefmt, ...) __printflike(4, 5); - -#if !defined(_KERNEL) || defined(_VA_LIST_DECLARED) -void nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap) __printflike(3, 0); -void nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt, va_list nameap) __printflike(3, 0); -void nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt, va_list nameap) __printflike(3, 0); -void nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, va_list nameap) __printflike(3, 0); -#ifndef _KERNEL -void nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt, va_list nameap) __printflike(3, 0); -#endif -void nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size, const char *namefmt, va_list nameap) __printflike(4, 0); -#endif - -void nvlist_movef_string(nvlist_t *nvl, char *value, const char *namefmt, ...) __printflike(3, 4); -void nvlist_movef_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt, ...) __printflike(3, 4); -#ifndef _KERNEL -void nvlist_movef_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...) __printflike(3, 4); -#endif -void nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size, const char *namefmt, ...) __printflike(4, 5); - -#if !defined(_KERNEL) || defined(_VA_LIST_DECLARED) -void nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt, va_list nameap) __printflike(3, 0); -void nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt, va_list nameap) __printflike(3, 0); -#ifndef _KERNEL -void nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt, va_list nameap) __printflike(3, 0); -#endif -void nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, const char *namefmt, va_list nameap) __printflike(4, 0); -#endif - -#ifndef _KERNEL -bool nvlist_getf_bool(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -uint64_t nvlist_getf_number(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -const char *nvlist_getf_string(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -const nvlist_t *nvlist_getf_nvlist(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -int nvlist_getf_descriptor(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -const void *nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) __printflike(3, 4); - -bool nvlist_getv_bool(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -uint64_t nvlist_getv_number(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -const char *nvlist_getv_string(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -const nvlist_t *nvlist_getv_nvlist(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -int nvlist_getv_descriptor(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -const void *nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, va_list nameap) __printflike(3, 0); - -bool nvlist_takef_bool(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -uint64_t nvlist_takef_number(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -char *nvlist_takef_string(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -nvlist_t *nvlist_takef_nvlist(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -int nvlist_takef_descriptor(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void *nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) __printflike(3, 4); - -bool nvlist_takev_bool(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -uint64_t nvlist_takev_number(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -char *nvlist_takev_string(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -nvlist_t *nvlist_takev_nvlist(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -int nvlist_takev_descriptor(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void *nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, va_list nameap) __printflike(3, 0); - -void nvlist_freef(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...) __printflike(3, 4); - -void nvlist_freef_null(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_bool(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_number(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_string(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_nvlist(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_descriptor(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_binary(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); - -void nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap) __printflike(3, 0); - -void nvlist_freev_null(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_freev_bool(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_freev_number(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_freev_string(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_freev_nvlist(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -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); -#endif /* _KERNEL */ - -__END_DECLS - -#endif /* !_NV_H_ */ Index: head/lib/libnv/nv_impl.h =================================================================== --- head/lib/libnv/nv_impl.h +++ head/lib/libnv/nv_impl.h @@ -1,157 +0,0 @@ -/*- - * 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 _NV_IMPL_H_ -#define _NV_IMPL_H_ - -#ifndef _NVPAIR_T_DECLARED -#define _NVPAIR_T_DECLARED -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 - -#define NV_FLAG_BIG_ENDIAN 0x80 - -#ifdef _KERNEL -#define nv_malloc(size) malloc((size), M_NVLIST, M_NOWAIT) -#define nv_calloc(n, size) malloc((n) * (size), M_NVLIST, \ - M_NOWAIT | M_ZERO) -#define nv_realloc(buf, size) realloc((buf), (size), M_NVLIST, \ - M_NOWAIT) -#define nv_free(buf) free((buf), M_NVLIST) -#define nv_strdup(buf) strdup((buf), M_NVLIST) -#define nv_vasprintf(ptr, ...) vasprintf(ptr, M_NVLIST, __VA_ARGS__) - -#define SAVE_ERRNO(var) ((void)(var)) -#define RESTORE_ERRNO(var) ((void)(var)) - -#define ERRNO_OR_DEFAULT(default) (default) - -#else - -#define nv_malloc(size) malloc((size)) -#define nv_calloc(n, size) calloc((n), (size)) -#define nv_realloc(buf, size) realloc((buf), (size)) -#define nv_free(buf) free((buf)) -#define nv_strdup(buf) strdup((buf)) -#define nv_vasprintf(ptr, ...) vasprintf(ptr, __VA_ARGS__) - -#define SAVE_ERRNO(var) (var) = errno -#define RESTORE_ERRNO(var) errno = (var) - -#define ERRNO_OR_DEFAULT(default) (errno == 0 ? (default) : errno) - -#endif - -int *nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp); -size_t nvlist_ndescriptors(const nvlist_t *nvl); - -nvpair_t *nvlist_first_nvpair(const nvlist_t *nvl); -nvpair_t *nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp); -nvpair_t *nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp); - -void nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp); - -void nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp); - -void nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent); - -const nvpair_t *nvlist_get_nvpair(const nvlist_t *nvl, const char *name); - -nvpair_t *nvlist_take_nvpair(nvlist_t *nvl, const char *name); - -/* Function removes the given nvpair from the nvlist. */ -void nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp); - -void nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp); - -int nvpair_type(const nvpair_t *nvp); -const char *nvpair_name(const nvpair_t *nvp); - -nvpair_t *nvpair_clone(const nvpair_t *nvp); - -nvpair_t *nvpair_create_null(const char *name); -nvpair_t *nvpair_create_bool(const char *name, bool value); -nvpair_t *nvpair_create_number(const char *name, uint64_t value); -nvpair_t *nvpair_create_string(const char *name, const char *value); -nvpair_t *nvpair_create_stringf(const char *name, const char *valuefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) __printflike(2, 0); -nvpair_t *nvpair_create_nvlist(const char *name, const nvlist_t *value); -nvpair_t *nvpair_create_descriptor(const char *name, int value); -nvpair_t *nvpair_create_binary(const char *name, const void *value, size_t size); - -nvpair_t *nvpair_move_string(const char *name, char *value); -nvpair_t *nvpair_move_nvlist(const char *name, nvlist_t *value); -nvpair_t *nvpair_move_descriptor(const char *name, int value); -nvpair_t *nvpair_move_binary(const char *name, void *value, size_t size); - -bool nvpair_get_bool(const nvpair_t *nvp); -uint64_t nvpair_get_number(const nvpair_t *nvp); -const char *nvpair_get_string(const nvpair_t *nvp); -const nvlist_t *nvpair_get_nvlist(const nvpair_t *nvp); -int nvpair_get_descriptor(const nvpair_t *nvp); -const void *nvpair_get_binary(const nvpair_t *nvp, size_t *sizep); - -void nvpair_free(nvpair_t *nvp); - -nvpair_t *nvpair_createf_null(const char *namefmt, ...) __printflike(1, 2); -nvpair_t *nvpair_createf_bool(bool value, const char *namefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_createf_number(uint64_t value, const char *namefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_createf_string(const char *value, const char *namefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_createf_nvlist(const nvlist_t *value, const char *namefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_createf_descriptor(int value, const char *namefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...) __printflike(3, 4); - -nvpair_t *nvpair_createv_null(const char *namefmt, va_list nameap) __printflike(1, 0); -nvpair_t *nvpair_createv_bool(bool value, const char *namefmt, va_list nameap) __printflike(2, 0); -nvpair_t *nvpair_createv_number(uint64_t value, const char *namefmt, va_list nameap) __printflike(2, 0); -nvpair_t *nvpair_createv_string(const char *value, const char *namefmt, va_list nameap) __printflike(2, 0); -nvpair_t *nvpair_createv_nvlist(const nvlist_t *value, const char *namefmt, va_list nameap) __printflike(2, 0); -nvpair_t *nvpair_createv_descriptor(int value, const char *namefmt, va_list nameap) __printflike(2, 0); -nvpair_t *nvpair_createv_binary(const void *value, size_t size, const char *namefmt, va_list nameap) __printflike(3, 0); - -nvpair_t *nvpair_movef_string(char *value, const char *namefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_movef_nvlist(nvlist_t *value, const char *namefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_movef_descriptor(int value, const char *namefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_movef_binary(void *value, size_t size, const char *namefmt, ...) __printflike(3, 4); - -nvpair_t *nvpair_movev_string(char *value, const char *namefmt, va_list nameap) __printflike(2, 0); -nvpair_t *nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap) __printflike(2, 0); -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); - -#endif /* !_NV_IMPL_H_ */ Index: head/lib/libnv/nvlist.c =================================================================== --- head/lib/libnv/nvlist.c +++ head/lib/libnv/nvlist.c @@ -1,2001 +0,0 @@ -/*- - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#ifdef _KERNEL - -#include -#include -#include -#include -#include - -#include - -#else -#include - -#include -#include -#include -#include -#define _WITH_DPRINTF -#include -#include -#include -#include -#endif - -#ifdef HAVE_PJDLOG -#include -#endif - -#include "msgio.h" -#include "nv.h" -#include "nv_impl.h" -#include "nvlist_impl.h" -#include "nvpair_impl.h" - -#ifndef HAVE_PJDLOG -#ifdef _KERNEL -#define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) -#define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) -#define PJDLOG_ABORT(...) panic(__VA_ARGS__) -#else -#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 -#endif - -#define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN) -#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; - nvpair_t *nvl_parent; - struct nvl_head nvl_head; -}; - -#define NVLIST_ASSERT(nvl) do { \ - PJDLOG_ASSERT((nvl) != NULL); \ - PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \ -} while (0) - -#ifdef _KERNEL -MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist"); -#endif - -#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) -{ - nvlist_t *nvl; - - PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); - - nvl = nv_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; - - return (nvl); -} - -void -nvlist_destroy(nvlist_t *nvl) -{ - nvpair_t *nvp; - int serrno; - - if (nvl == NULL) - return; - - SAVE_ERRNO(serrno); - - NVLIST_ASSERT(nvl); - - while ((nvp = nvlist_first_nvpair(nvl)) != NULL) { - nvlist_remove_nvpair(nvl, nvp); - nvpair_free(nvp); - } - nvl->nvl_magic = 0; - nv_free(nvl); - - RESTORE_ERRNO(serrno); -} - -void -nvlist_set_error(nvlist_t *nvl, int error) -{ - - PJDLOG_ASSERT(error != 0); - - /* - * Check for error != 0 so that we don't do the wrong thing if somebody - * tries to abuse this API when asserts are disabled. - */ - if (nvl != NULL && error != 0 && nvl->nvl_error == 0) - nvl->nvl_error = error; -} - -int -nvlist_error(const nvlist_t *nvl) -{ - - if (nvl == NULL) - return (ENOMEM); - - NVLIST_ASSERT(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) -{ - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - - return (nvlist_first_nvpair(nvl) == NULL); -} - -static void -nvlist_report_missing(int type, const char *name) -{ - - PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", - name, nvpair_type_string(type)); -} - -static nvpair_t * -nvlist_find(const nvlist_t *nvl, int type, const char *name) -{ - nvpair_t *nvp; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - PJDLOG_ASSERT(type == NV_TYPE_NONE || - (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); - - for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; - nvp = nvlist_next_nvpair(nvl, nvp)) { - if (type != NV_TYPE_NONE && nvpair_type(nvp) != type) - continue; - if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) { - if (strcasecmp(nvpair_name(nvp), name) != 0) - continue; - } else { - if (strcmp(nvpair_name(nvp), name) != 0) - continue; - } - break; - } - - if (nvp == NULL) - RESTORE_ERRNO(ENOENT); - - return (nvp); -} - -bool -nvlist_exists_type(const nvlist_t *nvl, const char *name, int type) -{ - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - PJDLOG_ASSERT(type == NV_TYPE_NONE || - (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); - - return (nvlist_find(nvl, type, name) != NULL); -} - -#ifndef _KERNEL -bool -nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...) -{ - va_list nameap; - bool ret; - - va_start(nameap, namefmt); - ret = nvlist_existsv_type(nvl, type, namefmt, nameap); - va_end(nameap); - - return (ret); -} - -bool -nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt, - va_list nameap) -{ - char *name; - bool exists; - - nv_vasprintf(&name, namefmt, nameap); - if (name == NULL) - return (false); - - exists = nvlist_exists_type(nvl, name, type); - nv_free(name); - return (exists); -} -#endif - -void -nvlist_free_type(nvlist_t *nvl, const char *name, int type) -{ - nvpair_t *nvp; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - PJDLOG_ASSERT(type == NV_TYPE_NONE || - (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); - - nvp = nvlist_find(nvl, type, name); - if (nvp != NULL) - nvlist_free_nvpair(nvl, nvp); - else - nvlist_report_missing(type, name); -} - -#ifndef _KERNEL -void -nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_freev_type(nvl, type, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap) -{ - char *name; - - nv_vasprintf(&name, namefmt, nameap); - if (name == NULL) - nvlist_report_missing(type, ""); - nvlist_free_type(nvl, name, type); - nv_free(name); -} -#endif - -nvlist_t * -nvlist_clone(const nvlist_t *nvl) -{ - nvlist_t *newnvl; - nvpair_t *nvp, *newnvp; - - NVLIST_ASSERT(nvl); - - if (nvl->nvl_error != 0) { - RESTORE_ERRNO(nvl->nvl_error); - return (NULL); - } - - newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); - for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; - nvp = nvlist_next_nvpair(nvl, nvp)) { - newnvp = nvpair_clone(nvp); - if (newnvp == NULL) - break; - nvlist_move_nvpair(newnvl, newnvp); - } - if (nvp != NULL) { - nvlist_destroy(newnvl); - return (NULL); - } - return (newnvl); -} - -#ifndef _KERNEL -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. - */ -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)) { - 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"); - 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)); - 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)); - } - - while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { - cookie = NULL; - nvl = nvlist_get_parent(nvl, &cookie); - if (nvl == NULL) - return; - nvp = cookie; - level--; - } - } -} - -void -nvlist_fdump(const nvlist_t *nvl, FILE *fp) -{ - - fflush(fp); - nvlist_dump(nvl, fileno(fp)); -} -#endif - -/* - * The function obtains size of the nvlist after nvlist_pack(). - */ -size_t -nvlist_size(const nvlist_t *nvl) -{ - const nvlist_t *tmpnvl; - const nvpair_t *nvp, *tmpnvp; - void *cookie; - size_t size; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - - size = sizeof(struct nvlist_header); - 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 += 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); -} - -#ifndef _KERNEL -static int * -nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level) -{ - const nvpair_t *nvp; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - PJDLOG_ASSERT(level < 3); - - for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; - nvp = nvlist_next_nvpair(nvl, nvp)) { - switch (nvpair_type(nvp)) { - case NV_TYPE_DESCRIPTOR: - *descs = nvpair_get_descriptor(nvp); - descs++; - break; - case NV_TYPE_NVLIST: - descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp), - descs, level + 1); - break; - } - } - - return (descs); -} -#endif - -#ifndef _KERNEL -int * -nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp) -{ - size_t nitems; - int *fds; - - nitems = nvlist_ndescriptors(nvl); - fds = nv_malloc(sizeof(fds[0]) * (nitems + 1)); - if (fds == NULL) - return (NULL); - if (nitems > 0) - nvlist_xdescriptors(nvl, fds, 0); - fds[nitems] = -1; - if (nitemsp != NULL) - *nitemsp = nitems; - return (fds); -} -#endif - -static size_t -nvlist_xndescriptors(const nvlist_t *nvl, int level) -{ -#ifndef _KERNEL - const nvpair_t *nvp; - size_t ndescs; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - PJDLOG_ASSERT(level < 3); - - ndescs = 0; - for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; - nvp = nvlist_next_nvpair(nvl, nvp)) { - switch (nvpair_type(nvp)) { - case NV_TYPE_DESCRIPTOR: - ndescs++; - break; - case NV_TYPE_NVLIST: - ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp), - level + 1); - break; - } - } - - return (ndescs); -#else - return (0); -#endif -} - -size_t -nvlist_ndescriptors(const nvlist_t *nvl) -{ - - return (nvlist_xndescriptors(nvl, 0)); -} - -static unsigned char * -nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp) -{ - struct nvlist_header nvlhdr; - - NVLIST_ASSERT(nvl); - - nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC; - nvlhdr.nvlh_version = NVLIST_HEADER_VERSION; - nvlhdr.nvlh_flags = nvl->nvl_flags; -#if BYTE_ORDER == BIG_ENDIAN - nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN; -#endif - nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl); - nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr); - PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr)); - memcpy(ptr, &nvlhdr, sizeof(nvlhdr)); - ptr += sizeof(nvlhdr); - *leftp -= sizeof(nvlhdr); - - return (ptr); -} - -void * -nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) -{ - unsigned char *buf, *ptr; - size_t left, size; - const nvlist_t *tmpnvl; - nvpair_t *nvp, *tmpnvp; - void *cookie; - - NVLIST_ASSERT(nvl); - - if (nvl->nvl_error != 0) { - RESTORE_ERRNO(nvl->nvl_error); - return (NULL); - } - - size = nvlist_size(nvl); - buf = nv_malloc(size); - if (buf == NULL) - return (NULL); - - ptr = buf; - left = size; - - ptr = nvlist_pack_header(nvl, ptr, &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) { - nv_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; -#ifndef _KERNEL - case NV_TYPE_DESCRIPTOR: - ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left); - break; -#endif - case NV_TYPE_BINARY: - ptr = nvpair_pack_binary(nvp, ptr, &left); - break; - default: - PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); - } - if (ptr == NULL) { - nv_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); -} - -void * -nvlist_pack(const nvlist_t *nvl, size_t *sizep) -{ - - NVLIST_ASSERT(nvl); - - if (nvl->nvl_error != 0) { - RESTORE_ERRNO(nvl->nvl_error); - return (NULL); - } - - if (nvlist_ndescriptors(nvl) > 0) { - RESTORE_ERRNO(EOPNOTSUPP); - return (NULL); - } - - return (nvlist_xpack(nvl, NULL, sizep)); -} - -static bool -nvlist_check_header(struct nvlist_header *nvlhdrp) -{ - - if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { - RESTORE_ERRNO(EINVAL); - return (false); - } - if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { - RESTORE_ERRNO(EINVAL); - return (false); - } -#if BYTE_ORDER == BIG_ENDIAN - if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) { - nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size); - nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors); - } -#else - if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) { - nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size); - nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); - } -#endif - return (true); -} - -const unsigned char * -nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, - bool *isbep, size_t *leftp) -{ - struct nvlist_header nvlhdr; - - if (*leftp < sizeof(nvlhdr)) - goto failed; - - memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); - - if (!nvlist_check_header(&nvlhdr)) - goto failed; - - if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) - goto failed; - - /* - * nvlh_descriptors might be smaller than nfds in embedded nvlists. - */ - if (nvlhdr.nvlh_descriptors > nfds) - goto failed; - - if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) - goto failed; - - nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK); - - ptr += sizeof(nvlhdr); - if (isbep != NULL) - *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0); - *leftp -= sizeof(nvlhdr); - - return (ptr); -failed: - RESTORE_ERRNO(EINVAL); - return (NULL); -} - -nvlist_t * -nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) -{ - const unsigned char *ptr; - nvlist_t *nvl, *retnvl, *tmpnvl; - nvpair_t *nvp; - size_t left; - bool isbe; - - left = size; - ptr = buf; - - tmpnvl = NULL; - nvl = retnvl = nvlist_create(0); - if (nvl == NULL) - goto failed; - - ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); - if (ptr == NULL) - goto failed; - - while (left > 0) { - 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; -#ifndef _KERNEL - case NV_TYPE_DESCRIPTOR: - ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left, - fds, nfds); - break; -#endif - 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 (retnvl); -failed: - nvlist_destroy(retnvl); - return (NULL); -} - -nvlist_t * -nvlist_unpack(const void *buf, size_t size) -{ - - return (nvlist_xunpack(buf, size, NULL, 0)); -} - -#ifndef _KERNEL -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, i; - 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) { - for (i = 0; i < nfds; i++) - close(fds[i]); - 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)); -} -#endif - -nvpair_t * -nvlist_first_nvpair(const nvlist_t *nvl) -{ - - NVLIST_ASSERT(nvl); - - return (TAILQ_FIRST(&nvl->nvl_head)); -} - -nvpair_t * -nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) -{ - nvpair_t *retnvp; - - NVLIST_ASSERT(nvl); - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); - - retnvp = nvpair_next(nvp); - PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl); - - return (retnvp); - -} - -nvpair_t * -nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) -{ - nvpair_t *retnvp; - - NVLIST_ASSERT(nvl); - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); - - retnvp = nvpair_prev(nvp); - PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl); - - return (retnvp); -} - -const char * -nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep) -{ - nvpair_t *nvp; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(cookiep != NULL); - - if (*cookiep == NULL) - nvp = nvlist_first_nvpair(nvl); - else - nvp = nvlist_next_nvpair(nvl, *cookiep); - if (nvp == NULL) - return (NULL); - if (typep != NULL) - *typep = nvpair_type(nvp); - *cookiep = nvp; - return (nvpair_name(nvp)); -} - -bool -nvlist_exists(const nvlist_t *nvl, const char *name) -{ - - return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL); -} - -#define NVLIST_EXISTS(type, TYPE) \ -bool \ -nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ -{ \ - \ - return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \ -} - -NVLIST_EXISTS(null, NULL) -NVLIST_EXISTS(bool, BOOL) -NVLIST_EXISTS(number, NUMBER) -NVLIST_EXISTS(string, STRING) -NVLIST_EXISTS(nvlist, NVLIST) -#ifndef _KERNEL -NVLIST_EXISTS(descriptor, DESCRIPTOR) -#endif -NVLIST_EXISTS(binary, BINARY) - -#undef NVLIST_EXISTS - -#ifndef _KERNEL -bool -nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...) -{ - va_list nameap; - bool ret; - - va_start(nameap, namefmt); - ret = nvlist_existsv(nvl, namefmt, nameap); - va_end(nameap); - 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) -#ifndef _KERNEL -NVLIST_EXISTSF(descriptor) -#endif -NVLIST_EXISTSF(binary) - -#undef NVLIST_EXISTSF - -bool -nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap) -{ - char *name; - bool exists; - - nv_vasprintf(&name, namefmt, nameap); - if (name == NULL) - return (false); - - exists = nvlist_exists(nvl, name); - nv_free(name); - return (exists); -} - -#define NVLIST_EXISTSV(type) \ -bool \ -nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \ - va_list nameap) \ -{ \ - char *name; \ - bool exists; \ - \ - vasprintf(&name, namefmt, nameap); \ - if (name == NULL) \ - return (false); \ - exists = nvlist_exists_##type(nvl, name); \ - free(name); \ - return (exists); \ -} - -NVLIST_EXISTSV(null) -NVLIST_EXISTSV(bool) -NVLIST_EXISTSV(number) -NVLIST_EXISTSV(string) -NVLIST_EXISTSV(nvlist) -NVLIST_EXISTSV(descriptor) -NVLIST_EXISTSV(binary) - -#undef NVLIST_EXISTSV -#endif - -void -nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) -{ - nvpair_t *newnvp; - - NVPAIR_ASSERT(nvp); - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - if (nvlist_exists(nvl, nvpair_name(nvp))) { - nvl->nvl_error = EEXIST; - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - newnvp = nvpair_clone(nvp); - if (newnvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvpair_insert(&nvl->nvl_head, newnvp, nvl); -} - -void -nvlist_add_null(nvlist_t *nvl, const char *name) -{ - - nvlist_addf_null(nvl, "%s", name); -} - -void -nvlist_add_bool(nvlist_t *nvl, const char *name, bool value) -{ - - nvlist_addf_bool(nvl, value, "%s", name); -} - -void -nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value) -{ - - nvlist_addf_number(nvl, value, "%s", name); -} - -void -nvlist_add_string(nvlist_t *nvl, const char *name, const char *value) -{ - - nvlist_addf_string(nvl, value, "%s", name); -} - -void -nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) -{ - va_list valueap; - - va_start(valueap, valuefmt); - nvlist_add_stringv(nvl, name, valuefmt, valueap); - va_end(valueap); -} - -void -nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, - va_list valueap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_create_stringv(name, valuefmt, valueap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value) -{ - - nvlist_addf_nvlist(nvl, value, "%s", name); -} - -#ifndef _KERNEL -void -nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value) -{ - - nvlist_addf_descriptor(nvl, value, "%s", name); -} -#endif - -void -nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, - size_t size) -{ - - nvlist_addf_binary(nvl, value, size, "%s", name); -} - -void -nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_null(nvl, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_bool(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_number(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_string(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, - ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_nvlist(nvl, value, namefmt, nameap); - va_end(nameap); -} - -#ifndef _KERNEL -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); -} -#endif - -void -nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size, - const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_binary(nvl, value, size, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_null(namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_bool(value, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_number(value, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_string(value, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_nvlist(value, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -#ifndef _KERNEL -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); -} -#endif - -void -nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size, - const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_binary(value, size, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); - - if (nvlist_error(nvl) != 0) { - nvpair_free(nvp); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - if (nvlist_exists(nvl, nvpair_name(nvp))) { - nvpair_free(nvp); - nvl->nvl_error = EEXIST; - RESTORE_ERRNO(nvl->nvl_error); - return; - } - - 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) -#ifndef _KERNEL -NVLIST_MOVE(int, descriptor) -#endif - -#undef NVLIST_MOVE - -void -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) -#ifndef _KERNEL -NVLIST_MOVEF(int, descriptor) -#endif - -#undef NVLIST_MOVEF - -void -nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size, - const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_movev_binary(nvl, value, size, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - nv_free(value); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_movev_string(value, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) - nvlist_destroy(value); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_movev_nvlist(value, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -#ifndef _KERNEL -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); -} -#endif - -void -nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, - const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - nv_free(value); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_movev_binary(value, size, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -const nvpair_t * -nvlist_get_nvpair(const nvlist_t *nvl, const char *name) -{ - - return (nvlist_find(nvl, NV_TYPE_NONE, name)); -} - -#define NVLIST_GET(ftype, type, TYPE) \ -ftype \ -nvlist_get_##type(const nvlist_t *nvl, const char *name) \ -{ \ - const nvpair_t *nvp; \ - \ - nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ - if (nvp == NULL) \ - nvlist_report_missing(NV_TYPE_##TYPE, name); \ - return (nvpair_get_##type(nvp)); \ -} - -NVLIST_GET(bool, bool, BOOL) -NVLIST_GET(uint64_t, number, NUMBER) -NVLIST_GET(const char *, string, STRING) -NVLIST_GET(const nvlist_t *, nvlist, NVLIST) -#ifndef _KERNEL -NVLIST_GET(int, descriptor, DESCRIPTOR) -#endif - -#undef NVLIST_GET - -const void * -nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) -{ - nvpair_t *nvp; - - nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); - if (nvp == NULL) - nvlist_report_missing(NV_TYPE_BINARY, name); - - return (nvpair_get_binary(nvp, sizep)); -} - -#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); \ -} - -#ifndef _KERNEL -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, ...) -{ - va_list nameap; - const void *value; - - va_start(nameap, namefmt); - value = nvlist_getv_binary(nvl, sizep, 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) \ -{ \ - char *name; \ - ftype value; \ - \ - vasprintf(&name, namefmt, nameap); \ - if (name == NULL) \ - nvlist_report_missing(NV_TYPE_##TYPE, ""); \ - value = nvlist_get_##type(nvl, name); \ - free(name); \ - \ - return (value); \ -} - -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, - va_list nameap) -{ - char *name; - const void *binary; - - nv_vasprintf(&name, namefmt, nameap); - if (name == NULL) - nvlist_report_missing(NV_TYPE_BINARY, ""); - - binary = nvlist_get_binary(nvl, name, sizep); - nv_free(name); - return (binary); -} -#endif - -#define NVLIST_TAKE(ftype, type, TYPE) \ -ftype \ -nvlist_take_##type(nvlist_t *nvl, const char *name) \ -{ \ - nvpair_t *nvp; \ - ftype value; \ - \ - nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ - if (nvp == NULL) \ - nvlist_report_missing(NV_TYPE_##TYPE, name); \ - value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ - nvlist_remove_nvpair(nvl, nvp); \ - nvpair_free_structure(nvp); \ - return (value); \ -} - -NVLIST_TAKE(bool, bool, BOOL) -NVLIST_TAKE(uint64_t, number, NUMBER) -NVLIST_TAKE(char *, string, STRING) -NVLIST_TAKE(nvlist_t *, nvlist, NVLIST) -#ifndef _KERNEL -NVLIST_TAKE(int, descriptor, DESCRIPTOR) -#endif - -#undef NVLIST_TAKE - -void * -nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) -{ - nvpair_t *nvp; - void *value; - - nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); - if (nvp == NULL) - nvlist_report_missing(NV_TYPE_BINARY, name); - - value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); - nvlist_remove_nvpair(nvl, nvp); - nvpair_free_structure(nvp); - return (value); -} - -#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); \ -} - -#ifndef _KERNEL -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, ...) -{ - va_list nameap; - void *value; - - va_start(nameap, namefmt); - value = nvlist_takev_binary(nvl, sizep, 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) \ -{ \ - char *name; \ - ftype value; \ - \ - vasprintf(&name, namefmt, nameap); \ - if (name == NULL) \ - nvlist_report_missing(NV_TYPE_##TYPE, ""); \ - value = nvlist_take_##type(nvl, name); \ - free(name); \ - 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, - va_list nameap) -{ - char *name; - void *binary; - - nv_vasprintf(&name, namefmt, nameap); - if (name == NULL) - nvlist_report_missing(NV_TYPE_BINARY, ""); - - binary = nvlist_take_binary(nvl, name, sizep); - nv_free(name); - return (binary); -} -#endif - -void -nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) -{ - - NVLIST_ASSERT(nvl); - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); - - nvpair_remove(&nvl->nvl_head, nvp, nvl); -} - -void -nvlist_free(nvlist_t *nvl, const char *name) -{ - - nvlist_free_type(nvl, name, NV_TYPE_NONE); -} - -#define NVLIST_FREE(type, TYPE) \ -void \ -nvlist_free_##type(nvlist_t *nvl, const char *name) \ -{ \ - \ - nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ -} - -NVLIST_FREE(null, NULL) -NVLIST_FREE(bool, BOOL) -NVLIST_FREE(number, NUMBER) -NVLIST_FREE(string, STRING) -NVLIST_FREE(nvlist, NVLIST) -#ifndef _KERNEL -NVLIST_FREE(descriptor, DESCRIPTOR) -#endif -NVLIST_FREE(binary, BINARY) - -#undef NVLIST_FREE - -#ifndef _KERNEL -void -nvlist_freef(nvlist_t *nvl, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_freev(nvl, namefmt, nameap); - 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) -{ - - 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) \ -{ \ - char *name; \ - \ - vasprintf(&name, namefmt, nameap); \ - if (name == NULL) \ - nvlist_report_missing(NV_TYPE_##TYPE, ""); \ - nvlist_free_##type(nvl, name); \ - free(name); \ -} - -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 -#endif - -void -nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) -{ - - NVLIST_ASSERT(nvl); - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); - - nvlist_remove_nvpair(nvl, nvp); - nvpair_free(nvp); -} Index: head/lib/libnv/nvlist_impl.h =================================================================== --- head/lib/libnv/nvlist_impl.h +++ head/lib/libnv/nvlist_impl.h @@ -1,49 +0,0 @@ -/*- - * 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_IMPL_H_ -#define _NVLIST_IMPL_H_ - -#ifndef _KERNEL -#include -#endif - -#include "nv.h" - -void *nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep); -nvlist_t *nvlist_xunpack(const void *buf, size_t size, const int *fds, - size_t nfds); - -nvpair_t *nvlist_get_nvpair_parent(const nvlist_t *nvl); -const unsigned char *nvlist_unpack_header(nvlist_t *nvl, - const unsigned char *ptr, size_t nfds, bool *isbep, size_t *leftp); - -#endif /* !_NVLIST_IMPL_H_ */ Index: head/lib/libnv/nvpair.c =================================================================== --- head/lib/libnv/nvpair.c +++ head/lib/libnv/nvpair.c @@ -1,1349 +0,0 @@ -/*- - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#ifdef _KERNEL - -#include -#include -#include -#include - -#include - -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#ifdef HAVE_PJDLOG -#include -#endif - -#include "common_impl.h" -#include "nv.h" -#include "nv_impl.h" -#include "nvlist_impl.h" -#include "nvpair_impl.h" - -#ifndef HAVE_PJDLOG -#ifdef _KERNEL -#define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) -#define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) -#define PJDLOG_ABORT(...) panic(__VA_ARGS__) -#else -#include -#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) -#define PJDLOG_RASSERT(expr, ...) assert(expr) -#define PJDLOG_ABORT(...) abort() -#endif -#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; - 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) -{ - - NVPAIR_ASSERT(nvp); -} - -nvlist_t * -nvpair_nvlist(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - - return (nvp->nvp_list); -} - -nvpair_t * -nvpair_next(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_list != NULL); - - return (TAILQ_NEXT(nvp, nvp_next)); -} - -nvpair_t * -nvpair_prev(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_list != NULL); - - return (TAILQ_PREV(nvp, nvl_head, nvp_next)); -} - -void -nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_list == NULL); - PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp))); - - TAILQ_INSERT_TAIL(head, nvp, nvp_next); - 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) -{ - - 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; -} - -nvpair_t * -nvpair_clone(const nvpair_t *nvp) -{ - nvpair_t *newnvp; - const char *name; - const void *data; - size_t datasize; - - NVPAIR_ASSERT(nvp); - - name = nvpair_name(nvp); - - switch (nvpair_type(nvp)) { - case NV_TYPE_NULL: - newnvp = nvpair_create_null(name); - break; - case NV_TYPE_BOOL: - newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); - break; - case NV_TYPE_NUMBER: - newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); - break; - case NV_TYPE_STRING: - newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); - break; - case NV_TYPE_NVLIST: - newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); - break; -#ifndef _KERNEL - case NV_TYPE_DESCRIPTOR: - newnvp = nvpair_create_descriptor(name, - nvpair_get_descriptor(nvp)); - break; -#endif - case NV_TYPE_BINARY: - data = nvpair_get_binary(nvp, &datasize); - newnvp = nvpair_create_binary(name, data, datasize); - break; - default: - PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); - } - - return (newnvp); -} - -size_t -nvpair_header_size(void) -{ - - return (sizeof(struct nvpair_header)); -} - -size_t -nvpair_size(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - - return (nvp->nvp_datasize); -} - -unsigned char * -nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) -{ - struct nvpair_header nvphdr; - size_t namesize; - - NVPAIR_ASSERT(nvp); - - nvphdr.nvph_type = nvp->nvp_type; - namesize = strlen(nvp->nvp_name) + 1; - PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX); - nvphdr.nvph_namesize = namesize; - nvphdr.nvph_datasize = nvp->nvp_datasize; - PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); - memcpy(ptr, &nvphdr, sizeof(nvphdr)); - ptr += sizeof(nvphdr); - *leftp -= sizeof(nvphdr); - - PJDLOG_ASSERT(*leftp >= namesize); - memcpy(ptr, nvp->nvp_name, namesize); - ptr += namesize; - *leftp -= namesize; - - return (ptr); -} - -unsigned char * -nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr, - size_t *leftp __unused) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); - - return (ptr); -} - -unsigned char * -nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) -{ - uint8_t value; - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); - - value = (uint8_t)nvp->nvp_data; - - PJDLOG_ASSERT(*leftp >= sizeof(value)); - memcpy(ptr, &value, sizeof(value)); - ptr += sizeof(value); - *leftp -= sizeof(value); - - return (ptr); -} - -unsigned char * -nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) -{ - uint64_t value; - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); - - value = (uint64_t)nvp->nvp_data; - - PJDLOG_ASSERT(*leftp >= sizeof(value)); - memcpy(ptr, &value, sizeof(value)); - ptr += sizeof(value); - *leftp -= sizeof(value); - - return (ptr); -} - -unsigned char * -nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); - - PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); - memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); - ptr += nvp->nvp_datasize; - *leftp -= nvp->nvp_datasize; - - return (ptr); -} - -unsigned char * -nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp) -{ - struct nvpair_header nvphdr; - size_t namesize; - const char *name = ""; - - 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); - - PJDLOG_ASSERT(*leftp >= namesize); - memcpy(ptr, name, namesize); - ptr += namesize; - *leftp -= namesize; - - return (ptr); -} - -#ifndef _KERNEL -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); -} -#endif - -unsigned char * -nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); - - PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); - memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); - ptr += nvp->nvp_datasize; - *leftp -= nvp->nvp_datasize; - - return (ptr); -} - -void -nvpair_init_datasize(nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - - if (nvp->nvp_type == NV_TYPE_NVLIST) { - if (nvp->nvp_data == 0) { - nvp->nvp_datasize = 0; - } else { - nvp->nvp_datasize = - nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); - } - } -} - -const unsigned char * -nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr, - size_t *leftp) -{ - struct nvpair_header nvphdr; - - if (*leftp < sizeof(nvphdr)) - goto failed; - - memcpy(&nvphdr, ptr, sizeof(nvphdr)); - ptr += sizeof(nvphdr); - *leftp -= sizeof(nvphdr); - -#if NV_TYPE_FIRST > 0 - if (nvphdr.nvph_type < NV_TYPE_FIRST) - goto failed; -#endif - if (nvphdr.nvph_type > NV_TYPE_LAST && - nvphdr.nvph_type != NV_TYPE_NVLIST_UP) { - goto failed; - } - -#if BYTE_ORDER == BIG_ENDIAN - if (!isbe) { - nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize); - nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize); - } -#else - if (isbe) { - nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); - nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); - } -#endif - - if (nvphdr.nvph_namesize > NV_NAME_MAX) - goto failed; - if (*leftp < nvphdr.nvph_namesize) - goto failed; - if (nvphdr.nvph_namesize < 1) - goto failed; - if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != - (size_t)(nvphdr.nvph_namesize - 1)) { - goto failed; - } - - memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); - ptr += nvphdr.nvph_namesize; - *leftp -= nvphdr.nvph_namesize; - - if (*leftp < nvphdr.nvph_datasize) - goto failed; - - nvp->nvp_type = nvphdr.nvph_type; - nvp->nvp_data = 0; - nvp->nvp_datasize = nvphdr.nvph_datasize; - - return (ptr); -failed: - RESTORE_ERRNO(EINVAL); - return (NULL); -} - -const unsigned char * -nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, - size_t *leftp __unused) -{ - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); - - if (nvp->nvp_datasize != 0) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - return (ptr); -} - -const unsigned char * -nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, - size_t *leftp) -{ - uint8_t value; - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); - - if (nvp->nvp_datasize != sizeof(value)) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - if (*leftp < sizeof(value)) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - memcpy(&value, ptr, sizeof(value)); - ptr += sizeof(value); - *leftp -= sizeof(value); - - if (value != 0 && value != 1) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - nvp->nvp_data = (uint64_t)value; - - return (ptr); -} - -const unsigned char * -nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr, - size_t *leftp) -{ - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); - - if (nvp->nvp_datasize != sizeof(uint64_t)) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - if (*leftp < sizeof(uint64_t)) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - if (isbe) - nvp->nvp_data = be64dec(ptr); - else - nvp->nvp_data = le64dec(ptr); - ptr += sizeof(uint64_t); - *leftp -= sizeof(uint64_t); - - return (ptr); -} - -const unsigned char * -nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp) -{ - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); - - if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - if (strnlen((const char *)ptr, nvp->nvp_datasize) != - nvp->nvp_datasize - 1) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr); - if (nvp->nvp_data == 0) - return (NULL); - - ptr += nvp->nvp_datasize; - *leftp -= nvp->nvp_datasize; - - return (ptr); -} - -const unsigned char * -nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child) -{ - nvlist_t *value; - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); - - if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - value = nvlist_create(0); - if (value == NULL) - return (NULL); - - ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp); - if (ptr == NULL) - return (NULL); - - nvp->nvp_data = (uint64_t)(uintptr_t)value; - *child = value; - - return (ptr); -} - -#ifndef _KERNEL -const unsigned char * -nvpair_unpack_descriptor(bool isbe, 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 (isbe) - 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); -} -#endif - -const unsigned char * -nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp) -{ - void *value; - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); - - if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - value = nv_malloc(nvp->nvp_datasize); - if (value == NULL) - return (NULL); - - memcpy(value, ptr, nvp->nvp_datasize); - ptr += nvp->nvp_datasize; - *leftp -= nvp->nvp_datasize; - - nvp->nvp_data = (uint64_t)(uintptr_t)value; - - return (ptr); -} - -const unsigned char * -nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, - nvpair_t **nvpp) -{ - nvpair_t *nvp, *tmp; - - nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); - if (nvp == NULL) - return (NULL); - nvp->nvp_name = (char *)(nvp + 1); - - ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); - if (ptr == NULL) - goto failed; - tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); - if (tmp == NULL) - goto failed; - nvp = tmp; - - /* Update nvp_name after realloc(). */ - nvp->nvp_name = (char *)(nvp + 1); - nvp->nvp_data = 0x00; - nvp->nvp_magic = NVPAIR_MAGIC; - *nvpp = nvp; - return (ptr); -failed: - nv_free(nvp); - return (NULL); -} - -int -nvpair_type(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - - return (nvp->nvp_type); -} - -const char * -nvpair_name(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - - return (nvp->nvp_name); -} - -static nvpair_t * -nvpair_allocv(int type, uint64_t data, size_t datasize, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - char *name; - int namelen; - - PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); - - namelen = nv_vasprintf(&name, namefmt, nameap); - if (namelen < 0) - return (NULL); - - PJDLOG_ASSERT(namelen > 0); - if (namelen >= NV_NAME_MAX) { - nv_free(name); - RESTORE_ERRNO(ENAMETOOLONG); - return (NULL); - } - - nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1); - if (nvp != NULL) { - nvp->nvp_name = (char *)(nvp + 1); - memcpy(nvp->nvp_name, name, namelen + 1); - nvp->nvp_type = type; - nvp->nvp_data = data; - nvp->nvp_datasize = datasize; - nvp->nvp_magic = NVPAIR_MAGIC; - } - nv_free(name); - - return (nvp); -}; - -nvpair_t * -nvpair_create_null(const char *name) -{ - - return (nvpair_createf_null("%s", name)); -} - -nvpair_t * -nvpair_create_bool(const char *name, bool value) -{ - - return (nvpair_createf_bool(value, "%s", name)); -} - -nvpair_t * -nvpair_create_number(const char *name, uint64_t value) -{ - - return (nvpair_createf_number(value, "%s", name)); -} - -nvpair_t * -nvpair_create_string(const char *name, const char *value) -{ - - return (nvpair_createf_string(value, "%s", name)); -} - -nvpair_t * -nvpair_create_stringf(const char *name, const char *valuefmt, ...) -{ - va_list valueap; - nvpair_t *nvp; - - va_start(valueap, valuefmt); - nvp = nvpair_create_stringv(name, valuefmt, valueap); - va_end(valueap); - - return (nvp); -} - -nvpair_t * -nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) -{ - nvpair_t *nvp; - char *str; - int len; - - len = nv_vasprintf(&str, valuefmt, valueap); - if (len < 0) - return (NULL); - nvp = nvpair_create_string(name, str); - if (nvp == NULL) - nv_free(str); - return (nvp); -} - -nvpair_t * -nvpair_create_nvlist(const char *name, const nvlist_t *value) -{ - - return (nvpair_createf_nvlist(value, "%s", name)); -} - -#ifndef _KERNEL -nvpair_t * -nvpair_create_descriptor(const char *name, int value) -{ - - return (nvpair_createf_descriptor(value, "%s", name)); -} -#endif - -nvpair_t * -nvpair_create_binary(const char *name, const void *value, size_t size) -{ - - return (nvpair_createf_binary(value, size, "%s", name)); -} - -nvpair_t * -nvpair_createf_null(const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_createv_null(namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -nvpair_t * -nvpair_createf_bool(bool value, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_createv_bool(value, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -nvpair_t * -nvpair_createf_number(uint64_t value, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_createv_number(value, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -nvpair_t * -nvpair_createf_string(const char *value, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_createv_string(value, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -nvpair_t * -nvpair_createf_nvlist(const nvlist_t *value, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_createv_nvlist(value, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -#ifndef _KERNEL -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); -} -#endif - -nvpair_t * -nvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_createv_binary(value, size, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -nvpair_t * -nvpair_createv_null(const char *namefmt, va_list nameap) -{ - - return (nvpair_allocv(NV_TYPE_NULL, 0, 0, namefmt, nameap)); -} - -nvpair_t * -nvpair_createv_bool(bool value, const char *namefmt, va_list nameap) -{ - - return (nvpair_allocv(NV_TYPE_BOOL, value ? 1 : 0, sizeof(uint8_t), - namefmt, nameap)); -} - -nvpair_t * -nvpair_createv_number(uint64_t value, const char *namefmt, va_list nameap) -{ - - return (nvpair_allocv(NV_TYPE_NUMBER, value, sizeof(value), namefmt, - nameap)); -} - -nvpair_t * -nvpair_createv_string(const char *value, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - size_t size; - char *data; - - if (value == NULL) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - data = nv_strdup(value); - if (data == NULL) - return (NULL); - size = strlen(value) + 1; - - nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)data, size, - namefmt, nameap); - if (nvp == NULL) - nv_free(data); - - return (nvp); -} - -nvpair_t * -nvpair_createv_nvlist(const nvlist_t *value, const char *namefmt, - va_list nameap) -{ - nvlist_t *nvl; - nvpair_t *nvp; - - if (value == NULL) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - nvl = nvlist_clone(value); - if (nvl == NULL) - return (NULL); - - nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, - namefmt, nameap); - if (nvp == NULL) - nvlist_destroy(nvl); - else - nvlist_set_parent(nvl, nvp); - - return (nvp); -} - -#ifndef _KERNEL -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); -} -#endif - -nvpair_t * -nvpair_createv_binary(const void *value, size_t size, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - void *data; - - if (value == NULL || size == 0) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - data = nv_malloc(size); - if (data == NULL) - return (NULL); - memcpy(data, value, size); - - nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, size, - namefmt, nameap); - if (nvp == NULL) - nv_free(data); - - return (nvp); -} - -nvpair_t * -nvpair_move_string(const char *name, char *value) -{ - - return (nvpair_movef_string(value, "%s", name)); -} - -nvpair_t * -nvpair_move_nvlist(const char *name, nvlist_t *value) -{ - - return (nvpair_movef_nvlist(value, "%s", name)); -} - -#ifndef _KERNEL -nvpair_t * -nvpair_move_descriptor(const char *name, int value) -{ - - return (nvpair_movef_descriptor(value, "%s", name)); -} -#endif - -nvpair_t * -nvpair_move_binary(const char *name, void *value, size_t size) -{ - - return (nvpair_movef_binary(value, size, "%s", name)); -} - -nvpair_t * -nvpair_movef_string(char *value, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_movev_string(value, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -nvpair_t * -nvpair_movef_nvlist(nvlist_t *value, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_movev_nvlist(value, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -#ifndef _KERNEL -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); -} -#endif - -nvpair_t * -nvpair_movef_binary(void *value, size_t size, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_movev_binary(value, size, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -nvpair_t * -nvpair_movev_string(char *value, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - int serrno; - - if (value == NULL) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value, - strlen(value) + 1, namefmt, nameap); - if (nvp == NULL) { - SAVE_ERRNO(serrno); - nv_free(value); - RESTORE_ERRNO(serrno); - } - - return (nvp); -} - -nvpair_t * -nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - if (nvlist_error(value) != 0) { - RESTORE_ERRNO(nvlist_error(value)); - nvlist_destroy(value); - return (NULL); - } - - nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 0, - namefmt, nameap); - if (nvp == NULL) - nvlist_destroy(value); - else - nvlist_set_parent(value, nvp); - - return (nvp); -} - -#ifndef _KERNEL -nvpair_t * -nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - int serrno; - - if (value < 0 || !fd_is_valid(value)) { - errno = EBADF; - return (NULL); - } - - nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, - sizeof(int64_t), namefmt, nameap); - if (nvp == NULL) { - serrno = errno; - close(value); - errno = serrno; - } - - return (nvp); -} -#endif - -nvpair_t * -nvpair_movev_binary(void *value, size_t size, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - int serrno; - - if (value == NULL || size == 0) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size, - namefmt, nameap); - if (nvp == NULL) { - SAVE_ERRNO(serrno); - nv_free(value); - RESTORE_ERRNO(serrno); - } - - return (nvp); -} - -bool -nvpair_get_bool(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - - return (nvp->nvp_data == 1); -} - -uint64_t -nvpair_get_number(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - - return (nvp->nvp_data); -} - -const char * -nvpair_get_string(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); - - return ((const char *)(intptr_t)nvp->nvp_data); -} - -const nvlist_t * -nvpair_get_nvlist(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); - - return ((const nvlist_t *)(intptr_t)nvp->nvp_data); -} - -#ifndef _KERNEL -int -nvpair_get_descriptor(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); - - return ((int)nvp->nvp_data); -} -#endif - -const void * -nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); - - if (sizep != NULL) - *sizep = nvp->nvp_datasize; - return ((const void *)(intptr_t)nvp->nvp_data); -} - -void -nvpair_free(nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_list == NULL); - - nvp->nvp_magic = 0; - switch (nvp->nvp_type) { -#ifndef _KERNEL - case NV_TYPE_DESCRIPTOR: - close((int)nvp->nvp_data); - break; -#endif - case NV_TYPE_NVLIST: - nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); - break; - case NV_TYPE_STRING: - nv_free((char *)(intptr_t)nvp->nvp_data); - break; - case NV_TYPE_BINARY: - nv_free((void *)(intptr_t)nvp->nvp_data); - break; - } - nv_free(nvp); -} - -void -nvpair_free_structure(nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_list == NULL); - - nvp->nvp_magic = 0; - nv_free(nvp); -} - -const char * -nvpair_type_string(int type) -{ - - switch (type) { - case NV_TYPE_NULL: - return ("NULL"); - case NV_TYPE_BOOL: - return ("BOOL"); - case NV_TYPE_NUMBER: - return ("NUMBER"); - case NV_TYPE_STRING: - return ("STRING"); - case NV_TYPE_NVLIST: - return ("NVLIST"); - case NV_TYPE_DESCRIPTOR: - return ("DESCRIPTOR"); - case NV_TYPE_BINARY: - return ("BINARY"); - default: - return (""); - } -} Index: head/lib/libnv/nvpair_impl.h =================================================================== --- head/lib/libnv/nvpair_impl.h +++ head/lib/libnv/nvpair_impl.h @@ -1,94 +0,0 @@ -/*- - * 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. - * - * $FreeBSD$ - */ - -#ifndef _NVPAIR_IMPL_H_ -#define _NVPAIR_IMPL_H_ - -#include - -#ifndef _KERNEL -#include -#endif - -#include "nv.h" - -TAILQ_HEAD(nvl_head, nvpair); - -void nvpair_assert(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); -const unsigned char *nvpair_unpack(bool isbe, const unsigned char *ptr, - 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(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); -const unsigned char *nvpair_unpack_null(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); -const unsigned char *nvpair_unpack_bool(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); -const unsigned char *nvpair_unpack_number(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); -const unsigned char *nvpair_unpack_string(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); -const unsigned char *nvpair_unpack_nvlist(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp, size_t nvlist, nvlist_t **child); -const unsigned char *nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds); -const unsigned char *nvpair_unpack_binary(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); - -#endif /* !_NVPAIR_IMPL_H_ */ Index: head/sys/conf/files =================================================================== --- head/sys/conf/files +++ head/sys/conf/files @@ -3076,6 +3076,7 @@ kern/subr_counter.c standard kern/subr_devstat.c standard kern/subr_disk.c standard +kern/subr_dnvlist.c standard kern/subr_eventhandler.c standard kern/subr_fattime.c standard kern/subr_firmware.c optional firmware @@ -3089,6 +3090,8 @@ kern/subr_mchain.c optional libmchain kern/subr_module.c standard kern/subr_msgbuf.c standard +kern/subr_nvlist.c standard +kern/subr_nvpair.c standard kern/subr_param.c standard kern/subr_pcpu.c standard kern/subr_pctrie.c standard Index: head/sys/kern/subr_dnvlist.c =================================================================== --- head/sys/kern/subr_dnvlist.c +++ head/sys/kern/subr_dnvlist.c @@ -0,0 +1,294 @@ +/*- + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifdef _KERNEL + +#include +#include +#include +#include +#include + +#include + +#else +#include +#include +#include +#include +#endif + +#include +#include + +#include + +#define DNVLIST_GET(ftype, type) \ +ftype \ +dnvlist_get_##type(const nvlist_t *nvl, const char *name, ftype defval) \ +{ \ + \ + if (nvlist_exists_##type(nvl, name)) \ + return (nvlist_get_##type(nvl, name)); \ + else \ + return (defval); \ +} + +DNVLIST_GET(bool, bool) +DNVLIST_GET(uint64_t, number) +DNVLIST_GET(const char *, string) +DNVLIST_GET(const nvlist_t *, nvlist) +#ifndef _KERNEL +DNVLIST_GET(int, descriptor) +#endif + +#undef DNVLIST_GET + +const void * +dnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep, + const void *defval, size_t defsize) +{ + const void *value; + + if (nvlist_exists_binary(nvl, name)) + value = nvlist_get_binary(nvl, name, sizep); + else { + if (sizep != NULL) + *sizep = defsize; + value = defval; + } + return (value); +} + +#ifndef _KERNEL +#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, + size_t defsize, const char *namefmt, ...) +{ + va_list nameap; + const void *value; + + va_start(nameap, namefmt); + value = dnvlist_getv_binary(nvl, sizep, defval, defsize, 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) \ +{ \ + char *name; \ + ftype value; \ + \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + return (defval); \ + value = dnvlist_get_##type(nvl, name, defval); \ + free(name); \ + 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, + size_t defsize, const char *namefmt, va_list nameap) +{ + char *name; + const void *value; + + nv_vasprintf(&name, namefmt, nameap); + if (name != NULL) { + value = dnvlist_get_binary(nvl, name, sizep, defval, defsize); + nv_free(name); + } else { + if (sizep != NULL) + *sizep = defsize; + value = defval; + } + return (value); +} +#endif + +#define DNVLIST_TAKE(ftype, type) \ +ftype \ +dnvlist_take_##type(nvlist_t *nvl, const char *name, ftype defval) \ +{ \ + \ + if (nvlist_exists_##type(nvl, name)) \ + return (nvlist_take_##type(nvl, name)); \ + else \ + return (defval); \ +} + +DNVLIST_TAKE(bool, bool) +DNVLIST_TAKE(uint64_t, number) +DNVLIST_TAKE(char *, string) +DNVLIST_TAKE(nvlist_t *, nvlist) +#ifndef _KERNEL +DNVLIST_TAKE(int, descriptor) +#endif + +#undef DNVLIST_TAKE + +void * +dnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep, + void *defval, size_t defsize) +{ + void *value; + + if (nvlist_exists_binary(nvl, name)) + value = nvlist_take_binary(nvl, name, sizep); + else { + if (sizep != NULL) + *sizep = defsize; + value = defval; + } + return (value); +} + +#ifndef _KERNEL +#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, + size_t defsize, const char *namefmt, ...) +{ + va_list nameap; + void *value; + + va_start(nameap, namefmt); + value = dnvlist_takev_binary(nvl, sizep, defval, defsize, 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) \ +{ \ + char *name; \ + ftype value; \ + \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + return (defval); \ + value = dnvlist_take_##type(nvl, name, defval); \ + free(name); \ + 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, + size_t defsize, const char *namefmt, va_list nameap) +{ + char *name; + void *value; + + nv_vasprintf(&name, namefmt, nameap); + if (name != NULL) { + value = dnvlist_take_binary(nvl, name, sizep, defval, defsize); + nv_free(name); + } else { + if (sizep != NULL) + *sizep = defsize; + value = defval; + } + + return (value); +} +#endif Index: head/sys/kern/subr_nvlist.c =================================================================== --- head/sys/kern/subr_nvlist.c +++ head/sys/kern/subr_nvlist.c @@ -0,0 +1,2002 @@ +/*- + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#ifdef _KERNEL + +#include +#include +#include +#include +#include + +#include + +#else +#include + +#include +#include +#include +#include +#define _WITH_DPRINTF +#include +#include +#include +#include + +#include "msgio.h" +#endif + +#ifdef HAVE_PJDLOG +#include +#endif + +#include +#include +#include +#include + +#ifndef HAVE_PJDLOG +#ifdef _KERNEL +#define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) +#define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) +#define PJDLOG_ABORT(...) panic(__VA_ARGS__) +#else +#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 +#endif + +#define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN) +#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; + nvpair_t *nvl_parent; + struct nvl_head nvl_head; +}; + +#define NVLIST_ASSERT(nvl) do { \ + PJDLOG_ASSERT((nvl) != NULL); \ + PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \ +} while (0) + +#ifdef _KERNEL +MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist"); +#endif + +#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) +{ + nvlist_t *nvl; + + PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); + + nvl = nv_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; + + return (nvl); +} + +void +nvlist_destroy(nvlist_t *nvl) +{ + nvpair_t *nvp; + int serrno; + + if (nvl == NULL) + return; + + SAVE_ERRNO(serrno); + + NVLIST_ASSERT(nvl); + + while ((nvp = nvlist_first_nvpair(nvl)) != NULL) { + nvlist_remove_nvpair(nvl, nvp); + nvpair_free(nvp); + } + nvl->nvl_magic = 0; + nv_free(nvl); + + RESTORE_ERRNO(serrno); +} + +void +nvlist_set_error(nvlist_t *nvl, int error) +{ + + PJDLOG_ASSERT(error != 0); + + /* + * Check for error != 0 so that we don't do the wrong thing if somebody + * tries to abuse this API when asserts are disabled. + */ + if (nvl != NULL && error != 0 && nvl->nvl_error == 0) + nvl->nvl_error = error; +} + +int +nvlist_error(const nvlist_t *nvl) +{ + + if (nvl == NULL) + return (ENOMEM); + + NVLIST_ASSERT(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) +{ + + NVLIST_ASSERT(nvl); + PJDLOG_ASSERT(nvl->nvl_error == 0); + + return (nvlist_first_nvpair(nvl) == NULL); +} + +static void +nvlist_report_missing(int type, const char *name) +{ + + PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", + name, nvpair_type_string(type)); +} + +static nvpair_t * +nvlist_find(const nvlist_t *nvl, int type, const char *name) +{ + nvpair_t *nvp; + + NVLIST_ASSERT(nvl); + PJDLOG_ASSERT(nvl->nvl_error == 0); + PJDLOG_ASSERT(type == NV_TYPE_NONE || + (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); + + for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; + nvp = nvlist_next_nvpair(nvl, nvp)) { + if (type != NV_TYPE_NONE && nvpair_type(nvp) != type) + continue; + if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) { + if (strcasecmp(nvpair_name(nvp), name) != 0) + continue; + } else { + if (strcmp(nvpair_name(nvp), name) != 0) + continue; + } + break; + } + + if (nvp == NULL) + RESTORE_ERRNO(ENOENT); + + return (nvp); +} + +bool +nvlist_exists_type(const nvlist_t *nvl, const char *name, int type) +{ + + NVLIST_ASSERT(nvl); + PJDLOG_ASSERT(nvl->nvl_error == 0); + PJDLOG_ASSERT(type == NV_TYPE_NONE || + (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); + + return (nvlist_find(nvl, type, name) != NULL); +} + +#ifndef _KERNEL +bool +nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...) +{ + va_list nameap; + bool ret; + + va_start(nameap, namefmt); + ret = nvlist_existsv_type(nvl, type, namefmt, nameap); + va_end(nameap); + + return (ret); +} + +bool +nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt, + va_list nameap) +{ + char *name; + bool exists; + + nv_vasprintf(&name, namefmt, nameap); + if (name == NULL) + return (false); + + exists = nvlist_exists_type(nvl, name, type); + nv_free(name); + return (exists); +} +#endif + +void +nvlist_free_type(nvlist_t *nvl, const char *name, int type) +{ + nvpair_t *nvp; + + NVLIST_ASSERT(nvl); + PJDLOG_ASSERT(nvl->nvl_error == 0); + PJDLOG_ASSERT(type == NV_TYPE_NONE || + (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); + + nvp = nvlist_find(nvl, type, name); + if (nvp != NULL) + nvlist_free_nvpair(nvl, nvp); + else + nvlist_report_missing(type, name); +} + +#ifndef _KERNEL +void +nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...) +{ + va_list nameap; + + va_start(nameap, namefmt); + nvlist_freev_type(nvl, type, namefmt, nameap); + va_end(nameap); +} + +void +nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap) +{ + char *name; + + nv_vasprintf(&name, namefmt, nameap); + if (name == NULL) + nvlist_report_missing(type, ""); + nvlist_free_type(nvl, name, type); + nv_free(name); +} +#endif + +nvlist_t * +nvlist_clone(const nvlist_t *nvl) +{ + nvlist_t *newnvl; + nvpair_t *nvp, *newnvp; + + NVLIST_ASSERT(nvl); + + if (nvl->nvl_error != 0) { + RESTORE_ERRNO(nvl->nvl_error); + return (NULL); + } + + newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); + for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; + nvp = nvlist_next_nvpair(nvl, nvp)) { + newnvp = nvpair_clone(nvp); + if (newnvp == NULL) + break; + nvlist_move_nvpair(newnvl, newnvp); + } + if (nvp != NULL) { + nvlist_destroy(newnvl); + return (NULL); + } + return (newnvl); +} + +#ifndef _KERNEL +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. + */ +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)) { + 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"); + 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)); + 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)); + } + + while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { + cookie = NULL; + nvl = nvlist_get_parent(nvl, &cookie); + if (nvl == NULL) + return; + nvp = cookie; + level--; + } + } +} + +void +nvlist_fdump(const nvlist_t *nvl, FILE *fp) +{ + + fflush(fp); + nvlist_dump(nvl, fileno(fp)); +} +#endif + +/* + * The function obtains size of the nvlist after nvlist_pack(). + */ +size_t +nvlist_size(const nvlist_t *nvl) +{ + const nvlist_t *tmpnvl; + const nvpair_t *nvp, *tmpnvp; + void *cookie; + size_t size; + + NVLIST_ASSERT(nvl); + PJDLOG_ASSERT(nvl->nvl_error == 0); + + size = sizeof(struct nvlist_header); + 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 += 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); +} + +#ifndef _KERNEL +static int * +nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level) +{ + const nvpair_t *nvp; + + NVLIST_ASSERT(nvl); + PJDLOG_ASSERT(nvl->nvl_error == 0); + PJDLOG_ASSERT(level < 3); + + for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; + nvp = nvlist_next_nvpair(nvl, nvp)) { + switch (nvpair_type(nvp)) { + case NV_TYPE_DESCRIPTOR: + *descs = nvpair_get_descriptor(nvp); + descs++; + break; + case NV_TYPE_NVLIST: + descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp), + descs, level + 1); + break; + } + } + + return (descs); +} +#endif + +#ifndef _KERNEL +int * +nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp) +{ + size_t nitems; + int *fds; + + nitems = nvlist_ndescriptors(nvl); + fds = nv_malloc(sizeof(fds[0]) * (nitems + 1)); + if (fds == NULL) + return (NULL); + if (nitems > 0) + nvlist_xdescriptors(nvl, fds, 0); + fds[nitems] = -1; + if (nitemsp != NULL) + *nitemsp = nitems; + return (fds); +} +#endif + +static size_t +nvlist_xndescriptors(const nvlist_t *nvl, int level) +{ +#ifndef _KERNEL + const nvpair_t *nvp; + size_t ndescs; + + NVLIST_ASSERT(nvl); + PJDLOG_ASSERT(nvl->nvl_error == 0); + PJDLOG_ASSERT(level < 3); + + ndescs = 0; + for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; + nvp = nvlist_next_nvpair(nvl, nvp)) { + switch (nvpair_type(nvp)) { + case NV_TYPE_DESCRIPTOR: + ndescs++; + break; + case NV_TYPE_NVLIST: + ndescs += nvlist_xndescriptors(nvpair_get_nvlist(nvp), + level + 1); + break; + } + } + + return (ndescs); +#else + return (0); +#endif +} + +size_t +nvlist_ndescriptors(const nvlist_t *nvl) +{ + + return (nvlist_xndescriptors(nvl, 0)); +} + +static unsigned char * +nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp) +{ + struct nvlist_header nvlhdr; + + NVLIST_ASSERT(nvl); + + nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC; + nvlhdr.nvlh_version = NVLIST_HEADER_VERSION; + nvlhdr.nvlh_flags = nvl->nvl_flags; +#if BYTE_ORDER == BIG_ENDIAN + nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN; +#endif + nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl); + nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr); + PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr)); + memcpy(ptr, &nvlhdr, sizeof(nvlhdr)); + ptr += sizeof(nvlhdr); + *leftp -= sizeof(nvlhdr); + + return (ptr); +} + +void * +nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) +{ + unsigned char *buf, *ptr; + size_t left, size; + const nvlist_t *tmpnvl; + nvpair_t *nvp, *tmpnvp; + void *cookie; + + NVLIST_ASSERT(nvl); + + if (nvl->nvl_error != 0) { + RESTORE_ERRNO(nvl->nvl_error); + return (NULL); + } + + size = nvlist_size(nvl); + buf = nv_malloc(size); + if (buf == NULL) + return (NULL); + + ptr = buf; + left = size; + + ptr = nvlist_pack_header(nvl, ptr, &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) { + nv_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; +#ifndef _KERNEL + case NV_TYPE_DESCRIPTOR: + ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left); + break; +#endif + case NV_TYPE_BINARY: + ptr = nvpair_pack_binary(nvp, ptr, &left); + break; + default: + PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); + } + if (ptr == NULL) { + nv_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); +} + +void * +nvlist_pack(const nvlist_t *nvl, size_t *sizep) +{ + + NVLIST_ASSERT(nvl); + + if (nvl->nvl_error != 0) { + RESTORE_ERRNO(nvl->nvl_error); + return (NULL); + } + + if (nvlist_ndescriptors(nvl) > 0) { + RESTORE_ERRNO(EOPNOTSUPP); + return (NULL); + } + + return (nvlist_xpack(nvl, NULL, sizep)); +} + +static bool +nvlist_check_header(struct nvlist_header *nvlhdrp) +{ + + if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { + RESTORE_ERRNO(EINVAL); + return (false); + } + if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { + RESTORE_ERRNO(EINVAL); + return (false); + } +#if BYTE_ORDER == BIG_ENDIAN + if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) { + nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size); + nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors); + } +#else + if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) { + nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size); + nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); + } +#endif + return (true); +} + +const unsigned char * +nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, + bool *isbep, size_t *leftp) +{ + struct nvlist_header nvlhdr; + + if (*leftp < sizeof(nvlhdr)) + goto failed; + + memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); + + if (!nvlist_check_header(&nvlhdr)) + goto failed; + + if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) + goto failed; + + /* + * nvlh_descriptors might be smaller than nfds in embedded nvlists. + */ + if (nvlhdr.nvlh_descriptors > nfds) + goto failed; + + if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) + goto failed; + + nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK); + + ptr += sizeof(nvlhdr); + if (isbep != NULL) + *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0); + *leftp -= sizeof(nvlhdr); + + return (ptr); +failed: + RESTORE_ERRNO(EINVAL); + return (NULL); +} + +nvlist_t * +nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) +{ + const unsigned char *ptr; + nvlist_t *nvl, *retnvl, *tmpnvl; + nvpair_t *nvp; + size_t left; + bool isbe; + + left = size; + ptr = buf; + + tmpnvl = NULL; + nvl = retnvl = nvlist_create(0); + if (nvl == NULL) + goto failed; + + ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); + if (ptr == NULL) + goto failed; + + while (left > 0) { + 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; +#ifndef _KERNEL + case NV_TYPE_DESCRIPTOR: + ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left, + fds, nfds); + break; +#endif + 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 (retnvl); +failed: + nvlist_destroy(retnvl); + return (NULL); +} + +nvlist_t * +nvlist_unpack(const void *buf, size_t size) +{ + + return (nvlist_xunpack(buf, size, NULL, 0)); +} + +#ifndef _KERNEL +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, i; + 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) { + for (i = 0; i < nfds; i++) + close(fds[i]); + 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)); +} +#endif + +nvpair_t * +nvlist_first_nvpair(const nvlist_t *nvl) +{ + + NVLIST_ASSERT(nvl); + + return (TAILQ_FIRST(&nvl->nvl_head)); +} + +nvpair_t * +nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) +{ + nvpair_t *retnvp; + + NVLIST_ASSERT(nvl); + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); + + retnvp = nvpair_next(nvp); + PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl); + + return (retnvp); + +} + +nvpair_t * +nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp) +{ + nvpair_t *retnvp; + + NVLIST_ASSERT(nvl); + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); + + retnvp = nvpair_prev(nvp); + PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl); + + return (retnvp); +} + +const char * +nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep) +{ + nvpair_t *nvp; + + NVLIST_ASSERT(nvl); + PJDLOG_ASSERT(cookiep != NULL); + + if (*cookiep == NULL) + nvp = nvlist_first_nvpair(nvl); + else + nvp = nvlist_next_nvpair(nvl, *cookiep); + if (nvp == NULL) + return (NULL); + if (typep != NULL) + *typep = nvpair_type(nvp); + *cookiep = nvp; + return (nvpair_name(nvp)); +} + +bool +nvlist_exists(const nvlist_t *nvl, const char *name) +{ + + return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL); +} + +#define NVLIST_EXISTS(type, TYPE) \ +bool \ +nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ +{ \ + \ + return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \ +} + +NVLIST_EXISTS(null, NULL) +NVLIST_EXISTS(bool, BOOL) +NVLIST_EXISTS(number, NUMBER) +NVLIST_EXISTS(string, STRING) +NVLIST_EXISTS(nvlist, NVLIST) +#ifndef _KERNEL +NVLIST_EXISTS(descriptor, DESCRIPTOR) +#endif +NVLIST_EXISTS(binary, BINARY) + +#undef NVLIST_EXISTS + +#ifndef _KERNEL +bool +nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...) +{ + va_list nameap; + bool ret; + + va_start(nameap, namefmt); + ret = nvlist_existsv(nvl, namefmt, nameap); + va_end(nameap); + 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) +#ifndef _KERNEL +NVLIST_EXISTSF(descriptor) +#endif +NVLIST_EXISTSF(binary) + +#undef NVLIST_EXISTSF + +bool +nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap) +{ + char *name; + bool exists; + + nv_vasprintf(&name, namefmt, nameap); + if (name == NULL) + return (false); + + exists = nvlist_exists(nvl, name); + nv_free(name); + return (exists); +} + +#define NVLIST_EXISTSV(type) \ +bool \ +nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \ + va_list nameap) \ +{ \ + char *name; \ + bool exists; \ + \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + return (false); \ + exists = nvlist_exists_##type(nvl, name); \ + free(name); \ + return (exists); \ +} + +NVLIST_EXISTSV(null) +NVLIST_EXISTSV(bool) +NVLIST_EXISTSV(number) +NVLIST_EXISTSV(string) +NVLIST_EXISTSV(nvlist) +NVLIST_EXISTSV(descriptor) +NVLIST_EXISTSV(binary) + +#undef NVLIST_EXISTSV +#endif + +void +nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) +{ + nvpair_t *newnvp; + + NVPAIR_ASSERT(nvp); + + if (nvlist_error(nvl) != 0) { + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + if (nvlist_exists(nvl, nvpair_name(nvp))) { + nvl->nvl_error = EEXIST; + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + newnvp = nvpair_clone(nvp); + if (newnvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvpair_insert(&nvl->nvl_head, newnvp, nvl); +} + +void +nvlist_add_null(nvlist_t *nvl, const char *name) +{ + + nvlist_addf_null(nvl, "%s", name); +} + +void +nvlist_add_bool(nvlist_t *nvl, const char *name, bool value) +{ + + nvlist_addf_bool(nvl, value, "%s", name); +} + +void +nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value) +{ + + nvlist_addf_number(nvl, value, "%s", name); +} + +void +nvlist_add_string(nvlist_t *nvl, const char *name, const char *value) +{ + + nvlist_addf_string(nvl, value, "%s", name); +} + +void +nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) +{ + va_list valueap; + + va_start(valueap, valuefmt); + nvlist_add_stringv(nvl, name, valuefmt, valueap); + va_end(valueap); +} + +void +nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, + va_list valueap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvp = nvpair_create_stringv(name, valuefmt, valueap); + if (nvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvl->nvl_error); + } else + nvlist_move_nvpair(nvl, nvp); +} + +void +nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value) +{ + + nvlist_addf_nvlist(nvl, value, "%s", name); +} + +#ifndef _KERNEL +void +nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value) +{ + + nvlist_addf_descriptor(nvl, value, "%s", name); +} +#endif + +void +nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, + size_t size) +{ + + nvlist_addf_binary(nvl, value, size, "%s", name); +} + +void +nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...) +{ + va_list nameap; + + va_start(nameap, namefmt); + nvlist_addv_null(nvl, namefmt, nameap); + va_end(nameap); +} + +void +nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...) +{ + va_list nameap; + + va_start(nameap, namefmt); + nvlist_addv_bool(nvl, value, namefmt, nameap); + va_end(nameap); +} + +void +nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...) +{ + va_list nameap; + + va_start(nameap, namefmt); + nvlist_addv_number(nvl, value, namefmt, nameap); + va_end(nameap); +} + +void +nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...) +{ + va_list nameap; + + va_start(nameap, namefmt); + nvlist_addv_string(nvl, value, namefmt, nameap); + va_end(nameap); +} + +void +nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, + ...) +{ + va_list nameap; + + va_start(nameap, namefmt); + nvlist_addv_nvlist(nvl, value, namefmt, nameap); + va_end(nameap); +} + +#ifndef _KERNEL +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); +} +#endif + +void +nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size, + const char *namefmt, ...) +{ + va_list nameap; + + va_start(nameap, namefmt); + nvlist_addv_binary(nvl, value, size, namefmt, nameap); + va_end(nameap); +} + +void +nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvp = nvpair_createv_null(namefmt, nameap); + if (nvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvl->nvl_error); + } else + nvlist_move_nvpair(nvl, nvp); +} + +void +nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvp = nvpair_createv_bool(value, namefmt, nameap); + if (nvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvl->nvl_error); + } else + nvlist_move_nvpair(nvl, nvp); +} + +void +nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt, + va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvp = nvpair_createv_number(value, namefmt, nameap); + if (nvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvl->nvl_error); + } else + nvlist_move_nvpair(nvl, nvp); +} + +void +nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt, + va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvp = nvpair_createv_string(value, namefmt, nameap); + if (nvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvl->nvl_error); + } else + nvlist_move_nvpair(nvl, nvp); +} + +void +nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, + va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvp = nvpair_createv_nvlist(value, namefmt, nameap); + if (nvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvl->nvl_error); + } else + nvlist_move_nvpair(nvl, nvp); +} + +#ifndef _KERNEL +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); +} +#endif + +void +nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size, + const char *namefmt, va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvp = nvpair_createv_binary(value, size, namefmt, nameap); + if (nvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvl->nvl_error); + } else + nvlist_move_nvpair(nvl, nvp); +} + +void +nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); + + if (nvlist_error(nvl) != 0) { + nvpair_free(nvp); + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + if (nvlist_exists(nvl, nvpair_name(nvp))) { + nvpair_free(nvp); + nvl->nvl_error = EEXIST; + RESTORE_ERRNO(nvl->nvl_error); + return; + } + + 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) +#ifndef _KERNEL +NVLIST_MOVE(int, descriptor) +#endif + +#undef NVLIST_MOVE + +void +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) +#ifndef _KERNEL +NVLIST_MOVEF(int, descriptor) +#endif + +#undef NVLIST_MOVEF + +void +nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size, + const char *namefmt, ...) +{ + va_list nameap; + + va_start(nameap, namefmt); + nvlist_movev_binary(nvl, value, size, namefmt, nameap); + va_end(nameap); +} + +void +nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt, + va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + nv_free(value); + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvp = nvpair_movev_string(value, namefmt, nameap); + if (nvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvl->nvl_error); + } else + nvlist_move_nvpair(nvl, nvp); +} + +void +nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt, + va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) + nvlist_destroy(value); + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvp = nvpair_movev_nvlist(value, namefmt, nameap); + if (nvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvl->nvl_error); + } else + nvlist_move_nvpair(nvl, nvp); +} + +#ifndef _KERNEL +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); +} +#endif + +void +nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, + const char *namefmt, va_list nameap) +{ + nvpair_t *nvp; + + if (nvlist_error(nvl) != 0) { + nv_free(value); + RESTORE_ERRNO(nvlist_error(nvl)); + return; + } + + nvp = nvpair_movev_binary(value, size, namefmt, nameap); + if (nvp == NULL) { + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); + RESTORE_ERRNO(nvl->nvl_error); + } else + nvlist_move_nvpair(nvl, nvp); +} + +const nvpair_t * +nvlist_get_nvpair(const nvlist_t *nvl, const char *name) +{ + + return (nvlist_find(nvl, NV_TYPE_NONE, name)); +} + +#define NVLIST_GET(ftype, type, TYPE) \ +ftype \ +nvlist_get_##type(const nvlist_t *nvl, const char *name) \ +{ \ + const nvpair_t *nvp; \ + \ + nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ + if (nvp == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, name); \ + return (nvpair_get_##type(nvp)); \ +} + +NVLIST_GET(bool, bool, BOOL) +NVLIST_GET(uint64_t, number, NUMBER) +NVLIST_GET(const char *, string, STRING) +NVLIST_GET(const nvlist_t *, nvlist, NVLIST) +#ifndef _KERNEL +NVLIST_GET(int, descriptor, DESCRIPTOR) +#endif + +#undef NVLIST_GET + +const void * +nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) +{ + nvpair_t *nvp; + + nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); + if (nvp == NULL) + nvlist_report_missing(NV_TYPE_BINARY, name); + + return (nvpair_get_binary(nvp, sizep)); +} + +#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); \ +} + +#ifndef _KERNEL +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, ...) +{ + va_list nameap; + const void *value; + + va_start(nameap, namefmt); + value = nvlist_getv_binary(nvl, sizep, 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) \ +{ \ + char *name; \ + ftype value; \ + \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, ""); \ + value = nvlist_get_##type(nvl, name); \ + free(name); \ + \ + return (value); \ +} + +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, + va_list nameap) +{ + char *name; + const void *binary; + + nv_vasprintf(&name, namefmt, nameap); + if (name == NULL) + nvlist_report_missing(NV_TYPE_BINARY, ""); + + binary = nvlist_get_binary(nvl, name, sizep); + nv_free(name); + return (binary); +} +#endif + +#define NVLIST_TAKE(ftype, type, TYPE) \ +ftype \ +nvlist_take_##type(nvlist_t *nvl, const char *name) \ +{ \ + nvpair_t *nvp; \ + ftype value; \ + \ + nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ + if (nvp == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, name); \ + value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ + nvlist_remove_nvpair(nvl, nvp); \ + nvpair_free_structure(nvp); \ + return (value); \ +} + +NVLIST_TAKE(bool, bool, BOOL) +NVLIST_TAKE(uint64_t, number, NUMBER) +NVLIST_TAKE(char *, string, STRING) +NVLIST_TAKE(nvlist_t *, nvlist, NVLIST) +#ifndef _KERNEL +NVLIST_TAKE(int, descriptor, DESCRIPTOR) +#endif + +#undef NVLIST_TAKE + +void * +nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) +{ + nvpair_t *nvp; + void *value; + + nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); + if (nvp == NULL) + nvlist_report_missing(NV_TYPE_BINARY, name); + + value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); + nvlist_remove_nvpair(nvl, nvp); + nvpair_free_structure(nvp); + return (value); +} + +#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); \ +} + +#ifndef _KERNEL +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, ...) +{ + va_list nameap; + void *value; + + va_start(nameap, namefmt); + value = nvlist_takev_binary(nvl, sizep, 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) \ +{ \ + char *name; \ + ftype value; \ + \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, ""); \ + value = nvlist_take_##type(nvl, name); \ + free(name); \ + 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, + va_list nameap) +{ + char *name; + void *binary; + + nv_vasprintf(&name, namefmt, nameap); + if (name == NULL) + nvlist_report_missing(NV_TYPE_BINARY, ""); + + binary = nvlist_take_binary(nvl, name, sizep); + nv_free(name); + return (binary); +} +#endif + +void +nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) +{ + + NVLIST_ASSERT(nvl); + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); + + nvpair_remove(&nvl->nvl_head, nvp, nvl); +} + +void +nvlist_free(nvlist_t *nvl, const char *name) +{ + + nvlist_free_type(nvl, name, NV_TYPE_NONE); +} + +#define NVLIST_FREE(type, TYPE) \ +void \ +nvlist_free_##type(nvlist_t *nvl, const char *name) \ +{ \ + \ + nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ +} + +NVLIST_FREE(null, NULL) +NVLIST_FREE(bool, BOOL) +NVLIST_FREE(number, NUMBER) +NVLIST_FREE(string, STRING) +NVLIST_FREE(nvlist, NVLIST) +#ifndef _KERNEL +NVLIST_FREE(descriptor, DESCRIPTOR) +#endif +NVLIST_FREE(binary, BINARY) + +#undef NVLIST_FREE + +#ifndef _KERNEL +void +nvlist_freef(nvlist_t *nvl, const char *namefmt, ...) +{ + va_list nameap; + + va_start(nameap, namefmt); + nvlist_freev(nvl, namefmt, nameap); + 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) +{ + + 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) \ +{ \ + char *name; \ + \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, ""); \ + nvlist_free_##type(nvl, name); \ + free(name); \ +} + +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 +#endif + +void +nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) +{ + + NVLIST_ASSERT(nvl); + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); + + nvlist_remove_nvpair(nvl, nvp); + nvpair_free(nvp); +} Index: head/sys/kern/subr_nvpair.c =================================================================== --- head/sys/kern/subr_nvpair.c +++ head/sys/kern/subr_nvpair.c @@ -0,0 +1,1350 @@ +/*- + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#ifdef _KERNEL + +#include +#include +#include +#include + +#include + +#else +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common_impl.h" +#endif + +#ifdef HAVE_PJDLOG +#include +#endif + +#include +#include +#include +#include + +#ifndef HAVE_PJDLOG +#ifdef _KERNEL +#define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) +#define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) +#define PJDLOG_ABORT(...) panic(__VA_ARGS__) +#else +#include +#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) +#define PJDLOG_RASSERT(expr, ...) assert(expr) +#define PJDLOG_ABORT(...) abort() +#endif +#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; + 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) +{ + + NVPAIR_ASSERT(nvp); +} + +nvlist_t * +nvpair_nvlist(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + + return (nvp->nvp_list); +} + +nvpair_t * +nvpair_next(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_list != NULL); + + return (TAILQ_NEXT(nvp, nvp_next)); +} + +nvpair_t * +nvpair_prev(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_list != NULL); + + return (TAILQ_PREV(nvp, nvl_head, nvp_next)); +} + +void +nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_list == NULL); + PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp))); + + TAILQ_INSERT_TAIL(head, nvp, nvp_next); + 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) +{ + + 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; +} + +nvpair_t * +nvpair_clone(const nvpair_t *nvp) +{ + nvpair_t *newnvp; + const char *name; + const void *data; + size_t datasize; + + NVPAIR_ASSERT(nvp); + + name = nvpair_name(nvp); + + switch (nvpair_type(nvp)) { + case NV_TYPE_NULL: + newnvp = nvpair_create_null(name); + break; + case NV_TYPE_BOOL: + newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); + break; + case NV_TYPE_NUMBER: + newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); + break; + case NV_TYPE_STRING: + newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); + break; + case NV_TYPE_NVLIST: + newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); + break; +#ifndef _KERNEL + case NV_TYPE_DESCRIPTOR: + newnvp = nvpair_create_descriptor(name, + nvpair_get_descriptor(nvp)); + break; +#endif + case NV_TYPE_BINARY: + data = nvpair_get_binary(nvp, &datasize); + newnvp = nvpair_create_binary(name, data, datasize); + break; + default: + PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); + } + + return (newnvp); +} + +size_t +nvpair_header_size(void) +{ + + return (sizeof(struct nvpair_header)); +} + +size_t +nvpair_size(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + + return (nvp->nvp_datasize); +} + +unsigned char * +nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + struct nvpair_header nvphdr; + size_t namesize; + + NVPAIR_ASSERT(nvp); + + nvphdr.nvph_type = nvp->nvp_type; + namesize = strlen(nvp->nvp_name) + 1; + PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX); + nvphdr.nvph_namesize = namesize; + nvphdr.nvph_datasize = nvp->nvp_datasize; + PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); + memcpy(ptr, &nvphdr, sizeof(nvphdr)); + ptr += sizeof(nvphdr); + *leftp -= sizeof(nvphdr); + + PJDLOG_ASSERT(*leftp >= namesize); + memcpy(ptr, nvp->nvp_name, namesize); + ptr += namesize; + *leftp -= namesize; + + return (ptr); +} + +unsigned char * +nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr, + size_t *leftp __unused) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); + + return (ptr); +} + +unsigned char * +nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + uint8_t value; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); + + value = (uint8_t)nvp->nvp_data; + + PJDLOG_ASSERT(*leftp >= sizeof(value)); + memcpy(ptr, &value, sizeof(value)); + ptr += sizeof(value); + *leftp -= sizeof(value); + + return (ptr); +} + +unsigned char * +nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + uint64_t value; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); + + value = (uint64_t)nvp->nvp_data; + + PJDLOG_ASSERT(*leftp >= sizeof(value)); + memcpy(ptr, &value, sizeof(value)); + ptr += sizeof(value); + *leftp -= sizeof(value); + + return (ptr); +} + +unsigned char * +nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); + + PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); + memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); + ptr += nvp->nvp_datasize; + *leftp -= nvp->nvp_datasize; + + return (ptr); +} + +unsigned char * +nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp) +{ + struct nvpair_header nvphdr; + size_t namesize; + const char *name = ""; + + 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); + + PJDLOG_ASSERT(*leftp >= namesize); + memcpy(ptr, name, namesize); + ptr += namesize; + *leftp -= namesize; + + return (ptr); +} + +#ifndef _KERNEL +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); +} +#endif + +unsigned char * +nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); + + PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); + memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); + ptr += nvp->nvp_datasize; + *leftp -= nvp->nvp_datasize; + + return (ptr); +} + +void +nvpair_init_datasize(nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + + if (nvp->nvp_type == NV_TYPE_NVLIST) { + if (nvp->nvp_data == 0) { + nvp->nvp_datasize = 0; + } else { + nvp->nvp_datasize = + nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); + } + } +} + +const unsigned char * +nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp) +{ + struct nvpair_header nvphdr; + + if (*leftp < sizeof(nvphdr)) + goto failed; + + memcpy(&nvphdr, ptr, sizeof(nvphdr)); + ptr += sizeof(nvphdr); + *leftp -= sizeof(nvphdr); + +#if NV_TYPE_FIRST > 0 + if (nvphdr.nvph_type < NV_TYPE_FIRST) + goto failed; +#endif + if (nvphdr.nvph_type > NV_TYPE_LAST && + nvphdr.nvph_type != NV_TYPE_NVLIST_UP) { + goto failed; + } + +#if BYTE_ORDER == BIG_ENDIAN + if (!isbe) { + nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize); + nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize); + } +#else + if (isbe) { + nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); + nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); + } +#endif + + if (nvphdr.nvph_namesize > NV_NAME_MAX) + goto failed; + if (*leftp < nvphdr.nvph_namesize) + goto failed; + if (nvphdr.nvph_namesize < 1) + goto failed; + if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != + (size_t)(nvphdr.nvph_namesize - 1)) { + goto failed; + } + + memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); + ptr += nvphdr.nvph_namesize; + *leftp -= nvphdr.nvph_namesize; + + if (*leftp < nvphdr.nvph_datasize) + goto failed; + + nvp->nvp_type = nvphdr.nvph_type; + nvp->nvp_data = 0; + nvp->nvp_datasize = nvphdr.nvph_datasize; + + return (ptr); +failed: + RESTORE_ERRNO(EINVAL); + return (NULL); +} + +const unsigned char * +nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp __unused) +{ + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); + + if (nvp->nvp_datasize != 0) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + return (ptr); +} + +const unsigned char * +nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp) +{ + uint8_t value; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); + + if (nvp->nvp_datasize != sizeof(value)) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + if (*leftp < sizeof(value)) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + memcpy(&value, ptr, sizeof(value)); + ptr += sizeof(value); + *leftp -= sizeof(value); + + if (value != 0 && value != 1) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + nvp->nvp_data = (uint64_t)value; + + return (ptr); +} + +const unsigned char * +nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr, + size_t *leftp) +{ + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); + + if (nvp->nvp_datasize != sizeof(uint64_t)) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + if (*leftp < sizeof(uint64_t)) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + if (isbe) + nvp->nvp_data = be64dec(ptr); + else + nvp->nvp_data = le64dec(ptr); + ptr += sizeof(uint64_t); + *leftp -= sizeof(uint64_t); + + return (ptr); +} + +const unsigned char * +nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp) +{ + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); + + if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + if (strnlen((const char *)ptr, nvp->nvp_datasize) != + nvp->nvp_datasize - 1) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr); + if (nvp->nvp_data == 0) + return (NULL); + + ptr += nvp->nvp_datasize; + *leftp -= nvp->nvp_datasize; + + return (ptr); +} + +const unsigned char * +nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child) +{ + nvlist_t *value; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); + + if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + value = nvlist_create(0); + if (value == NULL) + return (NULL); + + ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp); + if (ptr == NULL) + return (NULL); + + nvp->nvp_data = (uint64_t)(uintptr_t)value; + *child = value; + + return (ptr); +} + +#ifndef _KERNEL +const unsigned char * +nvpair_unpack_descriptor(bool isbe, 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 (isbe) + 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); +} +#endif + +const unsigned char * +nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp) +{ + void *value; + + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); + + if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + value = nv_malloc(nvp->nvp_datasize); + if (value == NULL) + return (NULL); + + memcpy(value, ptr, nvp->nvp_datasize); + ptr += nvp->nvp_datasize; + *leftp -= nvp->nvp_datasize; + + nvp->nvp_data = (uint64_t)(uintptr_t)value; + + return (ptr); +} + +const unsigned char * +nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, + nvpair_t **nvpp) +{ + nvpair_t *nvp, *tmp; + + nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); + if (nvp == NULL) + return (NULL); + nvp->nvp_name = (char *)(nvp + 1); + + ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); + if (ptr == NULL) + goto failed; + tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); + if (tmp == NULL) + goto failed; + nvp = tmp; + + /* Update nvp_name after realloc(). */ + nvp->nvp_name = (char *)(nvp + 1); + nvp->nvp_data = 0x00; + nvp->nvp_magic = NVPAIR_MAGIC; + *nvpp = nvp; + return (ptr); +failed: + nv_free(nvp); + return (NULL); +} + +int +nvpair_type(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + + return (nvp->nvp_type); +} + +const char * +nvpair_name(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + + return (nvp->nvp_name); +} + +static nvpair_t * +nvpair_allocv(int type, uint64_t data, size_t datasize, const char *namefmt, + va_list nameap) +{ + nvpair_t *nvp; + char *name; + int namelen; + + PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); + + namelen = nv_vasprintf(&name, namefmt, nameap); + if (namelen < 0) + return (NULL); + + PJDLOG_ASSERT(namelen > 0); + if (namelen >= NV_NAME_MAX) { + nv_free(name); + RESTORE_ERRNO(ENAMETOOLONG); + return (NULL); + } + + nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1); + if (nvp != NULL) { + nvp->nvp_name = (char *)(nvp + 1); + memcpy(nvp->nvp_name, name, namelen + 1); + nvp->nvp_type = type; + nvp->nvp_data = data; + nvp->nvp_datasize = datasize; + nvp->nvp_magic = NVPAIR_MAGIC; + } + nv_free(name); + + return (nvp); +}; + +nvpair_t * +nvpair_create_null(const char *name) +{ + + return (nvpair_createf_null("%s", name)); +} + +nvpair_t * +nvpair_create_bool(const char *name, bool value) +{ + + return (nvpair_createf_bool(value, "%s", name)); +} + +nvpair_t * +nvpair_create_number(const char *name, uint64_t value) +{ + + return (nvpair_createf_number(value, "%s", name)); +} + +nvpair_t * +nvpair_create_string(const char *name, const char *value) +{ + + return (nvpair_createf_string(value, "%s", name)); +} + +nvpair_t * +nvpair_create_stringf(const char *name, const char *valuefmt, ...) +{ + va_list valueap; + nvpair_t *nvp; + + va_start(valueap, valuefmt); + nvp = nvpair_create_stringv(name, valuefmt, valueap); + va_end(valueap); + + return (nvp); +} + +nvpair_t * +nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) +{ + nvpair_t *nvp; + char *str; + int len; + + len = nv_vasprintf(&str, valuefmt, valueap); + if (len < 0) + return (NULL); + nvp = nvpair_create_string(name, str); + if (nvp == NULL) + nv_free(str); + return (nvp); +} + +nvpair_t * +nvpair_create_nvlist(const char *name, const nvlist_t *value) +{ + + return (nvpair_createf_nvlist(value, "%s", name)); +} + +#ifndef _KERNEL +nvpair_t * +nvpair_create_descriptor(const char *name, int value) +{ + + return (nvpair_createf_descriptor(value, "%s", name)); +} +#endif + +nvpair_t * +nvpair_create_binary(const char *name, const void *value, size_t size) +{ + + return (nvpair_createf_binary(value, size, "%s", name)); +} + +nvpair_t * +nvpair_createf_null(const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_createv_null(namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +nvpair_t * +nvpair_createf_bool(bool value, const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_createv_bool(value, namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +nvpair_t * +nvpair_createf_number(uint64_t value, const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_createv_number(value, namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +nvpair_t * +nvpair_createf_string(const char *value, const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_createv_string(value, namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +nvpair_t * +nvpair_createf_nvlist(const nvlist_t *value, const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_createv_nvlist(value, namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +#ifndef _KERNEL +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); +} +#endif + +nvpair_t * +nvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_createv_binary(value, size, namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +nvpair_t * +nvpair_createv_null(const char *namefmt, va_list nameap) +{ + + return (nvpair_allocv(NV_TYPE_NULL, 0, 0, namefmt, nameap)); +} + +nvpair_t * +nvpair_createv_bool(bool value, const char *namefmt, va_list nameap) +{ + + return (nvpair_allocv(NV_TYPE_BOOL, value ? 1 : 0, sizeof(uint8_t), + namefmt, nameap)); +} + +nvpair_t * +nvpair_createv_number(uint64_t value, const char *namefmt, va_list nameap) +{ + + return (nvpair_allocv(NV_TYPE_NUMBER, value, sizeof(value), namefmt, + nameap)); +} + +nvpair_t * +nvpair_createv_string(const char *value, const char *namefmt, va_list nameap) +{ + nvpair_t *nvp; + size_t size; + char *data; + + if (value == NULL) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + data = nv_strdup(value); + if (data == NULL) + return (NULL); + size = strlen(value) + 1; + + nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)data, size, + namefmt, nameap); + if (nvp == NULL) + nv_free(data); + + return (nvp); +} + +nvpair_t * +nvpair_createv_nvlist(const nvlist_t *value, const char *namefmt, + va_list nameap) +{ + nvlist_t *nvl; + nvpair_t *nvp; + + if (value == NULL) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + nvl = nvlist_clone(value); + if (nvl == NULL) + return (NULL); + + nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, + namefmt, nameap); + if (nvp == NULL) + nvlist_destroy(nvl); + else + nvlist_set_parent(nvl, nvp); + + return (nvp); +} + +#ifndef _KERNEL +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); +} +#endif + +nvpair_t * +nvpair_createv_binary(const void *value, size_t size, const char *namefmt, + va_list nameap) +{ + nvpair_t *nvp; + void *data; + + if (value == NULL || size == 0) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + data = nv_malloc(size); + if (data == NULL) + return (NULL); + memcpy(data, value, size); + + nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, size, + namefmt, nameap); + if (nvp == NULL) + nv_free(data); + + return (nvp); +} + +nvpair_t * +nvpair_move_string(const char *name, char *value) +{ + + return (nvpair_movef_string(value, "%s", name)); +} + +nvpair_t * +nvpair_move_nvlist(const char *name, nvlist_t *value) +{ + + return (nvpair_movef_nvlist(value, "%s", name)); +} + +#ifndef _KERNEL +nvpair_t * +nvpair_move_descriptor(const char *name, int value) +{ + + return (nvpair_movef_descriptor(value, "%s", name)); +} +#endif + +nvpair_t * +nvpair_move_binary(const char *name, void *value, size_t size) +{ + + return (nvpair_movef_binary(value, size, "%s", name)); +} + +nvpair_t * +nvpair_movef_string(char *value, const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_movev_string(value, namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +nvpair_t * +nvpair_movef_nvlist(nvlist_t *value, const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_movev_nvlist(value, namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +#ifndef _KERNEL +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); +} +#endif + +nvpair_t * +nvpair_movef_binary(void *value, size_t size, const char *namefmt, ...) +{ + va_list nameap; + nvpair_t *nvp; + + va_start(nameap, namefmt); + nvp = nvpair_movev_binary(value, size, namefmt, nameap); + va_end(nameap); + + return (nvp); +} + +nvpair_t * +nvpair_movev_string(char *value, const char *namefmt, va_list nameap) +{ + nvpair_t *nvp; + int serrno; + + if (value == NULL) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value, + strlen(value) + 1, namefmt, nameap); + if (nvp == NULL) { + SAVE_ERRNO(serrno); + nv_free(value); + RESTORE_ERRNO(serrno); + } + + return (nvp); +} + +nvpair_t * +nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap) +{ + nvpair_t *nvp; + + if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + if (nvlist_error(value) != 0) { + RESTORE_ERRNO(nvlist_error(value)); + nvlist_destroy(value); + return (NULL); + } + + nvp = nvpair_allocv(NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 0, + namefmt, nameap); + if (nvp == NULL) + nvlist_destroy(value); + else + nvlist_set_parent(value, nvp); + + return (nvp); +} + +#ifndef _KERNEL +nvpair_t * +nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap) +{ + nvpair_t *nvp; + int serrno; + + if (value < 0 || !fd_is_valid(value)) { + errno = EBADF; + return (NULL); + } + + nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, + sizeof(int64_t), namefmt, nameap); + if (nvp == NULL) { + serrno = errno; + close(value); + errno = serrno; + } + + return (nvp); +} +#endif + +nvpair_t * +nvpair_movev_binary(void *value, size_t size, const char *namefmt, + va_list nameap) +{ + nvpair_t *nvp; + int serrno; + + if (value == NULL || size == 0) { + RESTORE_ERRNO(EINVAL); + return (NULL); + } + + nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size, + namefmt, nameap); + if (nvp == NULL) { + SAVE_ERRNO(serrno); + nv_free(value); + RESTORE_ERRNO(serrno); + } + + return (nvp); +} + +bool +nvpair_get_bool(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + + return (nvp->nvp_data == 1); +} + +uint64_t +nvpair_get_number(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + + return (nvp->nvp_data); +} + +const char * +nvpair_get_string(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); + + return ((const char *)(intptr_t)nvp->nvp_data); +} + +const nvlist_t * +nvpair_get_nvlist(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); + + return ((const nvlist_t *)(intptr_t)nvp->nvp_data); +} + +#ifndef _KERNEL +int +nvpair_get_descriptor(const nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); + + return ((int)nvp->nvp_data); +} +#endif + +const void * +nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); + + if (sizep != NULL) + *sizep = nvp->nvp_datasize; + return ((const void *)(intptr_t)nvp->nvp_data); +} + +void +nvpair_free(nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_list == NULL); + + nvp->nvp_magic = 0; + switch (nvp->nvp_type) { +#ifndef _KERNEL + case NV_TYPE_DESCRIPTOR: + close((int)nvp->nvp_data); + break; +#endif + case NV_TYPE_NVLIST: + nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); + break; + case NV_TYPE_STRING: + nv_free((char *)(intptr_t)nvp->nvp_data); + break; + case NV_TYPE_BINARY: + nv_free((void *)(intptr_t)nvp->nvp_data); + break; + } + nv_free(nvp); +} + +void +nvpair_free_structure(nvpair_t *nvp) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_list == NULL); + + nvp->nvp_magic = 0; + nv_free(nvp); +} + +const char * +nvpair_type_string(int type) +{ + + switch (type) { + case NV_TYPE_NULL: + return ("NULL"); + case NV_TYPE_BOOL: + return ("BOOL"); + case NV_TYPE_NUMBER: + return ("NUMBER"); + case NV_TYPE_STRING: + return ("STRING"); + case NV_TYPE_NVLIST: + return ("NVLIST"); + case NV_TYPE_DESCRIPTOR: + return ("DESCRIPTOR"); + case NV_TYPE_BINARY: + return ("BINARY"); + default: + return (""); + } +} Index: head/sys/sys/dnv.h =================================================================== --- head/sys/sys/dnv.h +++ head/sys/sys/dnv.h @@ -0,0 +1,116 @@ +/*- + * 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 _DNV_H_ +#define _DNV_H_ + +#include + +#ifndef _KERNEL +#include +#include +#include +#endif + +#ifndef _NVLIST_T_DECLARED +#define _NVLIST_T_DECLARED +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 + * not be freed by the caller. + * If no element of the given name and type exists, the function will return + * provided default value. + */ + +bool dnvlist_get_bool(const nvlist_t *nvl, const char *name, bool defval); +uint64_t dnvlist_get_number(const nvlist_t *nvl, const char *name, uint64_t defval); +const char *dnvlist_get_string(const nvlist_t *nvl, const char *name, const char *defval); +const nvlist_t *dnvlist_get_nvlist(const nvlist_t *nvl, const char *name, const nvlist_t *defval); +int dnvlist_get_descriptor(const nvlist_t *nvl, const char *name, int defval); +const void *dnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep, const void *defval, size_t defsize); + +#ifndef _KERNEL +bool dnvlist_getf_bool(const nvlist_t *nvl, bool defval, const char *namefmt, ...) __printflike(3, 4); +uint64_t dnvlist_getf_number(const nvlist_t *nvl, uint64_t defval, const char *namefmt, ...) __printflike(3, 4); +const char *dnvlist_getf_string(const nvlist_t *nvl, const char *defval, const char *namefmt, ...) __printflike(3, 4); +const nvlist_t *dnvlist_getf_nvlist(const nvlist_t *nvl, const nvlist_t *defval, const char *namefmt, ...) __printflike(3, 4); +int dnvlist_getf_descriptor(const nvlist_t *nvl, int defval, const char *namefmt, ...) __printflike(3, 4); +const void *dnvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const void *defval, size_t defsize, const char *namefmt, ...) __printflike(5, 6); + +bool dnvlist_getv_bool(const nvlist_t *nvl, bool defval, const char *namefmt, va_list nameap) __printflike(3, 0); +uint64_t dnvlist_getv_number(const nvlist_t *nvl, uint64_t defval, const char *namefmt, va_list nameap) __printflike(3, 0); +const char *dnvlist_getv_string(const nvlist_t *nvl, const char *defval, const char *namefmt, va_list nameap) __printflike(3, 0); +const nvlist_t *dnvlist_getv_nvlist(const nvlist_t *nvl, const nvlist_t *defval, const char *namefmt, va_list nameap) __printflike(3, 0); +int dnvlist_getv_descriptor(const nvlist_t *nvl, int defval, const char *namefmt, va_list nameap) __printflike(3, 0); +const void *dnvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const void *defval, size_t defsize, const char *namefmt, va_list nameap) __printflike(5, 0); +#endif + +/* + * The dnvlist_take functions returns value associated with the given name and + * remove corresponding nvpair. + * If it returns a pointer, the caller has to free it. + * If no element of the given name and type exists, the function will return + * provided default value. + */ + +bool dnvlist_take_bool(nvlist_t *nvl, const char *name, bool defval); +uint64_t dnvlist_take_number(nvlist_t *nvl, const char *name, uint64_t defval); +char *dnvlist_take_string(nvlist_t *nvl, const char *name, char *defval); +nvlist_t *dnvlist_take_nvlist(nvlist_t *nvl, const char *name, nvlist_t *defval); +int dnvlist_take_descriptor(nvlist_t *nvl, const char *name, int defval); +void *dnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep, void *defval, size_t defsize); + +#ifndef _KERNEL +bool dnvlist_takef_bool(nvlist_t *nvl, bool defval, const char *namefmt, ...) __printflike(3, 4); +uint64_t dnvlist_takef_number(nvlist_t *nvl, uint64_t defval, const char *namefmt, ...) __printflike(3, 4); +char *dnvlist_takef_string(nvlist_t *nvl, char *defval, const char *namefmt, ...) __printflike(3, 4); +nvlist_t *dnvlist_takef_nvlist(nvlist_t *nvl, nvlist_t *defval, const char *namefmt, ...) __printflike(3, 4); +int dnvlist_takef_descriptor(nvlist_t *nvl, int defval, const char *namefmt, ...) __printflike(3, 4); +void *dnvlist_takef_binary(nvlist_t *nvl, size_t *sizep, void *defval, size_t defsize, const char *namefmt, ...) __printflike(5, 6); + +bool dnvlist_takev_bool(nvlist_t *nvl, bool defval, const char *namefmt, va_list nameap) __printflike(3, 0); +uint64_t dnvlist_takev_number(nvlist_t *nvl, uint64_t defval, const char *namefmt, va_list nameap) __printflike(3, 0); +char *dnvlist_takev_string(nvlist_t *nvl, char *defval, const char *namefmt, va_list nameap) __printflike(3, 0); +nvlist_t *dnvlist_takev_nvlist(nvlist_t *nvl, nvlist_t *defval, const char *namefmt, va_list nameap) __printflike(3, 0); +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); +#endif + +__END_DECLS + +#endif /* !_DNV_H_ */ Index: head/sys/sys/nv.h =================================================================== --- head/sys/sys/nv.h +++ head/sys/sys/nv.h @@ -0,0 +1,322 @@ +/*- + * 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. + * + * $FreeBSD$ + */ + +#ifndef _NV_H_ +#define _NV_H_ + +#include + +#ifndef _KERNEL +#include +#include +#include +#include +#endif + +#ifndef _NVLIST_T_DECLARED +#define _NVLIST_T_DECLARED +struct nvlist; + +typedef struct nvlist nvlist_t; +#endif + +#define NV_NAME_MAX 2048 + +#define NV_TYPE_NONE 0 + +#define NV_TYPE_NULL 1 +#define NV_TYPE_BOOL 2 +#define NV_TYPE_NUMBER 3 +#define NV_TYPE_STRING 4 +#define NV_TYPE_NVLIST 5 +#define NV_TYPE_DESCRIPTOR 6 +#define NV_TYPE_BINARY 7 + +/* + * Perform case-insensitive lookups of provided names. + */ +#define NV_FLAG_IGNORE_CASE 0x01 + +#if defined(_KERNEL) && defined(MALLOC_DECLARE) +MALLOC_DECLARE(M_NVLIST); +#endif + +__BEGIN_DECLS + +nvlist_t *nvlist_create(int flags); +void nvlist_destroy(nvlist_t *nvl); +int nvlist_error(const nvlist_t *nvl); +bool nvlist_empty(const nvlist_t *nvl); +void nvlist_set_error(nvlist_t *nvl, int error); + +nvlist_t *nvlist_clone(const nvlist_t *nvl); + +#ifndef _KERNEL +void nvlist_dump(const nvlist_t *nvl, int fd); +void nvlist_fdump(const nvlist_t *nvl, FILE *fp); +#endif + +size_t nvlist_size(const nvlist_t *nvl); +void *nvlist_pack(const nvlist_t *nvl, size_t *sizep); +nvlist_t *nvlist_unpack(const void *buf, size_t size); + +int nvlist_send(int sock, const nvlist_t *nvl); +nvlist_t *nvlist_recv(int sock); +nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl); + +const char *nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep); + +const nvlist_t *nvlist_get_parent(const nvlist_t *nvl, void **cookiep); + +/* + * The nvlist_exists functions check if the given name (optionally of the given + * type) exists on nvlist. + */ + +bool nvlist_exists(const nvlist_t *nvl, const char *name); +bool nvlist_exists_type(const nvlist_t *nvl, const char *name, int type); + +bool nvlist_exists_null(const nvlist_t *nvl, const char *name); +bool nvlist_exists_bool(const nvlist_t *nvl, const char *name); +bool nvlist_exists_number(const nvlist_t *nvl, const char *name); +bool nvlist_exists_string(const nvlist_t *nvl, const char *name); +bool nvlist_exists_nvlist(const nvlist_t *nvl, const char *name); +#ifndef _KERNEL +bool nvlist_exists_descriptor(const nvlist_t *nvl, const char *name); +#endif +bool nvlist_exists_binary(const nvlist_t *nvl, const char *name); + +/* + * The nvlist_add functions add the given name/value pair. + * If a pointer is provided, nvlist_add will internally allocate memory for the + * given data (in other words it won't consume provided buffer). + */ + +void nvlist_add_null(nvlist_t *nvl, const char *name); +void nvlist_add_bool(nvlist_t *nvl, const char *name, bool value); +void nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value); +void nvlist_add_string(nvlist_t *nvl, const char *name, const char *value); +void nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) __printflike(3, 4); +#ifdef _VA_LIST_DECLARED +void nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, va_list valueap) __printflike(3, 0); +#endif +void nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value); +#ifndef _KERNEL +void nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value); +#endif +void nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, size_t size); + +/* + * The nvlist_move functions add the given name/value pair. + * The functions consumes provided buffer. + */ + +void nvlist_move_string(nvlist_t *nvl, const char *name, char *value); +void nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value); +#ifndef _KERNEL +void nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value); +#endif +void nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size); + +/* + * The nvlist_get functions returns value associated with the given name. + * If it returns a pointer, the pointer represents internal buffer and should + * not be freed by the caller. + */ + +bool nvlist_get_bool(const nvlist_t *nvl, const char *name); +uint64_t nvlist_get_number(const nvlist_t *nvl, const char *name); +const char *nvlist_get_string(const nvlist_t *nvl, const char *name); +const nvlist_t *nvlist_get_nvlist(const nvlist_t *nvl, const char *name); +#ifndef _KERNEL +int nvlist_get_descriptor(const nvlist_t *nvl, const char *name); +#endif +const void *nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep); + +/* + * The nvlist_take functions returns value associated with the given name and + * remove the given entry from the nvlist. + * The caller is responsible for freeing received data. + */ + +bool nvlist_take_bool(nvlist_t *nvl, const char *name); +uint64_t nvlist_take_number(nvlist_t *nvl, const char *name); +char *nvlist_take_string(nvlist_t *nvl, const char *name); +nvlist_t *nvlist_take_nvlist(nvlist_t *nvl, const char *name); +#ifndef _KERNEL +int nvlist_take_descriptor(nvlist_t *nvl, const char *name); +#endif +void *nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep); + +/* + * The nvlist_free functions removes the given name/value pair from the nvlist + * and frees memory associated with it. + */ + +void nvlist_free(nvlist_t *nvl, const char *name); +void nvlist_free_type(nvlist_t *nvl, const char *name, int type); + +void nvlist_free_null(nvlist_t *nvl, const char *name); +void nvlist_free_bool(nvlist_t *nvl, const char *name); +void nvlist_free_number(nvlist_t *nvl, const char *name); +void nvlist_free_string(nvlist_t *nvl, const char *name); +void nvlist_free_nvlist(nvlist_t *nvl, const char *name); +#ifndef _KERNEL +void nvlist_free_descriptor(nvlist_t *nvl, const char *name); +#endif +void nvlist_free_binary(nvlist_t *nvl, const char *name); + +/* + * Below are the same functions, but which operate on format strings and + * variable argument lists. + * + * Functions that are not inserting a new pair into the nvlist cannot handle + * a failure to allocate the memory to hold the new name. Therefore these + * functions are not provided in the kernel. + */ + +#ifndef _KERNEL +bool nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +bool nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...) __printflike(3, 4); + +bool nvlist_existsf_null(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +bool nvlist_existsf_bool(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +bool nvlist_existsf_number(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +bool nvlist_existsf_string(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +bool nvlist_existsf_nvlist(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +bool nvlist_existsf_descriptor(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +bool nvlist_existsf_binary(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); + +bool nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +bool nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap) __printflike(3, 0); + +bool nvlist_existsv_null(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +bool nvlist_existsv_bool(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +bool nvlist_existsv_number(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +bool nvlist_existsv_string(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +bool nvlist_existsv_nvlist(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +bool nvlist_existsv_descriptor(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +bool nvlist_existsv_binary(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +#endif + +void nvlist_addf_null(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +void nvlist_addf_bool(nvlist_t *nvl, bool value, const char *namefmt, ...) __printflike(3, 4); +void nvlist_addf_number(nvlist_t *nvl, uint64_t value, const char *namefmt, ...) __printflike(3, 4); +void nvlist_addf_string(nvlist_t *nvl, const char *value, const char *namefmt, ...) __printflike(3, 4); +void nvlist_addf_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, ...) __printflike(3, 4); +#ifndef _KERNEL +void nvlist_addf_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...) __printflike(3, 4); +#endif +void nvlist_addf_binary(nvlist_t *nvl, const void *value, size_t size, const char *namefmt, ...) __printflike(4, 5); + +#if !defined(_KERNEL) || defined(_VA_LIST_DECLARED) +void nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +void nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap) __printflike(3, 0); +void nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt, va_list nameap) __printflike(3, 0); +void nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt, va_list nameap) __printflike(3, 0); +void nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, va_list nameap) __printflike(3, 0); +#ifndef _KERNEL +void nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt, va_list nameap) __printflike(3, 0); +#endif +void nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size, const char *namefmt, va_list nameap) __printflike(4, 0); +#endif + +void nvlist_movef_string(nvlist_t *nvl, char *value, const char *namefmt, ...) __printflike(3, 4); +void nvlist_movef_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt, ...) __printflike(3, 4); +#ifndef _KERNEL +void nvlist_movef_descriptor(nvlist_t *nvl, int value, const char *namefmt, ...) __printflike(3, 4); +#endif +void nvlist_movef_binary(nvlist_t *nvl, void *value, size_t size, const char *namefmt, ...) __printflike(4, 5); + +#if !defined(_KERNEL) || defined(_VA_LIST_DECLARED) +void nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt, va_list nameap) __printflike(3, 0); +void nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt, va_list nameap) __printflike(3, 0); +#ifndef _KERNEL +void nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt, va_list nameap) __printflike(3, 0); +#endif +void nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, const char *namefmt, va_list nameap) __printflike(4, 0); +#endif + +#ifndef _KERNEL +bool nvlist_getf_bool(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +uint64_t nvlist_getf_number(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +const char *nvlist_getf_string(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +const nvlist_t *nvlist_getf_nvlist(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +int nvlist_getf_descriptor(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +const void *nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) __printflike(3, 4); + +bool nvlist_getv_bool(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +uint64_t nvlist_getv_number(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +const char *nvlist_getv_string(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +const nvlist_t *nvlist_getv_nvlist(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +int nvlist_getv_descriptor(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +const void *nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, va_list nameap) __printflike(3, 0); + +bool nvlist_takef_bool(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +uint64_t nvlist_takef_number(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +char *nvlist_takef_string(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +nvlist_t *nvlist_takef_nvlist(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +int nvlist_takef_descriptor(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +void *nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) __printflike(3, 4); + +bool nvlist_takev_bool(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +uint64_t nvlist_takev_number(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +char *nvlist_takev_string(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +nvlist_t *nvlist_takev_nvlist(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +int nvlist_takev_descriptor(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +void *nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, va_list nameap) __printflike(3, 0); + +void nvlist_freef(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +void nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...) __printflike(3, 4); + +void nvlist_freef_null(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +void nvlist_freef_bool(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +void nvlist_freef_number(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +void nvlist_freef_string(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +void nvlist_freef_nvlist(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +void nvlist_freef_descriptor(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); +void nvlist_freef_binary(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); + +void nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +void nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap) __printflike(3, 0); + +void nvlist_freev_null(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +void nvlist_freev_bool(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +void nvlist_freev_number(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +void nvlist_freev_string(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +void nvlist_freev_nvlist(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); +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); +#endif /* _KERNEL */ + +__END_DECLS + +#endif /* !_NV_H_ */ Index: head/sys/sys/nv_impl.h =================================================================== --- head/sys/sys/nv_impl.h +++ head/sys/sys/nv_impl.h @@ -0,0 +1,157 @@ +/*- + * 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 _NV_IMPL_H_ +#define _NV_IMPL_H_ + +#ifndef _NVPAIR_T_DECLARED +#define _NVPAIR_T_DECLARED +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 + +#define NV_FLAG_BIG_ENDIAN 0x80 + +#ifdef _KERNEL +#define nv_malloc(size) malloc((size), M_NVLIST, M_NOWAIT) +#define nv_calloc(n, size) malloc((n) * (size), M_NVLIST, \ + M_NOWAIT | M_ZERO) +#define nv_realloc(buf, size) realloc((buf), (size), M_NVLIST, \ + M_NOWAIT) +#define nv_free(buf) free((buf), M_NVLIST) +#define nv_strdup(buf) strdup((buf), M_NVLIST) +#define nv_vasprintf(ptr, ...) vasprintf(ptr, M_NVLIST, __VA_ARGS__) + +#define SAVE_ERRNO(var) ((void)(var)) +#define RESTORE_ERRNO(var) ((void)(var)) + +#define ERRNO_OR_DEFAULT(default) (default) + +#else + +#define nv_malloc(size) malloc((size)) +#define nv_calloc(n, size) calloc((n), (size)) +#define nv_realloc(buf, size) realloc((buf), (size)) +#define nv_free(buf) free((buf)) +#define nv_strdup(buf) strdup((buf)) +#define nv_vasprintf(ptr, ...) vasprintf(ptr, __VA_ARGS__) + +#define SAVE_ERRNO(var) (var) = errno +#define RESTORE_ERRNO(var) errno = (var) + +#define ERRNO_OR_DEFAULT(default) (errno == 0 ? (default) : errno) + +#endif + +int *nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp); +size_t nvlist_ndescriptors(const nvlist_t *nvl); + +nvpair_t *nvlist_first_nvpair(const nvlist_t *nvl); +nvpair_t *nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp); +nvpair_t *nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp); + +void nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp); + +void nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp); + +void nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent); + +const nvpair_t *nvlist_get_nvpair(const nvlist_t *nvl, const char *name); + +nvpair_t *nvlist_take_nvpair(nvlist_t *nvl, const char *name); + +/* Function removes the given nvpair from the nvlist. */ +void nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp); + +void nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp); + +int nvpair_type(const nvpair_t *nvp); +const char *nvpair_name(const nvpair_t *nvp); + +nvpair_t *nvpair_clone(const nvpair_t *nvp); + +nvpair_t *nvpair_create_null(const char *name); +nvpair_t *nvpair_create_bool(const char *name, bool value); +nvpair_t *nvpair_create_number(const char *name, uint64_t value); +nvpair_t *nvpair_create_string(const char *name, const char *value); +nvpair_t *nvpair_create_stringf(const char *name, const char *valuefmt, ...) __printflike(2, 3); +nvpair_t *nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) __printflike(2, 0); +nvpair_t *nvpair_create_nvlist(const char *name, const nvlist_t *value); +nvpair_t *nvpair_create_descriptor(const char *name, int value); +nvpair_t *nvpair_create_binary(const char *name, const void *value, size_t size); + +nvpair_t *nvpair_move_string(const char *name, char *value); +nvpair_t *nvpair_move_nvlist(const char *name, nvlist_t *value); +nvpair_t *nvpair_move_descriptor(const char *name, int value); +nvpair_t *nvpair_move_binary(const char *name, void *value, size_t size); + +bool nvpair_get_bool(const nvpair_t *nvp); +uint64_t nvpair_get_number(const nvpair_t *nvp); +const char *nvpair_get_string(const nvpair_t *nvp); +const nvlist_t *nvpair_get_nvlist(const nvpair_t *nvp); +int nvpair_get_descriptor(const nvpair_t *nvp); +const void *nvpair_get_binary(const nvpair_t *nvp, size_t *sizep); + +void nvpair_free(nvpair_t *nvp); + +nvpair_t *nvpair_createf_null(const char *namefmt, ...) __printflike(1, 2); +nvpair_t *nvpair_createf_bool(bool value, const char *namefmt, ...) __printflike(2, 3); +nvpair_t *nvpair_createf_number(uint64_t value, const char *namefmt, ...) __printflike(2, 3); +nvpair_t *nvpair_createf_string(const char *value, const char *namefmt, ...) __printflike(2, 3); +nvpair_t *nvpair_createf_nvlist(const nvlist_t *value, const char *namefmt, ...) __printflike(2, 3); +nvpair_t *nvpair_createf_descriptor(int value, const char *namefmt, ...) __printflike(2, 3); +nvpair_t *nvpair_createf_binary(const void *value, size_t size, const char *namefmt, ...) __printflike(3, 4); + +nvpair_t *nvpair_createv_null(const char *namefmt, va_list nameap) __printflike(1, 0); +nvpair_t *nvpair_createv_bool(bool value, const char *namefmt, va_list nameap) __printflike(2, 0); +nvpair_t *nvpair_createv_number(uint64_t value, const char *namefmt, va_list nameap) __printflike(2, 0); +nvpair_t *nvpair_createv_string(const char *value, const char *namefmt, va_list nameap) __printflike(2, 0); +nvpair_t *nvpair_createv_nvlist(const nvlist_t *value, const char *namefmt, va_list nameap) __printflike(2, 0); +nvpair_t *nvpair_createv_descriptor(int value, const char *namefmt, va_list nameap) __printflike(2, 0); +nvpair_t *nvpair_createv_binary(const void *value, size_t size, const char *namefmt, va_list nameap) __printflike(3, 0); + +nvpair_t *nvpair_movef_string(char *value, const char *namefmt, ...) __printflike(2, 3); +nvpair_t *nvpair_movef_nvlist(nvlist_t *value, const char *namefmt, ...) __printflike(2, 3); +nvpair_t *nvpair_movef_descriptor(int value, const char *namefmt, ...) __printflike(2, 3); +nvpair_t *nvpair_movef_binary(void *value, size_t size, const char *namefmt, ...) __printflike(3, 4); + +nvpair_t *nvpair_movev_string(char *value, const char *namefmt, va_list nameap) __printflike(2, 0); +nvpair_t *nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap) __printflike(2, 0); +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); + +#endif /* !_NV_IMPL_H_ */ Index: head/sys/sys/nvlist_impl.h =================================================================== --- head/sys/sys/nvlist_impl.h +++ head/sys/sys/nvlist_impl.h @@ -0,0 +1,49 @@ +/*- + * 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_IMPL_H_ +#define _NVLIST_IMPL_H_ + +#ifndef _KERNEL +#include +#endif + +#include "nv.h" + +void *nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep); +nvlist_t *nvlist_xunpack(const void *buf, size_t size, const int *fds, + size_t nfds); + +nvpair_t *nvlist_get_nvpair_parent(const nvlist_t *nvl); +const unsigned char *nvlist_unpack_header(nvlist_t *nvl, + const unsigned char *ptr, size_t nfds, bool *isbep, size_t *leftp); + +#endif /* !_NVLIST_IMPL_H_ */ Index: head/sys/sys/nvpair_impl.h =================================================================== --- head/sys/sys/nvpair_impl.h +++ head/sys/sys/nvpair_impl.h @@ -0,0 +1,94 @@ +/*- + * 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. + * + * $FreeBSD$ + */ + +#ifndef _NVPAIR_IMPL_H_ +#define _NVPAIR_IMPL_H_ + +#include + +#ifndef _KERNEL +#include +#endif + +#include "nv.h" + +TAILQ_HEAD(nvl_head, nvpair); + +void nvpair_assert(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); +const unsigned char *nvpair_unpack(bool isbe, const unsigned char *ptr, + 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(bool isbe, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp); +const unsigned char *nvpair_unpack_null(bool isbe, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp); +const unsigned char *nvpair_unpack_bool(bool isbe, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp); +const unsigned char *nvpair_unpack_number(bool isbe, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp); +const unsigned char *nvpair_unpack_string(bool isbe, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp); +const unsigned char *nvpair_unpack_nvlist(bool isbe, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp, size_t nvlist, nvlist_t **child); +const unsigned char *nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds); +const unsigned char *nvpair_unpack_binary(bool isbe, nvpair_t *nvp, + const unsigned char *ptr, size_t *leftp); + +#endif /* !_NVPAIR_IMPL_H_ */