Index: head/lib/libnv/dnv.h =================================================================== --- head/lib/libnv/dnv.h (revision 279437) +++ head/lib/libnv/dnv.h (revision 279438) @@ -1,110 +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/lib/libnv/dnvlist.c =================================================================== --- head/lib/libnv/dnvlist.c (revision 279437) +++ head/lib/libnv/dnvlist.c (revision 279438) @@ -1,274 +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 "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; - vasprintf(&name, namefmt, nameap); + nv_vasprintf(&name, namefmt, nameap); if (name != NULL) { value = dnvlist_get_binary(nvl, name, sizep, defval, defsize); - free(name); + 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; - vasprintf(&name, namefmt, nameap); + nv_vasprintf(&name, namefmt, nameap); if (name != NULL) { value = dnvlist_take_binary(nvl, name, sizep, defval, defsize); - free(name); + 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 (revision 279437) +++ head/lib/libnv/nv.h (revision 279438) @@ -1,280 +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/lib/libnv/nv_impl.h =================================================================== --- head/lib/libnv/nv_impl.h (revision 279437) +++ head/lib/libnv/nv_impl.h (revision 279438) @@ -1,126 +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/lib/libnv/nvlist.c =================================================================== --- head/lib/libnv/nvlist.c (revision 279437) +++ head/lib/libnv/nvlist.c (revision 279438) @@ -1,1915 +1,2001 @@ /*- * 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 = malloc(sizeof(*nvl)); + 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; - serrno = errno; + 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; - free(nvl); + nv_free(nvl); - errno = serrno; + 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) - errno = ENOENT; + 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; - vasprintf(&name, namefmt, nameap); + nv_vasprintf(&name, namefmt, nameap); if (name == NULL) return (false); exists = nvlist_exists_type(nvl, name, type); - free(name); + 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; - vasprintf(&name, namefmt, nameap); + nv_vasprintf(&name, namefmt, nameap); if (name == NULL) nvlist_report_missing(type, ""); nvlist_free_type(nvl, name, type); - free(name); + 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) { - errno = nvl->nvl_error; + 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 = malloc(sizeof(fds[0]) * (nitems + 1)); + 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) { - errno = nvl->nvl_error; + RESTORE_ERRNO(nvl->nvl_error); return (NULL); } size = nvlist_size(nvl); - buf = malloc(size); + 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) { - free(buf); + 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) { - free(buf); + 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) { - errno = nvl->nvl_error; + RESTORE_ERRNO(nvl->nvl_error); return (NULL); } if (nvlist_ndescriptors(nvl) > 0) { - errno = EOPNOTSUPP; + 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) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (false); } if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { - errno = EINVAL; + 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: - errno = EINVAL; + 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; - vasprintf(&name, namefmt, nameap); + nv_vasprintf(&name, namefmt, nameap); if (name == NULL) return (false); exists = nvlist_exists(nvl, name); - free(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) { - errno = nvlist_error(nvl); + RESTORE_ERRNO(nvlist_error(nvl)); return; } if (nvlist_exists(nvl, nvpair_name(nvp))) { - nvl->nvl_error = errno = EEXIST; + nvl->nvl_error = EEXIST; + RESTORE_ERRNO(nvlist_error(nvl)); return; } newnvp = nvpair_clone(nvp); if (newnvp == NULL) { - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); + 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) { - errno = nvlist_error(nvl); + RESTORE_ERRNO(nvlist_error(nvl)); return; } nvp = nvpair_create_stringv(name, valuefmt, valueap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else + 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) { - errno = nvlist_error(nvl); + RESTORE_ERRNO(nvlist_error(nvl)); return; } nvp = nvpair_createv_null(namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else + 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) { - errno = nvlist_error(nvl); + RESTORE_ERRNO(nvlist_error(nvl)); return; } nvp = nvpair_createv_bool(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else + 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) { - errno = nvlist_error(nvl); + RESTORE_ERRNO(nvlist_error(nvl)); return; } nvp = nvpair_createv_number(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else + 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) { - errno = nvlist_error(nvl); + RESTORE_ERRNO(nvlist_error(nvl)); return; } nvp = nvpair_createv_string(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else + 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) { - errno = nvlist_error(nvl); + RESTORE_ERRNO(nvlist_error(nvl)); return; } nvp = nvpair_createv_nvlist(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else + 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) { - errno = nvlist_error(nvl); + RESTORE_ERRNO(nvlist_error(nvl)); return; } nvp = nvpair_createv_binary(value, size, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else + 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); - errno = nvlist_error(nvl); + RESTORE_ERRNO(nvlist_error(nvl)); return; } if (nvlist_exists(nvl, nvpair_name(nvp))) { nvpair_free(nvp); - nvl->nvl_error = errno = EEXIST; + 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) { - free(value); - errno = nvlist_error(nvl); + nv_free(value); + RESTORE_ERRNO(nvlist_error(nvl)); return; } nvp = nvpair_movev_string(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else + 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); - errno = nvlist_error(nvl); + RESTORE_ERRNO(nvlist_error(nvl)); return; } nvp = nvpair_movev_nvlist(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else + 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) { - free(value); - errno = nvlist_error(nvl); + nv_free(value); + RESTORE_ERRNO(nvlist_error(nvl)); return; } nvp = nvpair_movev_binary(value, size, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else + 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; - vasprintf(&name, namefmt, nameap); + nv_vasprintf(&name, namefmt, nameap); if (name == NULL) nvlist_report_missing(NV_TYPE_BINARY, ""); binary = nvlist_get_binary(nvl, name, sizep); - free(name); + 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; - vasprintf(&name, namefmt, nameap); + nv_vasprintf(&name, namefmt, nameap); if (name == NULL) nvlist_report_missing(NV_TYPE_BINARY, ""); binary = nvlist_take_binary(nvl, name, sizep); - free(name); + 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 (revision 279437) +++ head/lib/libnv/nvlist_impl.h (revision 279438) @@ -1,47 +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/lib/libnv/nvpair.c =================================================================== --- head/lib/libnv/nvpair.c (revision 279437) +++ head/lib/libnv/nvpair.c (revision 279438) @@ -1,1310 +1,1349 @@ /*- * 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: - errno = EINVAL; + 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) { - errno = EINVAL; + 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)) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } if (*leftp < sizeof(value)) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } memcpy(&value, ptr, sizeof(value)); ptr += sizeof(value); *leftp -= sizeof(value); if (value != 0 && value != 1) { - errno = EINVAL; + 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)) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } if (*leftp < sizeof(uint64_t)) { - errno = EINVAL; + 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) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } if (strnlen((const char *)ptr, nvp->nvp_datasize) != nvp->nvp_datasize - 1) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } - nvp->nvp_data = (uint64_t)(uintptr_t)strdup((const char *)ptr); + 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) { - errno = EINVAL; + 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) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } - value = malloc(nvp->nvp_datasize); + 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 = calloc(1, sizeof(*nvp) + NV_NAME_MAX); + 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 = realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); + 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: - free(nvp); + 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 = vasprintf(&name, namefmt, nameap); + namelen = nv_vasprintf(&name, namefmt, nameap); if (namelen < 0) return (NULL); PJDLOG_ASSERT(namelen > 0); if (namelen >= NV_NAME_MAX) { - free(name); - errno = ENAMETOOLONG; + nv_free(name); + RESTORE_ERRNO(ENAMETOOLONG); return (NULL); } - nvp = calloc(1, sizeof(*nvp) + namelen + 1); + 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; } - free(name); + 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 = vasprintf(&str, valuefmt, valueap); + len = nv_vasprintf(&str, valuefmt, valueap); if (len < 0) return (NULL); nvp = nvpair_create_string(name, str); if (nvp == NULL) - free(str); + 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) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } - data = strdup(value); + 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) - free(data); + 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) { - errno = EINVAL; + 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) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } - data = malloc(size); + 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) - free(data); + 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) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value, strlen(value) + 1, namefmt, nameap); if (nvp == NULL) { - serrno = errno; - free(value); - errno = serrno; + 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) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } if (nvlist_error(value) != 0) { - errno = nvlist_error(value); + 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) { - errno = EINVAL; + RESTORE_ERRNO(EINVAL); return (NULL); } nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size, namefmt, nameap); if (nvp == NULL) { - serrno = errno; - free(value); - errno = serrno; + 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: - free((char *)(intptr_t)nvp->nvp_data); + nv_free((char *)(intptr_t)nvp->nvp_data); break; case NV_TYPE_BINARY: - free((void *)(intptr_t)nvp->nvp_data); + nv_free((void *)(intptr_t)nvp->nvp_data); break; } - free(nvp); + nv_free(nvp); } void nvpair_free_structure(nvpair_t *nvp) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_list == NULL); nvp->nvp_magic = 0; - free(nvp); + 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 (revision 279437) +++ head/lib/libnv/nvpair_impl.h (revision 279438) @@ -1,92 +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_ */