diff --git a/CMakeLists.txt b/CMakeLists.txt index 6921525..9a85bba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,8 +35,6 @@ set(xpc_sources xpc_private.c xpc_type.c subr_sbuf.c - subr_nvlist.c - subr_nvpair.c xpc_pipe.c reboot3.c ) diff --git a/nv.h b/nv.h deleted file mode 100644 index 22034c7..0000000 --- a/nv.h +++ /dev/null @@ -1,478 +0,0 @@ -/*- - * Copyright (c) 2009-2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _NV_H_ -#define _NV_H_ - -#include - -#ifndef _KERNEL -#include -#include -#include -#include -#include -#else -#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_STRING 3 -#define NV_TYPE_DESCRIPTOR 4 -#define NV_TYPE_BINARY 5 - -#define NV_TYPE_NUMBER 6 -#define NV_TYPE_PTR 7 -#define NV_TYPE_UINT64 8 -#define NV_TYPE_INT64 9 -#define NV_TYPE_ENDPOINT 10 -#define NV_TYPE_DATE 11 -#define NV_TYPE_UUID 12 - -#define NV_TYPE_NVLIST 13 -#define NV_TYPE_NVLIST_ARRAY 14 -#define NV_TYPE_NVLIST_DICTIONARY 15 - - -/* - * Perform case-insensitive lookups of provided names. - */ -#define NV_FLAG_IGNORE_CASE 0x01 -/* - * Names don't have to be unique. - */ -#define NV_FLAG_NO_UNIQUE 0x02 - -#if defined(_KERNEL) && defined(MALLOC_DECLARE) -MALLOC_DECLARE(M_NVLIST); -#endif - -__BEGIN_DECLS - -nvlist_t *nvlist_create(int flags); -nvlist_t *nvlist_create_array(int flags); -nvlist_t *nvlist_create_dictionary(int flags); -void nvlist_destroy(nvlist_t *nvl); -int nvlist_error(const nvlist_t *nvl); -bool nvlist_empty(const nvlist_t *nvl); -int nvlist_flags(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); -void *nvlist_pack_buffer(const nvlist_t *nvl, void *buf, 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_ptr(const nvlist_t *nvl, const char *name); -bool nvlist_exists_uint64(const nvlist_t *nvl, const char *name); -bool nvlist_exists_int64(const nvlist_t *nvl, const char *name); -bool nvlist_exists_endpoint(const nvlist_t *nvl, const char *name); -bool nvlist_exists_date(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); -bool nvlist_exists_nvlist_dictionary(const nvlist_t *nvl, const char *name); -bool nvlist_exists_nvlist_array(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); -bool nvlist_exists_uuid(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_ptr(nvlist_t *nvl, const char *name, uintptr_t value); -void nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t value); -void nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t value); -void nvlist_add_endpoint(nvlist_t *nvl, const char *name, int value); -void nvlist_add_date(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); -void nvlist_add_nvlist_dictionary(nvlist_t *nvl, const char *name, const nvlist_t *value); -void nvlist_add_nvlist_array(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); -void nvlist_add_uuid(nvlist_t *nvl, const char *name, const uuid_t *value); - -/* - * 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); -void nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t *value); -void nvlist_move_nvlist_dictionary(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); -void nvlist_move_uuid(nvlist_t *nvl, const char *name, uuid_t *value); - -/* - * 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); -uintptr_t nvlist_get_ptr(const nvlist_t *nvl, const char *name); -uint64_t nvlist_get_uint64(const nvlist_t *nvl, const char *name); -int64_t nvlist_get_int64(const nvlist_t *nvl, const char *name); -int nvlist_get_endpoint(const nvlist_t *nvl, const char *name); -uint64_t nvlist_get_date(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); -const nvlist_t *nvlist_get_nvlist_array(const nvlist_t *nvl, const char *name); -const nvlist_t *nvlist_get_nvlist_dictionary(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); -const uuid_t *nvlist_get_uuid(const nvlist_t *nvl, const char *name); - -/* - * 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); -uintptr_t nvlist_take_ptr(nvlist_t *nvl, const char *name); -uint64_t nvlist_take_uint64(nvlist_t *nvl, const char *name); -int64_t nvlist_take_int64(nvlist_t *nvl, const char *name); -int nvlist_take_endpoint(nvlist_t *nvl, const char *name); -uint64_t nvlist_take_date(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); -nvlist_t *nvlist_take_nvlist_array(nvlist_t *nvl, const char *name); -nvlist_t *nvlist_take_nvlist_dictionary(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); -uuid_t *nvlist_take_uuid(nvlist_t *nvl, const char *name); - -/* - * 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_ptr(nvlist_t *nvl, const char *name); -void nvlist_free_uint64(nvlist_t *nvl, const char *name); -void nvlist_free_int64(nvlist_t *nvl, const char *name); -void nvlist_free_endpoint(nvlist_t *nvl, const char *name); -void nvlist_free_date(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); -void nvlist_free_nvlist_array(nvlist_t *nvl, const char *name); -void nvlist_free_nvlist_dictionary(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); -void nvlist_free_uuid(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_ptr(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_uint64(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_int64(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_endpoint(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_date(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_nvlist_array(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -bool nvlist_existsf_nvlist_dictionary(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_existsf_uuid(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_ptr(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_uint64(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_int64(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_endpoint(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_date(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_nvlist_array(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -bool nvlist_existsv_nvlist_dictionary(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); -bool nvlist_existsv_uuid(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_ptr(nvlist_t *nvl, uintptr_t value, const char *namefmt, ...) __printflike(3, 4); -void nvlist_addf_uint64(nvlist_t *nvl, uint64_t value, const char *namefmt, ...) __printflike(3, 4); -void nvlist_addf_int64(nvlist_t *nvl, int64_t value, const char *namefmt, ...) __printflike(3, 4); -void nvlist_addf_endpoint(nvlist_t *nvl, int value, const char *namefmt, ...) __printflike(3, 4); -void nvlist_addf_date(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); -void nvlist_addf_nvlist_array(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, ...) __printflike(3, 4); -void nvlist_addf_nvlist_dictionary(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); -void nvlist_addf_uuid(nvlist_t *nvl, const uuid_t *value, const char *namefmt, ...) __printflike(3, 4); - -#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_ptr(nvlist_t *nvl, uintptr_t value, const char *namefmt, va_list nameap) __printflike(3, 0); -void nvlist_addv_uint64(nvlist_t *nvl, uint64_t value, const char *namefmt, va_list nameap) __printflike(3, 0); -void nvlist_addv_int64(nvlist_t *nvl, int64_t value, const char *namefmt, va_list nameap) __printflike(3, 0); -void nvlist_addv_endpoint(nvlist_t *nvl, int value, const char *namefmt, va_list nameap) __printflike(3, 0); -void nvlist_addv_date(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); -void nvlist_addv_nvlist_array(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, va_list nameap) __printflike(3, 0); -void nvlist_addv_nvlist_dictionary(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); -void nvlist_addv_uuid(nvlist_t *nvl, const uuid_t *value, const char *namefmt, va_list nameap) __printflike(3, 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); -void nvlist_movef_nvlist_array(nvlist_t *nvl, nvlist_t *value, const char *namefmt, ...) __printflike(3, 4); -void nvlist_movef_nvlist_dictionary(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); -void nvlist_movef_uuid(nvlist_t *nvl, uuid_t *value, const char *namefmt, ...) __printflike(3, 4); - -#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); -void nvlist_movev_nvlist_array(nvlist_t *nvl, nvlist_t *value, const char *namefmt, va_list nameap) __printflike(3, 0); -void nvlist_movev_nvlist_dictionary(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); -void nvlist_movev_uuid(nvlist_t *nvl, uuid_t *value, const char *namefmt, va_list nameap) __printflike(3, 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); -uintptr_t nvlist_getf_ptr(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -uint64_t nvlist_getf_uint64(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -int64_t nvlist_getf_int64(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -int nvlist_getf_endpoint(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -uint64_t nvlist_getf_date(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); -const nvlist_t *nvlist_getf_nvlist_array(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -const nvlist_t *nvlist_getf_nvlist_dictionary(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); -const uuid_t *nvlist_getf_uuid(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); - -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); -uintptr_t nvlist_getv_ptr(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -uint64_t nvlist_getv_uint64(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -int64_t nvlist_getv_int64(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -int nvlist_getv_endpoint(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -uint64_t nvlist_getv_date(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); -const nvlist_t *nvlist_getv_nvlist_array(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -const nvlist_t *nvlist_getv_nvlist_dictionary(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); -const uuid_t *nvlist_getv_uuid(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 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); -uintptr_t nvlist_takef_ptr(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -uint64_t nvlist_takef_uint64(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -int64_t nvlist_takef_int64(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -int nvlist_takef_endpoint(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -uint64_t nvlist_takef_date(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); -nvlist_t *nvlist_takef_nvlist_array(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -nvlist_t *nvlist_takef_nvlist_dictionary(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); -uuid_t *nvlist_takef_uuid(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); - -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); -uintptr_t nvlist_takev_ptr(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -uint64_t nvlist_takev_uint64(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -int64_t nvlist_takev_int64(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -int nvlist_takev_endpoint(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -uint64_t nvlist_takev_date(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); -nvlist_t *nvlist_takev_nvlist_array(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -nvlist_t *nvlist_takev_nvlist_dictionary(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); -uuid_t *nvlist_takev_uuid(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 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_ptr(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_uint64(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_int64(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_endpoint(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_date(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_nvlist_array(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); -void nvlist_freef_nvlist_dictionary(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_freef_uuid(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_ptr(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_freev_uint64(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_freev_int64(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_freev_endpoint(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_freev_date(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_nvlist_array(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -void nvlist_freev_nvlist_dictionary(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); -void nvlist_freev_uuid(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); -#endif /* _KERNEL */ - -__END_DECLS - -#endif /* !_NV_H_ */ diff --git a/nv_impl.h b/nv_impl.h deleted file mode 100644 index 6ca8972..0000000 --- a/nv_impl.h +++ /dev/null @@ -1,172 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _NV_IMPL_H_ -#define _NV_IMPL_H_ - -#ifndef _NVPAIR_T_DECLARED -#define _NVPAIR_T_DECLARED -struct nvpair; - -typedef struct nvpair nvpair_t; -#endif - -#define NV_TYPE_NVLIST_UP 255 - -#define NV_TYPE_FIRST NV_TYPE_NULL -#define NV_TYPE_LAST NV_TYPE_NVLIST_DICTIONARY - -#define NV_TYPE_NUMBER_MIN NV_TYPE_NUMBER -#define NV_TYPE_NUMBER_MAX NV_TYPE_ENDPOINT -#define NV_TYPE_NVLIST_MIN NV_TYPE_NVLIST -#define NV_TYPE_NVLIST_MAX NV_TYPE_NVLIST_DICTIONARY - - - -#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_type(const char *name, uint64_t value, int type); -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_type(const char *name, const nvlist_t *value, int type); -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_create_uuid(const char *name, const uuid_t *value); - -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_nvlist_type(const char *name, nvlist_t *value, int type); -nvpair_t *nvpair_move_descriptor(const char *name, int value); -nvpair_t *nvpair_move_binary(const char *name, void *value, size_t size); -nvpair_t *nvpair_move_uuid(const char *name, uuid_t *value); - -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); -const uuid_t *nvpair_get_uuid(const nvpair_t *nvp); - -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_type(uint64_t value, int type, const char *namefmt, ...) __printflike(3, 4); -nvpair_t *nvpair_createf_string(const char *value, const char *namefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_createf_nvlist_type(const nvlist_t *value, int type, const char *namefmt, ...) __printflike(3, 4); -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_createf_uuid(const uuid_t *value, const char *namefmt, ...) __printflike(2, 3); - -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_type(uint64_t value, int type, const char *namefmt, va_list nameap) __printflike(3, 0); -nvpair_t *nvpair_createv_string(const char *value, const char *namefmt, va_list nameap) __printflike(2, 0); -nvpair_t *nvpair_createv_nvlist_type(const nvlist_t *value, int type, const char *namefmt, va_list nameap) __printflike(3, 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_createv_uuid(const uuid_t *value, const char *namefmt, va_list nameap) __printflike(2, 0); - -nvpair_t *nvpair_movef_string(char *value, const char *namefmt, ...) __printflike(2, 3); -nvpair_t *nvpair_movef_nvlist_type(nvlist_t *value, int type, const char *namefmt, ...) __printflike(3, 4); -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_movef_uuid(uuid_t *value, const char *namefmt, ...) __printflike(2, 3); - -nvpair_t *nvpair_movev_string(char *value, const char *namefmt, va_list nameap) __printflike(2, 0); -nvpair_t *nvpair_movev_nvlist_type(nvlist_t *value, int type, const char *namefmt, va_list nameap) __printflike(3, 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); -nvpair_t *nvpair_movev_uuid(uuid_t *value, const char *namefmt, va_list nameap) __printflike(2, 0); - -#endif /* !_NV_IMPL_H_ */ diff --git a/nvlist_impl.h b/nvlist_impl.h deleted file mode 100644 index d34d0ce..0000000 --- a/nvlist_impl.h +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _NVLIST_IMPL_H_ -#define _NVLIST_IMPL_H_ - -#ifndef _KERNEL -#include -#endif - -#include "nv.h" - -void *nvlist_xpack(const nvlist_t *nvl, void *ubuf, 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_ */ diff --git a/nvpair_impl.h b/nvpair_impl.h deleted file mode 100644 index 121c8ab..0000000 --- a/nvpair_impl.h +++ /dev/null @@ -1,94 +0,0 @@ -/*- - * Copyright (c) 2009-2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _NVPAIR_IMPL_H_ -#define _NVPAIR_IMPL_H_ - -#include - -#ifndef _KERNEL -#include -#endif - -#include "nv.h" - -TAILQ_HEAD(nvl_head, nvpair); - -void nvpair_assert(const nvpair_t *nvp); -nvlist_t *nvpair_nvlist(const nvpair_t *nvp); -nvpair_t *nvpair_next(const nvpair_t *nvp); -nvpair_t *nvpair_prev(const nvpair_t *nvp); -void nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl); -void nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl); -size_t nvpair_header_size(void); -size_t nvpair_size(const nvpair_t *nvp); -const unsigned char *nvpair_unpack(bool isbe, const unsigned char *ptr, - size_t *leftp, nvpair_t **nvpp); -void nvpair_free_structure(nvpair_t *nvp); -void nvpair_init_datasize(nvpair_t *nvp); -const char *nvpair_type_string(int type); - -/* Pack functions. */ -unsigned char *nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, - size_t *leftp); -unsigned char *nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr, - size_t *leftp); -unsigned char *nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, - size_t *leftp); -unsigned char *nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, - size_t *leftp); -unsigned char *nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, - size_t *leftp); -unsigned char *nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, - int64_t *fdidxp, size_t *leftp); -unsigned char *nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, - size_t *leftp); -unsigned char *nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp); - -/* Unpack data functions. */ -const unsigned char *nvpair_unpack_header(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); -const unsigned char *nvpair_unpack_null(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); -const unsigned char *nvpair_unpack_bool(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); -const unsigned char *nvpair_unpack_number(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); -const unsigned char *nvpair_unpack_string(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); -const unsigned char *nvpair_unpack_nvlist(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp, size_t nvlist, nvlist_t **child); -const unsigned char *nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds); -const unsigned char *nvpair_unpack_binary(bool isbe, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp); - -#endif /* !_NVPAIR_IMPL_H_ */ diff --git a/subr_nvlist.c b/subr_nvlist.c deleted file mode 100644 index 56fad33..0000000 --- a/subr_nvlist.c +++ /dev/null @@ -1,2578 +0,0 @@ -/*- - * Copyright (c) 2009-2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include "endian_compat.h" -#include - -#ifdef _KERNEL - -#include -#include -#include -#include -#include - -#include - -#else -#include - -#include -#include -#include -#include -#define _WITH_DPRINTF -#include -#include -#include -#include - -//#include "msgio.h" -#endif - -#ifdef HAVE_PJDLOG -#include -#endif - -#include "nv.h" -#include "nv_impl.h" -#include "nvlist_impl.h" -#include "nvpair_impl.h" -#include "xpc_internal.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; - int nvl_type; - 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; - uint8_t nvlh_type; - uint64_t nvlh_descriptors; - uint64_t nvlh_size; -} __packed; - -nvlist_t * -nvlist_create(int flags) -{ - nvlist_t *nvl; - - PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); - - nvl = nv_malloc(sizeof(*nvl)); - nvl->nvl_error = 0; - nvl->nvl_flags = flags; - nvl->nvl_parent = NULL; - nvl->nvl_type = NV_TYPE_NVLIST; - TAILQ_INIT(&nvl->nvl_head); - nvl->nvl_magic = NVLIST_MAGIC; - - return (nvl); -} - -nvlist_t * -nvlist_create_array(int flags) -{ - nvlist_t *nvl; - - PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); - - nvl = nv_malloc(sizeof(*nvl)); - nvl->nvl_error = 0; - nvl->nvl_flags = flags; - nvl->nvl_parent = NULL; - nvl->nvl_type = NV_TYPE_NVLIST_ARRAY; - TAILQ_INIT(&nvl->nvl_head); - nvl->nvl_magic = NVLIST_MAGIC; - - return (nvl); -} - -nvlist_t * -nvlist_create_dictionary(int flags) -{ - nvlist_t *nvl; - - PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); - - nvl = nv_malloc(sizeof(*nvl)); - nvl->nvl_error = 0; - nvl->nvl_flags = flags; - nvl->nvl_parent = NULL; - nvl->nvl_type = NV_TYPE_NVLIST_DICTIONARY; - TAILQ_INIT(&nvl->nvl_head); - nvl->nvl_magic = NVLIST_MAGIC; - - debugf("1 nvl = %p\n", nvl); - return (nvl); -} - -void -nvlist_destroy(nvlist_t *nvl) -{ - nvpair_t *nvp; - int serrno; - - if (nvl == NULL) - return; - - SAVE_ERRNO(serrno); - - NVLIST_ASSERT(nvl); - - while ((nvp = nvlist_first_nvpair(nvl)) != NULL) { - nvlist_remove_nvpair(nvl, nvp); - nvpair_free(nvp); - } - nvl->nvl_magic = 0; - nv_free(nvl); - - RESTORE_ERRNO(serrno); -} - -void -nvlist_set_error(nvlist_t *nvl, int error) -{ - - PJDLOG_ASSERT(error != 0); - - /* - * Check for error != 0 so that we don't do the wrong thing if somebody - * tries to abuse this API when asserts are disabled. - */ - if (nvl != NULL && error != 0 && nvl->nvl_error == 0) - nvl->nvl_error = error; -} - -int -nvlist_error(const nvlist_t *nvl) -{ - - if (nvl == NULL) - return (ENOMEM); - - NVLIST_ASSERT(nvl); - - return (nvl->nvl_error); -} - -nvpair_t * -nvlist_get_nvpair_parent(const nvlist_t *nvl) -{ - - NVLIST_ASSERT(nvl); - - return (nvl->nvl_parent); -} - -const nvlist_t * -nvlist_get_parent(const nvlist_t *nvl, void **cookiep) -{ - nvpair_t *nvp; - - NVLIST_ASSERT(nvl); - - nvp = nvl->nvl_parent; - if (cookiep != NULL) - *cookiep = nvp; - if (nvp == NULL) - return (NULL); - - return (nvpair_nvlist(nvp)); -} - -void -nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent) -{ - - NVLIST_ASSERT(nvl); - - nvl->nvl_parent = parent; -} - -bool -nvlist_empty(const nvlist_t *nvl) -{ - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - - return (nvlist_first_nvpair(nvl) == NULL); -} - -int -nvlist_type(const nvlist_t *nvl) -{ - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - - return (nvl->nvl_type); -} - -static void -nvlist_report_missing(int type, const char *name) -{ - - PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", - name, nvpair_type_string(type)); -} - -static nvpair_t * -nvlist_find(const nvlist_t *nvl, int type, const char *name) -{ - nvpair_t *nvp; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - PJDLOG_ASSERT(type == NV_TYPE_NONE || - (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); - - for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; - nvp = nvlist_next_nvpair(nvl, nvp)) { - if (type != NV_TYPE_NONE && nvpair_type(nvp) != type) - continue; - if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) { - if (strcasecmp(nvpair_name(nvp), name) != 0) - continue; - } else { - if (strcmp(nvpair_name(nvp), name) != 0) - continue; - } - break; - } - - if (nvp == NULL) - RESTORE_ERRNO(ENOENT); - - return (nvp); -} - -bool -nvlist_exists_type(const nvlist_t *nvl, const char *name, int type) -{ - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - PJDLOG_ASSERT(type == NV_TYPE_NONE || - (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); - - return (nvlist_find(nvl, type, name) != NULL); -} - -#ifndef _KERNEL -bool -nvlist_existsf_type(const nvlist_t *nvl, int type, const char *namefmt, ...) -{ - va_list nameap; - bool ret; - - va_start(nameap, namefmt); - ret = nvlist_existsv_type(nvl, type, namefmt, nameap); - va_end(nameap); - - return (ret); -} - -bool -nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt, - va_list nameap) -{ - char *name; - bool exists; - - nv_vasprintf(&name, namefmt, nameap); - if (name == NULL) - return (false); - - exists = nvlist_exists_type(nvl, name, type); - nv_free(name); - return (exists); -} -#endif - -void -nvlist_free_type(nvlist_t *nvl, const char *name, int type) -{ - nvpair_t *nvp; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - PJDLOG_ASSERT(type == NV_TYPE_NONE || - (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); - - nvp = nvlist_find(nvl, type, name); - if (nvp != NULL) - nvlist_free_nvpair(nvl, nvp); - else - nvlist_report_missing(type, name); -} - -#ifndef _KERNEL -void -nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_freev_type(nvl, type, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap) -{ - char *name; - - nv_vasprintf(&name, namefmt, nameap); - if (name == NULL) - nvlist_report_missing(type, ""); - nvlist_free_type(nvl, name, type); - nv_free(name); -} -#endif - -nvlist_t * -nvlist_clone(const nvlist_t *nvl) -{ - nvlist_t *newnvl; - nvpair_t *nvp, *newnvp; - - NVLIST_ASSERT(nvl); - - if (nvl->nvl_error != 0) { - RESTORE_ERRNO(nvl->nvl_error); - return (NULL); - } - - newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); - newnvl->nvl_type = nvl->nvl_type; - 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: - case NV_TYPE_PTR: - case NV_TYPE_UINT64: - case NV_TYPE_INT64: - case NV_TYPE_ENDPOINT: - case NV_TYPE_DATE: - 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: - case NV_TYPE_NVLIST_ARRAY: - case NV_TYPE_NVLIST_DICTIONARY: - 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; - } - case NV_TYPE_UUID: - { - char str[40]; - int status; - const uuid_t *uuid; - - uuid = nvpair_get_uuid(nvp); - uuid_unparse(*uuid, str); - if (/*status == uuid_s_ok*/ 1) - dprintf(fd, " [%s]\n", str); - - free(str); - 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_ARRAY || - nvpair_type(nvp) == NV_TYPE_NVLIST_DICTIONARY || - 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: - case NV_TYPE_NVLIST_ARRAY: - case NV_TYPE_NVLIST_DICTIONARY: - descs = nvlist_xdescriptors(nvpair_get_nvlist(nvp), - descs, level + 1); - break; - } - } - - return (descs); -} -#endif - -#ifndef _KERNEL -int * -nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp) -{ - size_t nitems; - int *fds; - - nitems = nvlist_ndescriptors(nvl); - fds = nv_malloc(sizeof(fds[0]) * (nitems + 1)); - if (fds == NULL) - return (NULL); - if (nitems > 0) - nvlist_xdescriptors(nvl, fds, 0); - fds[nitems] = -1; - if (nitemsp != NULL) - *nitemsp = nitems; - return (fds); -} -#endif - -static size_t -nvlist_xndescriptors(const nvlist_t *nvl, int level) -{ -#ifndef _KERNEL - const nvpair_t *nvp; - size_t ndescs; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - //PJDLOG_ASSERT(level < 3); - - ndescs = 0; - for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; - nvp = nvlist_next_nvpair(nvl, nvp)) { - switch (nvpair_type(nvp)) { - case NV_TYPE_DESCRIPTOR: - ndescs++; - break; - case NV_TYPE_NVLIST: - case NV_TYPE_NVLIST_ARRAY: - case NV_TYPE_NVLIST_DICTIONARY: - 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; - nvlhdr.nvlh_type = (uint8_t)nvl->nvl_type; -#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, void *ubuf, int64_t *fdidxp, size_t *sizep) -{ - unsigned char *buf, *ptr; - size_t left, size; - const nvlist_t *tmpnvl; - nvpair_t *nvp, *tmpnvp; - void *cookie; - - NVLIST_ASSERT(nvl); - - if (nvl->nvl_error != 0) { - RESTORE_ERRNO(nvl->nvl_error); - return (NULL); - } - - size = nvlist_size(nvl); - if (ubuf) { - if (sizep == NULL || *sizep != size) - return (NULL); - else - buf = ubuf; - } else - buf = nv_malloc(size); - if (buf == NULL) - return (NULL); - - ptr = buf; - left = size; - - ptr = nvlist_pack_header(nvl, ptr, &left); - - nvp = nvlist_first_nvpair(nvl); - while (nvp != NULL) { - NVPAIR_ASSERT(nvp); - - nvpair_init_datasize(nvp); - ptr = nvpair_pack_header(nvp, ptr, &left); - if (ptr == NULL) { - nv_free(buf); - return (NULL); - } - switch (nvpair_type(nvp)) { - case NV_TYPE_NULL: - ptr = nvpair_pack_null(nvp, ptr, &left); - break; - case NV_TYPE_BOOL: - ptr = nvpair_pack_bool(nvp, ptr, &left); - break; - case NV_TYPE_NUMBER: - case NV_TYPE_PTR: - case NV_TYPE_UINT64: - case NV_TYPE_INT64: - case NV_TYPE_ENDPOINT: - ptr = nvpair_pack_number(nvp, ptr, &left); - break; - case NV_TYPE_STRING: - ptr = nvpair_pack_string(nvp, ptr, &left); - break; - case NV_TYPE_NVLIST: - case NV_TYPE_NVLIST_ARRAY: - case NV_TYPE_NVLIST_DICTIONARY: - 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: - case NV_TYPE_UUID: - ptr = nvpair_pack_binary(nvp, ptr, &left); - break; - default: - PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); - } - if (ptr == NULL) { - nv_free(buf); - return (NULL); - } - while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { - cookie = NULL; - nvl = nvlist_get_parent(nvl, &cookie); - if (nvl == NULL) - goto out; - nvp = cookie; - ptr = nvpair_pack_nvlist_up(ptr, &left); - if (ptr == NULL) - goto out; - } - } - -out: - if (sizep != NULL) - *sizep = size; - return (buf); -} - -void * -nvlist_pack(const nvlist_t *nvl, size_t *sizep) -{ - - return (nvlist_pack_buffer(nvl, NULL, sizep)); -} - -void * -nvlist_pack_buffer(const nvlist_t *nvl, void *ubuf, size_t *sizep) -{ - - NVLIST_ASSERT(nvl); - - if (nvl->nvl_error != 0) { - RESTORE_ERRNO(nvl->nvl_error); - return (NULL); - } - - if (nvlist_ndescriptors(nvl) > 0) { - RESTORE_ERRNO(EOPNOTSUPP); - return (NULL); - } - - return (nvlist_xpack(nvl, ubuf, NULL, sizep)); -} - -static bool -nvlist_check_header(struct nvlist_header *nvlhdrp) -{ - - if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { - RESTORE_ERRNO(EINVAL); - return (false); - } - if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { - RESTORE_ERRNO(EINVAL); - return (false); - } -#if BYTE_ORDER == BIG_ENDIAN - if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) { - nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size); - nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors); - } -#else - if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) { - nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size); - nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors); - } -#endif - return (true); -} - -const unsigned char * -nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds, - bool *isbep, size_t *leftp) -{ - struct nvlist_header nvlhdr; - - if (*leftp < sizeof(nvlhdr)) - goto failed; - - memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); - - if (!nvlist_check_header(&nvlhdr)) - goto failed; - - if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) - goto failed; - - /* - * nvlh_descriptors might be smaller than nfds in embedded nvlists. - */ - if (nvlhdr.nvlh_descriptors > nfds) - goto failed; - - if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) - goto failed; - - nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK); - - ptr += sizeof(nvlhdr); - if (isbep != NULL) - *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0); - *leftp -= sizeof(nvlhdr); - - nvl->nvl_type = nvlhdr.nvlh_type; - return (ptr); -failed: - RESTORE_ERRNO(EINVAL); - return (NULL); -} - -nvlist_t * -nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds) -{ - const unsigned char *ptr; - nvlist_t *nvl, *retnvl, *tmpnvl; - nvpair_t *nvp; - size_t left; - bool isbe; - - left = size; - ptr = buf; - - tmpnvl = NULL; - nvl = retnvl = nvlist_create(0); - if (nvl == NULL) - goto failed; - - ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); - if (ptr == NULL) - goto failed; - - while (left > 0) { - ptr = nvpair_unpack(isbe, ptr, &left, &nvp); - if (ptr == NULL) - goto failed; - switch (nvpair_type(nvp)) { - case NV_TYPE_NULL: - ptr = nvpair_unpack_null(isbe, nvp, ptr, &left); - break; - case NV_TYPE_BOOL: - ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left); - break; - case NV_TYPE_NUMBER: - case NV_TYPE_PTR: - case NV_TYPE_UINT64: - case NV_TYPE_INT64: - case NV_TYPE_ENDPOINT: - 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: - case NV_TYPE_NVLIST_ARRAY: - case NV_TYPE_NVLIST_DICTIONARY: - 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: - case NV_TYPE_UUID: - 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, NULL, &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(ptr, PTR) -NVLIST_EXISTS(uint64, UINT64) -NVLIST_EXISTS(int64, INT64) -NVLIST_EXISTS(endpoint, ENDPOINT) -NVLIST_EXISTS(date, DATE) -NVLIST_EXISTS(string, STRING) -NVLIST_EXISTS(nvlist, NVLIST) -#ifndef _KERNEL -NVLIST_EXISTS(descriptor, DESCRIPTOR) -#endif -NVLIST_EXISTS(binary, BINARY) -NVLIST_EXISTS(uuid, UUID) - -#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(ptr) -NVLIST_EXISTSF(uint64) -NVLIST_EXISTSF(int64) -NVLIST_EXISTSF(endpoint) -NVLIST_EXISTSF(date) -NVLIST_EXISTSF(string) -NVLIST_EXISTSF(nvlist) -#ifndef _KERNEL -NVLIST_EXISTSF(descriptor) -#endif -NVLIST_EXISTSF(binary) -NVLIST_EXISTSF(uuid) - -#undef NVLIST_EXISTSF - -bool -nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap) -{ - char *name; - bool exists; - - nv_vasprintf(&name, namefmt, nameap); - if (name == NULL) - return (false); - - exists = nvlist_exists(nvl, name); - nv_free(name); - return (exists); -} - -#define NVLIST_EXISTSV(type) \ -bool \ -nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \ - va_list nameap) \ -{ \ - char *name; \ - bool exists; \ - \ - vasprintf(&name, namefmt, nameap); \ - if (name == NULL) \ - return (false); \ - exists = nvlist_exists_##type(nvl, name); \ - free(name); \ - return (exists); \ -} - -NVLIST_EXISTSV(null) -NVLIST_EXISTSV(bool) -NVLIST_EXISTSV(number) -NVLIST_EXISTSV(ptr) -NVLIST_EXISTSV(uint64) -NVLIST_EXISTSV(int64) -NVLIST_EXISTSV(endpoint) -NVLIST_EXISTSV(date) -NVLIST_EXISTSV(string) -NVLIST_EXISTSV(nvlist) -NVLIST_EXISTSV(descriptor) -NVLIST_EXISTSV(binary) -NVLIST_EXISTSV(uuid) - -#undef NVLIST_EXISTSV -#endif - -void -nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) -{ - nvpair_t *newnvp; - - NVPAIR_ASSERT(nvp); - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - if (nvlist_exists(nvl, nvpair_name(nvp))) { - nvl->nvl_error = EEXIST; - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - newnvp = nvpair_clone(nvp); - if (newnvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvpair_insert(&nvl->nvl_head, newnvp, nvl); -} - -void -nvlist_add_null(nvlist_t *nvl, const char *name) -{ - - nvlist_addf_null(nvl, "%s", name); -} - -void -nvlist_add_bool(nvlist_t *nvl, const char *name, bool value) -{ - - nvlist_addf_bool(nvl, value, "%s", name); -} - -void -nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value) -{ - - nvlist_addf_number(nvl, value, "%s", name); -} - -void -nvlist_add_ptr(nvlist_t *nvl, const char *name, uintptr_t value) -{ - - nvlist_addf_ptr(nvl, value, "%s", name); -} - -void -nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t value) -{ - - nvlist_addf_uint64(nvl, value, "%s", name); -} - -void -nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t value) -{ - - nvlist_addf_int64(nvl, value, "%s", name); -} - -void -nvlist_add_endpoint(nvlist_t *nvl, const char *name, int value) -{ - - nvlist_addf_endpoint(nvl, value, "%s", name); -} - -void -nvlist_add_date(nvlist_t *nvl, const char *name, uint64_t value) -{ - - nvlist_addf_date(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_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, - va_list valueap); - -void -nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) -{ - va_list valueap; - - va_start(valueap, valuefmt); - nvlist_add_stringv(nvl, name, valuefmt, valueap); - va_end(valueap); -} - -void -nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, - va_list valueap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_create_stringv(name, valuefmt, valueap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value) -{ - - nvlist_addf_nvlist(nvl, value, "%s", name); -} - -void -nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, const nvlist_t *value) -{ - - nvlist_addf_nvlist_array(nvl, value, "%s", name); -} - -void -nvlist_add_nvlist_dictionary(nvlist_t *nvl, const char *name, const nvlist_t *value) -{ - - nvlist_addf_nvlist_dictionary(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_add_uuid(nvlist_t *nvl, const char *name, const uuid_t *value) -{ - - nvlist_addf_uuid(nvl, value, "%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_ptr(nvlist_t *nvl, uintptr_t value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_ptr(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addf_uint64(nvlist_t *nvl, uint64_t value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_uint64(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addf_int64(nvlist_t *nvl, int64_t value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_int64(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addf_endpoint(nvlist_t *nvl, int value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_endpoint(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addf_date(nvlist_t *nvl, uint64_t value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_date(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); -} - -void -nvlist_addf_nvlist_array(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, - ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_nvlist_array(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addf_nvlist_dictionary(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, - ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_nvlist_dictionary(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_addf_uuid(nvlist_t *nvl, const uuid_t *value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_addv_uuid(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_addv_null(nvlist_t *nvl, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_null(namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_bool(nvlist_t *nvl, bool value, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_bool(value, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_number(nvlist_t *nvl, uint64_t value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_number_type(value, NV_TYPE_NUMBER, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_ptr(nvlist_t *nvl, uintptr_t value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_number_type(value, NV_TYPE_PTR, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_uint64(nvlist_t *nvl, uint64_t value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_number_type(value, NV_TYPE_UINT64, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_int64(nvlist_t *nvl, int64_t value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_number_type(value, NV_TYPE_INT64, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_endpoint(nvlist_t *nvl, int value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_number_type(value, NV_TYPE_ENDPOINT, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_date(nvlist_t *nvl, uint64_t value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_number_type(value, NV_TYPE_DATE, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_string(nvlist_t *nvl, const char *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_string(value, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_nvlist(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_nvlist_type(value, NV_TYPE_NVLIST, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_nvlist_array(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_nvlist_type(value, NV_TYPE_NVLIST_ARRAY, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_nvlist_dictionary(nvlist_t *nvl, const nvlist_t *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_nvlist_type(value, NV_TYPE_NVLIST_DICTIONARY, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -#ifndef _KERNEL -void -nvlist_addv_descriptor(nvlist_t *nvl, int value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - errno = nvlist_error(nvl); - return; - } - - nvp = nvpair_createv_descriptor(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else - nvlist_move_nvpair(nvl, nvp); -} -#endif - -void -nvlist_addv_binary(nvlist_t *nvl, const void *value, size_t size, - const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - debugf("nvlist_error = %d\n", nvlist_error(nvl)); - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_binary(value, size, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_addv_uuid(nvlist_t *nvl, const uuid_t *value, - const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_createv_uuid(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); - - if (nvlist_error(nvl) != 0) { - nvpair_free(nvp); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - if (nvlist_exists(nvl, nvpair_name(nvp))) { - nvpair_free(nvp); - nvl->nvl_error = EEXIST; - RESTORE_ERRNO(nvl->nvl_error); - return; - } - - nvpair_insert(&nvl->nvl_head, nvp, nvl); -} - -#define NVLIST_MOVE(vtype, type) \ -void \ -nvlist_move_##type(nvlist_t *nvl, const char *name, vtype value) \ -{ \ - \ - nvlist_movef_##type(nvl, value, "%s", name); \ -} - -NVLIST_MOVE(char *, string) -NVLIST_MOVE(nvlist_t *, nvlist) -NVLIST_MOVE(nvlist_t *, nvlist_array) -NVLIST_MOVE(nvlist_t *, nvlist_dictionary) -#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); -} - -void -nvlist_move_uuid(nvlist_t *nvl, const char *name, uuid_t *value) -{ - - nvlist_movef_binary(nvl, value, sizeof(uuid_t), "%s", name); -} - -#define NVLIST_MOVEF(vtype, type) \ -void \ -nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt, \ - ...) \ -{ \ - va_list nameap; \ - \ - va_start(nameap, namefmt); \ - nvlist_movev_##type(nvl, value, namefmt, nameap); \ - va_end(nameap); \ -} - -NVLIST_MOVEF(char *, string) -NVLIST_MOVEF(nvlist_t *, nvlist) -NVLIST_MOVEF(nvlist_t *, nvlist_array) -NVLIST_MOVEF(nvlist_t *, nvlist_dictionary) -#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_movef_uuid(nvlist_t *nvl, uuid_t *value, const char *namefmt, ...) -{ - va_list nameap; - - va_start(nameap, namefmt); - nvlist_movev_uuid(nvl, value, namefmt, nameap); - va_end(nameap); -} - -void -nvlist_movev_string(nvlist_t *nvl, char *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - nv_free(value); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_movev_string(value, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) - nvlist_destroy(value); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_movev_nvlist_type(value, NV_TYPE_NVLIST, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_movev_nvlist_array(nvlist_t *nvl, nvlist_t *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) - nvlist_destroy(value); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_movev_nvlist_type(value, NV_TYPE_NVLIST_ARRAY, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_movev_nvlist_dictionary(nvlist_t *nvl, nvlist_t *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) - nvlist_destroy(value); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_movev_nvlist_type(value, NV_TYPE_NVLIST_DICTIONARY, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -#ifndef _KERNEL -void -nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - close(value); - errno = nvlist_error(nvl); - return; - } - - nvp = nvpair_movev_descriptor(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - else - nvlist_move_nvpair(nvl, nvp); -} -#endif - -void -nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, - const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - nv_free(value); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_movev_binary(value, size, namefmt, nameap); - if (nvp == NULL) { - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - RESTORE_ERRNO(nvl->nvl_error); - } else - nvlist_move_nvpair(nvl, nvp); -} - -void -nvlist_movev_uuid(nvlist_t *nvl, uuid_t *value, -const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (nvlist_error(nvl) != 0) { - nv_free(value); - RESTORE_ERRNO(nvlist_error(nvl)); - return; - } - - nvp = nvpair_movev_uuid(value, namefmt, nameap); - if (nvp == NULL) - nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); - 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, acc_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 ((ftype)nvpair_get_##acc_type(nvp)); \ -} - -NVLIST_GET(bool, bool, bool, BOOL) -NVLIST_GET(uint64_t, number, number, NUMBER) -NVLIST_GET(uintptr_t, ptr, number, PTR) -NVLIST_GET(uint64_t, uint64, number, UINT64) -NVLIST_GET(int64_t, int64, number, INT64) -NVLIST_GET(int, endpoint, number, ENDPOINT) -NVLIST_GET(uint64_t, date, number, DATE) -NVLIST_GET(const char *, string, string, STRING) -NVLIST_GET(const nvlist_t *, nvlist, nvlist, NVLIST) -NVLIST_GET(const nvlist_t *, nvlist_array, nvlist, NVLIST_ARRAY) -NVLIST_GET(const nvlist_t *, nvlist_dictionary, nvlist, NVLIST_DICTIONARY) -#ifndef _KERNEL -NVLIST_GET(int, descriptor, descriptor, DESCRIPTOR) -#endif -NVLIST_GET(const uuid_t *, uuid, uuid, UUID) - -#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(uintptr_t, ptr) -NVLIST_GETF(uint64_t, uint64) -NVLIST_GETF(int64_t, int64) -NVLIST_GETF(int, endpoint) -NVLIST_GETF(uint64_t, date) -NVLIST_GETF(const char *, string) -NVLIST_GETF(const nvlist_t *, nvlist) -NVLIST_GETF(const nvlist_t *, nvlist_array) -NVLIST_GETF(const nvlist_t *, nvlist_dictionary) -NVLIST_GETF(int, descriptor) -NVLIST_GETF(const uuid_t *, uuid) - -#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(uintptr_t, ptr, PTR) -NVLIST_GETV(uint64_t, uint64, UINT64) -NVLIST_GETV(int64_t, int64, INT64) -NVLIST_GETV(int, endpoint, ENDPOINT) -NVLIST_GETV(uint64_t, date, DATE) -NVLIST_GETV(const char *, string, STRING) -NVLIST_GETV(const nvlist_t *, nvlist, NVLIST) -NVLIST_GETV(const nvlist_t *, nvlist_array, NVLIST_ARRAY) -NVLIST_GETV(const nvlist_t *, nvlist_dictionary, NVLIST_DICTIONARY) -NVLIST_GETV(int, descriptor, DESCRIPTOR) -NVLIST_GETV(const uuid_t *, uuid, UUID) - -#undef NVLIST_GETV - -const void * -nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, - va_list nameap) -{ - char *name; - const void *binary; - - nv_vasprintf(&name, namefmt, nameap); - if (name == NULL) - nvlist_report_missing(NV_TYPE_BINARY, ""); - - binary = nvlist_get_binary(nvl, name, sizep); - nv_free(name); - return (binary); -} -#endif - -#define NVLIST_TAKE(ftype, type, acc_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_##acc_type(nvp); \ - nvlist_remove_nvpair(nvl, nvp); \ - nvpair_free_structure(nvp); \ - return (value); \ -} - -NVLIST_TAKE(bool, bool, bool, BOOL) -NVLIST_TAKE(uint64_t, number, number, NUMBER) -NVLIST_TAKE(uintptr_t, ptr, number, PTR) -NVLIST_TAKE(uint64_t, uint64, number, UINT64) -NVLIST_TAKE(int64_t, int64, number, INT64) -NVLIST_TAKE(int, endpoint, number, ENDPOINT) -NVLIST_TAKE(uint64_t, date, number, DATE) -NVLIST_TAKE(char *, string, string, STRING) -NVLIST_TAKE(nvlist_t *, nvlist, nvlist, NVLIST) -NVLIST_TAKE(nvlist_t *, nvlist_array, nvlist, NVLIST_ARRAY) -NVLIST_TAKE(nvlist_t *, nvlist_dictionary, nvlist, NVLIST_DICTIONARY) -#ifndef _KERNEL -NVLIST_TAKE(int, descriptor, descriptor, DESCRIPTOR) -#endif -NVLIST_TAKE(uuid_t *, uuid, uuid, UUID) - -#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(uintptr_t, ptr) -NVLIST_TAKEF(uint64_t, uint64) -NVLIST_TAKEF(int64_t, int64) -NVLIST_TAKEF(int, endpoint) -NVLIST_TAKEF(uint64_t, date) -NVLIST_TAKEF(char *, string) -NVLIST_TAKEF(nvlist_t *, nvlist) -NVLIST_TAKEF(nvlist_t *, nvlist_array) -NVLIST_TAKEF(nvlist_t *, nvlist_dictionary) -NVLIST_TAKEF(int, descriptor) -NVLIST_TAKEF(uuid_t *, uuid) - -#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, acc_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, BOOL) -NVLIST_TAKEV(uint64_t, number, number, NUMBER) -NVLIST_TAKEV(uintptr_t, ptr, number, PTR) -NVLIST_TAKEV(uint64_t, uint64, number, UINT64) -NVLIST_TAKEV(int64_t, int64, number, INT64) -NVLIST_TAKEV(int, endpoint, number, ENDPOINT) -NVLIST_TAKEV(uint64_t, date, number, DATE) -NVLIST_TAKEV(char *, string, string, STRING) -NVLIST_TAKEV(nvlist_t *, nvlist, nvlist, NVLIST) -NVLIST_TAKEV(nvlist_t *, nvlist_array, nvlist, NVLIST_ARRAY) -NVLIST_TAKEV(nvlist_t *, nvlist_dictionary, nvlist, NVLIST_DICTIONARY) -NVLIST_TAKEV(int, descriptor, descriptor, DESCRIPTOR) -NVLIST_TAKEV(uuid_t *, uuid, uuid, UUID) - -#undef NVLIST_TAKEV - -void * -nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, - va_list nameap) -{ - char *name; - void *binary; - - nv_vasprintf(&name, namefmt, nameap); - if (name == NULL) - nvlist_report_missing(NV_TYPE_BINARY, ""); - - binary = nvlist_take_binary(nvl, name, sizep); - nv_free(name); - return (binary); -} -#endif - -void -nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) -{ - - NVLIST_ASSERT(nvl); - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); - - nvpair_remove(&nvl->nvl_head, nvp, nvl); -} - -void -nvlist_free(nvlist_t *nvl, const char *name) -{ - - nvlist_free_type(nvl, name, NV_TYPE_NONE); -} - -#define NVLIST_FREE(type, TYPE) \ -void \ -nvlist_free_##type(nvlist_t *nvl, const char *name) \ -{ \ - \ - nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ -} - -NVLIST_FREE(null, NULL) -NVLIST_FREE(bool, BOOL) -NVLIST_FREE(number, NUMBER) -NVLIST_FREE(ptr, PTR) -NVLIST_FREE(uint64, UINT64) -NVLIST_FREE(int64, INT64) -NVLIST_FREE(endpoint, ENDPOINT) -NVLIST_FREE(date, DATE) -NVLIST_FREE(string, STRING) -NVLIST_FREE(nvlist, NVLIST) -NVLIST_FREE(nvlist_array, NVLIST_ARRAY) -NVLIST_FREE(nvlist_dictionary, NVLIST_DICTIONARY) -#ifndef _KERNEL -NVLIST_FREE(descriptor, DESCRIPTOR) -#endif -NVLIST_FREE(binary, BINARY) -NVLIST_FREE(uuid, UUID) - -#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(ptr) -NVLIST_FREEF(uint64) -NVLIST_FREEF(int64) -NVLIST_FREEF(endpoint) -NVLIST_FREEF(date) -NVLIST_FREEF(string) -NVLIST_FREEF(nvlist) -NVLIST_FREEF(nvlist_array) -NVLIST_FREEF(nvlist_dictionary) -NVLIST_FREEF(descriptor) -NVLIST_FREEF(binary) -NVLIST_FREEF(uuid) - -#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(ptr, PTR) -NVLIST_FREEV(uint64, UINT64) -NVLIST_FREEV(int64, INT64) -NVLIST_FREEV(endpoint, ENDPOINT) -NVLIST_FREEV(date, DATE) -NVLIST_FREEV(string, STRING) -NVLIST_FREEV(nvlist, NVLIST) -NVLIST_FREEV(nvlist_array, NVLIST_ARRAY) -NVLIST_FREEV(nvlist_dictionary, NVLIST_DICTIONARY) -NVLIST_FREEV(descriptor, DESCRIPTOR) -NVLIST_FREEV(binary, BINARY) -NVLIST_FREEV(uuid, UUID) -#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); -} diff --git a/subr_nvpair.c b/subr_nvpair.c deleted file mode 100644 index adcab22..0000000 --- a/subr_nvpair.c +++ /dev/null @@ -1,1506 +0,0 @@ -/*- - * Copyright (c) 2009-2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include "endian_compat.h" -#include - -#ifdef _KERNEL - -#include -#include -#include -#include - -#include - -#else -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common_impl.h" -#endif - -#ifdef HAVE_PJDLOG -#include -#endif - -#include "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_type(nvp) == NV_TYPE_NVLIST_ARRAY || - nvpair_type(nvp) == NV_TYPE_NVLIST_DICTIONARY) - 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: - case NV_TYPE_PTR: - case NV_TYPE_UINT64: - case NV_TYPE_INT64: - case NV_TYPE_ENDPOINT: - newnvp = nvpair_create_number_type(name, nvpair_get_number(nvp), nvpair_type(nvp)); - break; - case NV_TYPE_STRING: - newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); - break; - case NV_TYPE_NVLIST: - case NV_TYPE_NVLIST_ARRAY: - case NV_TYPE_NVLIST_DICTIONARY: - newnvp = nvpair_create_nvlist_type(name, nvpair_get_nvlist(nvp), nvpair_type(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; - case NV_TYPE_UUID: - data = nvpair_get_uuid(nvp); - newnvp = nvpair_create_uuid(name, data); - 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 || - nvp->nvp_type == NV_TYPE_PTR || - nvp->nvp_type == NV_TYPE_UINT64 || - nvp->nvp_type == NV_TYPE_INT64 || - nvp->nvp_type == NV_TYPE_ENDPOINT || - nvp->nvp_type == NV_TYPE_DATE - ); - - 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_ARRAY || - nvp->nvp_type == NV_TYPE_NVLIST_DICTIONARY || - nvp->nvp_type == NV_TYPE_NVLIST) { - if (nvp->nvp_data == 0) { - nvp->nvp_datasize = 0; - } else { - nvp->nvp_datasize = - nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); - } - } -} - -const unsigned char * -nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr, - size_t *leftp) -{ - struct nvpair_header nvphdr; - - if (*leftp < sizeof(nvphdr)) - goto failed; - - memcpy(&nvphdr, ptr, sizeof(nvphdr)); - ptr += sizeof(nvphdr); - *leftp -= sizeof(nvphdr); - -#if NV_TYPE_FIRST > 0 - if (nvphdr.nvph_type < NV_TYPE_FIRST) - goto failed; -#endif - if (nvphdr.nvph_type > NV_TYPE_LAST && - nvphdr.nvph_type != NV_TYPE_NVLIST_UP) { - goto failed; - } - -#if BYTE_ORDER == BIG_ENDIAN - if (!isbe) { - nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize); - nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize); - } -#else - if (isbe) { - nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize); - nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize); - } -#endif - - if (nvphdr.nvph_namesize > NV_NAME_MAX) - goto failed; - if (*leftp < nvphdr.nvph_namesize) - goto failed; - if (nvphdr.nvph_namesize < 1) - goto failed; - if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != - (size_t)(nvphdr.nvph_namesize - 1)) { - goto failed; - } - - memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); - ptr += nvphdr.nvph_namesize; - *leftp -= nvphdr.nvph_namesize; - - if (*leftp < nvphdr.nvph_datasize) - goto failed; - - nvp->nvp_type = nvphdr.nvph_type; - nvp->nvp_data = 0; - nvp->nvp_datasize = nvphdr.nvph_datasize; - - return (ptr); -failed: - RESTORE_ERRNO(EINVAL); - return (NULL); -} - -const unsigned char * -nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, - size_t *leftp __unused) -{ - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); - - if (nvp->nvp_datasize != 0) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - return (ptr); -} - -const unsigned char * -nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, - size_t *leftp) -{ - uint8_t value; - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); - - if (nvp->nvp_datasize != sizeof(value)) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - if (*leftp < sizeof(value)) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - memcpy(&value, ptr, sizeof(value)); - ptr += sizeof(value); - *leftp -= sizeof(value); - - if (value != 0 && value != 1) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - nvp->nvp_data = (uint64_t)value; - - return (ptr); -} - -const unsigned char * -nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr, - size_t *leftp) -{ - - PJDLOG_ASSERT( - nvp->nvp_type == NV_TYPE_NUMBER || - nvp->nvp_type == NV_TYPE_PTR || - nvp->nvp_type == NV_TYPE_UINT64 || - nvp->nvp_type == NV_TYPE_INT64 || - nvp->nvp_type == NV_TYPE_ENDPOINT || - nvp->nvp_type == NV_TYPE_DATE - ); - - if (nvp->nvp_datasize != sizeof(uint64_t)) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - if (*leftp < sizeof(uint64_t)) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - if (isbe) - nvp->nvp_data = be64dec(ptr); - else - nvp->nvp_data = le64dec(ptr); - ptr += sizeof(uint64_t); - *leftp -= sizeof(uint64_t); - - return (ptr); -} - -const unsigned char * -nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp) -{ - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); - - if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - if (strnlen((const char *)ptr, nvp->nvp_datasize) != - nvp->nvp_datasize - 1) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr); - if (nvp->nvp_data == 0) - return (NULL); - - ptr += nvp->nvp_datasize; - *leftp -= nvp->nvp_datasize; - - return (ptr); -} - -const unsigned char * -nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp, - const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child) -{ - nvlist_t *value; - - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST || - nvp->nvp_type == NV_TYPE_NVLIST_ARRAY || - nvp->nvp_type == NV_TYPE_NVLIST_DICTIONARY); - - if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - switch (nvp->nvp_type) { - case NV_TYPE_NVLIST: - value = nvlist_create(0); - break; - case NV_TYPE_NVLIST_ARRAY: - value = nvlist_create_array(0); - break; - case NV_TYPE_NVLIST_DICTIONARY: - value = nvlist_create_dictionary(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) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - value = nv_malloc(nvp->nvp_datasize); - if (value == NULL) - return (NULL); - - memcpy(value, ptr, nvp->nvp_datasize); - ptr += nvp->nvp_datasize; - *leftp -= nvp->nvp_datasize; - - nvp->nvp_data = (uint64_t)(uintptr_t)value; - - return (ptr); -} - -const unsigned char * -nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp, - nvpair_t **nvpp) -{ - nvpair_t *nvp, *tmp; - - nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX); - if (nvp == NULL) - return (NULL); - nvp->nvp_name = (char *)(nvp + 1); - - ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp); - if (ptr == NULL) - goto failed; - tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); - if (tmp == NULL) - goto failed; - nvp = tmp; - - /* Update nvp_name after realloc(). */ - nvp->nvp_name = (char *)(nvp + 1); - nvp->nvp_data = 0x00; - nvp->nvp_magic = NVPAIR_MAGIC; - *nvpp = nvp; - return (ptr); -failed: - nv_free(nvp); - return (NULL); -} - -int -nvpair_type(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - - return (nvp->nvp_type); -} - -const char * -nvpair_name(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - - return (nvp->nvp_name); -} - -static nvpair_t * -nvpair_allocv(int type, uint64_t data, size_t datasize, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - char *name; - int namelen; - - PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); - - namelen = nv_vasprintf(&name, namefmt, nameap); - if (namelen < 0) - return (NULL); - - PJDLOG_ASSERT(namelen > 0); - if (namelen >= NV_NAME_MAX) { - nv_free(name); - RESTORE_ERRNO(ENAMETOOLONG); - return (NULL); - } - - nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1); - if (nvp != NULL) { - nvp->nvp_name = (char *)(nvp + 1); - memcpy(nvp->nvp_name, name, namelen + 1); - nvp->nvp_type = type; - nvp->nvp_data = data; - nvp->nvp_datasize = datasize; - nvp->nvp_magic = NVPAIR_MAGIC; - } - nv_free(name); - - return (nvp); -}; - -nvpair_t * -nvpair_create_null(const char *name) -{ - - return (nvpair_createf_null("%s", name)); -} - -nvpair_t * -nvpair_create_bool(const char *name, bool value) -{ - - return (nvpair_createf_bool(value, "%s", name)); -} - -nvpair_t * -nvpair_create_number_type(const char *name, uint64_t value, int type) -{ - - return (nvpair_createf_number_type(value, type, "%s", name)); -} - -nvpair_t * -nvpair_create_string(const char *name, const char *value) -{ - - return (nvpair_createf_string(value, "%s", name)); -} - -nvpair_t * -nvpair_create_stringf(const char *name, const char *valuefmt, ...) -{ - va_list valueap; - nvpair_t *nvp; - - va_start(valueap, valuefmt); - nvp = nvpair_create_stringv(name, valuefmt, valueap); - va_end(valueap); - - return (nvp); -} - -nvpair_t * -nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) -{ - nvpair_t *nvp; - char *str; - int len; - - len = nv_vasprintf(&str, valuefmt, valueap); - if (len < 0) - return (NULL); - nvp = nvpair_create_string(name, str); - if (nvp == NULL) - nv_free(str); - return (nvp); -} - -nvpair_t * -nvpair_create_nvlist_type(const char *name, const nvlist_t *value, int type) -{ - - return (nvpair_createf_nvlist_type(value, type, "%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_create_uuid(const char *name, const uuid_t *value) -{ - - return (nvpair_createf_uuid(value, "%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_type(uint64_t value, int type, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_createv_number_type(value, type, 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_type(const nvlist_t *value, int type, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_createv_nvlist_type(value, type, 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_createf_uuid(const uuid_t *value, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_createv_uuid(value, 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_type(uint64_t value, int type, const char *namefmt, va_list nameap) -{ - if (type > NV_TYPE_NUMBER_MAX || type < NV_TYPE_NUMBER_MIN) - return (NULL); - - return (nvpair_allocv(type, value, sizeof(value), namefmt, - nameap)); -} - -nvpair_t * -nvpair_createv_string(const char *value, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - size_t size; - char *data; - - if (value == NULL) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - data = nv_strdup(value); - if (data == NULL) - return (NULL); - size = strlen(value) + 1; - - nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)data, size, - namefmt, nameap); - if (nvp == NULL) - nv_free(data); - - return (nvp); -} - -nvpair_t * -nvpair_createv_nvlist_type(const nvlist_t *value, int type, const char *namefmt, - va_list nameap) -{ - nvlist_t *nvl; - nvpair_t *nvp; - - if (value == NULL) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - nvl = nvlist_clone(value); - if (nvl == NULL) - return (NULL); - - nvp = nvpair_allocv(type, (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) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - data = nv_malloc(size); - if (data == NULL) - return (NULL); - memcpy(data, value, size); - - nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, size, - namefmt, nameap); - if (nvp == NULL) - nv_free(data); - - return (nvp); -} - -nvpair_t * -nvpair_createv_uuid(const uuid_t *value, const char *namefmt, - va_list nameap) -{ - nvpair_t *nvp; - void *data; - size_t size; - - size = sizeof(uuid_t); - - if (value == NULL) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - data = nv_malloc(size); - if (data == NULL) - return (NULL); - memcpy(data, value, size); - - nvp = nvpair_allocv(NV_TYPE_UUID, (uint64_t)(uintptr_t)data, size, - namefmt, nameap); - if (nvp == NULL) - nv_free(data); - - return (nvp); -} - -nvpair_t * -nvpair_move_string(const char *name, char *value) -{ - - return (nvpair_movef_string(value, "%s", name)); -} - -nvpair_t * -nvpair_move_nvlist(const char *name, nvlist_t *value) -{ - - return (nvpair_movef_nvlist_type(value, NV_TYPE_NVLIST, "%s", name)); -} - -nvpair_t * -nvpair_move_nvlist_type(const char *name, nvlist_t *value, int type) -{ - - return (nvpair_movef_nvlist_type(value, type, "%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_type(nvlist_t *value, int type, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_movev_nvlist_type(value, type, 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_movef_uuid(uuid_t *value, const char *namefmt, ...) -{ - va_list nameap; - nvpair_t *nvp; - - va_start(nameap, namefmt); - nvp = nvpair_movev_uuid(value, namefmt, nameap); - va_end(nameap); - - return (nvp); -} - -nvpair_t * -nvpair_movev_string(char *value, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - int serrno; - - if (value == NULL) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value, - strlen(value) + 1, namefmt, nameap); - if (nvp == NULL) { - SAVE_ERRNO(serrno); - nv_free(value); - RESTORE_ERRNO(serrno); - } - - return (nvp); -} - -nvpair_t * -nvpair_movev_nvlist_type(nvlist_t *value, int type, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - if (nvlist_error(value) != 0) { - RESTORE_ERRNO(nvlist_error(value)); - nvlist_destroy(value); - return (NULL); - } - - nvp = nvpair_allocv(type, (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) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size, - namefmt, nameap); - if (nvp == NULL) { - SAVE_ERRNO(serrno); - nv_free(value); - RESTORE_ERRNO(serrno); - } - - return (nvp); -} - -nvpair_t * -nvpair_movev_uuid(uuid_t *value, const char *namefmt, - va_list nameap) -{ - - if (value == NULL) { - RESTORE_ERRNO(EINVAL); - return (NULL); - } - - return (nvpair_allocv(NV_TYPE_UUID, (uint64_t)(uintptr_t)value, - sizeof(uuid_t), namefmt, nameap)); -} - -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_ARRAY || - nvp->nvp_type == NV_TYPE_NVLIST_DICTIONARY || - 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); -} - -const uuid_t * -nvpair_get_uuid(const nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_UUID); - - return ((const uuid_t *)(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: - case NV_TYPE_NVLIST_ARRAY: - case NV_TYPE_NVLIST_DICTIONARY: - nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); - break; - case NV_TYPE_STRING: - nv_free((char *)(intptr_t)nvp->nvp_data); - break; - case NV_TYPE_BINARY: - nv_free((void *)(intptr_t)nvp->nvp_data); - break; - case NV_TYPE_UUID: - nv_free((void *)(intptr_t)nvp->nvp_data); - break; - } - nv_free(nvp); -} - -void -nvpair_free_structure(nvpair_t *nvp) -{ - - NVPAIR_ASSERT(nvp); - PJDLOG_ASSERT(nvp->nvp_list == NULL); - - nvp->nvp_magic = 0; - nv_free(nvp); -} - -const char * -nvpair_type_string(int type) -{ - - switch (type) { - case NV_TYPE_NULL: - return ("NULL"); - case NV_TYPE_BOOL: - return ("BOOL"); - case NV_TYPE_NUMBER: - return ("NUMBER"); - case NV_TYPE_STRING: - return ("STRING"); - case NV_TYPE_NVLIST: - return ("NVLIST"); - case NV_TYPE_NVLIST_ARRAY: - return ("NVLIST_ARRAY"); - case NV_TYPE_NVLIST_DICTIONARY: - return ("NVLIST_DICTIONARY"); - case NV_TYPE_DESCRIPTOR: - return ("DESCRIPTOR"); - case NV_TYPE_BINARY: - return ("BINARY"); - case NV_TYPE_PTR: - return ("PTR"); - case NV_TYPE_UINT64: - return ("UINT64"); - case NV_TYPE_INT64: - return ("INT64"); - case NV_TYPE_ENDPOINT: - return ("ENDPOINT"); - case NV_TYPE_UUID: - return ("UUID"); - default: - return (""); - } -} diff --git a/xpc_array.c b/xpc_array.c index 7245070..d2a4312 100644 --- a/xpc_array.c +++ b/xpc_array.c @@ -85,6 +85,7 @@ xpc_array_append_value(xpc_object_t xarray, xpc_object_t value) TAILQ_INSERT_TAIL(arr, (struct xpc_object *)value, xo_link); xpc_retain(value); + ++xo->xo_size; } diff --git a/xpc_dictionary.c b/xpc_dictionary.c index 676a26c..5d3aac3 100644 --- a/xpc_dictionary.c +++ b/xpc_dictionary.c @@ -32,203 +32,6 @@ #include #include -#define NVLIST_XPC_TYPE "__XPC_TYPE" - -static void xpc2nv_primitive(nvlist_t *nv, const char *key, xpc_object_t value); - -__private_extern__ void -nv_release_entry(nvlist_t *nv, const char *key) -{ - xpc_object_t tmp; - - if (nvlist_exists_type(nv, key, NV_TYPE_PTR)) { - tmp = (void *)nvlist_take_number(nv, key); - xpc_release(tmp); - } -} - -struct xpc_object * -nv2xpc(const nvlist_t *nv) -{ - struct xpc_object *xo = NULL, *xotmp = NULL; - void *cookiep; - const char *key; - int type; - xpc_u val; - const nvlist_t *nvtmp; - - assert(nvlist_type(nv) == NV_TYPE_NVLIST_DICTIONARY || - nvlist_type(nv) == NV_TYPE_NVLIST_ARRAY); - - if (nvlist_type(nv) == NV_TYPE_NVLIST_DICTIONARY) - xo = xpc_dictionary_create(NULL, NULL, 0); - - if (nvlist_type(nv) == NV_TYPE_NVLIST_ARRAY) - xo = xpc_array_create(NULL, 0); - - cookiep = NULL; - while ((key = nvlist_next(nv, &type, &cookiep)) != NULL) { - xotmp = NULL; - - switch (type) { - case NV_TYPE_BOOL: - val.b = nvlist_get_bool(nv, key); - xotmp = xpc_bool_create(val.b); - break; - - case NV_TYPE_STRING: - val.str = nvlist_get_string(nv, key); - xotmp = xpc_string_create(val.str); - break; - - case NV_TYPE_INT64: - val.i = nvlist_get_int64(nv, key); - xotmp = xpc_int64_create(val.i); - break; - - case NV_TYPE_UINT64: - val.ui = nvlist_get_uint64(nv, key); - xotmp = xpc_uint64_create(val.ui); - break; - - case NV_TYPE_DESCRIPTOR: - val.fd = nvlist_get_descriptor(nv, key); - xotmp = _xpc_prim_create(_XPC_TYPE_FD, val, 0); - break; - - case NV_TYPE_PTR: - break; - - case NV_TYPE_BINARY: - break; - - case NV_TYPE_UUID: - memcpy(&val.uuid, nvlist_get_uuid(nv, key), - sizeof(uuid_t)); - xotmp = _xpc_prim_create(_XPC_TYPE_UUID, val, 0); - - case NV_TYPE_NVLIST_ARRAY: - nvtmp = nvlist_get_nvlist_array(nv, key); - xotmp = nv2xpc(nvtmp); - break; - - case NV_TYPE_NVLIST_DICTIONARY: - nvtmp = nvlist_get_nvlist_dictionary(nv, key); - xotmp = nv2xpc(nvtmp); - break; - } - - if (xotmp) { - if (nvlist_type(nv) == NV_TYPE_NVLIST_DICTIONARY) - xpc_dictionary_set_value(xo, key, xotmp); - - if (nvlist_type(nv) == NV_TYPE_NVLIST_ARRAY) - xpc_array_append_value(xo, xotmp); - } - } - - return (xo); -} - -static void -xpc2nv_primitive(nvlist_t *nv, const char *key, xpc_object_t value) -{ - struct xpc_object *xotmp = value; - - switch (xotmp->xo_xpc_type) { - case _XPC_TYPE_DICTIONARY: - nvlist_add_nvlist_dictionary(nv, key, xpc2nv(xotmp)); - break; - - case _XPC_TYPE_ARRAY: - nvlist_add_nvlist_array(nv, key, xpc2nv(xotmp)); - break; - - case _XPC_TYPE_BOOL: - nvlist_add_bool(nv, key, xpc_bool_get_value(xotmp)); - break; - - case _XPC_TYPE_CONNECTION: - break; - - case _XPC_TYPE_ENDPOINT: - break; - - case _XPC_TYPE_INT64: - nvlist_add_int64(nv, key, xpc_int64_get_value(xotmp)); - break; - - case _XPC_TYPE_UINT64: - nvlist_add_uint64(nv, key, xpc_uint64_get_value(xotmp)); - break; - - case _XPC_TYPE_DATE: - break; - - case _XPC_TYPE_DATA: - nvlist_add_binary(nv, key, - xpc_data_get_bytes_ptr(xotmp), - xpc_data_get_length(xotmp)); - break; - - case _XPC_TYPE_STRING: - nvlist_add_string(nv, key, - xpc_string_get_string_ptr(xotmp)); - break; - - case _XPC_TYPE_UUID: - nvlist_add_uuid(nv, key, (uuid_t*)xpc_uuid_get_bytes(xotmp)); - break; - - case _XPC_TYPE_FD: - nvlist_add_descriptor(nv, key, xotmp->xo_fd); - break; - - case _XPC_TYPE_SHMEM: - break; - - case _XPC_TYPE_ERROR: - break; - - case _XPC_TYPE_DOUBLE: - break; - } -} - -nvlist_t * -xpc2nv(struct xpc_object *xo) -{ - nvlist_t *nv; - struct xpc_object *xotmp; - - if (xo->xo_xpc_type == _XPC_TYPE_DICTIONARY) { - nv = nvlist_create_dictionary(0); - debugf("nv = %p\n", nv); - xpc_dictionary_apply(xo, ^(const char *k, xpc_object_t v) { - xpc2nv_primitive(nv, k, v); - return ((bool)true); - }); - - return nv; - } - - if (xo->xo_xpc_type == _XPC_TYPE_ARRAY) { - char *key = NULL; - nv = nvlist_create_array(0); - xpc_array_apply(xo, ^(size_t index, xpc_object_t v) { - asprintf(&key, "%ld", index); - xpc2nv_primitive(nv, key, v); - free(key); - return ((bool)true); - }); - - return nv; - } - - assert(0 && "xpc_object not array or dictionary"); - return NULL; -} - xpc_object_t xpc_dictionary_create(const char * const *keys, const xpc_object_t *values, size_t count) @@ -249,7 +52,6 @@ xpc_object_t xpc_dictionary_create_reply(xpc_object_t original) { struct xpc_object *xo, *xo_orig; - nvlist_t *nv; xpc_u val; if (xpc_get_type(original) != XPC_TYPE_DICTIONARY) diff --git a/xpc_internal.h b/xpc_internal.h index 9a18d52..6963f7c 100644 --- a/xpc_internal.h +++ b/xpc_internal.h @@ -30,7 +30,6 @@ #include #include "xpc/xpc.h" -#include #ifdef XPC_DEBUG #define debugf(...) \ @@ -150,7 +149,6 @@ struct xpc_service { TAILQ_HEAD(, xpc_connection) xs_connections; }; -#define xo_nv xo_u.nv #define xo_str xo_u.str #define xo_bool xo_u.b #define xo_uint xo_u.ui @@ -170,8 +168,6 @@ __private_extern__ struct xpc_object *_xpc_prim_create(int type, xpc_u value, __private_extern__ struct xpc_object *_xpc_prim_create_flags(int type, xpc_u value, size_t size, uint16_t flags); __private_extern__ const char *_xpc_get_type_name(xpc_object_t obj); -__private_extern__ struct xpc_object *nv2xpc(const nvlist_t *nv); -__private_extern__ nvlist_t *xpc2nv(struct xpc_object *xo); __private_extern__ void xpc_object_destroy(struct xpc_object *xo); __private_extern__ int xpc_pipe_send(xpc_object_t obj, mach_port_t dst, mach_port_t local, uint64_t id); diff --git a/xpc_misc.c b/xpc_misc.c index e9f7c33..91e4bce 100644 --- a/xpc_misc.c +++ b/xpc_misc.c @@ -37,6 +37,7 @@ #include #include #include "xpc_internal.h" +#include #define RECV_BUFFER_SIZE 65536 @@ -82,8 +83,6 @@ fail_log(const char *exp) //abort(); } -static void nvlist_add_prim(nvlist_t *nv, const char *key, xpc_object_t xobj); - static void xpc_dictionary_destroy(struct xpc_object *dict) { @@ -114,40 +113,457 @@ xpc_array_destroy(struct xpc_object *dict) } } -static int -xpc_pack(struct xpc_object *xo, void *buf, size_t *size) -{ - nvlist_t *nv; - void *packed; +/** + * encoded buffer layout for different types: + * dictionary = { 0x01, { key, encode_entry(encode_size(sizeof(value))?, value) }... } + * array = { 0x02, encode_entry(encode_size(sizeof(entry))?, entry)... } + * bool = { 0x03 | ((value ? 0x01 : 0x00) << XPC_PACK_TYPE_BITS) } + * connection = { 0x04 } + * endpoint = { 0x05 } + * null = { 0x06 } + * activity = { 0x07 } + * int64 = { encode_int(0x08, value, sizeof(int64_t)) } + * uint64 = { encode_int(0x09, value, sizeof(uint64_t)) } + * date = { encode_int(0x0a, value, sizeof(int64_t)) } + * data = { 0x0b, values... } + * string = { 0x0c, bytes... } + * uuid = { encode_int(0x0d, value, 16) } + * fd = { encode_int(0x0e, value, sizeof(int)) } + * shmem = { 0x0f } + * error = { 0x10 } + * double = { encode_int(0x11, value, sizeof(double)) } + * + * where: + * sizeof(x) = length of x in bytes + * encode_int(type, x, max_bytes) = encodes the provided integer into the minimum number of bytes + * possible. the high bit on each byte specifies whether the value has another byte. + * an optimization is made that uses the unused bits in the type byte to encode the value. + * encodes in little-endian. + * encode_size(x) = encodes the provided integer into the minimum number of bytes + * possible, much like `encode_int`. the difference is that it doesn't automatically + * encode the type into the first byte. + * encodes in little-endian. + * encode_entry(size, value) = if the value is variable-length type: + * { size[0] | value[0], size[1..], value[1..] } + * otherwise: + * { value } + * + * notes: + * * integral values are laid out in little-endian + * * many types that have variable length do not automatically include a stated length + * * this is done to save precious bytes + * * the only time size is explicitly specified is when variable-size structures are used + * inside other variable-size structures (e.g. dictionary in an array, data in a dictionary, array in an array, etc.). + * * this rule does *not* apply to strings and integral values, as they are technically not considered "variable-length" + * * strings are null-terminated, so it's obvious when you've reached their end + * * integral values encoded with encode_int likewise also already carry an indiciation + * of their length as part of their format + * * there may have been additional size optimization that could've been made that i didn't know about, + * but i was also trying to find a balance between size-efficiency, computational-efficiency, and simplicity. + */ - nv = xpc2nv(xo); +#define XPC_PACK_TYPE_MASK 0x1f +#define XPC_PACK_TYPE_BITS 5 +#define XPC_PACK_INT_INITIAL_BITS (8 - (XPC_PACK_TYPE_BITS + 1)) +#define XPC_PACK_INT_EXTRA_BYTES(x) (((x - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8) - packed = nvlist_pack_buffer(nv, NULL, size); - if (packed == NULL) { - errno = EINVAL; - return (-1); +XPC_INLINE bool xpc_pack_is_variable_length(uint8_t xo_xpc_type) { + return xo_xpc_type == _XPC_TYPE_DICTIONARY || xo_xpc_type == _XPC_TYPE_ARRAY || xo_xpc_type == _XPC_TYPE_DATA; +}; + +XPC_INLINE uint8_t xpc_pack_generate_mask(uint8_t bits, bool least_significant) { + static const uint8_t lookup_table[] = { + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, + }; + return lookup_table[bits] >> (least_significant ? (8 - bits) : 0); +}; + +// buf must be little-endian +XPC_INLINE size_t xpc_pack_encode_int_bits(const uint8_t* buf, size_t buf_size, bool raw) { + while (buf_size > 0 && buf[buf_size - 1] == 0) + --buf_size; + + if (buf_size == 0) + return 0; + + uint8_t msb = buf[buf_size - 1]; + size_t leading_bit_count = 8; + for (uint8_t i = 8; i > 0; --i) { + if ((msb & (1 << (i - 1))) == 0) { + --leading_bit_count; + } else { + break; + } } - if (buf != NULL) - memcpy(buf, packed, *size); + // number of bits needed for actual number + size_t raw_bits = ((buf_size - 1) * 8) + leading_bit_count; - nvlist_destroy(nv); - free(packed); - return (0); -} + if (raw) + return raw_bits; -static struct xpc_object * -xpc_unpack(void *buf, size_t size) -{ - struct xpc_object *xo; - nvlist_t *nv; + if (raw_bits <= XPC_PACK_INT_INITIAL_BITS) + return XPC_PACK_INT_INITIAL_BITS + 1; - nv = nvlist_unpack(buf, size); - xo = nv2xpc(nv); + return raw_bits + ((raw_bits - XPC_PACK_INT_INITIAL_BITS) / 7) + 1; +}; - nvlist_destroy(nv); - return (xo); -} +// buf must be little-endian +XPC_INLINE void xpc_pack_encode_int(uint8_t* out, const uint8_t* buf, size_t buf_size) { + if (buf_size == 0) + return; + + uint8_t initial_mask = xpc_pack_generate_mask(8 - XPC_PACK_TYPE_BITS - 1, true); + out[0] = ((buf[0] & initial_mask) << XPC_PACK_TYPE_BITS) | out[0] & XPC_PACK_TYPE_MASK; + + if ((buf[0] & ~initial_mask) == 0) + return; + + out[0] |= 1 << 7; + + size_t raw_bits = xpc_pack_encode_int_bits(buf, buf_size, true) - (8 - (XPC_PACK_TYPE_BITS + 1)); + size_t leftover_bits = XPC_PACK_TYPE_BITS + 1; + size_t buf_idx = 0; + size_t out_idx = 1; + + for (; raw_bits >= 7; raw_bits -= 7, ++out_idx) { + if (leftover_bits == 8) { + // 0x7f == 0b01111111 + out[out_idx] = (1 << 7) | buf[buf_idx] & 0x7f; + leftover_bits = 1; + } else { + uint8_t prev_byte_mask = xpc_pack_generate_mask(leftover_bits, false); + uint8_t bits_left_in_encoding_segment = 7 - leftover_bits; + uint8_t next_byte_mask = xpc_pack_generate_mask(bits_left_in_encoding_segment, true); + out[out_idx] = (1 << 7) | ((buf[buf_idx] & prev_byte_mask) >> (8 - leftover_bits)) | ((buf[buf_idx + 1] & next_byte_mask) << leftover_bits); + leftover_bits = 8 - bits_left_in_encoding_segment; + ++buf_idx; + } + } + + if (raw_bits == 0) { + // no next byte; remove the indicator + // 0x7f == 0b01111111 + out[out_idx - 1] &= 0x7f; + } else { + uint8_t prev_byte_mask = xpc_pack_generate_mask(leftover_bits, false); + out[out_idx] = (buf[buf_idx] & prev_byte_mask) >> (8 - leftover_bits); + if (leftover_bits < raw_bits) { + uint8_t bits_left_in_encoding_segment = 7 - leftover_bits; + uint8_t next_byte_mask = xpc_pack_generate_mask(bits_left_in_encoding_segment, true); + out[out_idx] |= (buf[buf_idx + 1] & next_byte_mask) << leftover_bits; + } + } +}; + +XPC_INLINE size_t xpc_unpack_decode_int(uint8_t* out, const uint8_t* buf) { + // `>> 1` because we don't want to include the most significant bit + uint8_t initial_mask = xpc_pack_generate_mask(8 - XPC_PACK_TYPE_BITS - 1, false) >> 1; + out[0] = (buf[0] & initial_mask) >> XPC_PACK_TYPE_BITS; + + if ((buf[0] & (1 << 7)) == 0) + return 1; + + size_t leftover_bits = XPC_PACK_TYPE_BITS + 1; + size_t out_idx = 0; + size_t buf_idx = 1; + + while ((buf[buf_idx] & (1 << 7)) != 0) { + if (leftover_bits == 8) { + // 0x7f == 0b01111111 + out[out_idx] = buf[buf_idx] & 0x7f; + leftover_bits = 1; + } else { + uint8_t prev_byte_mask = xpc_pack_generate_mask(leftover_bits, true); + uint8_t bits_left_in_encoding_segment = 7 - leftover_bits; + uint8_t next_byte_mask = xpc_pack_generate_mask(bits_left_in_encoding_segment, false) >> 1; + out[out_idx] |= (buf[buf_idx] & prev_byte_mask) << (8 - leftover_bits); + out[out_idx + 1] = (buf[buf_idx] & next_byte_mask) >> leftover_bits; + leftover_bits = 8 - bits_left_in_encoding_segment; + ++out_idx; + } + ++buf_idx; + } + + uint8_t prev_byte_mask = xpc_pack_generate_mask(leftover_bits, true); + uint8_t bits_left_in_encoding_segment = 7 - leftover_bits; + uint8_t next_byte_mask = xpc_pack_generate_mask(bits_left_in_encoding_segment, false) >> 1; + out[out_idx] |= (buf[buf_idx] & prev_byte_mask) << (8 - leftover_bits); + if ((buf[buf_idx] & next_byte_mask) != 0) { + out[out_idx + 1] = (buf[buf_idx] & next_byte_mask) >> leftover_bits; + } + + return buf_idx + 1; +}; + +XPC_INLINE int xpc_pack(struct xpc_object* xo, void* buf, size_t* final_size); +XPC_INLINE struct xpc_object* xpc_unpack(const void* buf, size_t size, size_t* packed_size, uint8_t declared_type); + +XPC_INLINE void xpc_pack_encode_entry(uint8_t* out, size_t* size, size_t* offset, struct xpc_object* val_xo) { + size_t val_size = 0; + xpc_pack(val_xo, out ? out + *offset : out, &val_size); + if (xpc_pack_is_variable_length(val_xo->xo_xpc_type)) { + size_t val_size_le = sizeof(size_t) == 4 ? OSSwapHostToLittleInt32(val_size) : OSSwapHostToLittleInt64(val_size); + size_t size_bits = xpc_pack_encode_int_bits(&val_size_le, sizeof(size_t), false); + size_t size_size = XPC_PACK_INT_EXTRA_BYTES(size_bits); + if (out) { + if (size_size > 0 && val_size > 1) + memmove(out + *offset + 1 + size_size, out + *offset + 1, val_size); + xpc_pack_encode_int(out + *offset, &val_size_le, sizeof(size_t)); + } + *size += size_size; + if (out) + *offset += size_size; + } + *size += val_size; + if (out) + *offset += val_size; +}; + +XPC_INLINE struct xpc_object* xpc_unpack_decode_entry(const uint8_t* in, size_t size, size_t* offset) { + struct xpc_object* xo = NULL; + uint8_t value_type = in[*offset] & XPC_PACK_TYPE_MASK; + size_t val_packed_size = 0; + if (xpc_pack_is_variable_length(value_type)) { + size_t val_size_le = 0; + // `- 1` because part of the size is encoded into the type byte + size_t val_size_size = xpc_unpack_decode_int(&val_size_le, in + *offset) - 1; + size_t val_size = sizeof(size_t) == 4 ? OSSwapLittleToHostInt32(val_size_le) : OSSwapLittleToHostInt64(val_size_le); + *offset += val_size_size; + xo = xpc_unpack(in + *offset, val_size, &val_packed_size, value_type); + if (val_packed_size != val_size) { + // something's up + debugf("val_packed_size != val_size (%zu != %zu)", val_packed_size, val_size); + return NULL; + } + } else { + xo = xpc_unpack(in + *offset, size - *offset, &val_packed_size, 0); + } + *offset += val_packed_size; + return xo; +}; + +XPC_INLINE int xpc_pack(struct xpc_object* xo, void* buf, size_t* final_size) { + uint8_t* out = buf; + __block size_t size = 1; + + if (out) + out[0] = xo->xo_xpc_type; + + switch (xo->xo_xpc_type) { + case _XPC_TYPE_DICTIONARY: { + __block size_t offset = size; + xpc_dictionary_apply(xo, ^bool(const char* key, xpc_object_t value) { + struct xpc_object* val_xo = value; + size_t key_size = strlen(key) + 1; + size += key_size; + if (out) { + strncpy(out + offset, key, key_size - 1); + offset += key_size; + out[offset - 1] = '\0'; + } + xpc_pack_encode_entry(out, &size, &offset, val_xo); + return true; + }); + } break; + case _XPC_TYPE_ARRAY: { + __block size_t offset = size; + xpc_array_apply(xo, ^bool(size_t idx, xpc_object_t value) { + struct xpc_object* val_xo = value; + xpc_pack_encode_entry(out, &size, &offset, val_xo); + return true; + }); + } break; + case _XPC_TYPE_BOOL: { + if (out) + out[0] |= (xpc_bool_get_value(xo) ? 1 : 0) << XPC_PACK_TYPE_BITS; + } break; + case _XPC_TYPE_DATE: + case _XPC_TYPE_INT64: { + int64_t val = xo->xo_xpc_type == _XPC_TYPE_DATE ? xpc_date_get_value(xo) : xpc_int64_get_value(xo); + int64_t val_le = OSSwapHostToLittleInt64(val); + size_t val_bits = xpc_pack_encode_int_bits(&val_le, sizeof(int64_t), false); + size += XPC_PACK_INT_EXTRA_BYTES(val_bits); + if (out) + xpc_pack_encode_int(out, &val_le, sizeof(int64_t)); + } break; + case _XPC_TYPE_UINT64: { + uint64_t val = xpc_uint64_get_value(xo); + uint64_t val_le = OSSwapHostToLittleInt64(val); + size_t val_bits = xpc_pack_encode_int_bits(&val_le, sizeof(uint64_t), false); + size += XPC_PACK_INT_EXTRA_BYTES(val_bits); + if (out) + xpc_pack_encode_int(out, &val_le, sizeof(uint64_t)); + } break; + case _XPC_TYPE_DATA: { + size_t len = xpc_data_get_length(xo); + size += len; + if (out) + memcpy(out + 1, xpc_data_get_bytes_ptr(xo), len); + } break; + case _XPC_TYPE_STRING: { + size_t len = xpc_string_get_length(xo); + size += len + 1; + if (out) { + strncpy(out + 1, xpc_string_get_string_ptr(xo), len); + out[1 + len] = '\0'; + } + } break; + // currently unimplemented + //case _XPC_TYPE_UUID: {} break; + case _XPC_TYPE_FD: { + int val = xo->xo_u.port; + int val_le = OSSwapHostToLittleInt32(val); + size_t val_bits = xpc_pack_encode_int_bits(&val_le, sizeof(int), false); + size += XPC_PACK_INT_EXTRA_BYTES(val_bits); + if (out) + xpc_pack_encode_int(out, &val_le, sizeof(int)); + } break; + case _XPC_TYPE_DOUBLE: { + // this is a rather simplistic implementation that assumes that the internal layout + // of a double is the same on sender and reeceiver + // that's never a good assumption. + // (although from what i can tell, XPC is only used for communication between processes + // on the same system, so this shouldn't be a problem) + // + // TODO: figure out how to encode the double portably + double val = xpc_double_get_value(xo); + uint64_t val_le = sizeof(double) == 4 ? (uint64_t)OSSwapHostToLittleInt32(*(uint32_t*)&val) : OSSwapHostToLittleInt64(*(uint64_t*)&val); + size_t val_bits = xpc_pack_encode_int_bits(&val_le, sizeof(uint64_t), false); + size += XPC_PACK_INT_EXTRA_BYTES(val_bits); + if (out) + xpc_pack_encode_int(out, &val_le, sizeof(uint64_t)); + } break; + case _XPC_TYPE_NULL: break; + default: { + debugf("can't pack unsupported type: %d", xo->xo_xpc_type); + } break; + }; + + if (final_size) + *final_size = size; + + return 0; +}; + +// initial calls (i.e. anyone using this function) should call it like so: +// xpc_unpack(data, data_size, NULL, 0) +// or +// xpc_unpack(data, data_size, &packed_size, 0) +// in other words, the `declared_type` parameter should always be 0 +XPC_INLINE struct xpc_object* xpc_unpack(const void* buf, size_t size, size_t* packed_size, uint8_t declared_type) { + if (size == 0) { + if (packed_size) + *packed_size = 0; + return NULL; + } + + const uint8_t* in = buf; + uint8_t xo_xpc_type = declared_type == 0 ? in[0] & XPC_PACK_TYPE_MASK : declared_type; + size_t offset = 0; + struct xpc_object* xo = NULL; + + switch (xo_xpc_type) { + case _XPC_TYPE_DICTIONARY: { + xo = xpc_dictionary_create(NULL, NULL, 0); + ++offset; + + while (offset < size) { + const char* key = in + offset; + size_t key_size = strlen(key) + 1; + offset += key_size; + struct xpc_object* val = xpc_unpack_decode_entry(in, size, &offset); + if (!val) { + debugf("failed to unpack dictionary entry"); + xpc_release(xo); + xo = NULL; + offset = 0; + break; + } + xpc_dictionary_set_value(xo, key, val); + xpc_release(val); + } + } break; + case _XPC_TYPE_ARRAY: { + xo = xpc_array_create(NULL, 0); + ++offset; + + while (offset < size) { + struct xpc_object* val = xpc_unpack_decode_entry(in, size, &offset); + if (!val) { + debugf("failed to unpack array entry"); + xpc_release(xo); + xo = NULL; + offset = 0; + break; + } + xpc_array_append_value(xo, val); + xpc_release(val); + } + } break; + case _XPC_TYPE_BOOL: { + xo = xpc_bool_create(in[0] >> XPC_PACK_TYPE_BITS); + ++offset; + } break; + case _XPC_TYPE_DATE: + case _XPC_TYPE_INT64: { + int64_t val_le = 0; + offset += xpc_unpack_decode_int(&val_le, in + offset); + int64_t val = OSSwapLittleToHostInt64(val_le); + xo = xo_xpc_type == _XPC_TYPE_DATE ? xpc_date_create(val) : xpc_int64_create(val); + } break; + case _XPC_TYPE_UINT64: { + uint64_t val_le = 0; + offset += xpc_unpack_decode_int(&val_le, in + offset); + uint64_t val = OSSwapLittleToHostInt64(val_le); + xo = xpc_uint64_create(val); + } break; + case _XPC_TYPE_DATA: { + ++offset; + xo = xpc_data_create(in + offset, size - offset); + offset += size - offset; + } break; + case _XPC_TYPE_STRING: { + ++offset; + xo = xpc_string_create(in + offset); + offset += strlen(in + offset) + 1; + } break; + case _XPC_TYPE_FD: { + int val_le = 0; + offset += xpc_unpack_decode_int(&val_le, in + offset); + int val = OSSwapLittleToHostInt32(val_le); + + xo = malloc(sizeof(struct xpc_object)); + if (xo) { + xo->xo_size = sizeof(xo->xo_u.port); + xo->xo_xpc_type = _XPC_TYPE_FD; + xo->xo_flags = 0; + xo->xo_u.port = val; + xo->xo_refcnt = 1; + xo->xo_audit_token = NULL; + } + } break; + case _XPC_TYPE_DOUBLE: { + uint64_t uval_le = 0; + offset += xpc_unpack_decode_int(&uval_le, in + offset); + uint64_t uval = OSSwapLittleToHostInt64(uval_le); + double val = *(double*)&uval_le; + xo = xpc_double_create(val); + } break; + case _XPC_TYPE_NULL: { + xo = xpc_null_create(); + ++offset; + } break; + default: { + debugf("can't unpack unsupported type: %d", xo_xpc_type); + } break; + } + + if (packed_size) + *packed_size = offset; + + return xo; +}; void xpc_object_destroy(struct xpc_object *xo) @@ -519,7 +935,7 @@ xpc_pipe_receive(mach_port_t local, mach_port_t *remote, xpc_object_t *result, *id = message.id; data_size = (int)message.size; LOG("unpacking data_size=%d", data_size); - xo = xpc_unpack(&message.data, data_size); + xo = xpc_unpack(message.data, data_size, NULL, 0); tr = (mach_msg_trailer_t *)(((char *)&message) + request->msgh_size); auditp = &((mach_msg_audit_trailer_t *)tr)->msgh_audit; @@ -582,7 +998,7 @@ xpc_pipe_try_receive(mach_port_t portset, xpc_object_t *requestobj, mach_port_t LOG("demux returned false\n"); data_size = request->msgh_size; LOG("unpacking data_size=%d", data_size); - xo = xpc_unpack(&message.data, data_size); + xo = xpc_unpack(message.data, data_size, NULL, 0); /* is padding for alignment enforced in the kernel?*/ tr = (mach_msg_trailer_t *)(((char *)&message) + request->msgh_size); auditp = &((mach_msg_audit_trailer_t *)tr)->msgh_audit;