From 9f3cbc2a66326ec81a7fbd5af01a45379b3cfa1a Mon Sep 17 00:00:00 2001 From: Ariel Abreu Date: Mon, 13 Apr 2020 19:05:18 -0400 Subject: [PATCH 1/6] Initial rewrite of XPC encoding/decoding code --- CMakeLists.txt | 3 - nv.h | 478 --------- nv_impl.h | 172 ---- nvlist_impl.h | 49 - nvpair_impl.h | 94 -- subr_nvlist.c | 2578 ---------------------------------------------- subr_nvpair.c | 1506 --------------------------- subr_sbuf.c | 590 ----------- xpc_dictionary.c | 198 ---- xpc_internal.h | 4 - xpc_misc.c | 450 +++++++- 11 files changed, 420 insertions(+), 5702 deletions(-) delete mode 100644 nv.h delete mode 100644 nv_impl.h delete mode 100644 nvlist_impl.h delete mode 100644 nvpair_impl.h delete mode 100644 subr_nvlist.c delete mode 100644 subr_nvpair.c delete mode 100644 subr_sbuf.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 6921525..6177054 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,9 +34,6 @@ set(xpc_sources xpc_misc.c 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/subr_sbuf.c b/subr_sbuf.c deleted file mode 100644 index 1a3ab5f..0000000 --- a/subr_sbuf.c +++ /dev/null @@ -1,590 +0,0 @@ -/*- - * Copyright (c) 2000 Poul-Henning Kamp and Dag-Erling Co•dan Sm¿rgrav - * All rights reserved. - * - * 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 - * in this position and unchanged. - * 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include - -#ifdef KERNEL -/* #include */ -#include -#include -#include -#include -#include -#include -#include -#else /* KERNEL */ -#include -#include -#include -#include -#include -#endif /* KERNEL */ - -#include - -#ifndef PAGE_SIZE -# define PAGE_SIZE 4096 -#endif - -#ifdef KERNEL -/* MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers"); */ -#define SBMALLOC(size) _MALLOC(size, M_SBUF, M_WAITOK) -#define SBFREE(buf) FREE(buf, M_SBUF) -#else /* KERNEL */ -#define KASSERT(e, m) -#define SBMALLOC(size) malloc(size) -#define SBFREE(buf) free(buf) -#define min(x,y) MIN(x,y) - -#endif /* KERNEL */ - -/* - * Predicates - */ -#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC) -#define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT) -#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED) -#define SBUF_HASOVERFLOWED(s) ((s)->s_flags & SBUF_OVERFLOWED) -#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1) -#define SBUF_FREESPACE(s) ((s)->s_size - (s)->s_len - 1) -#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND) - -/* - * Set / clear flags - */ -#define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0) -#define SBUF_CLEARFLAG(s, f) do { (s)->s_flags &= ~(f); } while (0) - -#define SBUF_MINEXTENDSIZE 16 /* Should be power of 2. */ -#define SBUF_MAXEXTENDSIZE PAGE_SIZE -#define SBUF_MAXEXTENDINCR PAGE_SIZE - -/* - * Debugging support - */ -#if defined(KERNEL) && defined(INVARIANTS) -static void -_assert_sbuf_integrity(const char *fun, struct sbuf *s) -{ - KASSERT(s != NULL, - ("%s called with a NULL sbuf pointer", fun)); - KASSERT(s->s_buf != NULL, - ("%s called with uninitialized or corrupt sbuf", fun)); - KASSERT(s->s_len < s->s_size, - ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); -} - -static void -_assert_sbuf_state(const char *fun, struct sbuf *s, int state) -{ - KASSERT((s->s_flags & SBUF_FINISHED) == state, - ("%s called with %sfinished or corrupt sbuf", fun, - (state ? "un" : ""))); -} -#define assert_sbuf_integrity(s) _assert_sbuf_integrity(__func__, (s)) -#define assert_sbuf_state(s, i) _assert_sbuf_state(__func__, (s), (i)) -#else /* KERNEL && INVARIANTS */ -#define assert_sbuf_integrity(s) do { } while (0) -#define assert_sbuf_state(s, i) do { } while (0) -#endif /* KERNEL && INVARIANTS */ - -static int -sbuf_extendsize(int size) -{ - int newsize; - - newsize = SBUF_MINEXTENDSIZE; - while (newsize < size) { - if (newsize < (int)SBUF_MAXEXTENDSIZE) - newsize *= 2; - else - newsize += SBUF_MAXEXTENDINCR; - } - - return (newsize); -} - - -/* - * Extend an sbuf. - */ -static int -sbuf_extend(struct sbuf *s, int addlen) -{ - char *newbuf; - int newsize; - - if (!SBUF_CANEXTEND(s)) - return (-1); - - newsize = sbuf_extendsize(s->s_size + addlen); - newbuf = (char *)SBMALLOC(newsize); - if (newbuf == NULL) - return (-1); - bcopy(s->s_buf, newbuf, s->s_size); - if (SBUF_ISDYNAMIC(s)) - SBFREE(s->s_buf); - else - SBUF_SETFLAG(s, SBUF_DYNAMIC); - s->s_buf = newbuf; - s->s_size = newsize; - return (0); -} - -/* - * Initialize an sbuf. - * If buf is non-NULL, it points to a static or already-allocated string - * big enough to hold at least length characters. - */ -struct sbuf * -sbuf_new(struct sbuf *s, char *buf, int length, int flags) -{ - KASSERT(length >= 0, - ("attempt to create an sbuf of negative length (%d)", length)); - KASSERT((flags & ~SBUF_USRFLAGMSK) == 0, - ("%s called with invalid flags", __func__)); - - flags &= SBUF_USRFLAGMSK; - if (s == NULL) { - s = (struct sbuf *)SBMALLOC(sizeof *s); - if (s == NULL) - return (NULL); - bzero(s, sizeof *s); - s->s_flags = flags; - SBUF_SETFLAG(s, SBUF_DYNSTRUCT); - } else { - bzero(s, sizeof *s); - s->s_flags = flags; - } - s->s_size = length; - if (buf) { - s->s_buf = buf; - return (s); - } - if (flags & SBUF_AUTOEXTEND) - s->s_size = sbuf_extendsize(s->s_size); - s->s_buf = (char *)SBMALLOC(s->s_size); - if (s->s_buf == NULL) { - if (SBUF_ISDYNSTRUCT(s)) - SBFREE(s); - return (NULL); - } - SBUF_SETFLAG(s, SBUF_DYNAMIC); - return (s); -} - -#ifdef KERNEL -/* - * Create an sbuf with uio data - */ -struct sbuf * -sbuf_uionew(struct sbuf *s, struct uio *uio, int *error) -{ - KASSERT(uio != NULL, - ("%s called with NULL uio pointer", __func__)); - KASSERT(error != NULL, - ("%s called with NULL error pointer", __func__)); - - s = sbuf_new(s, NULL, uio_resid(uio) + 1, 0); - if (s == NULL) { - *error = ENOMEM; - return (NULL); - } - *error = uiomove(s->s_buf, uio_resid(uio), uio); - if (*error != 0) { - sbuf_delete(s); - return (NULL); - } - s->s_len = s->s_size - 1; - *error = 0; - return (s); -} -#endif - -/* - * Clear an sbuf and reset its position. - */ -void -sbuf_clear(struct sbuf *s) -{ - assert_sbuf_integrity(s); - /* don't care if it's finished or not */ - - SBUF_CLEARFLAG(s, SBUF_FINISHED); - SBUF_CLEARFLAG(s, SBUF_OVERFLOWED); - s->s_len = 0; -} - -/* - * Set the sbuf's end position to an arbitrary value. - * Effectively truncates the sbuf at the new position. - */ -int -sbuf_setpos(struct sbuf *s, int pos) -{ - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - KASSERT(pos >= 0, - ("attempt to seek to a negative position (%d)", pos)); - KASSERT(pos < s->s_size, - ("attempt to seek past end of sbuf (%d >= %d)", pos, s->s_size)); - - if (pos < 0 || pos > s->s_len) - return (-1); - s->s_len = pos; - return (0); -} - -/* - * Append a byte string to an sbuf. - */ -int -sbuf_bcat(struct sbuf *s, const void *buf, size_t len) -{ - const char *str = buf; - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - if (SBUF_HASOVERFLOWED(s)) - return (-1); - - for (; len; len--) { - if (!SBUF_HASROOM(s) && sbuf_extend(s, len) < 0) - break; - s->s_buf[s->s_len++] = *str++; - } - if (len) { - SBUF_SETFLAG(s, SBUF_OVERFLOWED); - return (-1); - } - return (0); -} - -#ifdef KERNEL -/* - * Copy a byte string from userland into an sbuf. - */ -int -sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len) -{ - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - if (SBUF_HASOVERFLOWED(s)) - return (-1); - - if (len == 0) - return (0); - if (len > (unsigned) SBUF_FREESPACE(s)) { - sbuf_extend(s, len - SBUF_FREESPACE(s)); - len = min(len, SBUF_FREESPACE(s)); - } - if (copyin(CAST_USER_ADDR_T(uaddr), s->s_buf + s->s_len, len) != 0) - return (-1); - s->s_len += len; - - return (0); -} -#endif - -/* - * Copy a byte string into an sbuf. - */ -int -sbuf_bcpy(struct sbuf *s, const void *buf, size_t len) -{ - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - sbuf_clear(s); - return (sbuf_bcat(s, buf, len)); -} - -/* - * Append a string to an sbuf. - */ -int -sbuf_cat(struct sbuf *s, const char *str) -{ - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - if (SBUF_HASOVERFLOWED(s)) - return (-1); - - while (*str) { - if (!SBUF_HASROOM(s) && sbuf_extend(s, strlen(str)) < 0) - break; - s->s_buf[s->s_len++] = *str++; - } - if (*str) { - SBUF_SETFLAG(s, SBUF_OVERFLOWED); - return (-1); - } - return (0); -} - -#ifdef KERNEL -/* - * Append a string from userland to an sbuf. - */ -int -sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len) -{ - size_t done; - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - if (SBUF_HASOVERFLOWED(s)) - return (-1); - - if (len == 0) - len = SBUF_FREESPACE(s); /* XXX return 0? */ - if (len > (unsigned) SBUF_FREESPACE(s)) { - sbuf_extend(s, len); - len = min(len, SBUF_FREESPACE(s)); - } - switch (copyinstr(CAST_USER_ADDR_T(uaddr), s->s_buf + s->s_len, len + 1, &done)) { - case ENAMETOOLONG: - SBUF_SETFLAG(s, SBUF_OVERFLOWED); - /* fall through */ - case 0: - s->s_len += done - 1; - break; - default: - return (-1); /* XXX */ - } - - return (done); -} -#endif - -/* - * Copy a string into an sbuf. - */ -int -sbuf_cpy(struct sbuf *s, const char *str) -{ - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - sbuf_clear(s); - return (sbuf_cat(s, str)); -} - -/* - * Format the given argument list and append the resulting string to an sbuf. - */ -int -sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap) -{ - __builtin_va_list ap_copy; /* XXX tduffy - blame on him */ - int len; - - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - KASSERT(fmt != NULL, - ("%s called with a NULL format string", __func__)); - - if (SBUF_HASOVERFLOWED(s)) - return (-1); - - do { - va_copy(ap_copy, ap); - len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1, - fmt, ap_copy); - va_end(ap_copy); - } while (len > SBUF_FREESPACE(s) && - sbuf_extend(s, len - SBUF_FREESPACE(s)) == 0); - - /* - * s->s_len is the length of the string, without the terminating nul. - * When updating s->s_len, we must subtract 1 from the length that - * we passed into vsnprintf() because that length includes the - * terminating nul. - * - * vsnprintf() returns the amount that would have been copied, - * given sufficient space, hence the min() calculation below. - */ - s->s_len += min(len, SBUF_FREESPACE(s)); - if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s)) - SBUF_SETFLAG(s, SBUF_OVERFLOWED); - - KASSERT(s->s_len < s->s_size, - ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); - - if (SBUF_HASOVERFLOWED(s)) - return (-1); - return (0); -} - -/* - * Format the given arguments and append the resulting string to an sbuf. - */ -int -sbuf_printf(struct sbuf *s, const char *fmt, ...) -{ - va_list ap; - int result; - - va_start(ap, fmt); - result = sbuf_vprintf(s, fmt, ap); - va_end(ap); - return(result); -} - -/* - * Append a character to an sbuf. - */ -int -sbuf_putc(struct sbuf *s, int c) -{ - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - if (SBUF_HASOVERFLOWED(s)) - return (-1); - - if (!SBUF_HASROOM(s) && sbuf_extend(s, 1) < 0) { - SBUF_SETFLAG(s, SBUF_OVERFLOWED); - return (-1); - } - if (c != '\0') - s->s_buf[s->s_len++] = c; - return (0); -} - -#ifdef KERNEL -static inline int -isspace(char ch) -{ - return (ch == ' ' || ch == '\n' || ch == '\t'); -} -#endif - -/* - * Trim whitespace characters from end of an sbuf. - */ -int -sbuf_trim(struct sbuf *s) -{ - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - if (SBUF_HASOVERFLOWED(s)) - return (-1); - - while (s->s_len && isspace(s->s_buf[s->s_len-1])) - --s->s_len; - - return (0); -} - -/* - * Check if an sbuf overflowed - */ -int -sbuf_overflowed(struct sbuf *s) -{ - return SBUF_HASOVERFLOWED(s); -} - -/* - * Finish off an sbuf. - */ -void -sbuf_finish(struct sbuf *s) -{ - assert_sbuf_integrity(s); - assert_sbuf_state(s, 0); - - s->s_buf[s->s_len] = '\0'; - SBUF_CLEARFLAG(s, SBUF_OVERFLOWED); - SBUF_SETFLAG(s, SBUF_FINISHED); -} - -/* - * Return a pointer to the sbuf data. - */ -char * -sbuf_data(struct sbuf *s) -{ - assert_sbuf_integrity(s); - assert_sbuf_state(s, SBUF_FINISHED); - - return s->s_buf; -} - -/* - * Return the length of the sbuf data. - */ -int -sbuf_len(struct sbuf *s) -{ - assert_sbuf_integrity(s); - /* don't care if it's finished or not */ - - if (SBUF_HASOVERFLOWED(s)) - return (-1); - return s->s_len; -} - -/* - * Clear an sbuf, free its buffer if necessary. - */ -void -sbuf_delete(struct sbuf *s) -{ - int isdyn; - - assert_sbuf_integrity(s); - /* don't care if it's finished or not */ - - if (SBUF_ISDYNAMIC(s)) - SBFREE(s->s_buf); - isdyn = SBUF_ISDYNSTRUCT(s); - bzero(s, sizeof *s); - if (isdyn) - SBFREE(s); -} - -/* - * Check if an sbuf has been finished. - */ -int -sbuf_done(struct sbuf *s) -{ - - return(SBUF_ISFINISHED(s)); -} 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..00c06e0 100644 --- a/xpc_misc.c +++ b/xpc_misc.c @@ -37,6 +37,7 @@ #include #include #include "xpc_internal.h" +#include "endian_compat.h" #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,431 @@ 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; +// number of bytes to allocate for the initial call to mach_msg +// 8KiB +#define XPC_MACH_MSG_INTIAL_BUFFER_LEN 8192 - nv = xpc2nv(xo); +/** + * 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) << 4) } + * 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 high four 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 basically laid out in network-order (big-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, 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. + */ - packed = nvlist_pack_buffer(nv, NULL, size); - if (packed == NULL) { - errno = EINVAL; - return (-1); +#define XPC_PACK_TYPE_MASK 0x1f +#define XPC_PACK_TYPE_BITS 5 + +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; +}; + +// 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 == 0 && buf_size > 0) { + --buf_size; + ++buf; } - if (buf != NULL) - memcpy(buf, packed, *size); + if (buf_size == 0) + return 0; - nvlist_destroy(nv); - free(packed); - return (0); -} + size_t leading_bit_count = 8; + for (uint8_t i = 8; i > 0; --i) + if (*buf & (1 << (i - 1)) == 0) + --leading_bit_count; -static struct xpc_object * -xpc_unpack(void *buf, size_t size) -{ - struct xpc_object *xo; - nvlist_t *nv; + if (buf_size == 1 && leading_bit_count < XPC_PACK_TYPE_BITS) + return leading_bit_count + (raw ? 0 : 1); - nv = nvlist_unpack(buf, size); - xo = nv2xpc(nv); + // number of bits needed for actual number + size_t raw_bits = ((buf_size - 1) * 8) + leading_bit_count; - nvlist_destroy(nv); - return (xo); -} + if (raw) + return raw_bits; + + return raw_bits + ((raw_bits - (XPC_PACK_TYPE_BITS - 1)) / 7) + 1; +}; + +// 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 = (0xff << (XPC_PACK_TYPE_BITS + 1)) >> (XPC_PACK_TYPE_BITS + 1); + out[0] = ((buf[0] & initial_mask) << XPC_PACK_TYPE_BITS) | out[0] & XPC_PACK_TYPE_MASK; + + if (buf[0] & ~(uint8_t)initial_mask == 0) + return; + + out[0] |= 1 << 7; + + size_t raw_bits = xpc_pack_encode_int_bits(buf, buf_size, true) - (XPC_PACK_TYPE_BITS - 1); + size_t leftover_bits = 8 - (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 = (0xff >> (8 - leftover_bits)) << (8 - leftover_bits); + uint8_t bits_left_in_encoding_segment = 7 - leftover_bits; + uint8_t next_byte_mask = (0xff << (8 - bits_left_in_encoding_segment)) >> (8 - bits_left_in_encoding_segment); + 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 = (0xff >> (8 - leftover_bits)) << (8 - leftover_bits); + out[out_idx] = (buf[buf_idx] & prev_byte_mask) >> (8 - leftover_bits); + } +}; + +XPC_INLINE size_t xpc_unpack_decode_int(uint8_t* out, const uint8_t* buf) { + // 0x7f == 0b01111111 + uint8_t initial_mask = (0x7f >> XPC_PACK_TYPE_BITS) << XPC_PACK_TYPE_BITS; + out[0] = (buf[0] & initial_mask) >> XPC_PACK_TYPE_BITS; + + if (buf[0] & (1 << 7) == 0) + return 1; + + size_t leftover_bits = 8 - (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 = (0xff << (8 - leftover_bits)) >> (8 - leftover_bits); + uint8_t bits_left_in_encoding_segment = 7 - leftover_bits; + // 0x7f == 0b01111111 + uint8_t next_byte_mask = (0x7f >> (8 - bits_left_in_encoding_segment)) << (8 - bits_left_in_encoding_segment); + 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 = (0xff << (8 - leftover_bits)) >> (8 - leftover_bits); + out[out_idx] |= (buf[buf_idx] & prev_byte_mask) << (8 - 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 + *offset, &val_size); + if (xpc_pack_is_variable_length(val_xo->xo_xpc_type)) { + size_t val_size_le = sizeof(size_t) == 4 ? htole32(val_size) : htole64(val_size); + size_t size_bits = xpc_pack_encode_int_bits(&val_size_le, sizeof(size_t), false); + size_t size_size = ((size_bits - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8; + 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 ? le32toh(val_size_le) : le64toh(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 = 0; + 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 += 1 + key_size; + if (out) { + offset += 1; + strncpy(out + offset, key, key_size - 1); + offset += key_size; + out[offset - 1] = '\0'; + } + xpc_pack_encode_entry(out, &size, &offset, val_xo); + }); + } break; + case _XPC_TYPE_ARRAY: { + size_t offset = 0; + 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); + }); + } 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 = htole64(val); + size_t val_bits = xpc_pack_encode_int_bits(&val_le, sizeof(int64_t), false); + size += ((val_bits - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8; + 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->xo_uint); + uint64_t val_le = htole64(val); + size_t val_bits = xpc_pack_encode_int_bits(&val_le, sizeof(uint64_t), false); + size += ((val_bits - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8; + 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 = htole32(val); + size_t val_bits = xpc_pack_encode_int_bits(&val_le, sizeof(int), false); + size += ((val_bits - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8; + 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)htole32(*(uint32_t*)&val) : htole64(*(uint64_t*)&val); + size_t val_bits = xpc_pack_encode_int_bits(&val_le, sizeof(uint64_t), false); + size += ((val_bits - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8; + 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 = le64toh(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 = le64toh(val_le); + xo = xpc_uint64_create(val); + } break; + case _XPC_TYPE_DATA: {} break; + case _XPC_TYPE_STRING: {} break; + case _XPC_TYPE_FD: { + int val_le = 0; + offset += xpc_unpack_decode_int(&val_le, in + offset); + int val = le32toh(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 = le64toh(uval_le); + double val = *(double*)&uval_le; + xo = xpc_uint64_create(val); + } break; + case _XPC_TYPE_NULL: { + xo = xpc_null_create(); + } 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 +909,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 +972,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; From e4fa5b7a15c7193c9b9b3595faa7691964c0418b Mon Sep 17 00:00:00 2001 From: Ariel Abreu Date: Tue, 14 Apr 2020 21:18:44 -0400 Subject: [PATCH 2/6] Add back `subr_sbuf.c` I accidentally deleted it thinking it was part of the `nv` implementation (since it started with `subr_` just like the `nv` files) --- CMakeLists.txt | 1 + subr_sbuf.c | 590 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 591 insertions(+) create mode 100644 subr_sbuf.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 6177054..9a85bba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ set(xpc_sources xpc_misc.c xpc_private.c xpc_type.c + subr_sbuf.c xpc_pipe.c reboot3.c ) diff --git a/subr_sbuf.c b/subr_sbuf.c new file mode 100644 index 0000000..1a3ab5f --- /dev/null +++ b/subr_sbuf.c @@ -0,0 +1,590 @@ +/*- + * Copyright (c) 2000 Poul-Henning Kamp and Dag-Erling Co•dan Sm¿rgrav + * All rights reserved. + * + * 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 + * in this position and unchanged. + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +#ifdef KERNEL +/* #include */ +#include +#include +#include +#include +#include +#include +#include +#else /* KERNEL */ +#include +#include +#include +#include +#include +#endif /* KERNEL */ + +#include + +#ifndef PAGE_SIZE +# define PAGE_SIZE 4096 +#endif + +#ifdef KERNEL +/* MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers"); */ +#define SBMALLOC(size) _MALLOC(size, M_SBUF, M_WAITOK) +#define SBFREE(buf) FREE(buf, M_SBUF) +#else /* KERNEL */ +#define KASSERT(e, m) +#define SBMALLOC(size) malloc(size) +#define SBFREE(buf) free(buf) +#define min(x,y) MIN(x,y) + +#endif /* KERNEL */ + +/* + * Predicates + */ +#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC) +#define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT) +#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED) +#define SBUF_HASOVERFLOWED(s) ((s)->s_flags & SBUF_OVERFLOWED) +#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1) +#define SBUF_FREESPACE(s) ((s)->s_size - (s)->s_len - 1) +#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND) + +/* + * Set / clear flags + */ +#define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0) +#define SBUF_CLEARFLAG(s, f) do { (s)->s_flags &= ~(f); } while (0) + +#define SBUF_MINEXTENDSIZE 16 /* Should be power of 2. */ +#define SBUF_MAXEXTENDSIZE PAGE_SIZE +#define SBUF_MAXEXTENDINCR PAGE_SIZE + +/* + * Debugging support + */ +#if defined(KERNEL) && defined(INVARIANTS) +static void +_assert_sbuf_integrity(const char *fun, struct sbuf *s) +{ + KASSERT(s != NULL, + ("%s called with a NULL sbuf pointer", fun)); + KASSERT(s->s_buf != NULL, + ("%s called with uninitialized or corrupt sbuf", fun)); + KASSERT(s->s_len < s->s_size, + ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); +} + +static void +_assert_sbuf_state(const char *fun, struct sbuf *s, int state) +{ + KASSERT((s->s_flags & SBUF_FINISHED) == state, + ("%s called with %sfinished or corrupt sbuf", fun, + (state ? "un" : ""))); +} +#define assert_sbuf_integrity(s) _assert_sbuf_integrity(__func__, (s)) +#define assert_sbuf_state(s, i) _assert_sbuf_state(__func__, (s), (i)) +#else /* KERNEL && INVARIANTS */ +#define assert_sbuf_integrity(s) do { } while (0) +#define assert_sbuf_state(s, i) do { } while (0) +#endif /* KERNEL && INVARIANTS */ + +static int +sbuf_extendsize(int size) +{ + int newsize; + + newsize = SBUF_MINEXTENDSIZE; + while (newsize < size) { + if (newsize < (int)SBUF_MAXEXTENDSIZE) + newsize *= 2; + else + newsize += SBUF_MAXEXTENDINCR; + } + + return (newsize); +} + + +/* + * Extend an sbuf. + */ +static int +sbuf_extend(struct sbuf *s, int addlen) +{ + char *newbuf; + int newsize; + + if (!SBUF_CANEXTEND(s)) + return (-1); + + newsize = sbuf_extendsize(s->s_size + addlen); + newbuf = (char *)SBMALLOC(newsize); + if (newbuf == NULL) + return (-1); + bcopy(s->s_buf, newbuf, s->s_size); + if (SBUF_ISDYNAMIC(s)) + SBFREE(s->s_buf); + else + SBUF_SETFLAG(s, SBUF_DYNAMIC); + s->s_buf = newbuf; + s->s_size = newsize; + return (0); +} + +/* + * Initialize an sbuf. + * If buf is non-NULL, it points to a static or already-allocated string + * big enough to hold at least length characters. + */ +struct sbuf * +sbuf_new(struct sbuf *s, char *buf, int length, int flags) +{ + KASSERT(length >= 0, + ("attempt to create an sbuf of negative length (%d)", length)); + KASSERT((flags & ~SBUF_USRFLAGMSK) == 0, + ("%s called with invalid flags", __func__)); + + flags &= SBUF_USRFLAGMSK; + if (s == NULL) { + s = (struct sbuf *)SBMALLOC(sizeof *s); + if (s == NULL) + return (NULL); + bzero(s, sizeof *s); + s->s_flags = flags; + SBUF_SETFLAG(s, SBUF_DYNSTRUCT); + } else { + bzero(s, sizeof *s); + s->s_flags = flags; + } + s->s_size = length; + if (buf) { + s->s_buf = buf; + return (s); + } + if (flags & SBUF_AUTOEXTEND) + s->s_size = sbuf_extendsize(s->s_size); + s->s_buf = (char *)SBMALLOC(s->s_size); + if (s->s_buf == NULL) { + if (SBUF_ISDYNSTRUCT(s)) + SBFREE(s); + return (NULL); + } + SBUF_SETFLAG(s, SBUF_DYNAMIC); + return (s); +} + +#ifdef KERNEL +/* + * Create an sbuf with uio data + */ +struct sbuf * +sbuf_uionew(struct sbuf *s, struct uio *uio, int *error) +{ + KASSERT(uio != NULL, + ("%s called with NULL uio pointer", __func__)); + KASSERT(error != NULL, + ("%s called with NULL error pointer", __func__)); + + s = sbuf_new(s, NULL, uio_resid(uio) + 1, 0); + if (s == NULL) { + *error = ENOMEM; + return (NULL); + } + *error = uiomove(s->s_buf, uio_resid(uio), uio); + if (*error != 0) { + sbuf_delete(s); + return (NULL); + } + s->s_len = s->s_size - 1; + *error = 0; + return (s); +} +#endif + +/* + * Clear an sbuf and reset its position. + */ +void +sbuf_clear(struct sbuf *s) +{ + assert_sbuf_integrity(s); + /* don't care if it's finished or not */ + + SBUF_CLEARFLAG(s, SBUF_FINISHED); + SBUF_CLEARFLAG(s, SBUF_OVERFLOWED); + s->s_len = 0; +} + +/* + * Set the sbuf's end position to an arbitrary value. + * Effectively truncates the sbuf at the new position. + */ +int +sbuf_setpos(struct sbuf *s, int pos) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + KASSERT(pos >= 0, + ("attempt to seek to a negative position (%d)", pos)); + KASSERT(pos < s->s_size, + ("attempt to seek past end of sbuf (%d >= %d)", pos, s->s_size)); + + if (pos < 0 || pos > s->s_len) + return (-1); + s->s_len = pos; + return (0); +} + +/* + * Append a byte string to an sbuf. + */ +int +sbuf_bcat(struct sbuf *s, const void *buf, size_t len) +{ + const char *str = buf; + + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + + for (; len; len--) { + if (!SBUF_HASROOM(s) && sbuf_extend(s, len) < 0) + break; + s->s_buf[s->s_len++] = *str++; + } + if (len) { + SBUF_SETFLAG(s, SBUF_OVERFLOWED); + return (-1); + } + return (0); +} + +#ifdef KERNEL +/* + * Copy a byte string from userland into an sbuf. + */ +int +sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + + if (len == 0) + return (0); + if (len > (unsigned) SBUF_FREESPACE(s)) { + sbuf_extend(s, len - SBUF_FREESPACE(s)); + len = min(len, SBUF_FREESPACE(s)); + } + if (copyin(CAST_USER_ADDR_T(uaddr), s->s_buf + s->s_len, len) != 0) + return (-1); + s->s_len += len; + + return (0); +} +#endif + +/* + * Copy a byte string into an sbuf. + */ +int +sbuf_bcpy(struct sbuf *s, const void *buf, size_t len) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + sbuf_clear(s); + return (sbuf_bcat(s, buf, len)); +} + +/* + * Append a string to an sbuf. + */ +int +sbuf_cat(struct sbuf *s, const char *str) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + + while (*str) { + if (!SBUF_HASROOM(s) && sbuf_extend(s, strlen(str)) < 0) + break; + s->s_buf[s->s_len++] = *str++; + } + if (*str) { + SBUF_SETFLAG(s, SBUF_OVERFLOWED); + return (-1); + } + return (0); +} + +#ifdef KERNEL +/* + * Append a string from userland to an sbuf. + */ +int +sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len) +{ + size_t done; + + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + + if (len == 0) + len = SBUF_FREESPACE(s); /* XXX return 0? */ + if (len > (unsigned) SBUF_FREESPACE(s)) { + sbuf_extend(s, len); + len = min(len, SBUF_FREESPACE(s)); + } + switch (copyinstr(CAST_USER_ADDR_T(uaddr), s->s_buf + s->s_len, len + 1, &done)) { + case ENAMETOOLONG: + SBUF_SETFLAG(s, SBUF_OVERFLOWED); + /* fall through */ + case 0: + s->s_len += done - 1; + break; + default: + return (-1); /* XXX */ + } + + return (done); +} +#endif + +/* + * Copy a string into an sbuf. + */ +int +sbuf_cpy(struct sbuf *s, const char *str) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + sbuf_clear(s); + return (sbuf_cat(s, str)); +} + +/* + * Format the given argument list and append the resulting string to an sbuf. + */ +int +sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap) +{ + __builtin_va_list ap_copy; /* XXX tduffy - blame on him */ + int len; + + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + KASSERT(fmt != NULL, + ("%s called with a NULL format string", __func__)); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + + do { + va_copy(ap_copy, ap); + len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1, + fmt, ap_copy); + va_end(ap_copy); + } while (len > SBUF_FREESPACE(s) && + sbuf_extend(s, len - SBUF_FREESPACE(s)) == 0); + + /* + * s->s_len is the length of the string, without the terminating nul. + * When updating s->s_len, we must subtract 1 from the length that + * we passed into vsnprintf() because that length includes the + * terminating nul. + * + * vsnprintf() returns the amount that would have been copied, + * given sufficient space, hence the min() calculation below. + */ + s->s_len += min(len, SBUF_FREESPACE(s)); + if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s)) + SBUF_SETFLAG(s, SBUF_OVERFLOWED); + + KASSERT(s->s_len < s->s_size, + ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + return (0); +} + +/* + * Format the given arguments and append the resulting string to an sbuf. + */ +int +sbuf_printf(struct sbuf *s, const char *fmt, ...) +{ + va_list ap; + int result; + + va_start(ap, fmt); + result = sbuf_vprintf(s, fmt, ap); + va_end(ap); + return(result); +} + +/* + * Append a character to an sbuf. + */ +int +sbuf_putc(struct sbuf *s, int c) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + + if (!SBUF_HASROOM(s) && sbuf_extend(s, 1) < 0) { + SBUF_SETFLAG(s, SBUF_OVERFLOWED); + return (-1); + } + if (c != '\0') + s->s_buf[s->s_len++] = c; + return (0); +} + +#ifdef KERNEL +static inline int +isspace(char ch) +{ + return (ch == ' ' || ch == '\n' || ch == '\t'); +} +#endif + +/* + * Trim whitespace characters from end of an sbuf. + */ +int +sbuf_trim(struct sbuf *s) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + + while (s->s_len && isspace(s->s_buf[s->s_len-1])) + --s->s_len; + + return (0); +} + +/* + * Check if an sbuf overflowed + */ +int +sbuf_overflowed(struct sbuf *s) +{ + return SBUF_HASOVERFLOWED(s); +} + +/* + * Finish off an sbuf. + */ +void +sbuf_finish(struct sbuf *s) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + s->s_buf[s->s_len] = '\0'; + SBUF_CLEARFLAG(s, SBUF_OVERFLOWED); + SBUF_SETFLAG(s, SBUF_FINISHED); +} + +/* + * Return a pointer to the sbuf data. + */ +char * +sbuf_data(struct sbuf *s) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, SBUF_FINISHED); + + return s->s_buf; +} + +/* + * Return the length of the sbuf data. + */ +int +sbuf_len(struct sbuf *s) +{ + assert_sbuf_integrity(s); + /* don't care if it's finished or not */ + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + return s->s_len; +} + +/* + * Clear an sbuf, free its buffer if necessary. + */ +void +sbuf_delete(struct sbuf *s) +{ + int isdyn; + + assert_sbuf_integrity(s); + /* don't care if it's finished or not */ + + if (SBUF_ISDYNAMIC(s)) + SBFREE(s->s_buf); + isdyn = SBUF_ISDYNSTRUCT(s); + bzero(s, sizeof *s); + if (isdyn) + SBFREE(s); +} + +/* + * Check if an sbuf has been finished. + */ +int +sbuf_done(struct sbuf *s) +{ + + return(SBUF_ISFINISHED(s)); +} From 8253dd79a8bfd60085857022c4c5c1c03990b049 Mon Sep 17 00:00:00 2001 From: Ariel Abreu Date: Tue, 14 Apr 2020 21:20:03 -0400 Subject: [PATCH 3/6] Fix up the new implementation of the new packing algorithm --- xpc_misc.c | 135 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 52 deletions(-) diff --git a/xpc_misc.c b/xpc_misc.c index 00c06e0..1179809 100644 --- a/xpc_misc.c +++ b/xpc_misc.c @@ -37,7 +37,7 @@ #include #include #include "xpc_internal.h" -#include "endian_compat.h" +#include #define RECV_BUFFER_SIZE 65536 @@ -169,28 +169,37 @@ xpc_array_destroy(struct xpc_object *dict) #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) 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 == 0 && buf_size > 0) { + while (buf_size > 0 && buf[buf_size - 1] == 0) --buf_size; - ++buf; - } 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 (*buf & (1 << (i - 1)) == 0) + for (uint8_t i = 8; i > 0; --i) { + if ((msb & (1 << (i - 1))) == 0) { --leading_bit_count; - - if (buf_size == 1 && leading_bit_count < XPC_PACK_TYPE_BITS) - return leading_bit_count + (raw ? 0 : 1); + } else { + break; + } + } // number of bits needed for actual number size_t raw_bits = ((buf_size - 1) * 8) + leading_bit_count; @@ -198,7 +207,10 @@ XPC_INLINE size_t xpc_pack_encode_int_bits(const uint8_t* buf, size_t buf_size, if (raw) return raw_bits; - return raw_bits + ((raw_bits - (XPC_PACK_TYPE_BITS - 1)) / 7) + 1; + if (raw_bits <= XPC_PACK_INT_INITIAL_BITS) + return XPC_PACK_INT_INITIAL_BITS + 1; + + return raw_bits + ((raw_bits - XPC_PACK_INT_INITIAL_BITS) / 7) + 1; }; // buf must be little-endian @@ -206,28 +218,28 @@ XPC_INLINE void xpc_pack_encode_int(uint8_t* out, const uint8_t* buf, size_t buf if (buf_size == 0) return; - uint8_t initial_mask = (0xff << (XPC_PACK_TYPE_BITS + 1)) >> (XPC_PACK_TYPE_BITS + 1); + 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] & ~(uint8_t)initial_mask == 0) + if ((buf[0] & ~initial_mask) == 0) return; out[0] |= 1 << 7; - size_t raw_bits = xpc_pack_encode_int_bits(buf, buf_size, true) - (XPC_PACK_TYPE_BITS - 1); - size_t leftover_bits = 8 - (XPC_PACK_TYPE_BITS - 1); + 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) { + 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 = (0xff >> (8 - leftover_bits)) << (8 - leftover_bits); + 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 = (0xff << (8 - bits_left_in_encoding_segment)) >> (8 - bits_left_in_encoding_segment); + 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; @@ -239,33 +251,37 @@ XPC_INLINE void xpc_pack_encode_int(uint8_t* out, const uint8_t* buf, size_t buf // 0x7f == 0b01111111 out[out_idx - 1] &= 0x7f; } else { - uint8_t prev_byte_mask = (0xff >> (8 - leftover_bits)) << (8 - leftover_bits); + 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) { - // 0x7f == 0b01111111 - uint8_t initial_mask = (0x7f >> XPC_PACK_TYPE_BITS) << XPC_PACK_TYPE_BITS; + // `>> 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) + if ((buf[0] & (1 << 7)) == 0) return 1; - size_t leftover_bits = 8 - (XPC_PACK_TYPE_BITS - 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) { + 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 = (0xff << (8 - leftover_bits)) >> (8 - leftover_bits); + uint8_t prev_byte_mask = xpc_pack_generate_mask(leftover_bits, true); uint8_t bits_left_in_encoding_segment = 7 - leftover_bits; - // 0x7f == 0b01111111 - uint8_t next_byte_mask = (0x7f >> (8 - bits_left_in_encoding_segment)) << (8 - bits_left_in_encoding_segment); + 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; @@ -274,8 +290,13 @@ XPC_INLINE size_t xpc_unpack_decode_int(uint8_t* out, const uint8_t* buf) { ++buf_idx; } - uint8_t prev_byte_mask = (0xff << (8 - leftover_bits)) >> (8 - leftover_bits); + 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; }; @@ -285,11 +306,11 @@ XPC_INLINE struct xpc_object* xpc_unpack(const void* buf, size_t size, size_t* p 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 + *offset, &val_size); + 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 ? htole32(val_size) : htole64(val_size); + 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 = ((size_bits - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8; + 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); @@ -312,7 +333,7 @@ XPC_INLINE struct xpc_object* xpc_unpack_decode_entry(const uint8_t* in, size_t 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 ? le32toh(val_size_le) : le64toh(val_size_le); + 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) { @@ -336,25 +357,26 @@ XPC_INLINE int xpc_pack(struct xpc_object* xo, void* buf, size_t* final_size) { switch (xo->xo_xpc_type) { case _XPC_TYPE_DICTIONARY: { - __block size_t offset = 0; + __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 += 1 + key_size; + size += key_size; if (out) { - offset += 1; 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: { - size_t offset = 0; + __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: { @@ -364,17 +386,17 @@ XPC_INLINE int xpc_pack(struct xpc_object* xo, void* buf, size_t* final_size) { 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 = htole64(val); + int64_t val_le = OSSwapHostToLittleInt64(val); size_t val_bits = xpc_pack_encode_int_bits(&val_le, sizeof(int64_t), false); - size += ((val_bits - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8; + 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->xo_uint); - uint64_t val_le = htole64(val); + 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 += ((val_bits - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8; + size += XPC_PACK_INT_EXTRA_BYTES(val_bits); if (out) xpc_pack_encode_int(out, &val_le, sizeof(uint64_t)); } break; @@ -396,9 +418,9 @@ XPC_INLINE int xpc_pack(struct xpc_object* xo, void* buf, size_t* final_size) { //case _XPC_TYPE_UUID: {} break; case _XPC_TYPE_FD: { int val = xo->xo_u.port; - int val_le = htole32(val); + int val_le = OSSwapHostToLittleInt32(val); size_t val_bits = xpc_pack_encode_int_bits(&val_le, sizeof(int), false); - size += ((val_bits - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8; + size += XPC_PACK_INT_EXTRA_BYTES(val_bits); if (out) xpc_pack_encode_int(out, &val_le, sizeof(int)); } break; @@ -411,9 +433,9 @@ XPC_INLINE int xpc_pack(struct xpc_object* xo, void* buf, size_t* final_size) { // // 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)htole32(*(uint32_t*)&val) : htole64(*(uint64_t*)&val); + 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 += ((val_bits - (8 - XPC_PACK_TYPE_BITS)) + 7) / 8; + size += XPC_PACK_INT_EXTRA_BYTES(val_bits); if (out) xpc_pack_encode_int(out, &val_le, sizeof(uint64_t)); } break; @@ -492,21 +514,29 @@ XPC_INLINE struct xpc_object* xpc_unpack(const void* buf, size_t size, size_t* p case _XPC_TYPE_INT64: { int64_t val_le = 0; offset += xpc_unpack_decode_int(&val_le, in + offset); - int64_t val = le64toh(val_le); + 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 = le64toh(val_le); + uint64_t val = OSSwapLittleToHostInt64(val_le); xo = xpc_uint64_create(val); } break; - case _XPC_TYPE_DATA: {} break; - case _XPC_TYPE_STRING: {} 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 = le32toh(val_le); + int val = OSSwapLittleToHostInt32(val_le); xo = malloc(sizeof(struct xpc_object)); if (xo) { @@ -521,12 +551,13 @@ XPC_INLINE struct xpc_object* xpc_unpack(const void* buf, size_t size, size_t* p case _XPC_TYPE_DOUBLE: { uint64_t uval_le = 0; offset += xpc_unpack_decode_int(&uval_le, in + offset); - uint64_t uval = le64toh(uval_le); + uint64_t uval = OSSwapLittleToHostInt64(uval_le); double val = *(double*)&uval_le; xo = xpc_uint64_create(val); } break; case _XPC_TYPE_NULL: { xo = xpc_null_create(); + ++offset; } break; default: { debugf("can't unpack unsupported type: %d", xo_xpc_type); @@ -909,7 +940,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, NULL, 0); + 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; @@ -972,7 +1003,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, NULL, 0); + 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; From debabdb6bed45098dc24c1f5f23ed42628521571 Mon Sep 17 00:00:00 2001 From: Ariel Abreu Date: Tue, 14 Apr 2020 21:20:41 -0400 Subject: [PATCH 4/6] Increment xo_size when appending to arrays --- xpc_array.c | 1 + 1 file changed, 1 insertion(+) 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; } From 3532d84d705d3bfa8c141eb6b40d5380b88f26ae Mon Sep 17 00:00:00 2001 From: Ariel Abreu Date: Tue, 14 Apr 2020 21:32:30 -0400 Subject: [PATCH 5/6] Fix algorithm explanation note in `xpc_misc.c` --- xpc_misc.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/xpc_misc.c b/xpc_misc.c index 1179809..8216cfc 100644 --- a/xpc_misc.c +++ b/xpc_misc.c @@ -113,15 +113,11 @@ xpc_array_destroy(struct xpc_object *dict) } } -// number of bytes to allocate for the initial call to mach_msg -// 8KiB -#define XPC_MACH_MSG_INTIAL_BUFFER_LEN 8192 - /** * 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) << 4) } + * bool = { 0x03 | ((value ? 0x01 : 0x00) << XPC_PACK_TYPE_BITS) } * connection = { 0x04 } * endpoint = { 0x05 } * null = { 0x06 } @@ -141,8 +137,7 @@ xpc_array_destroy(struct xpc_object *dict) * 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 high four bits in the type byte - * to encode the value. + * 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 @@ -154,11 +149,11 @@ xpc_array_destroy(struct xpc_object *dict) * { value } * * notes: - * * integral values are basically laid out in network-order (big-endian) - * * many types that have variable length do not automatically include a stated length. + * * 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, etc.). + * * 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 From 49f351dda3f1e1d36001f987c20f7d9982322bb7 Mon Sep 17 00:00:00 2001 From: Ariel Abreu Date: Thu, 16 Apr 2020 09:30:12 -0400 Subject: [PATCH 6/6] `xpc_double_create`, not `xpc_uint64_create` --- xpc_misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xpc_misc.c b/xpc_misc.c index 8216cfc..91e4bce 100644 --- a/xpc_misc.c +++ b/xpc_misc.c @@ -548,7 +548,7 @@ XPC_INLINE struct xpc_object* xpc_unpack(const void* buf, size_t size, size_t* p offset += xpc_unpack_decode_int(&uval_le, in + offset); uint64_t uval = OSSwapLittleToHostInt64(uval_le); double val = *(double*)&uval_le; - xo = xpc_uint64_create(val); + xo = xpc_double_create(val); } break; case _XPC_TYPE_NULL: { xo = xpc_null_create();