Index: stable/11/lib/libmd/sha512.3 =================================================================== --- stable/11/lib/libmd/sha512.3 (revision 336345) +++ stable/11/lib/libmd/sha512.3 (revision 336346) @@ -1,210 +1,210 @@ .\" .\" ---------------------------------------------------------------------------- .\" "THE BEER-WARE LICENSE" (Revision 42): .\" wrote this file. As long as you retain this notice you .\" can do whatever you want with this stuff. If we meet some day, and you think .\" this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp .\" ---------------------------------------------------------------------------- .\" .\" From: Id: mdX.3,v 1.14 1999/02/11 20:31:49 wollman Exp .\" $FreeBSD$ .\" .Dd April 22, 2016 .Dt SHA512 3 .Os .Sh NAME .Nm SHA512_Init , .Nm SHA512_Update , .Nm SHA512_Final , .Nm SHA512_End , .Nm SHA512_File , .Nm SHA512_FileChunk , .Nm SHA512_Data , .Nm SHA384_Init , .Nm SHA384_Update , .Nm SHA384_Final , .Nm SHA384_End , .Nm SHA384_File , .Nm SHA384_FileChunk , -.Nm SHA384_Data, +.Nm SHA384_Data , .Nm SHA512_256_Init , .Nm SHA512_256_Update , .Nm SHA512_256_Final , .Nm SHA512_256_End , .Nm SHA512_256_File , .Nm SHA512_256_FileChunk , .Nm SHA512_256_Data .Nd calculate the FIPS 180-4 ``SHA-512'' family of message digests .Sh LIBRARY .Lb libmd .Sh SYNOPSIS .In sys/types.h .In sha512.h .Ft void .Fn SHA512_Init "SHA512_CTX *context" .Ft void .Fn SHA512_Update "SHA512_CTX *context" "const unsigned char *data" "size_t len" .Ft void .Fn SHA512_Final "unsigned char digest[64]" "SHA512_CTX *context" .Ft "char *" .Fn SHA512_End "SHA512_CTX *context" "char *buf" .Ft "char *" .Fn SHA512_File "const char *filename" "char *buf" .Ft "char *" .Fn SHA512_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length" .Ft "char *" .Fn SHA512_Data "const unsigned char *data" "unsigned int len" "char *buf" .In sha384.h .Ft void .Fn SHA384_Init "SHA384_CTX *context" .Ft void .Fn SHA384_Update "SHA384_CTX *context" "const unsigned char *data" "size_t len" .Ft void .Fn SHA384_Final "unsigned char digest[48]" "SHA384_CTX *context" .Ft "char *" .Fn SHA384_End "SHA384_CTX *context" "char *buf" .Ft "char *" .Fn SHA384_File "const char *filename" "char *buf" .Ft "char *" .Fn SHA384_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length" .Ft "char *" .Fn SHA384_Data "const unsigned char *data" "unsigned int len" "char *buf" .In sha512t.h .Ft void .Fn SHA512_256_Init "SHA512_CTX *context" .Ft void .Fn SHA512_256_Update "SHA512_CTX *context" "const unsigned char *data" "size_t len" .Ft void .Fn SHA512_256_Final "unsigned char digest[32]" "SHA512_CTX *context" .Ft "char *" .Fn SHA512_256_End "SHA512_CTX *context" "char *buf" .Ft "char *" .Fn SHA512_256_File "const char *filename" "char *buf" .Ft "char *" .Fn SHA512_256_FileChunk "const char *filename" "char *buf" "off_t offset" "off_t length" .Ft "char *" .Fn SHA512_256_Data "const unsigned char *data" "unsigned int len" "char *buf" .Sh DESCRIPTION The .Li SHA512_ functions calculate a 512-bit cryptographic checksum (digest) for any number of input bytes. A cryptographic checksum is a one-way hash function; that is, it is computationally impractical to find the input corresponding to a particular output. This net result is a .Dq fingerprint of the input-data, which does not disclose the actual input. .Pp The .Fn SHA512_Init , .Fn SHA512_Update , and .Fn SHA512_Final functions are the core functions. Allocate an .Vt SHA512_CTX , initialize it with .Fn SHA512_Init , run over the data with .Fn SHA512_Update , and finally extract the result using .Fn SHA512_Final . .Pp .Fn SHA512_End is a wrapper for .Fn SHA512_Final which converts the return value to a 129-character (including the terminating '\e0') .Tn ASCII string which represents the 512 bits in hexadecimal. .Pp .Fn SHA512_File calculates the digest of a file, and uses .Fn SHA512_End to return the result. If the file cannot be opened, a null pointer is returned. .Fn SHA512_FileChunk is similar to .Fn SHA512_File , but it only calculates the digest over a byte-range of the file specified, starting at .Fa offset and spanning .Fa length bytes. If the .Fa length parameter is specified as 0, or more than the length of the remaining part of the file, .Fn SHA512_FileChunk calculates the digest from .Fa offset to the end of file. .Fn SHA512_Data calculates the digest of a chunk of data in memory, and uses .Fn SHA512_End to return the result. .Pp When using .Fn SHA512_End , .Fn SHA512_File , or .Fn SHA512_Data , the .Fa buf argument can be a null pointer, in which case the returned string is allocated with .Xr malloc 3 and subsequently must be explicitly deallocated using .Xr free 3 after use. If the .Fa buf argument is non-null it must point to at least 129 characters of buffer space. .Pp The .Li SHA384_ and .Li SHA512_256_ functions are identical to the .Li SHA512_ functions except they use a different initial hash value and the output is truncated to 384 bits and 256 bits respectively. .Pp .Fn SHA384_End is a wrapper for .Fn SHA384_Final which converts the return value to a 97-character (including the terminating '\e0') .Tn ASCII string which represents the 384 bits in hexadecimal. .Pp .Fn SHA512_256_End is a wrapper for .Fn SHA512_Final which converts the return value to a 65-character (including the terminating '\e0') .Tn ASCII string which represents the 256 bits in hexadecimal. .Sh SEE ALSO .Xr md4 3 , .Xr md5 3 , .Xr ripemd 3 , .Xr sha 3 , .Xr sha256 3 , .Xr sha512 3 , .Xr skein 3 .Sh HISTORY These functions appeared in .Fx 9.0 . .Sh AUTHORS The core hash routines were implemented by Colin Percival based on the published .Tn FIPS 180-2 standard. .Sh BUGS No method is known to exist which finds two files having the same hash value, nor to find a file with a specific hash value. There is on the other hand no guarantee that such a method does not exist. Index: stable/11/lib/libnv/tests/Makefile =================================================================== --- stable/11/lib/libnv/tests/Makefile (revision 336345) +++ stable/11/lib/libnv/tests/Makefile (revision 336346) @@ -1,20 +1,21 @@ # $FreeBSD$ ATF_TESTS_CXX= \ cnv_tests \ dnv_tests \ nv_array_tests \ nv_tests \ TAP_TESTS_C+= nvlist_add_test +TAP_TESTS_C+= nvlist_append_test TAP_TESTS_C+= nvlist_exists_test TAP_TESTS_C+= nvlist_free_test TAP_TESTS_C+= nvlist_get_test TAP_TESTS_C+= nvlist_move_test TAP_TESTS_C+= nvlist_send_recv_test LIBADD+= nv WARNS?= 3 .include Index: stable/11/lib/libnv/tests/cnv_tests.cc =================================================================== --- stable/11/lib/libnv/tests/cnv_tests.cc (revision 336345) +++ stable/11/lib/libnv/tests/cnv_tests.cc (revision 336346) @@ -1,1508 +1,1508 @@ /*- * Copyright (c) 2016 Adam Starak * 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. * 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$ */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) /* ATF cnvlist_get tests. */ ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_bool); ATF_TEST_CASE_BODY(cnvlist_get_bool) { nvlist_t *nvl; const char *key; bool value; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; value = true; nvlist_add_bool(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_BOOL); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_bool(nvl, key)); ATF_REQUIRE_EQ(cnvlist_get_bool(cookie), value); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_number); ATF_TEST_CASE_BODY(cnvlist_get_number) { nvlist_t *nvl; const char *key; uint64_t value; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; value = 420; nvlist_add_number(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_number(nvl, key)); ATF_REQUIRE_EQ(cnvlist_get_number(cookie), value); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_string); ATF_TEST_CASE_BODY(cnvlist_get_string) { nvlist_t *nvl; const char *key; const char *value; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; value = "text"; nvlist_add_string(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_STRING); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_string(nvl, key)); ATF_REQUIRE_EQ(strcmp(cnvlist_get_string(cookie), value), 0); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_nvlist); ATF_TEST_CASE_BODY(cnvlist_get_nvlist) { nvlist_t *nvl, *value; const nvlist_t *result; const char *key, *subkey; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); value = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); key = "name"; subkey = "subname"; cookie = NULL; /* Add null to 'value' nvlist. */ nvlist_add_null(value, subkey); ATF_REQUIRE_EQ(strcmp(subkey, nvlist_next(value, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(value), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NULL); ATF_REQUIRE(!nvlist_empty(value)); ATF_REQUIRE(nvlist_exists(value, subkey)); ATF_REQUIRE(nvlist_exists_null(value, subkey)); ATF_REQUIRE_EQ(nvlist_next(value, &type, &cookie), static_cast(NULL)); /* Add 'value' nvlist. */ cookie = NULL; nvlist_add_nvlist(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_nvlist(nvl, key)); /* * Assuming nvlist_get_nvlist() is correct check if cnvlist returns * the same pointer. */ result = cnvlist_get_nvlist(cookie); ATF_REQUIRE_EQ(result, nvlist_get_nvlist(nvl, key)); ATF_REQUIRE(result != value); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); /* Validate data inside nvlist. */ cookie = NULL; ATF_REQUIRE_EQ(strcmp(subkey, nvlist_next(result, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(result), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NULL); ATF_REQUIRE(!nvlist_empty(result)); ATF_REQUIRE(nvlist_exists(result, subkey)); ATF_REQUIRE(nvlist_exists_null(result, subkey)); ATF_REQUIRE_EQ(nvlist_next(result, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); nvlist_destroy(value); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_descriptor); ATF_TEST_CASE_BODY(cnvlist_get_descriptor) { nvlist_t *nvl; const char *key; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; nvlist_add_descriptor(nvl, key, STDERR_FILENO); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_DESCRIPTOR); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_descriptor(nvl, key)); ATF_REQUIRE_EQ(fd_is_valid(cnvlist_get_descriptor(cookie)), 1); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_binary); ATF_TEST_CASE_BODY(cnvlist_get_binary) { nvlist_t *nvl; const char *key; void *in_binary; const void *out_binary; void *cookie; int type; size_t in_size, out_size; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; in_size = 13; in_binary = malloc(in_size); ATF_REQUIRE(in_binary != NULL); memset(in_binary, 0xa5, in_size); nvlist_add_binary(nvl, key, in_binary, in_size); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_BINARY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_binary(nvl, key)); out_binary = cnvlist_get_binary(cookie, &out_size); ATF_REQUIRE_EQ(out_size, in_size); ATF_REQUIRE_EQ(memcmp(in_binary, out_binary, out_size), 0); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } /* ATF cnvlist_get array tests. */ ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_bool_array); ATF_TEST_CASE_BODY(cnvlist_get_bool_array) { nvlist_t *nvl; bool in_array[16]; const bool *out_array; const char *key; void *cookie; int type, i; size_t nitems; for (i = 0; i < 16; i++) in_array[i] = (i % 2 == 0); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; nvlist_add_bool_array(nvl, key, in_array, 16); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_BOOL_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_bool_array(nvl, key)); out_array = cnvlist_get_bool_array(cookie, &nitems); ATF_REQUIRE_EQ(nitems, 16); ATF_REQUIRE(out_array != NULL); for (i = 0; i < 16; i++) ATF_REQUIRE_EQ(out_array[i], in_array[i]); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_number_array); ATF_TEST_CASE_BODY(cnvlist_get_number_array) { nvlist_t *nvl; uint64_t in_array[16]; const uint64_t *out_array; const char *key; void *cookie; int type, i; size_t nitems; for (i = 0; i < 16; i++) in_array[i] = i; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; nvlist_add_number_array(nvl, key, in_array, 16); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_number_array(nvl, key)); out_array = cnvlist_get_number_array(cookie, &nitems); ATF_REQUIRE(out_array != NULL); ATF_REQUIRE_EQ(nitems, 16); for (i = 0; i < 16; i++) ATF_REQUIRE_EQ(out_array[i], in_array[i]); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_string_array); ATF_TEST_CASE_BODY(cnvlist_get_string_array) { nvlist_t *nvl; const char *in_array[4] = {"inequality", "sucks", ".", ""}; const char * const *out_array; const char *key; void *cookie; int type, i; size_t nitems; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; nvlist_add_string_array(nvl, key, in_array, 4); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_STRING_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_string_array(nvl, key)); out_array = cnvlist_get_string_array(cookie, &nitems); ATF_REQUIRE_EQ(nitems, 4); ATF_REQUIRE(out_array != NULL); for (i = 0; i < 4; i++) { ATF_REQUIRE(out_array[i] != NULL); ATF_REQUIRE_EQ(strcmp(out_array[i], in_array[i]), 0); } ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_nvlist_array); ATF_TEST_CASE_BODY(cnvlist_get_nvlist_array) { nvlist_t *nvl; nvlist_t *in_array[6]; const nvlist_t * const *out_array; const nvlist_t * const *out_result; void *cookie; const char *key; const char *subkeys; int type, i; size_t nitems; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); subkeys = "123456"; for (i = 0; i < 6; i++) { in_array[i] = nvlist_create(0); ATF_REQUIRE(in_array[i] != NULL); ATF_REQUIRE_EQ(nvlist_error(in_array[i]), 0); ATF_REQUIRE(nvlist_empty(in_array[i])); cookie = NULL; nvlist_add_null(in_array[i], subkeys+i); ATF_REQUIRE_EQ(strcmp(subkeys+i, nvlist_next(in_array[i], &type, &cookie)),0); ATF_REQUIRE_EQ(nvlist_error(in_array[i]), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NULL); ATF_REQUIRE(!nvlist_empty(in_array[i])); ATF_REQUIRE(nvlist_exists(in_array[i], subkeys+i)); ATF_REQUIRE(nvlist_exists_null(in_array[i], subkeys+i)); ATF_REQUIRE_EQ(nvlist_next(in_array[i], &type, &cookie), static_cast(NULL)); } cookie = NULL; key = "name"; nvlist_add_nvlist_array(nvl, key, in_array, 6); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key)); /* Get nvlist array by cnvlist function. */ out_array = cnvlist_get_nvlist_array(cookie, &nitems); ATF_REQUIRE(out_array != NULL); ATF_REQUIRE_EQ(nitems, 6); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); /* Get nvlist array by nvlist function. */ out_result = nvlist_get_nvlist_array(nvl, key, &nitems); ATF_REQUIRE(out_result != NULL); ATF_REQUIRE_EQ(nitems, 6); /* Validate assuming that nvlist returned a proper pointer */ for (i = 0; i < 6; i++) { ATF_REQUIRE_EQ(out_result[i], out_array[i]); ATF_REQUIRE(out_array[i] != in_array[i]); /* Validate data inside nvlist. */ cookie = NULL; ATF_REQUIRE_EQ(strcmp(subkeys+i, nvlist_next(out_array[i], &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(out_array[i]), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NULL); ATF_REQUIRE(!nvlist_empty(out_array[i])); ATF_REQUIRE(nvlist_exists(out_array[i], subkeys+i)); ATF_REQUIRE(nvlist_exists_null(out_array[i], subkeys+i)); ATF_REQUIRE_EQ(nvlist_next(out_array[i], &type, &cookie), static_cast(NULL)); } nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_descriptor_array); ATF_TEST_CASE_BODY(cnvlist_get_descriptor_array) { nvlist_t *nvl; size_t count, i, nitems; const int *out_array; int *in_array, type; const char *key; void *cookie; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; count = 50; in_array = static_cast(malloc(sizeof(*in_array)*count)); ATF_REQUIRE(in_array != NULL); for (i = 0; i < count; i++) { in_array[i] = dup(STDERR_FILENO); ATF_REQUIRE(fd_is_valid(in_array[i])); } nvlist_add_descriptor_array(nvl, key, in_array, count); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_DESCRIPTOR_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, key)); out_array = cnvlist_get_descriptor_array(cookie, &nitems); ATF_REQUIRE_EQ(nitems, count); ATF_REQUIRE(out_array != NULL); for (i = 0; i < count; i++) ATF_REQUIRE_EQ(fd_is_valid(out_array[i]), 1); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } /* ATF cnvlist_take tests. */ ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_bool); ATF_TEST_CASE_BODY(cnvlist_take_bool) { nvlist_t *nvl; const char *key; bool value; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; value = true; nvlist_add_bool(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_BOOL); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_bool(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - ATF_REQUIRE_EQ(cnvlist_take_bool(nvl, cookie), value); + ATF_REQUIRE_EQ(cnvlist_take_bool(cookie), value); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_bool(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_number); ATF_TEST_CASE_BODY(cnvlist_take_number) { nvlist_t *nvl; const char *key; uint64_t value; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; value = 69; nvlist_add_number(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_number(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - ATF_REQUIRE_EQ(cnvlist_take_number(nvl, cookie), value); + ATF_REQUIRE_EQ(cnvlist_take_number(cookie), value); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_number(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_string); ATF_TEST_CASE_BODY(cnvlist_take_string) { nvlist_t *nvl; const char *key; const char *value; char *out_string; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; value = "text"; nvlist_add_string(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_STRING); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_string(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - out_string = cnvlist_take_string(nvl, cookie); + out_string = cnvlist_take_string(cookie); ATF_REQUIRE(out_string != NULL); ATF_REQUIRE_EQ(strcmp(out_string, value), 0); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_string(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); free(out_string); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_nvlist); ATF_TEST_CASE_BODY(cnvlist_take_nvlist) { nvlist_t *nvl, *value, *result; const char *key, *subkey; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); value = nvlist_create(0); ATF_REQUIRE(value != NULL); ATF_REQUIRE_EQ(nvlist_error(value), 0); ATF_REQUIRE(nvlist_empty(value)); key = "name"; subkey = "subname"; cookie = NULL; /* Add null to 'value' nvlist. */ nvlist_add_null(value, subkey); ATF_REQUIRE_EQ(strcmp(subkey, nvlist_next(value, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(value), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NULL); ATF_REQUIRE(!nvlist_empty(value)); ATF_REQUIRE(nvlist_exists(value, subkey)); ATF_REQUIRE(nvlist_exists_null(value, subkey)); ATF_REQUIRE_EQ(nvlist_next(value, &type, &cookie), static_cast(NULL)); /* Add 'value' nvlist. */ cookie = NULL; nvlist_move_nvlist(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_nvlist(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - result = cnvlist_take_nvlist(nvl, cookie); + result = cnvlist_take_nvlist(cookie); ATF_REQUIRE(!nvlist_exists_nvlist(nvl, key)); ATF_REQUIRE(result == value); /* Validate data inside nvlist. */ cookie = NULL; ATF_REQUIRE_EQ(strcmp(subkey, nvlist_next(result, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(value), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NULL); ATF_REQUIRE(!nvlist_empty(value)); ATF_REQUIRE(nvlist_exists(value, subkey)); ATF_REQUIRE(nvlist_exists_null(value, subkey)); ATF_REQUIRE_EQ(nvlist_next(value, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); nvlist_destroy(value); } /* ATF cnvlist_take array tests */ ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_bool_array); ATF_TEST_CASE_BODY(cnvlist_take_bool_array) { nvlist_t *nvl; bool in_array[16]; const bool *out_array; const char *key; void *cookie; int type, i; size_t nitems; for (i = 0; i < 16; i++) in_array[i] = (i % 2 == 0); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; nvlist_add_bool_array(nvl, key, in_array, 16); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_BOOL_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_bool_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - out_array = cnvlist_take_bool_array(nvl, cookie, &nitems); + out_array = cnvlist_take_bool_array(cookie, &nitems); ATF_REQUIRE_EQ(nitems, 16); ATF_REQUIRE(out_array != NULL); for (i = 0; i < 16; i++) ATF_REQUIRE_EQ(out_array[i], in_array[i]); cookie = NULL; ATF_REQUIRE(!nvlist_exists_bool_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_number_array); ATF_TEST_CASE_BODY(cnvlist_take_number_array) { nvlist_t *nvl; uint64_t in_array[16]; const uint64_t *out_array; const char *key; void *cookie; int type, i; size_t nitems; for (i = 0; i < 16; i++) in_array[i] = i; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; nvlist_add_number_array(nvl, key, in_array, 16); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_number_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - out_array = cnvlist_take_number_array(nvl, cookie, &nitems); + out_array = cnvlist_take_number_array(cookie, &nitems); ATF_REQUIRE(out_array != NULL); ATF_REQUIRE_EQ(nitems, 16); for (i = 0; i < 16; i++) ATF_REQUIRE_EQ(out_array[i], in_array[i]); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_number_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_string_array); ATF_TEST_CASE_BODY(cnvlist_take_string_array) { nvlist_t *nvl; const char *in_array[4] = {"inequality", "sks", ".", ""}; char **out_array; const char *key; void *cookie; int type, i; size_t nitems; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; nvlist_add_string_array(nvl, key, in_array, 4); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_STRING_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_string_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - out_array = cnvlist_take_string_array(nvl, cookie, &nitems); + out_array = cnvlist_take_string_array(cookie, &nitems); ATF_REQUIRE_EQ(nitems, 4); for (i = 0; i < 4; i++) { ATF_REQUIRE(out_array[i] != NULL); ATF_REQUIRE_EQ(strcmp(out_array[i], in_array[i]), 0); } ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_number_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); free(out_array); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_nvlist_array); ATF_TEST_CASE_BODY(cnvlist_take_nvlist_array) { nvlist_t *testnvl[8]; nvlist_t **result; nvlist_t *nvl; void *cookie; size_t num_items; unsigned int i; int type; const char *somestr[8] = { "a", "b", "c", "d", "e", "f", "g", "h" }; const char *key; for (i = 0; i < 8; i++) { testnvl[i] = nvlist_create(0); ATF_REQUIRE(testnvl[i] != NULL); ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0); ATF_REQUIRE(nvlist_empty(testnvl[i])); nvlist_add_string(testnvl[i], "nvl/string", somestr[i]); cookie = NULL; ATF_REQUIRE_EQ(strcmp("nvl/string", nvlist_next(testnvl[i], &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0); ATF_REQUIRE_EQ(type, NV_TYPE_STRING); ATF_REQUIRE(!nvlist_empty(testnvl[i])); ATF_REQUIRE(nvlist_exists(testnvl[i], "nvl/string")); ATF_REQUIRE(nvlist_exists_string(testnvl[i], "nvl/string")); ATF_REQUIRE_EQ(nvlist_next(testnvl[i], &type, &cookie), static_cast(NULL)); } nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); key = "nvl/nvlist"; cookie = NULL; nvlist_add_nvlist_array(nvl, key, (const nvlist_t * const *)testnvl, 8); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - result = cnvlist_take_nvlist_array(nvl, cookie, &num_items); + result = cnvlist_take_nvlist_array(cookie, &num_items); ATF_REQUIRE(result != NULL); ATF_REQUIRE_EQ(num_items, 8); for (i = 0; i < num_items; i++) { ATF_REQUIRE_EQ(nvlist_error(result[i]), 0); ATF_REQUIRE(nvlist_get_array_next(result[i]) == NULL); } ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_nvlist_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); for (i = 0; i < 8; i++) { nvlist_destroy(result[i]); nvlist_destroy(testnvl[i]); } free(result); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_binary); ATF_TEST_CASE_BODY(cnvlist_take_binary) { nvlist_t *nvl; const char *key; void *in_binary; const void *out_binary; void *cookie; int type; size_t in_size, out_size; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; in_size = 13; in_binary = malloc(in_size); ATF_REQUIRE(in_binary != NULL); memset(in_binary, 0xa5, in_size); nvlist_add_binary(nvl, key, in_binary, in_size); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_BINARY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_binary(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - out_binary = cnvlist_take_binary(nvl, cookie, &out_size); + out_binary = cnvlist_take_binary(cookie, &out_size); ATF_REQUIRE_EQ(out_size, in_size); ATF_REQUIRE_EQ(memcmp(in_binary, out_binary, out_size), 0); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_binary(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } /* ATF cnvlist_free tests. */ ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_bool); ATF_TEST_CASE_BODY(cnvlist_free_bool) { nvlist_t *nvl; const char *key; bool value; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; value = true; nvlist_add_bool(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_BOOL); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_bool(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - cnvlist_free_bool(nvl, cookie); + cnvlist_free_bool(cookie); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_bool(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_number); ATF_TEST_CASE_BODY(cnvlist_free_number) { nvlist_t *nvl; const char *key; uint64_t value; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; value = 69; nvlist_add_number(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_number(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - cnvlist_free_number(nvl, cookie); + cnvlist_free_number(cookie); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_number(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_string); ATF_TEST_CASE_BODY(cnvlist_free_string) { nvlist_t *nvl; const char *key; const char *value; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; value = "text"; nvlist_add_string(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_STRING); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_string(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - cnvlist_free_string(nvl, cookie); + cnvlist_free_string(cookie); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_string(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_nvlist); ATF_TEST_CASE_BODY(cnvlist_free_nvlist) { nvlist_t *nvl, *value; const char *key, *subkey; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); value = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); key = "name"; subkey = "subname"; cookie = NULL; /* Add null to 'value' nvlist. */ nvlist_add_null(value, subkey); ATF_REQUIRE_EQ(strcmp(subkey, nvlist_next(value, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(value), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NULL); ATF_REQUIRE(!nvlist_empty(value)); ATF_REQUIRE(nvlist_exists(value, subkey)); ATF_REQUIRE(nvlist_exists_null(value, subkey)); ATF_REQUIRE_EQ(nvlist_next(value, &type, &cookie), static_cast(NULL)); /* Add 'value' nvlist. */ cookie = NULL; nvlist_move_nvlist(nvl, key, value); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_nvlist(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - cnvlist_free_nvlist(nvl, cookie); + cnvlist_free_nvlist(cookie); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_nvlist(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_binary); ATF_TEST_CASE_BODY(cnvlist_free_binary) { nvlist_t *nvl; const char *key; void *in_binary; void *cookie; int type; size_t in_size; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; in_size = 13; in_binary = malloc(in_size); ATF_REQUIRE(in_binary != NULL); memset(in_binary, 0xa5, in_size); nvlist_add_binary(nvl, key, in_binary, in_size); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_BINARY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_binary(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - cnvlist_free_binary(nvl, cookie); + cnvlist_free_binary(cookie); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_nvlist(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } /* ATF cnvlist_free array tests. */ ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_bool_array); ATF_TEST_CASE_BODY(cnvlist_free_bool_array) { nvlist_t *nvl; bool in_array[16]; const char *key; void *cookie; int type, i; for (i = 0; i < 16; i++) in_array[i] = (i % 2 == 0); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; nvlist_add_bool_array(nvl, key, in_array, 16); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_BOOL_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_bool_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - cnvlist_free_bool_array(nvl, cookie); + cnvlist_free_bool_array(cookie); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_bool(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_number_array); ATF_TEST_CASE_BODY(cnvlist_free_number_array) { nvlist_t *nvl; uint64_t in_array[16]; const char *key; void *cookie; int type, i; for (i = 0; i < 16; i++) in_array[i] = i; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; nvlist_add_number_array(nvl, key, in_array, 16); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_number_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - cnvlist_free_number_array(nvl, cookie); + cnvlist_free_number_array(cookie); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_number_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_string_array); ATF_TEST_CASE_BODY(cnvlist_free_string_array) { nvlist_t *nvl; const char *in_array[4] = {"inequality", "sucks", ".", ""}; const char *key; void *cookie; int type; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); cookie = NULL; key = "name"; nvlist_add_string_array(nvl, key, in_array, 4); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_STRING_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_string_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - cnvlist_free_string_array(nvl, cookie); + cnvlist_free_string_array(cookie); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_nvlist_array); ATF_TEST_CASE_BODY(cnvlist_free_nvlist_array) { nvlist_t *testnvl[8]; nvlist_t *nvl; void *cookie; unsigned int i; int type; const char *somestr[8] = { "a", "b", "c", "d", "e", "f", "g", "h" }; const char *key; for (i = 0; i < 8; i++) { testnvl[i] = nvlist_create(0); ATF_REQUIRE(testnvl[i] != NULL); ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0); ATF_REQUIRE(nvlist_empty(testnvl[i])); nvlist_add_string(testnvl[i], "nvl/string", somestr[i]); cookie = NULL; ATF_REQUIRE_EQ(strcmp("nvl/string", nvlist_next(testnvl[i], &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0); ATF_REQUIRE_EQ(type, NV_TYPE_STRING); ATF_REQUIRE(!nvlist_empty(testnvl[i])); ATF_REQUIRE(nvlist_exists(testnvl[i], "nvl/string")); ATF_REQUIRE(nvlist_exists_string(testnvl[i], "nvl/string")); ATF_REQUIRE_EQ(nvlist_next(testnvl[i], &type, &cookie), static_cast(NULL)); } nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); key = "nvl/nvlist"; cookie = NULL; nvlist_add_nvlist_array(nvl, key, (const nvlist_t * const *)testnvl, 8); ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST_ARRAY); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists(nvl, key)); ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); cookie = NULL; ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0); - cnvlist_free_nvlist_array(nvl, cookie); + cnvlist_free_nvlist_array(cookie); cookie = NULL; ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists(nvl, key)); ATF_REQUIRE(!nvlist_exists_nvlist_array(nvl, key)); ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie), static_cast(NULL)); for (i = 0; i < 8; i++) nvlist_destroy(testnvl[i]); nvlist_destroy(nvl); } ATF_INIT_TEST_CASES(tp) { ATF_ADD_TEST_CASE(tp, cnvlist_get_bool); ATF_ADD_TEST_CASE(tp, cnvlist_get_bool_array); ATF_ADD_TEST_CASE(tp, cnvlist_get_number); ATF_ADD_TEST_CASE(tp, cnvlist_get_string); ATF_ADD_TEST_CASE(tp, cnvlist_get_nvlist); ATF_ADD_TEST_CASE(tp, cnvlist_get_descriptor); ATF_ADD_TEST_CASE(tp, cnvlist_get_binary); ATF_ADD_TEST_CASE(tp, cnvlist_get_number_array); ATF_ADD_TEST_CASE(tp, cnvlist_get_string_array); ATF_ADD_TEST_CASE(tp, cnvlist_get_nvlist_array); ATF_ADD_TEST_CASE(tp, cnvlist_get_descriptor_array); ATF_ADD_TEST_CASE(tp, cnvlist_take_bool); ATF_ADD_TEST_CASE(tp, cnvlist_take_number); ATF_ADD_TEST_CASE(tp, cnvlist_take_string); ATF_ADD_TEST_CASE(tp, cnvlist_take_nvlist); ATF_ADD_TEST_CASE(tp, cnvlist_take_binary); ATF_ADD_TEST_CASE(tp, cnvlist_take_bool_array); ATF_ADD_TEST_CASE(tp, cnvlist_take_number_array); ATF_ADD_TEST_CASE(tp, cnvlist_take_string_array); ATF_ADD_TEST_CASE(tp, cnvlist_take_nvlist_array); ATF_ADD_TEST_CASE(tp, cnvlist_free_bool); ATF_ADD_TEST_CASE(tp, cnvlist_free_number); ATF_ADD_TEST_CASE(tp, cnvlist_free_string); ATF_ADD_TEST_CASE(tp, cnvlist_free_nvlist); ATF_ADD_TEST_CASE(tp, cnvlist_free_binary); ATF_ADD_TEST_CASE(tp, cnvlist_free_bool_array); ATF_ADD_TEST_CASE(tp, cnvlist_free_number_array); ATF_ADD_TEST_CASE(tp, cnvlist_free_string_array); ATF_ADD_TEST_CASE(tp, cnvlist_free_nvlist_array); } Index: stable/11/lib/libnv/tests/nv_array_tests.cc =================================================================== --- stable/11/lib/libnv/tests/nv_array_tests.cc (revision 336345) +++ stable/11/lib/libnv/tests/nv_array_tests.cc (revision 336346) @@ -1,1196 +1,1197 @@ /*- * Copyright (c) 2015 Mariusz Zaborski * 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. * 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 AUTHOR 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 AUTHOR 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 #include #include #include #include #include #include #include #include #include #define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) ATF_TEST_CASE_WITHOUT_HEAD(nvlist_bool_array__basic); ATF_TEST_CASE_BODY(nvlist_bool_array__basic) { bool testbool[16]; const bool *const_result; bool *result; nvlist_t *nvl; size_t num_items; unsigned int i; const char *key; key = "nvl/bool"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); for (i = 0; i < 16; i++) testbool[i] = (i % 2 == 0); nvlist_add_bool_array(nvl, key, testbool, 16); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_bool_array(nvl, key)); ATF_REQUIRE(nvlist_exists_bool_array(nvl, "nvl/bool")); const_result = nvlist_get_bool_array(nvl, key, &num_items); ATF_REQUIRE_EQ(num_items, 16); ATF_REQUIRE(const_result != NULL); for (i = 0; i < num_items; i++) ATF_REQUIRE_EQ(const_result[i], testbool[i]); result = nvlist_take_bool_array(nvl, key, &num_items); ATF_REQUIRE_EQ(num_items, 16); ATF_REQUIRE(const_result != NULL); for (i = 0; i < num_items; i++) ATF_REQUIRE_EQ(result[i], testbool[i]); ATF_REQUIRE(!nvlist_exists_bool_array(nvl, key)); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); free(result); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array__basic); ATF_TEST_CASE_BODY(nvlist_string_array__basic) { const char * const *const_result; char **result; nvlist_t *nvl; size_t num_items; unsigned int i; const char *key; const char *string_arr[8] = { "a", "b", "kot", "foo", "tests", "nice test", "", "abcdef" }; key = "nvl/string"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); nvlist_add_string_array(nvl, key, string_arr, nitems(string_arr)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_string_array(nvl, key)); ATF_REQUIRE(nvlist_exists_string_array(nvl, "nvl/string")); const_result = nvlist_get_string_array(nvl, key, &num_items); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE(num_items == nitems(string_arr)); for (i = 0; i < num_items; i++) { if (string_arr[i] != NULL) { ATF_REQUIRE(strcmp(const_result[i], string_arr[i]) == 0); } else { ATF_REQUIRE(const_result[i] == string_arr[i]); } } result = nvlist_take_string_array(nvl, key, &num_items); ATF_REQUIRE(result != NULL); ATF_REQUIRE_EQ(num_items, nitems(string_arr)); for (i = 0; i < num_items; i++) { if (string_arr[i] != NULL) { ATF_REQUIRE_EQ(strcmp(result[i], string_arr[i]), 0); } else { ATF_REQUIRE_EQ(result[i], string_arr[i]); } } ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); for (i = 0; i < num_items; i++) free(result[i]); free(result); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_descriptor_array__basic); ATF_TEST_CASE_BODY(nvlist_descriptor_array__basic) { int fd[32], *result; const int *const_result; nvlist_t *nvl; size_t num_items; unsigned int i; const char *key; for (i = 0; i < nitems(fd); i++) { fd[i] = dup(STDERR_FILENO); ATF_REQUIRE(fd_is_valid(fd[i])); } key = "nvl/descriptor"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_descriptor_array(nvl, key)); nvlist_add_descriptor_array(nvl, key, fd, nitems(fd)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, key)); ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, "nvl/descriptor")); const_result = nvlist_get_descriptor_array(nvl, key, &num_items); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE(num_items == nitems(fd)); for (i = 0; i < num_items; i++) { ATF_REQUIRE(fd_is_valid(const_result[i])); if (i > 0) ATF_REQUIRE(const_result[i] != const_result[i - 1]); } result = nvlist_take_descriptor_array(nvl, key, &num_items); ATF_REQUIRE(result != NULL); ATF_REQUIRE_EQ(num_items, nitems(fd)); for (i = 0; i < num_items; i++) { ATF_REQUIRE(fd_is_valid(result[i])); if (i > 0) ATF_REQUIRE(const_result[i] != const_result[i - 1]); } ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); for (i = 0; i < num_items; i++) { close(result[i]); close(fd[i]); } free(result); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_number_array__basic); ATF_TEST_CASE_BODY(nvlist_number_array__basic) { const uint64_t *const_result; uint64_t *result; nvlist_t *nvl; size_t num_items; unsigned int i; const char *key; const uint64_t number[8] = { 0, UINT_MAX, 7, 123, 90, 100000, 8, 1 }; key = "nvl/number"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); nvlist_add_number_array(nvl, key, number, nitems(number)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_number_array(nvl, key)); ATF_REQUIRE(nvlist_exists_number_array(nvl, "nvl/number")); const_result = nvlist_get_number_array(nvl, key, &num_items); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE(num_items == nitems(number)); for (i = 0; i < num_items; i++) ATF_REQUIRE_EQ(const_result[i], number[i]); result = nvlist_take_number_array(nvl, key, &num_items); ATF_REQUIRE(result != NULL); ATF_REQUIRE_EQ(num_items, nitems(number)); for (i = 0; i < num_items; i++) ATF_REQUIRE_EQ(result[i], number[i]); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); free(result); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_nvlist_array__basic); ATF_TEST_CASE_BODY(nvlist_nvlist_array__basic) { nvlist_t *testnvl[8]; const nvlist_t * const *const_result; nvlist_t **result; nvlist_t *nvl; size_t num_items; unsigned int i; const char *somestr[8] = { "a", "b", "c", "d", "e", "f", "g", "h" }; const char *key; for (i = 0; i < 8; i++) { testnvl[i] = nvlist_create(0); ATF_REQUIRE(testnvl[i] != NULL); ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0); nvlist_add_string(testnvl[i], "nvl/string", somestr[i]); ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0); ATF_REQUIRE(nvlist_exists_string(testnvl[i], "nvl/string")); } key = "nvl/nvlist"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); nvlist_add_nvlist_array(nvl, key, (const nvlist_t * const *)testnvl, 8); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key)); ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, "nvl/nvlist")); const_result = nvlist_get_nvlist_array(nvl, key, &num_items); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE(num_items == nitems(testnvl)); for (i = 0; i < num_items; i++) { ATF_REQUIRE_EQ(nvlist_error(const_result[i]), 0); if (i < num_items - 1) { ATF_REQUIRE(nvlist_get_array_next(const_result[i]) == const_result[i + 1]); } else { ATF_REQUIRE(nvlist_get_array_next(const_result[i]) == NULL); } ATF_REQUIRE(nvlist_get_parent(const_result[i], NULL) == nvl); ATF_REQUIRE(nvlist_in_array(const_result[i])); ATF_REQUIRE(nvlist_exists_string(const_result[i], "nvl/string")); ATF_REQUIRE(strcmp(nvlist_get_string(const_result[i], "nvl/string"), somestr[i]) == 0); } result = nvlist_take_nvlist_array(nvl, key, &num_items); ATF_REQUIRE(result != NULL); ATF_REQUIRE_EQ(num_items, 8); for (i = 0; i < num_items; i++) { ATF_REQUIRE_EQ(nvlist_error(result[i]), 0); ATF_REQUIRE(nvlist_get_array_next(result[i]) == NULL); + ATF_REQUIRE(nvlist_get_parent(result[i], NULL) == NULL); ATF_REQUIRE(nvlist_get_array_next(const_result[i]) == NULL); ATF_REQUIRE(!nvlist_in_array(const_result[i])); } ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); for (i = 0; i < 8; i++) { nvlist_destroy(result[i]); nvlist_destroy(testnvl[i]); } free(result); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_clone_array); ATF_TEST_CASE_BODY(nvlist_clone_array) { nvlist_t *testnvl[8]; nvlist_t *src, *dst; const nvlist_t *nvl; bool testbool[16]; int testfd[16]; size_t i, num_items; const char *string_arr[8] = { "a", "b", "kot", "foo", "tests", "nice test", "", "abcdef" }; const char *somestr[8] = { "a", "b", "c", "d", "e", "f", "g", "h" }; const uint64_t number[8] = { 0, UINT_MAX, 7, 123, 90, 100000, 8, 1 }; for (i = 0; i < nitems(testfd); i++) { testbool[i] = (i % 2 == 0); testfd[i] = dup(STDERR_FILENO); ATF_REQUIRE(fd_is_valid(testfd[i])); } for (i = 0; i < nitems(testnvl); i++) { testnvl[i] = nvlist_create(0); ATF_REQUIRE(nvlist_error(testnvl[i]) == 0); nvlist_add_string(testnvl[i], "nvl/nvl/teststr", somestr[i]); ATF_REQUIRE(nvlist_error(testnvl[i]) == 0); } src = nvlist_create(0); ATF_REQUIRE(nvlist_error(src) == 0); ATF_REQUIRE(!nvlist_exists_bool_array(src, "nvl/bool")); nvlist_add_bool_array(src, "nvl/bool", testbool, nitems(testbool)); ATF_REQUIRE_EQ(nvlist_error(src), 0); ATF_REQUIRE(nvlist_exists_bool_array(src, "nvl/bool")); ATF_REQUIRE(!nvlist_exists_string_array(src, "nvl/string")); nvlist_add_string_array(src, "nvl/string", string_arr, nitems(string_arr)); ATF_REQUIRE_EQ(nvlist_error(src), 0); ATF_REQUIRE(nvlist_exists_string_array(src, "nvl/string")); ATF_REQUIRE(!nvlist_exists_descriptor_array(src, "nvl/fd")); nvlist_add_descriptor_array(src, "nvl/fd", testfd, nitems(testfd)); ATF_REQUIRE_EQ(nvlist_error(src), 0); ATF_REQUIRE(nvlist_exists_descriptor_array(src, "nvl/fd")); ATF_REQUIRE(!nvlist_exists_number_array(src, "nvl/number")); nvlist_add_number_array(src, "nvl/number", number, nitems(number)); ATF_REQUIRE_EQ(nvlist_error(src), 0); ATF_REQUIRE(nvlist_exists_number_array(src, "nvl/number")); ATF_REQUIRE(!nvlist_exists_nvlist_array(src, "nvl/array")); nvlist_add_nvlist_array(src, "nvl/array", (const nvlist_t * const *)testnvl, nitems(testnvl)); ATF_REQUIRE_EQ(nvlist_error(src), 0); ATF_REQUIRE(nvlist_exists_nvlist_array(src, "nvl/array")); dst = nvlist_clone(src); ATF_REQUIRE(dst != NULL); ATF_REQUIRE(nvlist_exists_bool_array(dst, "nvl/bool")); (void) nvlist_get_bool_array(dst, "nvl/bool", &num_items); ATF_REQUIRE_EQ(num_items, nitems(testbool)); for (i = 0; i < num_items; i++) { ATF_REQUIRE( nvlist_get_bool_array(dst, "nvl/bool", &num_items)[i] == nvlist_get_bool_array(src, "nvl/bool", &num_items)[i]); } ATF_REQUIRE(nvlist_exists_string_array(dst, "nvl/string")); (void) nvlist_get_string_array(dst, "nvl/string", &num_items); ATF_REQUIRE_EQ(num_items, nitems(string_arr)); for (i = 0; i < num_items; i++) { if (nvlist_get_string_array(dst, "nvl/string", &num_items)[i] == NULL) { ATF_REQUIRE(nvlist_get_string_array(dst, "nvl/string", &num_items)[i] == nvlist_get_string_array(src, "nvl/string", &num_items)[i]); } else { ATF_REQUIRE(strcmp(nvlist_get_string_array(dst, "nvl/string", &num_items)[i], nvlist_get_string_array( src, "nvl/string", &num_items)[i]) == 0); } } ATF_REQUIRE(nvlist_exists_descriptor_array(dst, "nvl/fd")); (void) nvlist_get_descriptor_array(dst, "nvl/fd", &num_items); ATF_REQUIRE_EQ(num_items, nitems(testfd)); for (i = 0; i < num_items; i++) { ATF_REQUIRE(fd_is_valid( nvlist_get_descriptor_array(dst, "nvl/fd", &num_items)[i])); } ATF_REQUIRE(nvlist_exists_number_array(dst, "nvl/number")); (void) nvlist_get_number_array(dst, "nvl/number", &num_items); ATF_REQUIRE_EQ(num_items, nitems(number)); for (i = 0; i < num_items; i++) { ATF_REQUIRE( nvlist_get_number_array(dst, "nvl/number", &num_items)[i] == nvlist_get_number_array(src, "nvl/number", &num_items)[i]); } ATF_REQUIRE(nvlist_exists_nvlist_array(dst, "nvl/array")); (void) nvlist_get_nvlist_array(dst, "nvl/array", &num_items); ATF_REQUIRE_EQ(num_items, nitems(testnvl)); for (i = 0; i < num_items; i++) { nvl = nvlist_get_nvlist_array(dst, "nvl/array", &num_items)[i]; ATF_REQUIRE(nvlist_exists_string(nvl, "nvl/nvl/teststr")); ATF_REQUIRE(strcmp(nvlist_get_string(nvl, "nvl/nvl/teststr"), somestr[i]) == 0); } for (i = 0; i < nitems(testfd); i++) { close(testfd[i]); } for (i = 0; i < nitems(testnvl); i++) { nvlist_destroy(testnvl[i]); } nvlist_destroy(src); nvlist_destroy(dst); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_bool_array__move); ATF_TEST_CASE_BODY(nvlist_bool_array__move) { bool *testbool; const bool *const_result; nvlist_t *nvl; size_t num_items, count; unsigned int i; const char *key; key = "nvl/bool"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); count = 16; testbool = (bool*)malloc(sizeof(*testbool) * count); ATF_REQUIRE(testbool != NULL); for (i = 0; i < count; i++) testbool[i] = (i % 2 == 0); nvlist_move_bool_array(nvl, key, testbool, count); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_bool_array(nvl, key)); const_result = nvlist_get_bool_array(nvl, key, &num_items); ATF_REQUIRE_EQ(num_items, count); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE(const_result == testbool); for (i = 0; i < num_items; i++) ATF_REQUIRE_EQ(const_result[i], (i % 2 == 0)); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array__move); ATF_TEST_CASE_BODY(nvlist_string_array__move) { char **teststr; const char * const *const_result; nvlist_t *nvl; size_t num_items, count; unsigned int i; const char *key; key = "nvl/string"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); count = 26; teststr = (char**)malloc(sizeof(*teststr) * count); ATF_REQUIRE(teststr != NULL); for (i = 0; i < count; i++) { teststr[i] = (char*)malloc(sizeof(**teststr) * 2); ATF_REQUIRE(teststr[i] != NULL); teststr[i][0] = 'a' + i; teststr[i][1] = '\0'; } nvlist_move_string_array(nvl, key, teststr, count); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_string_array(nvl, key)); const_result = nvlist_get_string_array(nvl, key, &num_items); ATF_REQUIRE_EQ(num_items, count); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE((intptr_t)const_result == (intptr_t)teststr); for (i = 0; i < num_items; i++) { ATF_REQUIRE_EQ(const_result[i][0], (char)('a' + i)); ATF_REQUIRE_EQ(const_result[i][1], '\0'); } nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_nvlist_array__move); ATF_TEST_CASE_BODY(nvlist_nvlist_array__move) { nvlist **testnv; const nvlist * const *const_result; nvlist_t *nvl; size_t num_items, count; unsigned int i; const char *key; key = "nvl/nvlist"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_nvlist_array(nvl, key)); count = 26; testnv = (nvlist**)malloc(sizeof(*testnv) * count); ATF_REQUIRE(testnv != NULL); for (i = 0; i < count; i++) { testnv[i] = nvlist_create(0); ATF_REQUIRE(testnv[i] != NULL); } nvlist_move_nvlist_array(nvl, key, testnv, count); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key)); const_result = nvlist_get_nvlist_array(nvl, key, &num_items); ATF_REQUIRE_EQ(num_items, count); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE((intptr_t)const_result == (intptr_t)testnv); for (i = 0; i < num_items; i++) { ATF_REQUIRE_EQ(nvlist_error(const_result[i]), 0); ATF_REQUIRE(nvlist_empty(const_result[i])); if (i < num_items - 1) { ATF_REQUIRE(nvlist_get_array_next(const_result[i]) == const_result[i + 1]); } else { ATF_REQUIRE(nvlist_get_array_next(const_result[i]) == NULL); } ATF_REQUIRE(nvlist_get_parent(const_result[i], NULL) == nvl); ATF_REQUIRE(nvlist_in_array(const_result[i])); } nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_number_array__move); ATF_TEST_CASE_BODY(nvlist_number_array__move) { uint64_t *testnumber; const uint64_t *const_result; nvlist_t *nvl; size_t num_items, count; unsigned int i; const char *key; key = "nvl/number"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); count = 1000; testnumber = (uint64_t*)malloc(sizeof(*testnumber) * count); ATF_REQUIRE(testnumber != NULL); for (i = 0; i < count; i++) testnumber[i] = i; nvlist_move_number_array(nvl, key, testnumber, count); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_number_array(nvl, key)); const_result = nvlist_get_number_array(nvl, key, &num_items); ATF_REQUIRE_EQ(num_items, count); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE(const_result == testnumber); for (i = 0; i < num_items; i++) ATF_REQUIRE_EQ(const_result[i], i); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_descriptor_array__move); ATF_TEST_CASE_BODY(nvlist_descriptor_array__move) { int *testfd; const int *const_result; nvlist_t *nvl; size_t num_items, count; unsigned int i; const char *key; key = "nvl/fd"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); count = 50; testfd = (int*)malloc(sizeof(*testfd) * count); ATF_REQUIRE(testfd != NULL); for (i = 0; i < count; i++) { testfd[i] = dup(STDERR_FILENO); ATF_REQUIRE(fd_is_valid(testfd[i])); } nvlist_move_descriptor_array(nvl, key, testfd, count); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, key)); const_result = nvlist_get_descriptor_array(nvl, key, &num_items); ATF_REQUIRE_EQ(num_items, count); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE(const_result == testfd); for (i = 0; i < num_items; i++) ATF_REQUIRE(fd_is_valid(const_result[i])); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_arrays__error_null); ATF_TEST_CASE_BODY(nvlist_arrays__error_null) { nvlist_t *nvl; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_add_number_array(nvl, "nvl/number", NULL, 0); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_move_number_array(nvl, "nvl/number", NULL, 0); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_add_descriptor_array(nvl, "nvl/fd", NULL, 0); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_move_descriptor_array(nvl, "nvl/fd", NULL, 0); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_add_string_array(nvl, "nvl/string", NULL, 0); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_move_string_array(nvl, "nvl/string", NULL, 0); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_add_nvlist_array(nvl, "nvl/nvlist", NULL, 0); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_move_nvlist_array(nvl, "nvl/nvlist", NULL, 0); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_add_bool_array(nvl, "nvl/bool", NULL, 0); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_move_bool_array(nvl, "nvl/bool", NULL, 0); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_arrays__bad_value); ATF_TEST_CASE_BODY(nvlist_arrays__bad_value) { nvlist_t *nvl, *nvladd[1], **nvlmove; int fdadd[1], *fdmove; nvladd[0] = NULL; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_add_nvlist_array(nvl, "nvl/nvlist", nvladd, 1); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); nvlmove = (nvlist_t**)malloc(sizeof(*nvlmove)); ATF_REQUIRE(nvlmove != NULL); nvlmove[0] = NULL; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_move_nvlist_array(nvl, "nvl/nvlist", nvlmove, 1); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); fdadd[0] = -2; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_add_descriptor_array(nvl, "nvl/fd", fdadd, 1); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); fdmove = (int*)malloc(sizeof(*fdmove)); ATF_REQUIRE(fdmove != NULL); fdmove[0] = -2; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_move_descriptor_array(nvl, "nvl/fd", fdmove, 1); ATF_REQUIRE(nvlist_error(nvl) != 0); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_nvlist_array__travel); ATF_TEST_CASE_BODY(nvlist_nvlist_array__travel) { nvlist_t *nvl, *test[5], *nasted; const nvlist_t *travel; const char *name; void *cookie; int type; unsigned int i, index; for (i = 0; i < nitems(test); i++) { test[i] = nvlist_create(0); ATF_REQUIRE(test[i] != NULL); nvlist_add_number(test[i], "nvl/number", i); ATF_REQUIRE(nvlist_error(test[i]) == 0); } nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_add_nvlist_array(nvl, "nvl/nvlist_array", test, nitems(test)); ATF_REQUIRE(nvlist_error(nvl) == 0); nasted = nvlist_create(0); ATF_REQUIRE(nasted != NULL); nvlist_add_nvlist_array(nasted, "nvl/nvl/nvlist_array", test, nitems(test)); ATF_REQUIRE(nvlist_error(nasted) == 0); nvlist_move_nvlist(nvl, "nvl/nvl", nasted); ATF_REQUIRE(nvlist_error(nvl) == 0); nvlist_add_string(nvl, "nvl/string", "END"); ATF_REQUIRE(nvlist_error(nvl) == 0); cookie = NULL; index = 0; travel = nvl; do { while ((name = nvlist_next(travel, &type, &cookie)) != NULL) { if (index == 0) { ATF_REQUIRE(type == NV_TYPE_NVLIST_ARRAY); } else if (index >= 1 && index <= nitems(test)) { ATF_REQUIRE(type == NV_TYPE_NUMBER); } else if (index == nitems(test) + 1) { ATF_REQUIRE(type == NV_TYPE_NVLIST); } else if (index == nitems(test) + 2) { ATF_REQUIRE(type == NV_TYPE_NVLIST_ARRAY); } else if (index >= nitems(test) + 3 && index <= 2 * nitems(test) + 2) { ATF_REQUIRE(type == NV_TYPE_NUMBER); } else if (index == 2 * nitems(test) + 3) { ATF_REQUIRE(type == NV_TYPE_STRING); } if (type == NV_TYPE_NVLIST) { travel = nvlist_get_nvlist(travel, name); cookie = NULL; } else if (type == NV_TYPE_NVLIST_ARRAY) { travel = nvlist_get_nvlist_array(travel, name, NULL)[0]; cookie = NULL; } index ++; } } while ((travel = nvlist_get_pararr(travel, &cookie)) != NULL); for (i = 0; i < nitems(test); i++) nvlist_destroy(test[i]); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_nvlist_array__travel_alternative); ATF_TEST_CASE_BODY(nvlist_nvlist_array__travel_alternative) { nvlist_t *nvl, *test[5], *nasted; const nvlist_t *travel, *tmp; void *cookie; int index, i, type; const char *name; for (i = 0; i < 5; i++) { test[i] = nvlist_create(0); ATF_REQUIRE(test[i] != NULL); nvlist_add_number(test[i], "nvl/number", i); ATF_REQUIRE(nvlist_error(test[i]) == 0); } nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); nvlist_add_nvlist_array(nvl, "nvl/nvlist_array", test, 5); ATF_REQUIRE(nvlist_error(nvl) == 0); nasted = nvlist_create(0); ATF_REQUIRE(nasted != NULL); nvlist_add_nvlist_array(nasted, "nvl/nvl/nvlist_array", test, 5); ATF_REQUIRE(nvlist_error(nasted) == 0); nvlist_move_nvlist(nvl, "nvl/nvl", nasted); ATF_REQUIRE(nvlist_error(nvl) == 0); nvlist_add_string(nvl, "nvl/string", "END"); ATF_REQUIRE(nvlist_error(nvl) == 0); cookie = NULL; index = 0; tmp = travel = nvl; do { do { travel = tmp; while ((name = nvlist_next(travel, &type, &cookie)) != NULL) { if (index == 0) { ATF_REQUIRE(type == NV_TYPE_NVLIST_ARRAY); } else if (index >= 1 && index <= 5) { ATF_REQUIRE(type == NV_TYPE_NUMBER); } else if (index == 6) { ATF_REQUIRE(type == NV_TYPE_NVLIST); } else if (index == 7) { ATF_REQUIRE(type == NV_TYPE_NVLIST_ARRAY); } else if (index >= 8 && index <= 12) { ATF_REQUIRE(type == NV_TYPE_NUMBER); } else if (index == 13) { ATF_REQUIRE(type == NV_TYPE_STRING); } if (type == NV_TYPE_NVLIST) { travel = nvlist_get_nvlist(travel, name); cookie = NULL; } else if (type == NV_TYPE_NVLIST_ARRAY) { travel = nvlist_get_nvlist_array(travel, name, NULL)[0]; cookie = NULL; } index ++; } cookie = NULL; } while ((tmp = nvlist_get_array_next(travel)) != NULL); } while ((tmp = nvlist_get_parent(travel, &cookie)) != NULL); for (i = 0; i < 5; i++) nvlist_destroy(test[i]); nvlist_destroy(nvl); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_bool_array__pack); ATF_TEST_CASE_BODY(nvlist_bool_array__pack) { nvlist_t *nvl, *unpacked; const char *key; size_t packed_size, count; void *packed; unsigned int i; const bool *const_result; bool testbool[16]; for (i = 0; i < nitems(testbool); i++) testbool[i] = (i % 2 == 0); key = "nvl/bool"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); nvlist_add_bool_array(nvl, key, testbool, nitems(testbool)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_bool_array(nvl, key)); packed = nvlist_pack(nvl, &packed_size); ATF_REQUIRE(packed != NULL); unpacked = nvlist_unpack(packed, packed_size, 0); ATF_REQUIRE(unpacked != NULL); ATF_REQUIRE_EQ(nvlist_error(unpacked), 0); ATF_REQUIRE(nvlist_exists_bool_array(unpacked, key)); const_result = nvlist_get_bool_array(unpacked, key, &count); ATF_REQUIRE_EQ(count, nitems(testbool)); for (i = 0; i < count; i++) { ATF_REQUIRE_EQ(testbool[i], const_result[i]); } nvlist_destroy(nvl); nvlist_destroy(unpacked); free(packed); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_number_array__pack); ATF_TEST_CASE_BODY(nvlist_number_array__pack) { nvlist_t *nvl, *unpacked; const char *key; size_t packed_size, count; void *packed; unsigned int i; const uint64_t *const_result; const uint64_t number[8] = { 0, UINT_MAX, 7, 123, 90, 100000, 8, 1 }; key = "nvl/number"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); nvlist_add_number_array(nvl, key, number, 8); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_number_array(nvl, key)); packed = nvlist_pack(nvl, &packed_size); ATF_REQUIRE(packed != NULL); unpacked = nvlist_unpack(packed, packed_size, 0); ATF_REQUIRE(unpacked != NULL); ATF_REQUIRE_EQ(nvlist_error(unpacked), 0); ATF_REQUIRE(nvlist_exists_number_array(unpacked, key)); const_result = nvlist_get_number_array(unpacked, key, &count); ATF_REQUIRE_EQ(count, nitems(number)); for (i = 0; i < count; i++) { ATF_REQUIRE_EQ(number[i], const_result[i]); } nvlist_destroy(nvl); nvlist_destroy(unpacked); free(packed); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_descriptor_array__pack); ATF_TEST_CASE_BODY(nvlist_descriptor_array__pack) { nvlist_t *nvl; const char *key; size_t num_items; unsigned int i; const int *const_result; int desc[32], fd, socks[2]; pid_t pid; key = "nvl/descriptor"; ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0); pid = atf::utils::fork(); ATF_REQUIRE(pid >= 0); if (pid == 0) { /* Child. */ fd = socks[0]; close(socks[1]); for (i = 0; i < nitems(desc); i++) { desc[i] = dup(STDERR_FILENO); ATF_REQUIRE(fd_is_valid(desc[i])); } nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_descriptor_array(nvl, key)); nvlist_add_descriptor_array(nvl, key, desc, nitems(desc)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, key)); ATF_REQUIRE(nvlist_send(fd, nvl) >= 0); for (i = 0; i < nitems(desc); i++) close(desc[i]); } else { /* Parent */ fd = socks[1]; close(socks[0]); errno = 0; nvl = nvlist_recv(fd, 0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, key)); const_result = nvlist_get_descriptor_array(nvl, key, &num_items); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE_EQ(num_items, nitems(desc)); for (i = 0; i < num_items; i++) ATF_REQUIRE(fd_is_valid(const_result[i])); atf::utils::wait(pid, 0, "", ""); } nvlist_destroy(nvl); close(fd); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array__pack); ATF_TEST_CASE_BODY(nvlist_string_array__pack) { nvlist_t *nvl, *unpacked; const char *key; size_t packed_size, count; void *packed; unsigned int i; const char * const *const_result; const char *string_arr[8] = { "a", "b", "kot", "foo", "tests", "nice test", "", "abcdef" }; key = "nvl/string"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); nvlist_add_string_array(nvl, key, string_arr, nitems(string_arr)); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_string_array(nvl, key)); packed = nvlist_pack(nvl, &packed_size); ATF_REQUIRE(packed != NULL); unpacked = nvlist_unpack(packed, packed_size, 0); ATF_REQUIRE(unpacked != NULL); ATF_REQUIRE_EQ(nvlist_error(unpacked), 0); ATF_REQUIRE(nvlist_exists_string_array(unpacked, key)); const_result = nvlist_get_string_array(unpacked, key, &count); ATF_REQUIRE_EQ(count, nitems(string_arr)); for (i = 0; i < count; i++) { ATF_REQUIRE_EQ(strcmp(string_arr[i], const_result[i]), 0); } nvlist_destroy(nvl); nvlist_destroy(unpacked); free(packed); } ATF_TEST_CASE_WITHOUT_HEAD(nvlist_nvlist_array__pack); ATF_TEST_CASE_BODY(nvlist_nvlist_array__pack) { nvlist_t *testnvl[8], *unpacked; const nvlist_t * const *const_result; nvlist_t *nvl; size_t num_items, packed_size; unsigned int i; void *packed; const char *somestr[8] = { "a", "b", "c", "d", "e", "f", "g", "h" }; const char *key; for (i = 0; i < nitems(testnvl); i++) { testnvl[i] = nvlist_create(0); ATF_REQUIRE(testnvl[i] != NULL); ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0); nvlist_add_string(testnvl[i], "nvl/string", somestr[i]); ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0); ATF_REQUIRE(nvlist_exists_string(testnvl[i], "nvl/string")); } key = "nvl/nvlist"; nvl = nvlist_create(0); ATF_REQUIRE(nvl != NULL); ATF_REQUIRE(nvlist_empty(nvl)); ATF_REQUIRE(!nvlist_exists_string_array(nvl, key)); nvlist_add_nvlist_array(nvl, key, (const nvlist_t * const *)testnvl, 8); ATF_REQUIRE_EQ(nvlist_error(nvl), 0); ATF_REQUIRE(!nvlist_empty(nvl)); ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key)); ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, "nvl/nvlist")); packed = nvlist_pack(nvl, &packed_size); ATF_REQUIRE(packed != NULL); unpacked = nvlist_unpack(packed, packed_size, 0); ATF_REQUIRE(unpacked != NULL); ATF_REQUIRE_EQ(nvlist_error(unpacked), 0); ATF_REQUIRE(nvlist_exists_nvlist_array(unpacked, key)); const_result = nvlist_get_nvlist_array(unpacked, key, &num_items); ATF_REQUIRE(const_result != NULL); ATF_REQUIRE_EQ(num_items, nitems(testnvl)); for (i = 0; i < num_items; i++) { ATF_REQUIRE_EQ(nvlist_error(const_result[i]), 0); if (i < num_items - 1) { ATF_REQUIRE(nvlist_get_array_next(const_result[i]) == const_result[i + 1]); } else { ATF_REQUIRE(nvlist_get_array_next(const_result[i]) == NULL); } ATF_REQUIRE(nvlist_get_parent(const_result[i], NULL) == unpacked); ATF_REQUIRE(nvlist_in_array(const_result[i])); ATF_REQUIRE(nvlist_exists_string(const_result[i], "nvl/string")); ATF_REQUIRE(strcmp(nvlist_get_string(const_result[i], "nvl/string"), somestr[i]) == 0); } for (i = 0; i < nitems(testnvl); i++) nvlist_destroy(testnvl[i]); nvlist_destroy(nvl); nvlist_destroy(unpacked); free(packed); } ATF_INIT_TEST_CASES(tp) { ATF_ADD_TEST_CASE(tp, nvlist_bool_array__basic); ATF_ADD_TEST_CASE(tp, nvlist_string_array__basic); ATF_ADD_TEST_CASE(tp, nvlist_descriptor_array__basic); ATF_ADD_TEST_CASE(tp, nvlist_number_array__basic); ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__basic) ATF_ADD_TEST_CASE(tp, nvlist_clone_array) ATF_ADD_TEST_CASE(tp, nvlist_bool_array__move); ATF_ADD_TEST_CASE(tp, nvlist_string_array__move); ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__move); ATF_ADD_TEST_CASE(tp, nvlist_number_array__move); ATF_ADD_TEST_CASE(tp, nvlist_descriptor_array__move); ATF_ADD_TEST_CASE(tp, nvlist_arrays__error_null); ATF_ADD_TEST_CASE(tp, nvlist_arrays__bad_value) ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__travel) ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__travel_alternative) ATF_ADD_TEST_CASE(tp, nvlist_bool_array__pack) ATF_ADD_TEST_CASE(tp, nvlist_number_array__pack) ATF_ADD_TEST_CASE(tp, nvlist_descriptor_array__pack) ATF_ADD_TEST_CASE(tp, nvlist_string_array__pack) ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__pack) } Index: stable/11/lib/libnv/tests/nvlist_append_test.c =================================================================== --- stable/11/lib/libnv/tests/nvlist_append_test.c (nonexistent) +++ stable/11/lib/libnv/tests/nvlist_append_test.c (revision 336346) @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 2018 The NetBSD Foundation, Inc. + * 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. + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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$ + */ + +#include + +#include +#include +#include +#include +#include + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ + ntest++; \ +} while (0) + +int +main(void) +{ + const bool *bool_result; + const char * const *string_result; + const nvlist_t * const *nvl_result; + nvlist_t *nvl, *nvl1, *nvl2, **items; + unsigned int i; + size_t nitems; + + printf("1..32\n"); + + nvl = nvlist_create(0); + + for (i = 0; i < 16; i++) + nvlist_append_bool_array(nvl, "nvl/bool", i % 2 == 0); + + CHECK(nvlist_error(nvl) == 0); + CHECK(!nvlist_empty(nvl)); + CHECK(nvlist_exists_bool_array(nvl, "nvl/bool")); + + bool_result = nvlist_get_bool_array(nvl, "nvl/bool", &nitems); + CHECK(nitems == 16); + CHECK(bool_result != NULL); + for (i = 0; i < nitems; i++) + CHECK(bool_result[i] == (i % 2 == 0)); + + + nvlist_append_string_array(nvl, "nvl/string", "a"); + nvlist_append_string_array(nvl, "nvl/string", "abc"); + string_result = nvlist_get_string_array(nvl, "nvl/string", &nitems); + CHECK(nitems == 2); + CHECK(strcmp(string_result[0], "a") == 0); + CHECK(strcmp(string_result[1], "abc") == 0); + + + nvl1 = nvlist_create(0); + nvlist_add_string(nvl1, "key1", "test1"); + nvlist_append_nvlist_array(nvl, "nvl/nvl", nvl1); + nvlist_destroy(nvl1); + + nvl2 = nvlist_create(0); + nvlist_add_string(nvl2, "key2", "test2"); + nvlist_append_nvlist_array(nvl, "nvl/nvl", nvl2); + nvlist_destroy(nvl2); + + nvl_result = nvlist_get_nvlist_array(nvl, "nvl/nvl", &nitems); + CHECK(nitems == 2); + CHECK(strcmp(nvlist_get_string(nvl_result[0], "key1"), "test1") == 0); + CHECK(strcmp(nvlist_get_string(nvl_result[1], "key2"), "test2") == 0); + + nvl1 = nvlist_create(0); + nvlist_add_number(nvl1, "key1", 10); + nvlist_append_nvlist_array(nvl, "nvl/nvl_array", nvl1); + nvlist_destroy(nvl1); + + nvl2 = nvlist_create(0); + nvlist_add_number(nvl2, "key1", 20); + nvlist_append_nvlist_array(nvl, "nvl/nvl_array", nvl2); + nvlist_destroy(nvl2); + + items = nvlist_take_nvlist_array(nvl, "nvl/nvl_array", &nitems); + CHECK(nvlist_get_number(items[0], "key1") == 10); + CHECK(nvlist_get_number(items[1], "key1") == 20); + CHECK(nvlist_error(items[0]) == 0); + CHECK(nvlist_error(items[1]) == 0); + + nvlist_move_nvlist_array(nvl, "nvl/nvl_new_array", items, nitems); + CHECK(nvlist_error(nvl) == 0); + + nvlist_destroy(nvl); + + return (0); +} Property changes on: stable/11/lib/libnv/tests/nvlist_append_test.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/share/man/man9/Makefile =================================================================== --- stable/11/share/man/man9/Makefile (revision 336345) +++ stable/11/share/man/man9/Makefile (revision 336346) @@ -1,1991 +1,2027 @@ # $FreeBSD$ .include PACKAGE=runtime-manuals MAN= accept_filter.9 \ accf_data.9 \ accf_dns.9 \ accf_http.9 \ acl.9 \ alq.9 \ altq.9 \ atomic.9 \ bios.9 \ bitset.9 \ boot.9 \ bpf.9 \ buf.9 \ buf_ring.9 \ BUF_ISLOCKED.9 \ BUF_LOCK.9 \ BUF_LOCKFREE.9 \ BUF_LOCKINIT.9 \ BUF_RECURSED.9 \ BUF_TIMELOCK.9 \ BUF_UNLOCK.9 \ bus_activate_resource.9 \ BUS_ADD_CHILD.9 \ bus_adjust_resource.9 \ bus_alloc_resource.9 \ BUS_BIND_INTR.9 \ bus_child_present.9 \ BUS_CHILD_DELETED.9 \ BUS_CHILD_DETACHED.9 \ BUS_CONFIG_INTR.9 \ BUS_DESCRIBE_INTR.9 \ bus_dma.9 \ bus_generic_attach.9 \ bus_generic_detach.9 \ bus_generic_new_pass.9 \ bus_generic_print_child.9 \ bus_generic_read_ivar.9 \ bus_generic_shutdown.9 \ BUS_GET_CPUS.9 \ bus_get_resource.9 \ bus_map_resource.9 \ BUS_NEW_PASS.9 \ BUS_PRINT_CHILD.9 \ BUS_READ_IVAR.9 \ BUS_RESCAN.9 \ bus_release_resource.9 \ bus_set_pass.9 \ bus_set_resource.9 \ BUS_SETUP_INTR.9 \ bus_space.9 \ byteorder.9 \ casuword.9 \ cd.9 \ + cnv.9 \ condvar.9 \ config_intrhook.9 \ contigmalloc.9 \ copy.9 \ counter.9 \ cpuset.9 \ cr_cansee.9 \ critical_enter.9 \ cr_seeothergids.9 \ cr_seeotheruids.9 \ crypto.9 \ CTASSERT.9 \ DB_COMMAND.9 \ DECLARE_GEOM_CLASS.9 \ DECLARE_MODULE.9 \ DELAY.9 \ devclass.9 \ devclass_find.9 \ devclass_get_device.9 \ devclass_get_devices.9 \ devclass_get_drivers.9 \ devclass_get_maxunit.9 \ devclass_get_name.9 \ devclass_get_softc.9 \ dev_clone.9 \ devfs_set_cdevpriv.9 \ device.9 \ device_add_child.9 \ DEVICE_ATTACH.9 \ device_delete_child.9 \ DEVICE_DETACH.9 \ device_enable.9 \ device_find_child.9 \ device_get_children.9 \ device_get_devclass.9 \ device_get_driver.9 \ device_get_ivars.9 \ device_get_name.9 \ device_get_parent.9 \ device_get_softc.9 \ device_get_state.9 \ device_get_sysctl.9 \ device_get_unit.9 \ DEVICE_IDENTIFY.9 \ device_printf.9 \ DEVICE_PROBE.9 \ device_probe_and_attach.9 \ device_quiet.9 \ device_set_desc.9 \ device_set_driver.9 \ device_set_flags.9 \ DEVICE_SHUTDOWN.9 \ DEV_MODULE.9 \ devstat.9 \ devtoname.9 \ disk.9 \ domain.9 \ drbr.9 \ driver.9 \ DRIVER_MODULE.9 \ EVENTHANDLER.9 \ eventtimers.9 \ extattr.9 \ fail.9 \ fdt_pinctrl.9 \ fetch.9 \ firmware.9 \ fpu_kern.9 \ g_access.9 \ g_attach.9 \ g_bio.9 \ g_consumer.9 \ g_data.9 \ get_cyclecount.9 \ getenv.9 \ getnewvnode.9 \ g_event.9 \ g_geom.9 \ g_provider.9 \ g_provider_by_name.9 \ groupmember.9 \ g_wither_geom.9 \ hash.9 \ hashinit.9 \ hexdump.9 \ hhook.9 \ ieee80211.9 \ ieee80211_amrr.9 \ ieee80211_beacon.9 \ ieee80211_bmiss.9 \ ieee80211_crypto.9 \ ieee80211_ddb.9 \ ieee80211_input.9 \ ieee80211_node.9 \ ieee80211_output.9 \ ieee80211_proto.9 \ ieee80211_radiotap.9 \ ieee80211_regdomain.9 \ ieee80211_scan.9 \ ieee80211_vap.9 \ ifnet.9 \ inittodr.9 \ insmntque.9 \ intro.9 \ ithread.9 \ KASSERT.9 \ kern_testfrwk.9 \ kernacc.9 \ kernel_mount.9 \ khelp.9 \ kobj.9 \ kproc.9 \ kqueue.9 \ kthread.9 \ ktr.9 \ lock.9 \ locking.9 \ LOCK_PROFILING.9 \ mac.9 \ make_dev.9 \ malloc.9 \ mbchain.9 \ mbpool.9 \ mbuf.9 \ mbuf_tags.9 \ MD5.9 \ mdchain.9 \ memcchr.9 \ memguard.9 \ microseq.9 \ microtime.9 \ microuptime.9 \ mi_switch.9 \ mod_cc.9 \ module.9 \ MODULE_DEPEND.9 \ MODULE_VERSION.9 \ mtx_pool.9 \ mutex.9 \ namei.9 \ netisr.9 \ nv.9 \ osd.9 \ owll.9 \ own.9 \ panic.9 \ pbuf.9 \ PCBGROUP.9 \ p_candebug.9 \ p_cansee.9 \ pci.9 \ PCI_IOV_ADD_VF.9 \ PCI_IOV_INIT.9 \ pci_iov_schema.9 \ PCI_IOV_UNINIT.9 \ pfil.9 \ pfind.9 \ pget.9 \ pgfind.9 \ PHOLD.9 \ physio.9 \ pmap.9 \ pmap_activate.9 \ pmap_clear_modify.9 \ pmap_copy.9 \ pmap_enter.9 \ pmap_extract.9 \ pmap_growkernel.9 \ pmap_init.9 \ pmap_is_modified.9 \ pmap_is_prefaultable.9 \ pmap_map.9 \ pmap_mincore.9 \ pmap_object_init_pt.9 \ pmap_page_exists_quick.9 \ pmap_page_init.9 \ pmap_pinit.9 \ pmap_protect.9 \ pmap_qenter.9 \ pmap_quick_enter_page.9 \ pmap_release.9 \ pmap_remove.9 \ pmap_resident_count.9 \ pmap_unwire.9 \ pmap_zero_page.9 \ printf.9 \ prison_check.9 \ priv.9 \ proc_rwmem.9 \ pseudofs.9 \ psignal.9 \ random.9 \ random_harvest.9 \ redzone.9 \ refcount.9 \ resettodr.9 \ resource_int_value.9 \ rijndael.9 \ rman.9 \ rmlock.9 \ rtalloc.9 \ rtentry.9 \ runqueue.9 \ rwlock.9 \ sbuf.9 \ scheduler.9 \ SDT.9 \ securelevel_gt.9 \ selrecord.9 \ sema.9 \ sf_buf.9 \ sglist.9 \ shm_map.9 \ signal.9 \ sleep.9 \ sleepqueue.9 \ socket.9 \ stack.9 \ store.9 \ style.9 \ swi.9 \ sx.9 \ SYSCALL_MODULE.9 \ sysctl.9 \ sysctl_add_oid.9 \ sysctl_ctx_init.9 \ SYSINIT.9 \ taskqueue.9 \ tcp_functions.9 \ thread_exit.9 \ time.9 \ timeout.9 \ tvtohz.9 \ ucred.9 \ uidinfo.9 \ uio.9 \ unr.9 \ utopia.9 \ vaccess.9 \ vaccess_acl_nfs4.9 \ vaccess_acl_posix1e.9 \ vcount.9 \ vflush.9 \ VFS.9 \ vfs_busy.9 \ VFS_CHECKEXP.9 \ vfsconf.9 \ VFS_FHTOVP.9 \ vfs_getnewfsid.9 \ vfs_getopt.9 \ vfs_getvfs.9 \ VFS_MOUNT.9 \ vfs_mountedfrom.9 \ VFS_QUOTACTL.9 \ VFS_ROOT.9 \ vfs_rootmountalloc.9 \ VFS_SET.9 \ VFS_STATFS.9 \ vfs_suser.9 \ VFS_SYNC.9 \ vfs_timestamp.9 \ vfs_unbusy.9 \ VFS_UNMOUNT.9 \ vfs_unmountall.9 \ VFS_VGET.9 \ vget.9 \ vgone.9 \ vhold.9 \ vinvalbuf.9 \ vm_fault_prefault.9 \ vm_map.9 \ vm_map_check_protection.9 \ vm_map_create.9 \ vm_map_delete.9 \ vm_map_entry_resize_free.9 \ vm_map_find.9 \ vm_map_findspace.9 \ vm_map_inherit.9 \ vm_map_init.9 \ vm_map_insert.9 \ vm_map_lock.9 \ vm_map_lookup.9 \ vm_map_madvise.9 \ vm_map_max.9 \ vm_map_protect.9 \ vm_map_remove.9 \ vm_map_simplify_entry.9 \ vm_map_stack.9 \ vm_map_submap.9 \ vm_map_sync.9 \ vm_map_wire.9 \ vm_page_alloc.9 \ vm_page_bits.9 \ vm_page_busy.9 \ vm_page_cache.9 \ vm_page_deactivate.9 \ vm_page_dontneed.9 \ vm_page_aflag.9 \ vm_page_free.9 \ vm_page_grab.9 \ vm_page_hold.9 \ vm_page_insert.9 \ vm_page_lookup.9 \ vm_page_rename.9 \ vm_page_wire.9 \ vm_set_page_size.9 \ vmem.9 \ vn_fullpath.9 \ vn_isdisk.9 \ vnet.9 \ vnode.9 \ VOP_ACCESS.9 \ VOP_ACLCHECK.9 \ VOP_ADVISE.9 \ VOP_ADVLOCK.9 \ VOP_ALLOCATE.9 \ VOP_ATTRIB.9 \ VOP_BWRITE.9 \ VOP_CREATE.9 \ VOP_FSYNC.9 \ VOP_GETACL.9 \ VOP_GETEXTATTR.9 \ VOP_GETPAGES.9 \ VOP_INACTIVE.9 \ VOP_IOCTL.9 \ VOP_LINK.9 \ VOP_LISTEXTATTR.9 \ VOP_LOCK.9 \ VOP_LOOKUP.9 \ VOP_OPENCLOSE.9 \ VOP_PATHCONF.9 \ VOP_PRINT.9 \ VOP_RDWR.9 \ VOP_READDIR.9 \ VOP_READLINK.9 \ VOP_REALLOCBLKS.9 \ VOP_REMOVE.9 \ VOP_RENAME.9 \ VOP_REVOKE.9 \ VOP_SETACL.9 \ VOP_SETEXTATTR.9 \ VOP_STRATEGY.9 \ VOP_VPTOCNP.9 \ VOP_VPTOFH.9 \ vref.9 \ vrefcnt.9 \ vrele.9 \ vslock.9 \ watchdog.9 \ zone.9 MLINKS= unr.9 alloc_unr.9 \ unr.9 alloc_unrl.9 \ unr.9 alloc_unr_specific.9 \ unr.9 delete_unrhdr.9 \ unr.9 free_unr.9 \ unr.9 new_unrhdr.9 MLINKS+=accept_filter.9 accept_filt_add.9 \ accept_filter.9 accept_filt_del.9 \ accept_filter.9 accept_filt_generic_mod_event.9 \ accept_filter.9 accept_filt_get.9 MLINKS+=alq.9 ALQ.9 \ alq.9 alq_close.9 \ alq.9 alq_flush.9 \ alq.9 alq_get.9 \ alq.9 alq_getn.9 \ alq.9 alq_open.9 \ alq.9 alq_open_flags.9 \ alq.9 alq_post.9 \ alq.9 alq_post_flags.9 \ alq.9 alq_write.9 \ alq.9 alq_writen.9 MLINKS+=altq.9 ALTQ.9 MLINKS+=atomic.9 atomic_add.9 \ atomic.9 atomic_clear.9 \ atomic.9 atomic_cmpset.9 \ atomic.9 atomic_fcmpset.9 \ atomic.9 atomic_fetchadd.9 \ atomic.9 atomic_load.9 \ atomic.9 atomic_readandclear.9 \ atomic.9 atomic_set.9 \ atomic.9 atomic_store.9 \ atomic.9 atomic_subtract.9 \ atomic.9 atomic_swap.9 \ atomic.9 atomic_testandset.9 MLINKS+=bitset.9 BITSET_DEFINE.9 \ bitset.9 BITSET_T_INITIALIZER.9 \ bitset.9 BITSET_FSET.9 \ bitset.9 BIT_CLR.9 \ bitset.9 BIT_COPY.9 \ bitset.9 BIT_ISSET.9 \ bitset.9 BIT_SET.9 \ bitset.9 BIT_ZERO.9 \ bitset.9 BIT_FILL.9 \ bitset.9 BIT_SETOF.9 \ bitset.9 BIT_EMPTY.9 \ bitset.9 BIT_ISFULLSET.9 \ bitset.9 BIT_FFS.9 \ bitset.9 BIT_COUNT.9 \ bitset.9 BIT_SUBSET.9 \ bitset.9 BIT_OVERLAP.9 \ bitset.9 BIT_CMP.9 \ bitset.9 BIT_OR.9 \ bitset.9 BIT_AND.9 \ bitset.9 BIT_NAND.9 \ bitset.9 BIT_CLR_ATOMIC.9 \ bitset.9 BIT_SET_ATOMIC.9 \ bitset.9 BIT_SET_ATOMIC_ACQ.9 \ bitset.9 BIT_AND_ATOMIC.9 \ bitset.9 BIT_OR_ATOMIC.9 \ bitset.9 BIT_COPY_STORE_REL.9 MLINKS+=bpf.9 bpfattach.9 \ bpf.9 bpfattach2.9 \ bpf.9 bpfdetach.9 \ bpf.9 bpf_filter.9 \ bpf.9 bpf_mtap.9 \ bpf.9 bpf_mtap2.9 \ bpf.9 bpf_tap.9 \ bpf.9 bpf_validate.9 MLINKS+=buf.9 bp.9 MLINKS+=buf_ring.9 buf_ring_alloc.9 \ buf_ring.9 buf_ring_free.9 \ buf_ring.9 buf_ring_enqueue.9 \ buf_ring.9 buf_ring_enqueue_bytes.9 \ buf_ring.9 buf_ring_dequeue_mc.9 \ buf_ring.9 buf_ring_dequeue_sc.9 \ buf_ring.9 buf_ring_count.9 \ buf_ring.9 buf_ring_empty.9 \ buf_ring.9 buf_ring_full.9 \ buf_ring.9 buf_ring_peek.9 MLINKS+=bus_activate_resource.9 bus_deactivate_resource.9 MLINKS+=bus_alloc_resource.9 bus_alloc_resource_any.9 MLINKS+=BUS_BIND_INTR.9 bus_bind_intr.9 MLINKS+=BUS_DESCRIBE_INTR.9 bus_describe_intr.9 MLINKS+=bus_dma.9 busdma.9 \ bus_dma.9 bus_dmamap_create.9 \ bus_dma.9 bus_dmamap_destroy.9 \ bus_dma.9 bus_dmamap_load.9 \ bus_dma.9 bus_dmamap_load_bio.9 \ bus_dma.9 bus_dmamap_load_ccb.9 \ bus_dma.9 bus_dmamap_load_mbuf.9 \ bus_dma.9 bus_dmamap_load_mbuf_sg.9 \ bus_dma.9 bus_dmamap_load_uio.9 \ bus_dma.9 bus_dmamap_sync.9 \ bus_dma.9 bus_dmamap_unload.9 \ bus_dma.9 bus_dmamem_alloc.9 \ bus_dma.9 bus_dmamem_free.9 \ bus_dma.9 bus_dma_tag_create.9 \ bus_dma.9 bus_dma_tag_destroy.9 MLINKS+=bus_generic_read_ivar.9 bus_generic_write_ivar.9 MLINKS+=BUS_GET_CPUS.9 bus_get_cpus.9 MLINKS+=bus_map_resource.9 bus_unmap_resource.9 \ bus_map_resource.9 resource_init_map_request.9 MLINKS+=BUS_READ_IVAR.9 BUS_WRITE_IVAR.9 MLINKS+=BUS_SETUP_INTR.9 bus_setup_intr.9 \ BUS_SETUP_INTR.9 BUS_TEARDOWN_INTR.9 \ BUS_SETUP_INTR.9 bus_teardown_intr.9 MLINKS+=bus_space.9 bus_space_alloc.9 \ bus_space.9 bus_space_barrier.9 \ bus_space.9 bus_space_copy_region_1.9 \ bus_space.9 bus_space_copy_region_2.9 \ bus_space.9 bus_space_copy_region_4.9 \ bus_space.9 bus_space_copy_region_8.9 \ bus_space.9 bus_space_copy_region_stream_1.9 \ bus_space.9 bus_space_copy_region_stream_2.9 \ bus_space.9 bus_space_copy_region_stream_4.9 \ bus_space.9 bus_space_copy_region_stream_8.9 \ bus_space.9 bus_space_free.9 \ bus_space.9 bus_space_map.9 \ bus_space.9 bus_space_read_1.9 \ bus_space.9 bus_space_read_2.9 \ bus_space.9 bus_space_read_4.9 \ bus_space.9 bus_space_read_8.9 \ bus_space.9 bus_space_read_multi_1.9 \ bus_space.9 bus_space_read_multi_2.9 \ bus_space.9 bus_space_read_multi_4.9 \ bus_space.9 bus_space_read_multi_8.9 \ bus_space.9 bus_space_read_multi_stream_1.9 \ bus_space.9 bus_space_read_multi_stream_2.9 \ bus_space.9 bus_space_read_multi_stream_4.9 \ bus_space.9 bus_space_read_multi_stream_8.9 \ bus_space.9 bus_space_read_region_1.9 \ bus_space.9 bus_space_read_region_2.9 \ bus_space.9 bus_space_read_region_4.9 \ bus_space.9 bus_space_read_region_8.9 \ bus_space.9 bus_space_read_region_stream_1.9 \ bus_space.9 bus_space_read_region_stream_2.9 \ bus_space.9 bus_space_read_region_stream_4.9 \ bus_space.9 bus_space_read_region_stream_8.9 \ bus_space.9 bus_space_read_stream_1.9 \ bus_space.9 bus_space_read_stream_2.9 \ bus_space.9 bus_space_read_stream_4.9 \ bus_space.9 bus_space_read_stream_8.9 \ bus_space.9 bus_space_set_multi_1.9 \ bus_space.9 bus_space_set_multi_2.9 \ bus_space.9 bus_space_set_multi_4.9 \ bus_space.9 bus_space_set_multi_8.9 \ bus_space.9 bus_space_set_multi_stream_1.9 \ bus_space.9 bus_space_set_multi_stream_2.9 \ bus_space.9 bus_space_set_multi_stream_4.9 \ bus_space.9 bus_space_set_multi_stream_8.9 \ bus_space.9 bus_space_set_region_1.9 \ bus_space.9 bus_space_set_region_2.9 \ bus_space.9 bus_space_set_region_4.9 \ bus_space.9 bus_space_set_region_8.9 \ bus_space.9 bus_space_set_region_stream_1.9 \ bus_space.9 bus_space_set_region_stream_2.9 \ bus_space.9 bus_space_set_region_stream_4.9 \ bus_space.9 bus_space_set_region_stream_8.9 \ bus_space.9 bus_space_subregion.9 \ bus_space.9 bus_space_unmap.9 \ bus_space.9 bus_space_write_1.9 \ bus_space.9 bus_space_write_2.9 \ bus_space.9 bus_space_write_4.9 \ bus_space.9 bus_space_write_8.9 \ bus_space.9 bus_space_write_multi_1.9 \ bus_space.9 bus_space_write_multi_2.9 \ bus_space.9 bus_space_write_multi_4.9 \ bus_space.9 bus_space_write_multi_8.9 \ bus_space.9 bus_space_write_multi_stream_1.9 \ bus_space.9 bus_space_write_multi_stream_2.9 \ bus_space.9 bus_space_write_multi_stream_4.9 \ bus_space.9 bus_space_write_multi_stream_8.9 \ bus_space.9 bus_space_write_region_1.9 \ bus_space.9 bus_space_write_region_2.9 \ bus_space.9 bus_space_write_region_4.9 \ bus_space.9 bus_space_write_region_8.9 \ bus_space.9 bus_space_write_region_stream_1.9 \ bus_space.9 bus_space_write_region_stream_2.9 \ bus_space.9 bus_space_write_region_stream_4.9 \ bus_space.9 bus_space_write_region_stream_8.9 \ bus_space.9 bus_space_write_stream_1.9 \ bus_space.9 bus_space_write_stream_2.9 \ bus_space.9 bus_space_write_stream_4.9 \ bus_space.9 bus_space_write_stream_8.9 MLINKS+=byteorder.9 be16dec.9 \ byteorder.9 be16enc.9 \ byteorder.9 be16toh.9 \ byteorder.9 be32dec.9 \ byteorder.9 be32enc.9 \ byteorder.9 be32toh.9 \ byteorder.9 be64dec.9 \ byteorder.9 be64enc.9 \ byteorder.9 be64toh.9 \ byteorder.9 bswap16.9 \ byteorder.9 bswap32.9 \ byteorder.9 bswap64.9 \ byteorder.9 htobe16.9 \ byteorder.9 htobe32.9 \ byteorder.9 htobe64.9 \ byteorder.9 htole16.9 \ byteorder.9 htole32.9 \ byteorder.9 htole64.9 \ byteorder.9 le16dec.9 \ byteorder.9 le16enc.9 \ byteorder.9 le16toh.9 \ byteorder.9 le32dec.9 \ byteorder.9 le32enc.9 \ byteorder.9 le32toh.9 \ byteorder.9 le64dec.9 \ byteorder.9 le64enc.9 \ byteorder.9 le64toh.9 +MLINKS+=cnv.9 cnvlist.9 \ + cnv.9 cnvlist_free_binary.9 \ + cnv.9 cnvlist_free_bool.9 \ + cnv.9 cnvlist_free_bool_array.9 \ + cnv.9 cnvlist_free_descriptor.9 \ + cnv.9 cnvlist_free_descriptor_array.9 \ + cnv.9 cnvlist_free_null.9 \ + cnv.9 cnvlist_free_number.9 \ + cnv.9 cnvlist_free_number_array.9 \ + cnv.9 cnvlist_free_nvlist.9 \ + cnv.9 cnvlist_free_nvlist_array.9 \ + cnv.9 cnvlist_free_string.9 \ + cnv.9 cnvlist_free_string_array.9 \ + cnv.9 cnvlist_get_binary.9 \ + cnv.9 cnvlist_get_bool.9 \ + cnv.9 cnvlist_get_bool_array.9 \ + cnv.9 cnvlist_get_descriptor.9 \ + cnv.9 cnvlist_get_descriptor_array.9 \ + cnv.9 cnvlist_get_number.9 \ + cnv.9 cnvlist_get_number_array.9 \ + cnv.9 cnvlist_get_nvlist.9 \ + cnv.9 cnvlist_get_nvlist_array.9 \ + cnv.9 cnvlist_get_string.9 \ + cnv.9 cnvlist_get_string_array.9 \ + cnv.9 cnvlist_take_binary.9 \ + cnv.9 cnvlist_take_bool.9 \ + cnv.9 cnvlist_take_bool_array.9 \ + cnv.9 cnvlist_take_descriptor.9 \ + cnv.9 cnvlist_take_descriptor_array.9 \ + cnv.9 cnvlist_take_number.9 \ + cnv.9 cnvlist_take_number_array.9 \ + cnv.9 cnvlist_take_nvlist.9 \ + cnv.9 cnvlist_take_nvlist_array.9 \ + cnv.9 cnvlist_take_string.9 \ + cnv.9 cnvlist_take_string_array.9 MLINKS+=condvar.9 cv_broadcast.9 \ condvar.9 cv_broadcastpri.9 \ condvar.9 cv_destroy.9 \ condvar.9 cv_init.9 \ condvar.9 cv_signal.9 \ condvar.9 cv_timedwait.9 \ condvar.9 cv_timedwait_sig.9 \ condvar.9 cv_timedwait_sig_sbt.9 \ condvar.9 cv_wait.9 \ condvar.9 cv_wait_sig.9 \ condvar.9 cv_wait_unlock.9 \ condvar.9 cv_wmesg.9 MLINKS+=config_intrhook.9 config_intrhook_disestablish.9 \ config_intrhook.9 config_intrhook_establish.9 \ config_intrhook.9 config_intrhook_oneshot.9 MLINKS+=contigmalloc.9 contigfree.9 MLINKS+=casuword.9 casueword.9 \ casuword.9 casueword32.9 \ casuword.9 casuword32.9 MLINKS+=copy.9 copyin.9 \ copy.9 copyin_nofault.9 \ copy.9 copyinstr.9 \ copy.9 copyout.9 \ copy.9 copyout_nofault.9 \ copy.9 copystr.9 MLINKS+=counter.9 counter_u64_alloc.9 \ counter.9 counter_u64_free.9 \ counter.9 counter_u64_add.9 \ counter.9 counter_enter.9 \ counter.9 counter_exit.9 \ counter.9 counter_u64_add_protected.9 \ counter.9 counter_u64_fetch.9 \ counter.9 counter_u64_zero.9 \ counter.9 SYSCTL_COUNTER_U64.9 \ counter.9 SYSCTL_ADD_COUNTER_U64.9 \ counter.9 SYSCTL_COUNTER_U64_ARRAY.9 \ counter.9 SYSCTL_ADD_COUNTER_U64_ARRAY.9 MLINKS+=cpuset.9 CPUSET_T_INITIALIZER.9 \ cpuset.9 CPUSET_FSET.9 \ cpuset.9 CPU_CLR.9 \ cpuset.9 CPU_COPY.9 \ cpuset.9 CPU_ISSET.9 \ cpuset.9 CPU_SET.9 \ cpuset.9 CPU_ZERO.9 \ cpuset.9 CPU_FILL.9 \ cpuset.9 CPU_SETOF.9 \ cpuset.9 CPU_EMPTY.9 \ cpuset.9 CPU_ISFULLSET.9 \ cpuset.9 CPU_FFS.9 \ cpuset.9 CPU_COUNT.9 \ cpuset.9 CPU_SUBSET.9 \ cpuset.9 CPU_OVERLAP.9 \ cpuset.9 CPU_CMP.9 \ cpuset.9 CPU_OR.9 \ cpuset.9 CPU_AND.9 \ cpuset.9 CPU_NAND.9 \ cpuset.9 CPU_CLR_ATOMIC.9 \ cpuset.9 CPU_SET_ATOMIC.9 \ cpuset.9 CPU_SET_ATOMIC_ACQ.9 \ cpuset.9 CPU_AND_ATOMIC.9 \ cpuset.9 CPU_OR_ATOMIC.9 \ cpuset.9 CPU_COPY_STORE_REL.9 MLINKS+=critical_enter.9 critical.9 \ critical_enter.9 critical_exit.9 MLINKS+=crypto.9 crypto_dispatch.9 \ crypto.9 crypto_done.9 \ crypto.9 crypto_freereq.9 \ crypto.9 crypto_freesession.9 \ crypto.9 crypto_get_driverid.9 \ crypto.9 crypto_getreq.9 \ crypto.9 crypto_kdispatch.9 \ crypto.9 crypto_kdone.9 \ crypto.9 crypto_kregister.9 \ crypto.9 crypto_newsession.9 \ crypto.9 crypto_register.9 \ crypto.9 crypto_unblock.9 \ crypto.9 crypto_unregister.9 \ crypto.9 crypto_unregister_all.9 MLINKS+=DB_COMMAND.9 DB_SHOW_ALL_COMMAND.9 \ DB_COMMAND.9 DB_SHOW_COMMAND.9 MLINKS+=dev_clone.9 drain_dev_clone_events.9 MLINKS+=devfs_set_cdevpriv.9 devfs_clear_cdevpriv.9 \ devfs_set_cdevpriv.9 devfs_get_cdevpriv.9 MLINKS+=device_add_child.9 device_add_child_ordered.9 MLINKS+=device_enable.9 device_disable.9 \ device_enable.9 device_is_enabled.9 MLINKS+=device_get_ivars.9 device_set_ivars.9 MLINKS+=device_get_name.9 device_get_nameunit.9 MLINKS+=device_get_state.9 device_busy.9 \ device_get_state.9 device_is_alive.9 \ device_get_state.9 device_is_attached.9 \ device_get_state.9 device_unbusy.9 MLINKS+=device_get_sysctl.9 device_get_sysctl_ctx.9 \ device_get_sysctl.9 device_get_sysctl_tree.9 MLINKS+=device_quiet.9 device_is_quiet.9 \ device_quiet.9 device_verbose.9 MLINKS+=device_set_desc.9 device_get_desc.9 \ device_set_desc.9 device_set_desc_copy.9 MLINKS+=device_set_flags.9 device_get_flags.9 MLINKS+=devstat.9 devicestat.9 \ devstat.9 devstat_add_entry.9 \ devstat.9 devstat_end_transaction.9 \ devstat.9 devstat_remove_entry.9 \ devstat.9 devstat_start_transaction.9 MLINKS+=disk.9 disk_add_alias.9 \ disk.9 disk_alloc.9 \ disk.9 disk_create.9 \ disk.9 disk_destroy.9 \ disk.9 disk_gone.9 \ disk.9 disk_resize.9 MLINKS+=domain.9 DOMAIN_SET.9 \ domain.9 domain_add.9 \ domain.9 pfctlinput.9 \ domain.9 pfctlinput2.9 \ domain.9 pffinddomain.9 \ domain.9 pffindproto.9 \ domain.9 pffindtype.9 MLINKS+=drbr.9 drbr_free.9 \ drbr.9 drbr_enqueue.9 \ drbr.9 drbr_dequeue.9 \ drbr.9 drbr_dequeue_cond.9 \ drbr.9 drbr_flush.9 \ drbr.9 drbr_empty.9 \ drbr.9 drbr_inuse.9 \ drbr.9 drbr_stats_update.9 MLINKS+=DRIVER_MODULE.9 DRIVER_MODULE_ORDERED.9 \ DRIVER_MODULE.9 EARLY_DRIVER_MODULE.9 \ DRIVER_MODULE.9 EARLY_DRIVER_MODULE_ORDERED.9 MLINKS+=EVENTHANDLER.9 EVENTHANDLER_DECLARE.9 \ EVENTHANDLER.9 EVENTHANDLER_DEFINE.9 \ EVENTHANDLER.9 EVENTHANDLER_DEREGISTER.9 \ EVENTHANDLER.9 eventhandler_deregister.9 \ EVENTHANDLER.9 eventhandler_find_list.9 \ EVENTHANDLER.9 EVENTHANDLER_INVOKE.9 \ EVENTHANDLER.9 eventhandler_prune_list.9 \ EVENTHANDLER.9 EVENTHANDLER_REGISTER.9 \ EVENTHANDLER.9 eventhandler_register.9 MLINKS+=eventtimers.9 et_register.9 \ eventtimers.9 et_deregister.9 \ eventtimers.9 et_ban.9 \ eventtimers.9 et_find.9 \ eventtimers.9 et_free.9 \ eventtimers.9 et_init.9 \ eventtimers.9 ET_LOCK.9 \ eventtimers.9 ET_UNLOCK.9 \ eventtimers.9 et_start.9 \ eventtimers.9 et_stop.9 MLINKS+=fail.9 KFAIL_POINT_CODE.9 \ fail.9 KFAIL_POINT_ERROR.9 \ fail.9 KFAIL_POINT_GOTO.9 \ fail.9 KFAIL_POINT_RETURN.9 \ fail.9 KFAIL_POINT_RETURN_VOID.9 MLINKS+=fdt_pinctrl.9 fdt_pinctrl_configure.9 \ fdt_pinctrl.9 fdt_pinctrl_configure_by_name.9 \ fdt_pinctrl.9 fdt_pinctrl_configure_tree.9 \ fdt_pinctrl.9 fdt_pinctrl_register.9 MLINKS+=fetch.9 fubyte.9 \ fetch.9 fuswintr.9 \ fetch.9 fuword.9 \ fetch.9 fuword16.9 \ fetch.9 fuword32.9 \ fetch.9 fuword64.9 \ fetch.9 fueword.9 \ fetch.9 fueword32.9 \ fetch.9 fueword64.9 MLINKS+=firmware.9 firmware_get.9 \ firmware.9 firmware_put.9 \ firmware.9 firmware_register.9 \ firmware.9 firmware_unregister.9 MLINKS+=fpu_kern.9 fpu_kern_alloc_ctx.9 \ fpu_kern.9 fpu_kern_free_ctx.9 \ fpu_kern.9 fpu_kern_enter.9 \ fpu_kern.9 fpu_kern_leave.9 \ fpu_kern.9 fpu_kern_thread.9 \ fpu_kern.9 is_fpu_kern_thread.9 MLINKS+=g_attach.9 g_detach.9 MLINKS+=g_bio.9 g_alloc_bio.9 \ g_bio.9 g_clone_bio.9 \ g_bio.9 g_destroy_bio.9 \ g_bio.9 g_duplicate_bio.9 \ g_bio.9 g_new_bio.9 \ g_bio.9 g_print_bio.9 \ g_bio.9 g_reset_bio.9 MLINKS+=g_consumer.9 g_destroy_consumer.9 \ g_consumer.9 g_new_consumer.9 MLINKS+=g_data.9 g_read_data.9 \ g_data.9 g_write_data.9 MLINKS+=getenv.9 freeenv.9 \ getenv.9 getenv_int.9 \ getenv.9 getenv_long.9 \ getenv.9 getenv_string.9 \ getenv.9 getenv_quad.9 \ getenv.9 getenv_uint.9 \ getenv.9 getenv_ulong.9 \ getenv.9 setenv.9 \ getenv.9 testenv.9 \ getenv.9 unsetenv.9 MLINKS+=g_event.9 g_cancel_event.9 \ g_event.9 g_post_event.9 \ g_event.9 g_waitfor_event.9 MLINKS+=g_geom.9 g_destroy_geom.9 \ g_geom.9 g_new_geomf.9 MLINKS+=g_provider.9 g_destroy_provider.9 \ g_provider.9 g_error_provider.9 \ g_provider.9 g_new_providerf.9 MLINKS+=hash.9 hash32.9 \ hash.9 hash32_buf.9 \ hash.9 hash32_str.9 \ hash.9 hash32_stre.9 \ hash.9 hash32_strn.9 \ hash.9 hash32_strne.9 \ hash.9 jenkins_hash.9 \ hash.9 jenkins_hash32.9 MLINKS+=hashinit.9 hashdestroy.9 \ hashinit.9 hashinit_flags.9 \ hashinit.9 phashinit.9 MLINKS+=hhook.9 hhook_head_register.9 \ hhook.9 hhook_head_deregister.9 \ hhook.9 hhook_head_deregister_lookup.9 \ hhook.9 hhook_run_hooks.9 \ hhook.9 HHOOKS_RUN_IF.9 \ hhook.9 HHOOKS_RUN_LOOKUP_IF.9 MLINKS+=ieee80211.9 ieee80211_ifattach.9 \ ieee80211.9 ieee80211_ifdetach.9 MLINKS+=ieee80211_amrr.9 ieee80211_amrr_choose.9 \ ieee80211_amrr.9 ieee80211_amrr_cleanup.9 \ ieee80211_amrr.9 ieee80211_amrr_init.9 \ ieee80211_amrr.9 ieee80211_amrr_node_init.9 \ ieee80211_amrr.9 ieee80211_amrr_setinterval.9 \ ieee80211_amrr.9 ieee80211_amrr_tx_complete.9 \ ieee80211_amrr.9 ieee80211_amrr_tx_update.9 MLINKS+=ieee80211_beacon.9 ieee80211_beacon_alloc.9 \ ieee80211_beacon.9 ieee80211_beacon_notify.9 \ ieee80211_beacon.9 ieee80211_beacon_update.9 MLINKS+=ieee80211_bmiss.9 ieee80211_beacon_miss.9 MLINKS+=ieee80211_crypto.9 ieee80211_crypto_available.9 \ ieee80211_crypto.9 ieee80211_crypto_decap.9 \ ieee80211_crypto.9 ieee80211_crypto_delglobalkeys.9 \ ieee80211_crypto.9 ieee80211_crypto_delkey.9 \ ieee80211_crypto.9 ieee80211_crypto_demic.9 \ ieee80211_crypto.9 ieee80211_crypto_encap.9 \ ieee80211_crypto.9 ieee80211_crypto_enmic.9 \ ieee80211_crypto.9 ieee80211_crypto_newkey.9 \ ieee80211_crypto.9 ieee80211_crypto_register.9 \ ieee80211_crypto.9 ieee80211_crypto_reload_keys.9 \ ieee80211_crypto.9 ieee80211_crypto_setkey.9 \ ieee80211_crypto.9 ieee80211_crypto_unregister.9 \ ieee80211_crypto.9 ieee80211_key_update_begin.9 \ ieee80211_crypto.9 ieee80211_key_update_end.9 \ ieee80211_crypto.9 ieee80211_notify_michael_failure.9 \ ieee80211_crypto.9 ieee80211_notify_replay_failure.9 MLINKS+=ieee80211_input.9 ieee80211_input_all.9 MLINKS+=ieee80211_node.9 ieee80211_dump_node.9 \ ieee80211_node.9 ieee80211_dump_nodes.9 \ ieee80211_node.9 ieee80211_find_rxnode.9 \ ieee80211_node.9 ieee80211_find_rxnode_withkey.9 \ ieee80211_node.9 ieee80211_free_node.9 \ ieee80211_node.9 ieee80211_iterate_nodes.9 \ ieee80211_node.9 ieee80211_ref_node.9 \ ieee80211_node.9 ieee80211_unref_node.9 MLINKS+=ieee80211_output.9 ieee80211_process_callback.9 \ ieee80211_output.9 M_SEQNO_GET.9 \ ieee80211_output.9 M_WME_GETAC.9 MLINKS+=ieee80211_proto.9 ieee80211_new_state.9 \ ieee80211_proto.9 ieee80211_resume_all.9 \ ieee80211_proto.9 ieee80211_start_all.9 \ ieee80211_proto.9 ieee80211_stop_all.9 \ ieee80211_proto.9 ieee80211_suspend_all.9 \ ieee80211_proto.9 ieee80211_waitfor_parent.9 MLINKS+=ieee80211_radiotap.9 ieee80211_radiotap_active.9 \ ieee80211_radiotap.9 ieee80211_radiotap_active_vap.9 \ ieee80211_radiotap.9 ieee80211_radiotap_attach.9 \ ieee80211_radiotap.9 ieee80211_radiotap_tx.9 \ ieee80211_radiotap.9 radiotap.9 MLINKS+=ieee80211_regdomain.9 ieee80211_alloc_countryie.9 \ ieee80211_regdomain.9 ieee80211_init_channels.9 \ ieee80211_regdomain.9 ieee80211_sort_channels.9 MLINKS+=ieee80211_scan.9 ieee80211_add_scan.9 \ ieee80211_scan.9 ieee80211_bg_scan.9 \ ieee80211_scan.9 ieee80211_cancel_scan.9 \ ieee80211_scan.9 ieee80211_cancel_scan_any.9 \ ieee80211_scan.9 ieee80211_check_scan.9 \ ieee80211_scan.9 ieee80211_check_scan_current.9 \ ieee80211_scan.9 ieee80211_flush.9 \ ieee80211_scan.9 ieee80211_probe_curchan.9 \ ieee80211_scan.9 ieee80211_scan_assoc_fail.9 \ ieee80211_scan.9 ieee80211_scan_done.9 \ ieee80211_scan.9 ieee80211_scan_dump_channels.9 \ ieee80211_scan.9 ieee80211_scan_flush.9 \ ieee80211_scan.9 ieee80211_scan_iterate.9 \ ieee80211_scan.9 ieee80211_scan_next.9 \ ieee80211_scan.9 ieee80211_scan_timeout.9 \ ieee80211_scan.9 ieee80211_scanner_get.9 \ ieee80211_scan.9 ieee80211_scanner_register.9 \ ieee80211_scan.9 ieee80211_scanner_unregister.9 \ ieee80211_scan.9 ieee80211_scanner_unregister_all.9 \ ieee80211_scan.9 ieee80211_start_scan.9 MLINKS+=ieee80211_vap.9 ieee80211_vap_attach.9 \ ieee80211_vap.9 ieee80211_vap_detach.9 \ ieee80211_vap.9 ieee80211_vap_setup.9 MLINKS+=ifnet.9 if_addmulti.9 \ ifnet.9 if_alloc.9 \ ifnet.9 if_allmulti.9 \ ifnet.9 if_attach.9 \ ifnet.9 if_data.9 \ ifnet.9 IF_DEQUEUE.9 \ ifnet.9 if_delmulti.9 \ ifnet.9 if_detach.9 \ ifnet.9 if_down.9 \ ifnet.9 if_findmulti.9 \ ifnet.9 if_free.9 \ ifnet.9 if_free_type.9 \ ifnet.9 if_up.9 \ ifnet.9 ifa_free.9 \ ifnet.9 ifa_ifwithaddr.9 \ ifnet.9 ifa_ifwithdstaddr.9 \ ifnet.9 ifa_ifwithnet.9 \ ifnet.9 ifa_ref.9 \ ifnet.9 ifaddr.9 \ ifnet.9 ifaddr_byindex.9 \ ifnet.9 ifaof_ifpforaddr.9 \ ifnet.9 ifioctl.9 \ ifnet.9 ifpromisc.9 \ ifnet.9 ifqueue.9 \ ifnet.9 ifunit.9 \ ifnet.9 ifunit_ref.9 MLINKS+=insmntque.9 insmntque1.9 MLINKS+=ithread.9 ithread_add_handler.9 \ ithread.9 ithread_create.9 \ ithread.9 ithread_destroy.9 \ ithread.9 ithread_priority.9 \ ithread.9 ithread_remove_handler.9 \ ithread.9 ithread_schedule.9 MLINKS+=kernacc.9 useracc.9 MLINKS+=kernel_mount.9 free_mntarg.9 \ kernel_mount.9 kernel_vmount.9 \ kernel_mount.9 mount_arg.9 \ kernel_mount.9 mount_argb.9 \ kernel_mount.9 mount_argf.9 \ kernel_mount.9 mount_argsu.9 MLINKS+=khelp.9 khelp_add_hhook.9 \ khelp.9 KHELP_DECLARE_MOD.9 \ khelp.9 KHELP_DECLARE_MOD_UMA.9 \ khelp.9 khelp_destroy_osd.9 \ khelp.9 khelp_get_id.9 \ khelp.9 khelp_get_osd.9 \ khelp.9 khelp_init_osd.9 \ khelp.9 khelp_remove_hhook.9 MLINKS+=kobj.9 DEFINE_CLASS.9 \ kobj.9 kobj_class_compile.9 \ kobj.9 kobj_class_compile_static.9 \ kobj.9 kobj_class_free.9 \ kobj.9 kobj_create.9 \ kobj.9 kobj_delete.9 \ kobj.9 kobj_init.9 \ kobj.9 kobj_init_static.9 MLINKS+=kproc.9 kproc_create.9 \ kproc.9 kproc_exit.9 \ kproc.9 kproc_kthread_add.9 \ kproc.9 kproc_resume.9 \ kproc.9 kproc_shutdown.9 \ kproc.9 kproc_start.9 \ kproc.9 kproc_suspend.9 \ kproc.9 kproc_suspend_check.9 \ kproc.9 kthread_create.9 MLINKS+=kqueue.9 knlist_add.9 \ kqueue.9 knlist_clear.9 \ kqueue.9 knlist_delete.9 \ kqueue.9 knlist_destroy.9 \ kqueue.9 knlist_empty.9 \ kqueue.9 knlist_init.9 \ kqueue.9 knlist_init_mtx.9 \ kqueue.9 knlist_init_rw_reader.9 \ kqueue.9 knlist_remove.9 \ kqueue.9 knlist_remove_inevent.9 \ kqueue.9 knote_fdclose.9 \ kqueue.9 KNOTE_LOCKED.9 \ kqueue.9 KNOTE_UNLOCKED.9 \ kqueue.9 kqfd_register.9 \ kqueue.9 kqueue_add_filteropts.9 \ kqueue.9 kqueue_del_filteropts.9 MLINKS+=kthread.9 kthread_add.9 \ kthread.9 kthread_exit.9 \ kthread.9 kthread_resume.9 \ kthread.9 kthread_shutdown.9 \ kthread.9 kthread_start.9 \ kthread.9 kthread_suspend.9 \ kthread.9 kthread_suspend_check.9 MLINKS+=ktr.9 CTR0.9 \ ktr.9 CTR1.9 \ ktr.9 CTR2.9 \ ktr.9 CTR3.9 \ ktr.9 CTR4.9 \ ktr.9 CTR5.9 \ ktr.9 CTR6.9 MLINKS+=lock.9 lockdestroy.9 \ lock.9 lockinit.9 \ lock.9 lockmgr.9 \ lock.9 lockmgr_args.9 \ lock.9 lockmgr_args_rw.9 \ lock.9 lockmgr_assert.9 \ lock.9 lockmgr_disown.9 \ lock.9 lockmgr_printinfo.9 \ lock.9 lockmgr_recursed.9 \ lock.9 lockmgr_rw.9 \ lock.9 lockmgr_waiters.9 \ lock.9 lockstatus.9 MLINKS+=LOCK_PROFILING.9 MUTEX_PROFILING.9 MLINKS+=make_dev.9 destroy_dev.9 \ make_dev.9 destroy_dev_drain.9 \ make_dev.9 destroy_dev_sched.9 \ make_dev.9 destroy_dev_sched_cb.9 \ make_dev.9 dev_depends.9 \ make_dev.9 make_dev_alias.9 \ make_dev.9 make_dev_alias_p.9 \ make_dev.9 make_dev_cred.9 \ make_dev.9 make_dev_credf.9 \ make_dev.9 make_dev_p.9 \ make_dev.9 make_dev_s.9 MLINKS+=malloc.9 free.9 \ malloc.9 MALLOC_DECLARE.9 \ malloc.9 MALLOC_DEFINE.9 \ malloc.9 realloc.9 \ malloc.9 reallocf.9 MLINKS+=mbchain.9 mb_detach.9 \ mbchain.9 mb_done.9 \ mbchain.9 mb_fixhdr.9 \ mbchain.9 mb_init.9 \ mbchain.9 mb_initm.9 \ mbchain.9 mb_put_int64be.9 \ mbchain.9 mb_put_int64le.9 \ mbchain.9 mb_put_mbuf.9 \ mbchain.9 mb_put_mem.9 \ mbchain.9 mb_put_uint16be.9 \ mbchain.9 mb_put_uint16le.9 \ mbchain.9 mb_put_uint32be.9 \ mbchain.9 mb_put_uint32le.9 \ mbchain.9 mb_put_uint8.9 \ mbchain.9 mb_put_uio.9 \ mbchain.9 mb_reserve.9 MLINKS+=mbpool.9 mbp_alloc.9 \ mbpool.9 mbp_card_free.9 \ mbpool.9 mbp_count.9 \ mbpool.9 mbp_create.9 \ mbpool.9 mbp_destroy.9 \ mbpool.9 mbp_ext_free.9 \ mbpool.9 mbp_free.9 \ mbpool.9 mbp_get.9 \ mbpool.9 mbp_get_keep.9 \ mbpool.9 mbp_sync.9 MLINKS+=\ mbuf.9 m_adj.9 \ mbuf.9 m_align.9 \ mbuf.9 M_ALIGN.9 \ mbuf.9 m_append.9 \ mbuf.9 m_apply.9 \ mbuf.9 m_cat.9 \ mbuf.9 m_catpkt.9 \ mbuf.9 MCHTYPE.9 \ mbuf.9 MCLGET.9 \ mbuf.9 m_collapse.9 \ mbuf.9 m_copyback.9 \ mbuf.9 m_copydata.9 \ mbuf.9 m_copym.9 \ mbuf.9 m_copypacket.9 \ mbuf.9 m_copyup.9 \ mbuf.9 m_defrag.9 \ mbuf.9 m_devget.9 \ mbuf.9 m_dup.9 \ mbuf.9 m_dup_pkthdr.9 \ mbuf.9 MEXTADD.9 \ mbuf.9 m_fixhdr.9 \ mbuf.9 m_free.9 \ mbuf.9 m_freem.9 \ mbuf.9 MGET.9 \ mbuf.9 m_get.9 \ mbuf.9 m_get2.9 \ mbuf.9 m_getjcl.9 \ mbuf.9 m_getcl.9 \ mbuf.9 MGETHDR.9 \ mbuf.9 m_gethdr.9 \ mbuf.9 m_getm.9 \ mbuf.9 m_getptr.9 \ mbuf.9 MH_ALIGN.9 \ mbuf.9 M_LEADINGSPACE.9 \ mbuf.9 m_length.9 \ mbuf.9 M_MOVE_PKTHDR.9 \ mbuf.9 m_move_pkthdr.9 \ mbuf.9 M_PREPEND.9 \ mbuf.9 m_prepend.9 \ mbuf.9 m_pulldown.9 \ mbuf.9 m_pullup.9 \ mbuf.9 m_split.9 \ mbuf.9 mtod.9 \ mbuf.9 M_TRAILINGSPACE.9 \ mbuf.9 m_unshare.9 \ mbuf.9 M_WRITABLE.9 MLINKS+=\ mbuf_tags.9 m_tag_alloc.9 \ mbuf_tags.9 m_tag_copy.9 \ mbuf_tags.9 m_tag_copy_chain.9 \ mbuf_tags.9 m_tag_delete.9 \ mbuf_tags.9 m_tag_delete_chain.9 \ mbuf_tags.9 m_tag_delete_nonpersistent.9 \ mbuf_tags.9 m_tag_find.9 \ mbuf_tags.9 m_tag_first.9 \ mbuf_tags.9 m_tag_free.9 \ mbuf_tags.9 m_tag_get.9 \ mbuf_tags.9 m_tag_init.9 \ mbuf_tags.9 m_tag_locate.9 \ mbuf_tags.9 m_tag_next.9 \ mbuf_tags.9 m_tag_prepend.9 \ mbuf_tags.9 m_tag_unlink.9 MLINKS+=MD5.9 MD5Init.9 \ MD5.9 MD5Transform.9 MLINKS+=mdchain.9 md_append_record.9 \ mdchain.9 md_done.9 \ mdchain.9 md_get_int64.9 \ mdchain.9 md_get_int64be.9 \ mdchain.9 md_get_int64le.9 \ mdchain.9 md_get_mbuf.9 \ mdchain.9 md_get_mem.9 \ mdchain.9 md_get_uint16.9 \ mdchain.9 md_get_uint16be.9 \ mdchain.9 md_get_uint16le.9 \ mdchain.9 md_get_uint32.9 \ mdchain.9 md_get_uint32be.9 \ mdchain.9 md_get_uint32le.9 \ mdchain.9 md_get_uint8.9 \ mdchain.9 md_get_uio.9 \ mdchain.9 md_initm.9 \ mdchain.9 md_next_record.9 MLINKS+=microtime.9 bintime.9 \ microtime.9 getbintime.9 \ microtime.9 getmicrotime.9 \ microtime.9 getnanotime.9 \ microtime.9 nanotime.9 MLINKS+=microuptime.9 binuptime.9 \ microuptime.9 getbinuptime.9 \ microuptime.9 getmicrouptime.9 \ microuptime.9 getnanouptime.9 \ microuptime.9 getsbinuptime.9 \ microuptime.9 nanouptime.9 \ microuptime.9 sbinuptime.9 MLINKS+=mi_switch.9 cpu_switch.9 \ mi_switch.9 cpu_throw.9 MLINKS+=mod_cc.9 CCV.9 \ mod_cc.9 DECLARE_CC_MODULE.9 MLINKS+=mtx_pool.9 mtx_pool_alloc.9 \ mtx_pool.9 mtx_pool_create.9 \ mtx_pool.9 mtx_pool_destroy.9 \ mtx_pool.9 mtx_pool_find.9 \ mtx_pool.9 mtx_pool_lock.9 \ mtx_pool.9 mtx_pool_lock_spin.9 \ mtx_pool.9 mtx_pool_unlock.9 \ mtx_pool.9 mtx_pool_unlock_spin.9 MLINKS+=mutex.9 mtx_assert.9 \ mutex.9 mtx_destroy.9 \ mutex.9 mtx_init.9 \ mutex.9 mtx_initialized.9 \ mutex.9 mtx_lock.9 \ mutex.9 mtx_lock_flags.9 \ mutex.9 mtx_lock_spin.9 \ mutex.9 mtx_lock_spin_flags.9 \ mutex.9 mtx_owned.9 \ mutex.9 mtx_recursed.9 \ mutex.9 mtx_sleep.9 \ mutex.9 MTX_SYSINIT.9 \ mutex.9 mtx_trylock.9 \ mutex.9 mtx_trylock_flags.9 \ mutex.9 mtx_trylock_spin.9 \ mutex.9 mtx_trylock_spin_flags.9 \ mutex.9 mtx_unlock.9 \ mutex.9 mtx_unlock_flags.9 \ mutex.9 mtx_unlock_spin.9 \ mutex.9 mtx_unlock_spin_flags.9 MLINKS+=namei.9 NDFREE.9 \ namei.9 NDINIT.9 MLINKS+=netisr.9 netisr_clearqdrops.9 \ netisr.9 netisr_default_flow2cpu.9 \ netisr.9 netisr_dispatch.9 \ netisr.9 netisr_dispatch_src.9 \ netisr.9 netisr_get_cpucount.9 \ netisr.9 netisr_get_cpuid.9 \ netisr.9 netisr_getqdrops.9 \ netisr.9 netisr_getqlimit.9 \ netisr.9 netisr_queue.9 \ netisr.9 netisr_queue_src.9 \ netisr.9 netisr_register.9 \ netisr.9 netisr_setqlimit.9 \ netisr.9 netisr_unregister.9 MLINKS+=nv.9 libnv.9 \ nv.9 nvlist.9 \ nv.9 nvlist_add_binary.9 \ nv.9 nvlist_add_bool.9 \ nv.9 nvlist_add_bool_array.9 \ nv.9 nvlist_add_descriptor.9 \ nv.9 nvlist_add_descriptor_array.9 \ nv.9 nvlist_add_null.9 \ nv.9 nvlist_add_number.9 \ nv.9 nvlist_add_number_array.9 \ nv.9 nvlist_add_nvlist.9 \ nv.9 nvlist_add_nvlist_array.9 \ nv.9 nvlist_add_string.9 \ nv.9 nvlist_add_stringf.9 \ nv.9 nvlist_add_stringv.9 \ nv.9 nvlist_add_string_array.9 \ nv.9 nvlist_clone.9 \ nv.9 nvlist_create.9 \ nv.9 nvlist_destroy.9 \ nv.9 nvlist_dump.9 \ nv.9 nvlist_empty.9 \ nv.9 nvlist_error.9 \ nv.9 nvlist_exists.9 \ nv.9 nvlist_exists_binary.9 \ nv.9 nvlist_exists_bool.9 \ nv.9 nvlist_exists_bool_array.9 \ nv.9 nvlist_exists_descriptor.9 \ nv.9 nvlist_exists_descriptor_array.9 \ nv.9 nvlist_exists_null.9 \ nv.9 nvlist_exists_number.9 \ nv.9 nvlist_exists_number_array.9 \ nv.9 nvlist_exists_nvlist.9 \ nv.9 nvlist_exists_nvlist_array.9 \ nv.9 nvlist_exists_string.9 \ nv.9 nvlist_exists_type.9 \ nv.9 nvlist_fdump.9 \ nv.9 nvlist_flags.9 \ nv.9 nvlist_free.9 \ nv.9 nvlist_free_binary.9 \ nv.9 nvlist_free_bool.9 \ nv.9 nvlist_free_bool_array.9 \ nv.9 nvlist_free_descriptor.9 \ nv.9 nvlist_free_descriptor_array.9 \ nv.9 nvlist_free_null.9 \ nv.9 nvlist_free_number.9 \ nv.9 nvlist_free_number_array.9 \ nv.9 nvlist_free_nvlist.9 \ nv.9 nvlist_free_nvlist_array.9 \ nv.9 nvlist_free_string.9 \ nv.9 nvlist_free_string_array.9 \ nv.9 nvlist_free_type.9 \ nv.9 nvlist_get_binary.9 \ nv.9 nvlist_get_bool.9 \ nv.9 nvlist_get_bool_array.9 \ nv.9 nvlist_get_descriptor.9 \ nv.9 nvlist_get_descriptor_array.9 \ nv.9 nvlist_get_number.9 \ nv.9 nvlist_get_number_array.9 \ nv.9 nvlist_get_nvlist.9 \ nv.9 nvlist_get_nvlist_array.9 \ nv.9 nvlist_get_parent.9 \ nv.9 nvlist_get_string.9 \ nv.9 nvlist_get_string_array.9 \ nv.9 nvlist_move_binary.9 \ nv.9 nvlist_move_descriptor.9 \ nv.9 nvlist_move_descriptor_array.9 \ nv.9 nvlist_move_nvlist.9 \ nv.9 nvlist_move_nvlist_array.9 \ nv.9 nvlist_move_string.9 \ nv.9 nvlist_move_string_array.9 \ nv.9 nvlist_next.9 \ nv.9 nvlist_pack.9 \ nv.9 nvlist_recv.9 \ nv.9 nvlist_send.9 \ nv.9 nvlist_set_error.9 \ nv.9 nvlist_size.9 \ nv.9 nvlist_take_binary.9 \ nv.9 nvlist_take_bool.9 \ nv.9 nvlist_take_bool_array.9 \ nv.9 nvlist_take_descriptor.9 \ nv.9 nvlist_take_descriptor_array.9 \ nv.9 nvlist_take_number.9 \ nv.9 nvlist_take_number_array.9 \ nv.9 nvlist_take_nvlist.9 \ nv.9 nvlist_take_nvlist_array.9 \ nv.9 nvlist_take_string.9 \ nv.9 nvlist_take_string_array.9 \ nv.9 nvlist_unpack.9 \ nv.9 nvlist_xfer.9 MLINKS+=osd.9 osd_call.9 \ osd.9 osd_del.9 \ osd.9 osd_deregister.9 \ osd.9 osd_exit.9 \ osd.9 osd_get.9 \ osd.9 osd_register.9 \ osd.9 osd_set.9 MLINKS+=panic.9 vpanic.9 MLINKS+=pbuf.9 getpbuf.9 \ pbuf.9 relpbuf.9 \ pbuf.9 trypbuf.9 MLINKS+=PCBGROUP.9 in_pcbgroup_byhash.9 \ PCBGROUP.9 in_pcbgroup_byinpcb.9 \ PCBGROUP.9 in_pcbgroup_destroy.9 \ PCBGROUP.9 in_pcbgroup_enabled.9 \ PCBGROUP.9 in_pcbgroup_init.9 \ PCBGROUP.9 in_pcbgroup_remove.9 \ PCBGROUP.9 in_pcbgroup_update.9 \ PCBGROUP.9 in_pcbgroup_update_mbuf.9 \ PCBGROUP.9 in6_pcbgroup_byhash.9 MLINKS+=pci.9 pci_alloc_msi.9 \ pci.9 pci_alloc_msix.9 \ pci.9 pci_disable_busmaster.9 \ pci.9 pci_disable_io.9 \ pci.9 pci_enable_busmaster.9 \ pci.9 pci_enable_io.9 \ pci.9 pci_find_bsf.9 \ pci.9 pci_find_cap.9 \ pci.9 pci_find_dbsf.9 \ pci.9 pci_find_device.9 \ pci.9 pci_find_extcap.9 \ pci.9 pci_find_htcap.9 \ pci.9 pci_find_pcie_root_port.9 \ pci.9 pci_get_id.9 \ pci.9 pci_get_max_read_req.9 \ pci.9 pci_get_powerstate.9 \ pci.9 pci_get_vpd_ident.9 \ pci.9 pci_get_vpd_readonly.9 \ pci.9 pci_iov_attach.9 \ pci.9 pci_iov_attach_name.9 \ pci.9 pci_iov_detach.9 \ pci.9 pci_msi_count.9 \ pci.9 pci_msix_count.9 \ pci.9 pci_msix_pba_bar.9 \ pci.9 pci_msix_table_bar.9 \ pci.9 pci_pending_msix.9 \ pci.9 pci_read_config.9 \ pci.9 pci_release_msi.9 \ pci.9 pci_remap_msix.9 \ pci.9 pci_restore_state.9 \ pci.9 pci_save_state.9 \ pci.9 pci_set_powerstate.9 \ pci.9 pci_set_max_read_req.9 \ pci.9 pci_write_config.9 \ pci.9 pcie_adjust_config.9 \ pci.9 pcie_flr.9 \ pci.9 pcie_max_completion_timeout.9 \ pci.9 pcie_read_config.9 \ pci.9 pcie_wait_for_pending_transactions.9 \ pci.9 pcie_write_config.9 MLINKS+=pci_iov_schema.9 pci_iov_schema_alloc_node.9 \ pci_iov_schema.9 pci_iov_schema_add_bool.9 \ pci_iov_schema.9 pci_iov_schema_add_string.9 \ pci_iov_schema.9 pci_iov_schema_add_uint8.9 \ pci_iov_schema.9 pci_iov_schema_add_uint16.9 \ pci_iov_schema.9 pci_iov_schema_add_uint32.9 \ pci_iov_schema.9 pci_iov_schema_add_uint64.9 \ pci_iov_schema.9 pci_iov_schema_add_unicast_mac.9 MLINKS+=pfil.9 pfil_add_hook.9 \ pfil.9 pfil_head_register.9 \ pfil.9 pfil_head_unregister.9 \ pfil.9 pfil_hook_get.9 \ pfil.9 pfil_remove_hook.9 \ pfil.9 pfil_rlock.9 \ pfil.9 pfil_run_hooks.9 \ pfil.9 pfil_runlock.9 \ pfil.9 pfil_wlock.9 \ pfil.9 pfil_wunlock.9 MLINKS+=pfind.9 zpfind.9 MLINKS+=PHOLD.9 PRELE.9 \ PHOLD.9 _PHOLD.9 \ PHOLD.9 _PRELE.9 \ PHOLD.9 PROC_ASSERT_HELD.9 \ PHOLD.9 PROC_ASSERT_NOT_HELD.9 MLINKS+=pmap_copy.9 pmap_copy_page.9 MLINKS+=pmap_extract.9 pmap_extract_and_hold.9 MLINKS+=pmap_init.9 pmap_init2.9 MLINKS+=pmap_is_modified.9 pmap_ts_referenced.9 MLINKS+=pmap_pinit.9 pmap_pinit0.9 \ pmap_pinit.9 pmap_pinit2.9 MLINKS+=pmap_qenter.9 pmap_qremove.9 MLINKS+=pmap_quick_enter_page.9 pmap_quick_remove_page.9 MLINKS+=pmap_remove.9 pmap_remove_all.9 \ pmap_remove.9 pmap_remove_pages.9 MLINKS+=pmap_resident_count.9 pmap_wired_count.9 MLINKS+=pmap_zero_page.9 pmap_zero_area.9 \ pmap_zero_page.9 pmap_zero_idle.9 MLINKS+=printf.9 log.9 \ printf.9 tprintf.9 \ printf.9 uprintf.9 MLINKS+=priv.9 priv_check.9 \ priv.9 priv_check_cred.9 MLINKS+=proc_rwmem.9 proc_readmem.9 \ proc_rwmem.9 proc_writemem.9 MLINKS+=psignal.9 gsignal.9 \ psignal.9 pgsignal.9 \ psignal.9 tdsignal.9 MLINKS+=random.9 arc4rand.9 \ random.9 arc4random.9 \ random.9 read_random.9 \ random.9 read_random_uio.9 \ random.9 srandom.9 MLINKS+=refcount.9 refcount_acquire.9 \ refcount.9 refcount_init.9 \ refcount.9 refcount_release.9 MLINKS+=resource_int_value.9 resource_long_value.9 \ resource_int_value.9 resource_string_value.9 MLINKS+=rman.9 rman_activate_resource.9 \ rman.9 rman_adjust_resource.9 \ rman.9 rman_deactivate_resource.9 \ rman.9 rman_fini.9 \ rman.9 rman_first_free_region.9 \ rman.9 rman_get_bushandle.9 \ rman.9 rman_get_bustag.9 \ rman.9 rman_get_device.9 \ rman.9 rman_get_end.9 \ rman.9 rman_get_flags.9 \ rman.9 rman_get_mapping.9 \ rman.9 rman_get_rid.9 \ rman.9 rman_get_size.9 \ rman.9 rman_get_start.9 \ rman.9 rman_get_virtual.9 \ rman.9 rman_init.9 \ rman.9 rman_init_from_resource.9 \ rman.9 rman_is_region_manager.9 \ rman.9 rman_last_free_region.9 \ rman.9 rman_make_alignment_flags.9 \ rman.9 rman_manage_region.9 \ rman.9 rman_release_resource.9 \ rman.9 rman_reserve_resource.9 \ rman.9 rman_reserve_resource_bound.9 \ rman.9 rman_set_bushandle.9 \ rman.9 rman_set_bustag.9 \ rman.9 rman_set_mapping.9 \ rman.9 rman_set_rid.9 \ rman.9 rman_set_virtual.9 MLINKS+=rmlock.9 rm_assert.9 \ rmlock.9 rm_destroy.9 \ rmlock.9 rm_init.9 \ rmlock.9 rm_init_flags.9 \ rmlock.9 rm_rlock.9 \ rmlock.9 rm_runlock.9 \ rmlock.9 rm_sleep.9 \ rmlock.9 RM_SYSINIT.9 \ rmlock.9 RM_SYSINIT_FLAGS.9 \ rmlock.9 rm_try_rlock.9 \ rmlock.9 rm_wlock.9 \ rmlock.9 rm_wowned.9 \ rmlock.9 rm_wunlock.9 MLINKS+=rtalloc.9 rtalloc1.9 \ rtalloc.9 rtalloc_ign.9 \ rtalloc.9 RT_ADDREF.9 \ rtalloc.9 RT_LOCK.9 \ rtalloc.9 RT_REMREF.9 \ rtalloc.9 RT_RTFREE.9 \ rtalloc.9 RT_UNLOCK.9 \ rtalloc.9 RTFREE_LOCKED.9 \ rtalloc.9 RTFREE.9 \ rtalloc.9 rtfree.9 \ rtalloc.9 rtalloc1_fib.9 \ rtalloc.9 rtalloc_ign_fib.9 \ rtalloc.9 rtalloc_fib.9 MLINKS+=runqueue.9 choosethread.9 \ runqueue.9 procrunnable.9 \ runqueue.9 remrunqueue.9 \ runqueue.9 setrunqueue.9 MLINKS+=rwlock.9 rw_assert.9 \ rwlock.9 rw_destroy.9 \ rwlock.9 rw_downgrade.9 \ rwlock.9 rw_init.9 \ rwlock.9 rw_init_flags.9 \ rwlock.9 rw_initialized.9 \ rwlock.9 rw_rlock.9 \ rwlock.9 rw_runlock.9 \ rwlock.9 rw_unlock.9 \ rwlock.9 rw_sleep.9 \ rwlock.9 RW_SYSINIT.9 \ rwlock.9 RW_SYSINIT_FLAGS.9 \ rwlock.9 rw_try_rlock.9 \ rwlock.9 rw_try_upgrade.9 \ rwlock.9 rw_try_wlock.9 \ rwlock.9 rw_wlock.9 \ rwlock.9 rw_wowned.9 \ rwlock.9 rw_wunlock.9 MLINKS+=sbuf.9 sbuf_bcat.9 \ sbuf.9 sbuf_bcopyin.9 \ sbuf.9 sbuf_bcpy.9 \ sbuf.9 sbuf_cat.9 \ sbuf.9 sbuf_clear.9 \ sbuf.9 sbuf_clear_flags.9 \ sbuf.9 sbuf_copyin.9 \ sbuf.9 sbuf_cpy.9 \ sbuf.9 sbuf_data.9 \ sbuf.9 sbuf_delete.9 \ sbuf.9 sbuf_done.9 \ sbuf.9 sbuf_error.9 \ sbuf.9 sbuf_finish.9 \ sbuf.9 sbuf_get_flags.9 \ sbuf.9 sbuf_hexdump.9 \ sbuf.9 sbuf_len.9 \ sbuf.9 sbuf_new.9 \ sbuf.9 sbuf_new_auto.9 \ sbuf.9 sbuf_new_for_sysctl.9 \ sbuf.9 sbuf_printf.9 \ sbuf.9 sbuf_putc.9 \ sbuf.9 sbuf_set_drain.9 \ sbuf.9 sbuf_set_flags.9 \ sbuf.9 sbuf_setpos.9 \ sbuf.9 sbuf_start_section.9 \ sbuf.9 sbuf_end_section.9 \ sbuf.9 sbuf_trim.9 \ sbuf.9 sbuf_vprintf.9 MLINKS+=scheduler.9 curpriority_cmp.9 \ scheduler.9 maybe_resched.9 \ scheduler.9 propagate_priority.9 \ scheduler.9 resetpriority.9 \ scheduler.9 roundrobin.9 \ scheduler.9 roundrobin_interval.9 \ scheduler.9 schedclock.9 \ scheduler.9 schedcpu.9 \ scheduler.9 sched_setup.9 \ scheduler.9 setrunnable.9 \ scheduler.9 updatepri.9 MLINKS+=SDT.9 SDT_PROVIDER_DECLARE.9 \ SDT.9 SDT_PROVIDER_DEFINE.9 \ SDT.9 SDT_PROBE_DECLARE.9 \ SDT.9 SDT_PROBE_DEFINE.9 \ SDT.9 SDT_PROBE.9 MLINKS+=securelevel_gt.9 securelevel_ge.9 MLINKS+=selrecord.9 seldrain.9 \ selrecord.9 selwakeup.9 MLINKS+=sema.9 sema_destroy.9 \ sema.9 sema_init.9 \ sema.9 sema_post.9 \ sema.9 sema_timedwait.9 \ sema.9 sema_trywait.9 \ sema.9 sema_value.9 \ sema.9 sema_wait.9 MLINKS+=sf_buf.9 sf_buf_alloc.9 \ sf_buf.9 sf_buf_free.9 \ sf_buf.9 sf_buf_kva.9 \ sf_buf.9 sf_buf_page.9 MLINKS+=sglist.9 sglist_alloc.9 \ sglist.9 sglist_append.9 \ sglist.9 sglist_append_bio.9 \ sglist.9 sglist_append_mbuf.9 \ sglist.9 sglist_append_phys.9 \ sglist.9 sglist_append_uio.9 \ sglist.9 sglist_append_user.9 \ sglist.9 sglist_append_vmpages.9 \ sglist.9 sglist_build.9 \ sglist.9 sglist_clone.9 \ sglist.9 sglist_consume_uio.9 \ sglist.9 sglist_count.9 \ sglist.9 sglist_count_vmpages.9 \ sglist.9 sglist_free.9 \ sglist.9 sglist_hold.9 \ sglist.9 sglist_init.9 \ sglist.9 sglist_join.9 \ sglist.9 sglist_length.9 \ sglist.9 sglist_reset.9 \ sglist.9 sglist_slice.9 \ sglist.9 sglist_split.9 MLINKS+=shm_map.9 shm_unmap.9 MLINKS+=signal.9 cursig.9 \ signal.9 execsigs.9 \ signal.9 issignal.9 \ signal.9 killproc.9 \ signal.9 pgsigio.9 \ signal.9 postsig.9 \ signal.9 SETSETNEQ.9 \ signal.9 SETSETOR.9 \ signal.9 SIGADDSET.9 \ signal.9 SIG_CONTSIGMASK.9 \ signal.9 SIGDELSET.9 \ signal.9 SIGEMPTYSET.9 \ signal.9 sigexit.9 \ signal.9 SIGFILLSET.9 \ signal.9 siginit.9 \ signal.9 SIGISEMPTY.9 \ signal.9 SIGISMEMBER.9 \ signal.9 SIGNOTEMPTY.9 \ signal.9 signotify.9 \ signal.9 SIGPENDING.9 \ signal.9 SIGSETAND.9 \ signal.9 SIGSETCANTMASK.9 \ signal.9 SIGSETEQ.9 \ signal.9 SIGSETNAND.9 \ signal.9 SIG_STOPSIGMASK.9 \ signal.9 trapsignal.9 MLINKS+=sleep.9 msleep.9 \ sleep.9 msleep_sbt.9 \ sleep.9 msleep_spin.9 \ sleep.9 msleep_spin_sbt.9 \ sleep.9 pause.9 \ sleep.9 pause_sig.9 \ sleep.9 pause_sbt.9 \ sleep.9 tsleep.9 \ sleep.9 tsleep_sbt.9 \ sleep.9 wakeup.9 \ sleep.9 wakeup_one.9 MLINKS+=sleepqueue.9 init_sleepqueues.9 \ sleepqueue.9 sleepq_abort.9 \ sleepqueue.9 sleepq_add.9 \ sleepqueue.9 sleepq_alloc.9 \ sleepqueue.9 sleepq_broadcast.9 \ sleepqueue.9 sleepq_free.9 \ sleepqueue.9 sleepq_lookup.9 \ sleepqueue.9 sleepq_lock.9 \ sleepqueue.9 sleepq_release.9 \ sleepqueue.9 sleepq_remove.9 \ sleepqueue.9 sleepq_set_timeout.9 \ sleepqueue.9 sleepq_set_timeout_sbt.9 \ sleepqueue.9 sleepq_signal.9 \ sleepqueue.9 sleepq_sleepcnt.9 \ sleepqueue.9 sleepq_timedwait.9 \ sleepqueue.9 sleepq_timedwait_sig.9 \ sleepqueue.9 sleepq_type.9 \ sleepqueue.9 sleepq_wait.9 \ sleepqueue.9 sleepq_wait_sig.9 MLINKS+=socket.9 soabort.9 \ socket.9 soaccept.9 \ socket.9 sobind.9 \ socket.9 socheckuid.9 \ socket.9 soclose.9 \ socket.9 soconnect.9 \ socket.9 socreate.9 \ socket.9 sodisconnect.9 \ socket.9 sodupsockaddr.9 \ socket.9 sofree.9 \ socket.9 sogetopt.9 \ socket.9 sohasoutofband.9 \ socket.9 solisten.9 \ socket.9 solisten_proto.9 \ socket.9 solisten_proto_check.9 \ socket.9 sonewconn.9 \ socket.9 sooptcopyin.9 \ socket.9 sooptcopyout.9 \ socket.9 sopoll.9 \ socket.9 sopoll_generic.9 \ socket.9 soreceive.9 \ socket.9 soreceive_dgram.9 \ socket.9 soreceive_generic.9 \ socket.9 soreceive_stream.9 \ socket.9 soreserve.9 \ socket.9 sorflush.9 \ socket.9 sosend.9 \ socket.9 sosend_dgram.9 \ socket.9 sosend_generic.9 \ socket.9 sosetopt.9 \ socket.9 soshutdown.9 \ socket.9 sotoxsocket.9 \ socket.9 soupcall_clear.9 \ socket.9 soupcall_set.9 \ socket.9 sowakeup.9 MLINKS+=stack.9 stack_copy.9 \ stack.9 stack_create.9 \ stack.9 stack_destroy.9 \ stack.9 stack_print.9 \ stack.9 stack_print_ddb.9 \ stack.9 stack_print_short.9 \ stack.9 stack_print_short_ddb.9 \ stack.9 stack_put.9 \ stack.9 stack_save.9 \ stack.9 stack_sbuf_print.9 \ stack.9 stack_sbuf_print_ddb.9 \ stack.9 stack_zero.9 MLINKS+=store.9 subyte.9 \ store.9 suswintr.9 \ store.9 suword.9 \ store.9 suword16.9 \ store.9 suword32.9 \ store.9 suword64.9 MLINKS+=swi.9 swi_add.9 \ swi.9 swi_remove.9 \ swi.9 swi_sched.9 MLINKS+=sx.9 sx_assert.9 \ sx.9 sx_destroy.9 \ sx.9 sx_downgrade.9 \ sx.9 sx_init.9 \ sx.9 sx_init_flags.9 \ sx.9 sx_sleep.9 \ sx.9 sx_slock.9 \ sx.9 sx_slock_sig.9 \ sx.9 sx_sunlock.9 \ sx.9 SX_SYSINIT.9 \ sx.9 SX_SYSINIT_FLAGS.9 \ sx.9 sx_try_slock.9 \ sx.9 sx_try_upgrade.9 \ sx.9 sx_try_xlock.9 \ sx.9 sx_unlock.9 \ sx.9 sx_xholder.9 \ sx.9 sx_xlock.9 \ sx.9 sx_xlock_sig.9 \ sx.9 sx_xlocked.9 \ sx.9 sx_xunlock.9 MLINKS+=sysctl.9 SYSCTL_DECL.9 \ sysctl.9 SYSCTL_ADD_INT.9 \ sysctl.9 SYSCTL_ADD_LONG.9 \ sysctl.9 SYSCTL_ADD_NODE.9 \ sysctl.9 SYSCTL_ADD_OPAQUE.9 \ sysctl.9 SYSCTL_ADD_PROC.9 \ sysctl.9 SYSCTL_ADD_QUAD.9 \ sysctl.9 SYSCTL_ADD_ROOT_NODE.9 \ sysctl.9 SYSCTL_ADD_S8.9 \ sysctl.9 SYSCTL_ADD_S16.9 \ sysctl.9 SYSCTL_ADD_S32.9 \ sysctl.9 SYSCTL_ADD_S64.9 \ sysctl.9 SYSCTL_ADD_STRING.9 \ sysctl.9 SYSCTL_ADD_STRUCT.9 \ sysctl.9 SYSCTL_ADD_U8.9 \ sysctl.9 SYSCTL_ADD_U16.9 \ sysctl.9 SYSCTL_ADD_U32.9 \ sysctl.9 SYSCTL_ADD_U64.9 \ sysctl.9 SYSCTL_ADD_UAUTO.9 \ sysctl.9 SYSCTL_ADD_UINT.9 \ sysctl.9 SYSCTL_ADD_ULONG.9 \ sysctl.9 SYSCTL_ADD_UQUAD.9 \ sysctl.9 SYSCTL_CHILDREN.9 \ sysctl.9 SYSCTL_STATIC_CHILDREN.9 \ sysctl.9 SYSCTL_NODE_CHILDREN.9 \ sysctl.9 SYSCTL_PARENT.9 \ sysctl.9 SYSCTL_INT.9 \ sysctl.9 SYSCTL_LONG.9 \ sysctl.9 SYSCTL_NODE.9 \ sysctl.9 SYSCTL_OPAQUE.9 \ sysctl.9 SYSCTL_PROC.9 \ sysctl.9 SYSCTL_QUAD.9 \ sysctl.9 SYSCTL_ROOT_NODE.9 \ sysctl.9 SYSCTL_S8.9 \ sysctl.9 SYSCTL_S16.9 \ sysctl.9 SYSCTL_S32.9 \ sysctl.9 SYSCTL_S64.9 \ sysctl.9 SYSCTL_STRING.9 \ sysctl.9 SYSCTL_STRUCT.9 \ sysctl.9 SYSCTL_U8.9 \ sysctl.9 SYSCTL_U16.9 \ sysctl.9 SYSCTL_U32.9 \ sysctl.9 SYSCTL_U64.9 \ sysctl.9 SYSCTL_UINT.9 \ sysctl.9 SYSCTL_ULONG.9 \ sysctl.9 SYSCTL_UQUAD.9 MLINKS+=sysctl_add_oid.9 sysctl_move_oid.9 \ sysctl_add_oid.9 sysctl_remove_oid.9 \ sysctl_add_oid.9 sysctl_remove_name.9 MLINKS+=sysctl_ctx_init.9 sysctl_ctx_entry_add.9 \ sysctl_ctx_init.9 sysctl_ctx_entry_del.9 \ sysctl_ctx_init.9 sysctl_ctx_entry_find.9 \ sysctl_ctx_init.9 sysctl_ctx_free.9 MLINKS+=SYSINIT.9 SYSUNINIT.9 MLINKS+=taskqueue.9 TASK_INIT.9 \ taskqueue.9 TASK_INITIALIZER.9 \ taskqueue.9 taskqueue_block.9 \ taskqueue.9 taskqueue_cancel.9 \ taskqueue.9 taskqueue_cancel_timeout.9 \ taskqueue.9 taskqueue_create.9 \ taskqueue.9 taskqueue_create_fast.9 \ taskqueue.9 TASKQUEUE_DECLARE.9 \ taskqueue.9 TASKQUEUE_DEFINE.9 \ taskqueue.9 TASKQUEUE_DEFINE_THREAD.9 \ taskqueue.9 taskqueue_drain.9 \ taskqueue.9 taskqueue_drain_all.9 \ taskqueue.9 taskqueue_drain_timeout.9 \ taskqueue.9 taskqueue_enqueue.9 \ taskqueue.9 taskqueue_enqueue_timeout.9 \ taskqueue.9 TASKQUEUE_FAST_DEFINE.9 \ taskqueue.9 TASKQUEUE_FAST_DEFINE_THREAD.9 \ taskqueue.9 taskqueue_free.9 \ taskqueue.9 taskqueue_member.9 \ taskqueue.9 taskqueue_run.9 \ taskqueue.9 taskqueue_set_callback.9 \ taskqueue.9 taskqueue_start_threads.9 \ taskqueue.9 taskqueue_start_threads_pinned.9 \ taskqueue.9 taskqueue_unblock.9 \ taskqueue.9 TIMEOUT_TASK_INIT.9 MLINKS+=tcp_functions.9 register_tcp_functions.9 \ tcp_functions.9 deregister_tcp_functions.9 MLINKS+=time.9 boottime.9 \ time.9 time_second.9 \ time.9 time_uptime.9 MLINKS+=timeout.9 callout.9 \ timeout.9 callout_active.9 \ timeout.9 callout_async_drain.9 \ timeout.9 callout_deactivate.9 \ timeout.9 callout_drain.9 \ timeout.9 callout_handle_init.9 \ timeout.9 callout_init.9 \ timeout.9 callout_init_mtx.9 \ timeout.9 callout_init_rm.9 \ timeout.9 callout_init_rw.9 \ timeout.9 callout_pending.9 \ timeout.9 callout_reset.9 \ timeout.9 callout_reset_curcpu.9 \ timeout.9 callout_reset_on.9 \ timeout.9 callout_reset_sbt.9 \ timeout.9 callout_reset_sbt_curcpu.9 \ timeout.9 callout_reset_sbt_on.9 \ timeout.9 callout_schedule.9 \ timeout.9 callout_schedule_curcpu.9 \ timeout.9 callout_schedule_on.9 \ timeout.9 callout_schedule_sbt.9 \ timeout.9 callout_schedule_sbt_curcpu.9 \ timeout.9 callout_schedule_sbt_on.9 \ timeout.9 callout_stop.9 \ timeout.9 callout_when.9 \ timeout.9 untimeout.9 MLINKS+=ucred.9 cred_update_thread.9 \ ucred.9 crcopy.9 \ ucred.9 crcopysafe.9 \ ucred.9 crdup.9 \ ucred.9 crfree.9 \ ucred.9 crget.9 \ ucred.9 crhold.9 \ ucred.9 crsetgroups.9 \ ucred.9 crshared.9 \ ucred.9 cru2x.9 MLINKS+=uidinfo.9 uifind.9 \ uidinfo.9 uifree.9 \ uidinfo.9 uihashinit.9 \ uidinfo.9 uihold.9 MLINKS+=uio.9 uiomove.9 \ uio.9 uiomove_frombuf.9 \ uio.9 uiomove_nofault.9 .if ${MK_USB} != "no" MAN+= usbdi.9 MLINKS+=usbdi.9 usbd_do_request.9 \ usbdi.9 usbd_do_request_flags.9 \ usbdi.9 usbd_errstr.9 \ usbdi.9 usbd_lookup_id_by_info.9 \ usbdi.9 usbd_lookup_id_by_uaa.9 \ usbdi.9 usbd_transfer_clear_stall.9 \ usbdi.9 usbd_transfer_drain.9 \ usbdi.9 usbd_transfer_pending.9 \ usbdi.9 usbd_transfer_poll.9 \ usbdi.9 usbd_transfer_setup.9 \ usbdi.9 usbd_transfer_start.9 \ usbdi.9 usbd_transfer_stop.9 \ usbdi.9 usbd_transfer_submit.9 \ usbdi.9 usbd_transfer_unsetup.9 \ usbdi.9 usbd_xfer_clr_flag.9 \ usbdi.9 usbd_xfer_frame_data.9 \ usbdi.9 usbd_xfer_frame_len.9 \ usbdi.9 usbd_xfer_get_frame.9 \ usbdi.9 usbd_xfer_get_priv.9 \ usbdi.9 usbd_xfer_is_stalled.9 \ usbdi.9 usbd_xfer_max_framelen.9 \ usbdi.9 usbd_xfer_max_frames.9 \ usbdi.9 usbd_xfer_max_len.9 \ usbdi.9 usbd_xfer_set_flag.9 \ usbdi.9 usbd_xfer_set_frame_data.9 \ usbdi.9 usbd_xfer_set_frame_len.9 \ usbdi.9 usbd_xfer_set_frame_offset.9 \ usbdi.9 usbd_xfer_set_frames.9 \ usbdi.9 usbd_xfer_set_interval.9 \ usbdi.9 usbd_xfer_set_priv.9 \ usbdi.9 usbd_xfer_set_stall.9 \ usbdi.9 usbd_xfer_set_timeout.9 \ usbdi.9 usbd_xfer_softc.9 \ usbdi.9 usbd_xfer_state.9 \ usbdi.9 usbd_xfer_status.9 \ usbdi.9 usb_fifo_alloc_buffer.9 \ usbdi.9 usb_fifo_attach.9 \ usbdi.9 usb_fifo_detach.9 \ usbdi.9 usb_fifo_free_buffer.9 \ usbdi.9 usb_fifo_get_data.9 \ usbdi.9 usb_fifo_get_data_buffer.9 \ usbdi.9 usb_fifo_get_data_error.9 \ usbdi.9 usb_fifo_get_data_linear.9 \ usbdi.9 usb_fifo_put_bytes_max.9 \ usbdi.9 usb_fifo_put_data.9 \ usbdi.9 usb_fifo_put_data_buffer.9 \ usbdi.9 usb_fifo_put_data_error.9 \ usbdi.9 usb_fifo_put_data_linear.9 \ usbdi.9 usb_fifo_reset.9 \ usbdi.9 usb_fifo_softc.9 \ usbdi.9 usb_fifo_wakeup.9 .endif MLINKS+=vcount.9 count_dev.9 MLINKS+=vfsconf.9 vfs_modevent.9 \ vfsconf.9 vfs_register.9 \ vfsconf.9 vfs_unregister.9 MLINKS+=vfs_getopt.9 vfs_copyopt.9 \ vfs_getopt.9 vfs_filteropt.9 \ vfs_getopt.9 vfs_flagopt.9 \ vfs_getopt.9 vfs_getopts.9 \ vfs_getopt.9 vfs_scanopt.9 \ vfs_getopt.9 vfs_setopt.9 \ vfs_getopt.9 vfs_setopt_part.9 \ vfs_getopt.9 vfs_setopts.9 MLINKS+=vhold.9 vdrop.9 \ vhold.9 vdropl.9 \ vhold.9 vholdl.9 MLINKS+=vmem.9 vmem_add.9 \ vmem.9 vmem_alloc.9 \ vmem.9 vmem_create.9 \ vmem.9 vmem_destroy.9 \ vmem.9 vmem_free.9 \ vmem.9 vmem_xalloc.9 \ vmem.9 vmem_xfree.9 MLINKS+=vm_map_lock.9 vm_map_lock_downgrade.9 \ vm_map_lock.9 vm_map_lock_read.9 \ vm_map_lock.9 vm_map_lock_upgrade.9 \ vm_map_lock.9 vm_map_trylock.9 \ vm_map_lock.9 vm_map_trylock_read.9 \ vm_map_lock.9 vm_map_unlock.9 \ vm_map_lock.9 vm_map_unlock_read.9 MLINKS+=vm_map_lookup.9 vm_map_lookup_done.9 MLINKS+=vm_map_max.9 vm_map_min.9 \ vm_map_max.9 vm_map_pmap.9 MLINKS+=vm_map_stack.9 vm_map_growstack.9 MLINKS+=vm_map_wire.9 vm_map_unwire.9 MLINKS+=vm_page_bits.9 vm_page_clear_dirty.9 \ vm_page_bits.9 vm_page_dirty.9 \ vm_page_bits.9 vm_page_is_valid.9 \ vm_page_bits.9 vm_page_set_invalid.9 \ vm_page_bits.9 vm_page_set_validclean.9 \ vm_page_bits.9 vm_page_test_dirty.9 \ vm_page_bits.9 vm_page_undirty.9 \ vm_page_bits.9 vm_page_zero_invalid.9 MLINKS+=vm_page_busy.9 vm_page_busied.9 \ vm_page_busy.9 vm_page_busy_downgrade.9 \ vm_page_busy.9 vm_page_busy_sleep.9 \ vm_page_busy.9 vm_page_sbusied.9 \ vm_page_busy.9 vm_page_sbusy.9 \ vm_page_busy.9 vm_page_sleep_if_busy.9 \ vm_page_busy.9 vm_page_sunbusy.9 \ vm_page_busy.9 vm_page_trysbusy.9 \ vm_page_busy.9 vm_page_tryxbusy.9 \ vm_page_busy.9 vm_page_xbusied.9 \ vm_page_busy.9 vm_page_xbusy.9 \ vm_page_busy.9 vm_page_xunbusy.9 \ vm_page_busy.9 vm_page_assert_sbusied.9 \ vm_page_busy.9 vm_page_assert_unbusied.9 \ vm_page_busy.9 vm_page_assert_xbusied.9 MLINKS+=vm_page_aflag.9 vm_page_aflag_clear.9 \ vm_page_aflag.9 vm_page_aflag_set.9 \ vm_page_aflag.9 vm_page_reference.9 MLINKS+=vm_page_free.9 vm_page_free_toq.9 \ vm_page_free.9 vm_page_free_zero.9 \ vm_page_free.9 vm_page_try_to_free.9 MLINKS+=vm_page_hold.9 vm_page_unhold.9 MLINKS+=vm_page_insert.9 vm_page_remove.9 MLINKS+=vm_page_wire.9 vm_page_unwire.9 MLINKS+=VOP_ACCESS.9 VOP_ACCESSX.9 MLINKS+=VOP_ATTRIB.9 VOP_GETATTR.9 \ VOP_ATTRIB.9 VOP_SETATTR.9 MLINKS+=VOP_CREATE.9 VOP_MKDIR.9 \ VOP_CREATE.9 VOP_MKNOD.9 \ VOP_CREATE.9 VOP_SYMLINK.9 MLINKS+=VOP_GETPAGES.9 VOP_PUTPAGES.9 MLINKS+=VOP_INACTIVE.9 VOP_RECLAIM.9 MLINKS+=VOP_LOCK.9 vn_lock.9 \ VOP_LOCK.9 VOP_ISLOCKED.9 \ VOP_LOCK.9 VOP_UNLOCK.9 MLINKS+=VOP_OPENCLOSE.9 VOP_CLOSE.9 \ VOP_OPENCLOSE.9 VOP_OPEN.9 MLINKS+=VOP_RDWR.9 VOP_READ.9 \ VOP_RDWR.9 VOP_WRITE.9 MLINKS+=VOP_REMOVE.9 VOP_RMDIR.9 MLINKS+=vnet.9 vimage.9 MLINKS+=vref.9 VREF.9 \ vref.9 vrefl.9 MLINKS+=vrele.9 vput.9 \ vrele.9 vunref.9 MLINKS+=vslock.9 vsunlock.9 MLINKS+=zone.9 uma.9 \ zone.9 uma_zalloc.9 \ zone.9 uma_zalloc_arg.9 \ zone.9 uma_zcreate.9 \ zone.9 uma_zdestroy.9 \ zone.9 uma_zfree.9 \ zone.9 uma_zfree_arg.9 \ zone.9 uma_zone_get_cur.9 \ zone.9 uma_zone_get_max.9 \ zone.9 uma_zone_set_max.9 \ zone.9 uma_zone_set_warning.9 \ zone.9 uma_zone_set_maxaction.9 .include Index: stable/11/share/man/man9/cnv.9 =================================================================== --- stable/11/share/man/man9/cnv.9 (nonexistent) +++ stable/11/share/man/man9/cnv.9 (revision 336346) @@ -0,0 +1,214 @@ +.\" +.\" Copyright (c) 2016 Adam Starak +.\" 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. +.\" 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 AUTHOR 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 AUTHOR 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$ +.\" +.Dd June 18, 2018 +.Dt CNV 9 +.Os +.Sh NAME +.Nm cnvlist_get , +.Nm cnvlist_take , +.Nm cnvlist_free +.Nd "API for managing name/value pairs by cookie." +.Sh LIBRARY +.Lb libnv +.Sh SYNOPSIS +.In sys/cnv.h +.Ft const char * +.Fn cnvlist_name "const void *cookie" +.Ft int +.Fn cnvlist_type "const void *cookie" +.\" +.Ft bool +.Fn cnvlist_get_bool "const void *cookie" +.Ft uint64_t +.Fn cnvlist_get_number "const void *cookie" +.Ft "const char *" +.Fn cnvlist_get_string "const void *cookie" +.Ft "const nvlist_t *" +.Fn cnvlist_get_nvlist "const void *cookie" +.Ft "const void *" +.Fn cnvlist_get_binary "const void *cookie" "size_t *sizep" +.Ft "const bool *" +.Fn cnvlist_get_bool_array "const void *cookie" "size_t *nitemsp" +.Ft "const uint64_t *" +.Fn cnvlist_get_number_array "const void *cookie" "size_t *nitemsp" +.Ft "const char * const *" +.Fn cnvlist_get_string_array "const void *cookie" "size_t *nitemsp" +.Ft "const nvlist_t * const *" +.Fn cnvlist_get_nvlist_array "const void *cookie" "size_t *nitemsp" +.Ft int +.Fn cnvlist_get_descriptor "const void *cookie" +.Ft "const int *" +.Fn cnvlist_get_descriptor_array "const void *cookie" "size_t *nitemsp" +.\" +.Ft bool +.Fn cnvlist_take_bool "void *cookie" +.Ft uint64_t +.Fn cnvlist_take_number "void *cookie" +.Ft "const char *" +.Fn cnvlist_take_string "void *cookie" +.Ft "const nvlist_t *" +.Fn cnvlist_take_nvlist "void *cookie" +.Ft "const void *" +.Fn cnvlist_take_binary "void *cookie" "size_t *sizep" +.Ft "const bool *" +.Fn cnvlist_take_bool_array "void *cookie" "size_t *nitemsp" +.Ft "const uint64_t *" +.Fn cnvlist_take_number_array "void *cookie" "size_t *nitemsp" +.Ft "const char * const *" +.Fn cnvlist_take_string_array "void *cookie" "size_t *nitemsp" +.Ft "const nvlist_t * const *" +.Fn cnvlist_take_nvlist_array "void *cookie" "size_t *nitemsp" +.Ft int +.Fn cnvlist_take_descriptor "void *cookie" +.Ft "const int *' +.Fn cnvlist_take_descriptor_array "void *cookie" "size_t *nitemsp" +.\" +.Ft void +.Fn cnvlist_free_null "void *cookie" +.Ft void +.Fn cnvlist_free_bool "void *cookie" +.Ft void +.Fn cnvlist_free_number "void *cookie" +.Ft void +.Fn cnvlist_free_string "void *cookie" +.Ft void +.Fn cnvlist_free_nvlist "void *cookie" +.Ft void +.Fn cnvlist_free_descriptor "void *cookie" +.Ft void +.Fn cnvlist_free_binary "void *cookie" +.Ft void +.Fn cnvlist_free_bool_array "void *cookie" +.Ft void +.Fn cnvlist_free_number_array "void *cookie" +.Ft void +.Fn cnvlist_free_string_array "void *cookie" +.Ft void +.Fn cnvlist_free_nvlist_array "void *cookie" +.Ft void +.Fn cnvlist_free_descriptor_array "void *cookie" +.Sh DESCRIPTION +The +.Nm libnv +library permits easy management of name/value pairs and can send and receive +them over sockets. +For more information, also see +.Xr nv 9 . +.Pp +The concept of cookies is explained in +.Fn nvlist_next , +.Fn nvlist_get_parent , +and +.Fn nvlist_get_pararr +from +.Xr nv 9 . +.Pp +The +.Fn cnvlist_name +function returns the name of an element associated with the given cookie. +.Pp +The +.Fn cnvlist_type +function returns the type of an element associated with the given cookie. +Types which can be returned are described in +.Xr nv 9 . +.Pp +The +.Nm cnvlist_get +family of functions obtains the value associated with the given cookie. +Returned strings, nvlists, descriptors, binaries, or arrays must not be modified +by the user, since they still belong to the nvlist. +The nvlist must not be in an error state. +.Pp +The +.Nm cnvlist_take +family of functions returns the value associated with the given cookie and +removes the element from the nvlist. +When the value is a string, binary, or array value, the caller is responsible +for freeing the returned memory with +.Fn free 3 . +When the value is an nvlist, the caller is responsible for destroying the +returned nvlist with +.Fn nvlist_destroy . +When the value is a descriptor, the caller is responsible for closing the +returned descriptor with the +.Fn close 2 . +.Pp +The +.Nm cnvlist_free +family of functions removes an element of the supplied cookie and frees all +resources. +If an element of the given cookie has the wrong type or does not exist, the +program +is aborted. +.Sh EXAMPLE +The following example demonstrates how to deal with cnvlist API. +.Bd -literal +int type; +void *cookie, *scookie, *bcookie; +nvlist_t *nvl; +char *name; + +nvl = nvlist_create(0); +nvlist_add_bool(nvl, "test", 1 == 2); +nvlist_add_string(nvl, "test2", "cnvlist"); +cookie = NULL; + +while (nvlist_next(nvl, &type, &cookie) != NULL) { + switch (type) { + case NV_TYPE_BOOL: + printf("test: %d\\n", cnvlist_get_bool(cookie)); + bcookie = cookie; + break; + case NV_TYPE_STRING: + printf("test2: %s\\n", cnvlist_get_string(cookie)); + scookie = cookie; + break; + } +} + +name = cnvlist_take_string(scookie); +cnvlist_free_bool(bcookie); + +printf("test2: %s\\n", name); +free(name); + +printf("nvlist_empty = %d\\n", nvlist_empty(nvl)); +nvlist_destroy(nvl); + +return (0); +.Ed +.Sh SEE ALSO +.Xr nv 9 , +.Xr close 2 , +.Xr free 3 +.Sh AUTHORS +.An -nosplit +The +.Nm cnv +API was created during the Google Summer Of Code 2016 by Property changes on: stable/11/share/man/man9/cnv.9 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/share/man/man9/nv.9 =================================================================== --- stable/11/share/man/man9/nv.9 (revision 336345) +++ stable/11/share/man/man9/nv.9 (revision 336346) @@ -1,935 +1,961 @@ .\" .\" Copyright (c) 2013 The FreeBSD Foundation .\" Copyright (c) 2013-2015 Mariusz Zaborski .\" All rights reserved. .\" .\" This documentation was written by Pawel Jakub Dawidek under sponsorship .\" 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 AUTHOR 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 AUTHOR 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$ .\" -.Dd September 16, 2017 +.Dd June 19, 2018 .Dt NV 9 .Os .Sh NAME .Nm nvlist_create , .Nm nvlist_destroy , .Nm nvlist_error , .Nm nvlist_set_error , .Nm nvlist_empty , .Nm nvlist_flags , .Nm nvlist_exists , .Nm nvlist_free , .Nm nvlist_clone , .Nm nvlist_dump , .Nm nvlist_fdump , .Nm nvlist_size , .Nm nvlist_pack , .Nm nvlist_unpack , .Nm nvlist_send , .Nm nvlist_recv , .Nm nvlist_xfer , .Nm nvlist_in_array , .Nm nvlist_next , .Nm nvlist_add , .Nm nvlist_move , .Nm nvlist_get , -.Nm nvlist_take +.Nm nvlist_take , +.Nm nvlist_append .Nd "library for name/value pairs" .Sh LIBRARY .Lb libnv .Sh SYNOPSIS .In sys/nv.h .Ft "nvlist_t *" .Fn nvlist_create "int flags" .Ft void .Fn nvlist_destroy "nvlist_t *nvl" .Ft int .Fn nvlist_error "const nvlist_t *nvl" .Ft void .Fn nvlist_set_error "nvlist_t *nvl" "int error" .Ft bool .Fn nvlist_empty "const nvlist_t *nvl" .Ft int .Fn nvlist_flags "const nvlist_t *nvl" .Ft bool .Fn nvlist_in_array "const nvlist_t *nvl" .\" .Ft "nvlist_t *" .Fn nvlist_clone "const nvlist_t *nvl" .\" .Ft void .Fn nvlist_dump "const nvlist_t *nvl" "int fd" .Ft void .Fn nvlist_fdump "const nvlist_t *nvl" "FILE *fp" .\" .Ft size_t .Fn nvlist_size "const nvlist_t *nvl" .Ft "void *" .Fn nvlist_pack "const nvlist_t *nvl" "size_t *sizep" .Ft "nvlist_t *" .Fn nvlist_unpack "const void *buf" "size_t size" "int flags" .\" .Ft int .Fn nvlist_send "int sock" "const nvlist_t *nvl" .Ft "nvlist_t *" .Fn nvlist_recv "int sock" "int flags" .Ft "nvlist_t *" .Fn nvlist_xfer "int sock" "nvlist_t *nvl" "int flags" .\" .Ft "const char *" .Fn nvlist_next "const nvlist_t *nvl" "int *typep" "void **cookiep" .\" .Ft bool .Fn nvlist_exists "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_type "const nvlist_t *nvl" "const char *name" "int type" .Ft bool .Fn nvlist_exists_null "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_bool "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_number "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_string "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_nvlist "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_descriptor "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_binary "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_bool_array "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_number_array "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_string_array "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_nvlist_array "const nvlist_t *nvl" "const char *name" .Ft bool .Fn nvlist_exists_descriptor_array "const nvlist_t *nvl" "const char *name" .\" .Ft void .Fn nvlist_add_null "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_add_bool "nvlist_t *nvl" "const char *name" "bool value" .Ft void .Fn nvlist_add_number "nvlist_t *nvl" "const char *name" "uint64_t value" .Ft void .Fn nvlist_add_string "nvlist_t *nvl" "const char *name" "const char *value" .Ft void .Fn nvlist_add_stringf "nvlist_t *nvl" "const char *name" "const char *valuefmt" "..." .Ft void .Fn nvlist_add_stringv "nvlist_t *nvl" "const char *name" "const char *valuefmt" "va_list valueap" .Ft void .Fn nvlist_add_nvlist "nvlist_t *nvl" "const char *name" "const nvlist_t *value" .Ft void .Fn nvlist_add_descriptor "nvlist_t *nvl" "const char *name" "int value" .Ft void .Fn nvlist_add_binary "nvlist_t *nvl" "const char *name" "const void *value" "size_t size" .Ft void .Fn nvlist_add_bool_array "nvlist_t *nvl" "const char *name" "const bool *value" "size_t nitems" . .Ft void .Fn nvlist_add_number_array "nvlist_t *nvl" "const char *name" "const uint64_t *value" "size_t nitems" . .Ft void .Fn nvlist_add_string_array "nvlist_t *nvl" "const char *name" "const char * const * value" "size_t nitems" . .Ft void .Fn nvlist_add_nvlist_array "nvlist_t *nvl" "const char *name" "const nvlist_t * const * value" "size_t nitems" . .Ft void .Fn nvlist_add_descriptor_array "nvlist_t *nvl" "const char *name" "const int *value" "size_t nitems" .\" .Ft void .Fn nvlist_move_string "nvlist_t *nvl" "const char *name" "char *value" .Ft void .Fn nvlist_move_nvlist "nvlist_t *nvl" "const char *name" "nvlist_t *value" .Ft void .Fn nvlist_move_descriptor "nvlist_t *nvl" "const char *name" "int value" .Ft void .Fn nvlist_move_binary "nvlist_t *nvl" "const char *name" "void *value" "size_t size" .Ft void .Fn nvlist_move_bool_array "nvlist_t *nvl" "const char *name" "bool *value" "size_t nitems" . .Ft void .Fn nvlist_move_number_array "nvlist_t *nvl" "const char *name" "uint64_t *value" "size_t nitems" . .Ft void .Fn nvlist_move_string_array "nvlist_t *nvl" "const char *name" "char **value" "size_t nitems" . .Ft void .Fn nvlist_move_nvlist_array "nvlist_t *nvl" "const char *name" "nvlist_t **value" "size_t nitems" . .Ft void .Fn nvlist_move_descriptor_array "nvlist_t *nvl" "const char *name" "int *value" "size_t nitems" .\" .Ft bool .Fn nvlist_get_bool "const nvlist_t *nvl" "const char *name" .Ft uint64_t .Fn nvlist_get_number "const nvlist_t *nvl" "const char *name" .Ft "const char *" .Fn nvlist_get_string "const nvlist_t *nvl" "const char *name" .Ft "const nvlist_t *" .Fn nvlist_get_nvlist "const nvlist_t *nvl" "const char *name" .Ft int .Fn nvlist_get_descriptor "const nvlist_t *nvl" "const char *name" .Ft "const void *" .Fn nvlist_get_binary "const nvlist_t *nvl" "const char *name" "size_t *sizep" .Ft "const bool *" .Fn nvlist_get_bool_array "const nvlist_t *nvl" "const char *name" "size_t *nitems" .Ft "const uint64_t *" .Fn nvlist_get_number_array "const nvlist_t *nvl" "const char *name" "size_t *nitems" .Ft "const char * const *" .Fn nvlist_get_string_array "const nvlist_t *nvl" "const char *name" "size_t *nitems" .Ft "const nvlist_t * const *" .Fn nvlist_get_nvlist_array "const nvlist_t *nvl" "const char *name" "size_t *nitems" .Ft "const int *" .Fn nvlist_get_descriptor_array "const nvlist_t *nvl" "const char *name" "size_t *nitems" .Ft "const nvlist_t *" .Fn nvlist_get_parent "const nvlist_t *nvl" "void **cookiep" .Ft "const nvlist_t *" .Fn nvlist_get_array_next "const nvlist_t *nvl" .Ft "const nvlist_t *" .Fn nvlist_get_pararr "const nvlist_t *nvl" "void **cookiep" .\" .Ft bool .Fn nvlist_take_bool "nvlist_t *nvl" "const char *name" .Ft uint64_t .Fn nvlist_take_number "nvlist_t *nvl" "const char *name" .Ft "char *" .Fn nvlist_take_string "nvlist_t *nvl" "const char *name" .Ft "nvlist_t *" .Fn nvlist_take_nvlist "nvlist_t *nvl" "const char *name" .Ft int .Fn nvlist_take_descriptor "nvlist_t *nvl" "const char *name" .Ft "void *" .Fn nvlist_take_binary "nvlist_t *nvl" "const char *name" "size_t *sizep" .Ft "bool *" .Fn nvlist_take_bool_array "nvlist_t *nvl" "const char *name" "size_t *nitems" .Ft "uint64_t **" .Fn nvlist_take_number_array "nvlist_t *nvl" "const char *name" "size_t *nitems" .Ft "char **" .Fn nvlist_take_string_array "nvlist_t *nvl" "const char *name" "size_t *nitems" .Ft "nvlist_t **" .Fn nvlist_take_nvlist_array "nvlist_t *nvl" "const char *name" "size_t *nitems" .Ft "int *" .Fn nvlist_take_descriptor_array "nvlist_t *nvl" "const char *name" "size_t *nitems" .\" .Ft void +.Fn nvlist_append_bool_array "nvlist_t *nvl" "const char *name" "const bool value" +.Ft void +.Fn nvlist_append_number_array "nvlist_t *nvl" "const char *name" "const uint64_t value" +.Ft void +.Fn nvlist_append_string_array "nvlist_t *nvl" "const char *name" "const char * const value" +.Ft void +.Fn nvlist_append_nvlist_array "nvlist_t *nvl" "const char *name" "const nvlist_t * const value" +.Ft void +.Fn nvlist_append_descriptor_array "nvlist_t *nvl" "const char *name" "int value" +.\" +.Ft void .Fn nvlist_free "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_type "nvlist_t *nvl" "const char *name" "int type" .\" .Ft void .Fn nvlist_free_null "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_bool "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_number "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_string "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_nvlist "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_descriptor "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_binary "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_bool_array "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_number_array "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_string_array "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_nvlist_array "nvlist_t *nvl" "const char *name" .Ft void .Fn nvlist_free_descriptor_array "nvlist_t *nvl" "const char *name" .Sh DESCRIPTION The .Nm libnv library allows to easily manage name value pairs as well as send and receive them over sockets. A group (list) of name value pairs is called an .Nm nvlist . The API supports the following data types: .Bl -ohang -offset indent .It Sy null ( NV_TYPE_NULL ) There is no data associated with the name. .It Sy bool ( NV_TYPE_BOOL ) The value can be either .Dv true or .Dv false . .It Sy number ( NV_TYPE_NUMBER ) The value is a number stored as .Vt uint64_t . .It Sy string ( NV_TYPE_STRING ) The value is a C string. .It Sy nvlist ( NV_TYPE_NVLIST ) The value is a nested nvlist. .It Sy descriptor ( NV_TYPE_DESCRIPTOR ) The value is a file descriptor. Note that file descriptors can be sent only over .Xr unix 4 domain sockets. .It Sy binary ( NV_TYPE_BINARY ) The value is a binary buffer. .It Sy bool array ( NV_TYPE_BOOL_ARRAY ) The value is an array of boolean values. .It Sy number array ( NV_TYPE_NUMBER_ARRAY ) The value is an array of numbers, each stored as .Vt uint64_t . .It Sy string array ( NV_TYPE_STRING_ARRAY ) The value is an array of C strings. .It Sy nvlist array ( NV_TYPE_NVLIST_ARRAY ) The value is an array of nvlists. When an nvlist is added to an array, it becomes part of the primary nvlist. Traversing these arrays can be done using the .Fn nvlist_get_array_next and .Fn nvlist_get_pararr functions. .It Sy descriptor array ( NV_TYPE_DESCRIPTOR_ARRAY ) The value is an array of files descriptors. .El .Pp The .Fn nvlist_create function allocates memory and initializes an nvlist. .Pp The following flag can be provided: .Pp .Bl -tag -width "NV_FLAG_IGNORE_CASE" -compact -offset indent .It Dv NV_FLAG_IGNORE_CASE Perform case-insensitive lookups of provided names. .It Dv NV_FLAG_NO_UNIQUE Names in the nvlist do not have to be unique. .El .Pp The .Fn nvlist_destroy function destroys the given nvlist. Function does nothing if .Dv NULL nvlist is provided. Function never modifies the .Va errno global variable. .Pp The .Fn nvlist_error function returns any error value that the nvlist accumulated. If the given nvlist is .Dv NULL the .Er ENOMEM error will be returned. .Pp The .Fn nvlist_set_error function sets an nvlist to be in the error state. Subsequent calls to .Fn nvlist_error will return the given error value. This function cannot be used to clear the error state from an nvlist. This function does nothing if the nvlist is already in the error state. .Pp The .Fn nvlist_empty function returns .Dv true if the given nvlist is empty and .Dv false otherwise. The nvlist must not be in error state. .Pp The .Fn nvlist_flags function returns flags used to create the nvlist with the .Fn nvlist_create function. .Pp The .Fn nvlist_in_array function returns .Dv true if .Fa nvl is part of an array that is a member of another nvlist. .Pp The .Fn nvlist_clone functions clones the given nvlist. The clone shares no resources with its origin. This also means that all file descriptors that are part of the nvlist will be duplicated with the .Xr dup 2 system call before placing them in the clone. .Pp The .Fn nvlist_dump dumps nvlist content for debugging purposes to the given file descriptor .Fa fd . .Pp The .Fn nvlist_fdump dumps nvlist content for debugging purposes to the given file stream .Fa fp . .Pp The .Fn nvlist_size function returns the size of the given nvlist after converting it to binary buffer with the .Fn nvlist_pack function. .Pp The .Fn nvlist_pack function converts the given nvlist to a binary buffer. The function allocates memory for the buffer, which should be freed with the .Xr free 3 function. If the .Fa sizep argument is not .Dv NULL , the size of the buffer will be stored there. The function returns .Dv NULL in case of an error (allocation failure). If the nvlist contains any file descriptors .Dv NULL will be returned. The nvlist must not be in error state. .Pp The .Fn nvlist_unpack function converts the given buffer to the nvlist. The .Fa flags argument defines what type of the top level nvlist is expected to be. Flags are set up using the .Fn nvlist_create function. If the nvlist flags do not match the flags passed to .Fn nvlist_unpack , the nvlist will not be returned. Every nested nvlist list should be checked using .Fn nvlist_flags function. The function returns .Dv NULL in case of an error. .Pp The .Fn nvlist_send function sends the given nvlist over the socket given by the .Fa sock argument. Note that nvlist that contains file descriptors can only be send over .Xr unix 4 domain sockets. .Pp The .Fn nvlist_recv function receives nvlist over the socket given by the .Fa sock argument. The .Fa flags argument defines what type of the top level nvlist is expected to be. Flags are set up using the .Fn nvlist_create function. If the nvlist flags do not match the flags passed to .Fn nvlist_recv , the nvlist will not be returned. Every nested nvlist list should be checked using .Fn nvlist_flags function. .Pp The .Fn nvlist_xfer function sends the given nvlist over the socket given by the .Fa sock argument and receives nvlist over the same socket. The .Fa flags argument defines what type of the top level nvlist is expected to be. Flags are set up using the .Fn nvlist_create function. If the nvlist flags do not match the flags passed to .Fn nvlist_xfer , the nvlist will not be returned. Every nested nvlist list should be checked using .Fn nvlist_flags function. The given nvlist is always destroyed. .Pp The .Fn nvlist_next function iterates over the given nvlist returning names and types of subsequent elements. The .Fa cookiep argument allows the function to figure out which element should be returned next. The .Va *cookiep should be set to .Dv NULL for the first call and should not be changed later. Returning .Dv NULL means there are no more elements on the nvlist. The .Fa typep argument can be NULL. Elements may not be removed from the nvlist while traversing it. The nvlist must not be in error state. Note that .Fn nvlist_next will handle .Va cookiep being set to .Dv NULL . In this case first element is returned or .Dv NULL if nvlist is empty. This behavior simplifies removing the first element from the list. .Pp The .Fn nvlist_exists function returns .Dv true if element of the given name exists (besides of its type) or .Dv false otherwise. The nvlist must not be in error state. .Pp The .Fn nvlist_exists_type function returns .Dv true if element of the given name and the given type exists or .Dv false otherwise. The nvlist must not be in error state. .Pp The .Fn nvlist_exists_null , .Fn nvlist_exists_bool , .Fn nvlist_exists_number , .Fn nvlist_exists_string , .Fn nvlist_exists_nvlist , .Fn nvlist_exists_descriptor , .Fn nvlist_exists_binary , .Fn nvlist_exists_bool_array , .Fn nvlist_exists_number_array , .Fn nvlist_exists_string_array , .Fn nvlist_exists_nvlist_array , .Fn nvlist_exists_descriptor_array functions return .Dv true if element of the given name and the given type determined by the function name exists or .Dv false otherwise. The nvlist must not be in error state. .Pp The .Fn nvlist_add_null , .Fn nvlist_add_bool , .Fn nvlist_add_number , .Fn nvlist_add_string , .Fn nvlist_add_stringf , .Fn nvlist_add_stringv , .Fn nvlist_add_nvlist , .Fn nvlist_add_descriptor , .Fn nvlist_add_binary , .Fn nvlist_add_bool_array , .Fn nvlist_add_number_array , .Fn nvlist_add_string_array , .Fn nvlist_add_nvlist_array , .Fn nvlist_add_descriptor_array functions add element to the given nvlist. When adding string or binary buffor the functions will allocate memory and copy the data over. When adding nvlist, the nvlist will be cloned and clone will be added. When adding descriptor, the descriptor will be duplicated using the .Xr dup 2 system call and the new descriptor will be added. The array functions will fail if there are any .Dv NULL elements in the array, or if the array pointer is .Dv NULL . If an error occurs while adding new element, internal error is set which can be examined using the .Fn nvlist_error function. .Pp The .Fn nvlist_move_string , .Fn nvlist_move_nvlist , .Fn nvlist_move_descriptor , .Fn nvlist_move_binary , .Fn nvlist_move_bool_array , .Fn nvlist_move_number_array , .Fn nvlist_move_string_array , .Fn nvlist_move_nvlist_array , .Fn nvlist_move_descriptor_array functions add new element to the given nvlist, but unlike .Fn nvlist_add_ functions they will consume the given resource. In the case of strings, descriptors, or nvlists every elements must be unique, or it could cause a double free. The array functions will fail if there are any .Dv NULL elements, or if the array pointer is .Dv NULL . If an error occurs while adding new element, the resource is destroyed and internal error is set which can be examined using the .Fn nvlist_error function. .Pp The .Fn nvlist_get_bool , .Fn nvlist_get_number , .Fn nvlist_get_string , .Fn nvlist_get_nvlist , .Fn nvlist_get_descriptor , .Fn nvlist_get_binary , .Fn nvlist_get_bool_array , .Fn nvlist_get_number_array , .Fn nvlist_get_string_array , .Fn nvlist_get_nvlist_array , .Fn nvlist_get_descriptor_array functions return the value that corresponds to the given key name. In the case of strings, nvlists, descriptors, binary, or arrays, the returned resource should not be modified - they still belong to the nvlist. If an element of the given name does not exist, the program will be aborted. To avoid this, the caller should check for the existence of the name before trying to obtain the value, or use the .Xr dnvlist 3 extension, which can provide a default value in the case of a missing element. The nvlist must not be in error state. .Pp The .Fn nvlist_get_parent function returns the parent nvlist of the nested nvlist. .Pp The .Fn nvlist_get_array_next function returns the next element from the array or .Dv NULL if the nvlist is not in array or it is the last element. Note that .Fn nvlist_get_array_next only works if you added the nvlist array using the .Fn nvlist_move_nvlist_array or .Fn nvlist_add_nvlist_array functions. .Pp The .Fn nvlist_get_pararr function returns the next element in the array, or if not available the parent of the nested nvlist. .Pp The .Fn nvlist_take_bool , .Fn nvlist_take_number , .Fn nvlist_take_string , .Fn nvlist_take_nvlist , .Fn nvlist_take_descriptor , .Fn nvlist_take_binary , .Fn nvlist_take_bool_array , .Fn nvlist_take_number_array , .Fn nvlist_take_string_array , .Fn nvlist_take_nvlist_array , .Fn nvlist_take_descriptor_array functions return value associated with the given name and remove the element from the nvlist. In case of string and binary values, the caller is responsible for free returned memory using the .Xr free 3 function. In case of nvlist, the caller is responsible for destroying returned nvlist using the .Fn nvlist_destroy function. In case of descriptor, the caller is responsible for closing returned descriptor using the .Fn close 2 system call. If an element of the given name does not exist, the program will be aborted. To avoid that the caller should check for the existence of the given name before trying to obtain the value, or use the .Xr dnvlist 3 extension, which can provide a default value in the case of a missing element. In the case of an array of strings or binary values, the caller is responsible for freeing every element of the array using the .Xr free 3 function. In the case of an array of nvlists, the caller is responsible for destroying every element of array using the .Fn nvlist_destroy function. In the case of descriptors, the caller is responsible for closing every element of array using the .Fn close 2 system call. In every case involving an array, the caller must also free the pointer to the array using the .Xr free 3 function. The nvlist must not be in error state. +.Pp +The +.Fn nvlist_append_bool_array , +.Fn nvlist_append_number_array , +.Fn nvlist_append_string_array , +.Fn nvlist_append_nvlist_array , +.Fn nvlist_append_descriptor_array +functions append an element to the existing array using the same semantics +as the add functions (i.e. the element will be copied when applicable). +If the array for a given key does not exist, then it will be created +as if using the +.Fn nvlist_add__array +function. +The internal error is set on append failure. .Pp The .Fn nvlist_free function removes element of the given name from the nvlist (besides of its type) and frees all resources associated with it. If element of the given name does not exist, the program will be aborted. The nvlist must not be in error state. .Pp The .Fn nvlist_free_type function removes element of the given name and the given type from the nvlist and frees all resources associated with it. If element of the given name and the given type does not exist, the program will be aborted. The nvlist must not be in error state. .Pp The .Fn nvlist_free_null , .Fn nvlist_free_bool , .Fn nvlist_free_number , .Fn nvlist_free_string , .Fn nvlist_free_nvlist , .Fn nvlist_free_descriptor , .Fn nvlist_free_binary , .Fn nvlist_free_bool_array , .Fn nvlist_free_number_array , .Fn nvlist_free_string_array , .Fn nvlist_free_nvlist_array , .Fn nvlist_free_descriptor_array functions remove element of the given name and the given type determined by the function name from the nvlist and free all resources associated with it. If element of the given name and the given type does not exist, the program will be aborted. The nvlist must not be in error state. .Sh EXAMPLES The following example demonstrates how to prepare an nvlist and send it over .Xr unix 4 domain socket. .Bd -literal nvlist_t *nvl; int fd; fd = open("/tmp/foo", O_RDONLY); if (fd < 0) err(1, "open(\\"/tmp/foo\\") failed"); nvl = nvlist_create(0); /* * There is no need to check if nvlist_create() succeeded, * as the nvlist_add_() functions can cope. * If it failed, nvlist_send() will fail. */ nvlist_add_string(nvl, "filename", "/tmp/foo"); nvlist_add_number(nvl, "flags", O_RDONLY); /* * We just want to send the descriptor, so we can give it * for the nvlist to consume (that's why we use nvlist_move * not nvlist_add). */ nvlist_move_descriptor(nvl, "fd", fd); if (nvlist_send(sock, nvl) < 0) { nvlist_destroy(nvl); err(1, "nvlist_send() failed"); } nvlist_destroy(nvl); .Ed .Pp Receiving nvlist and getting data: .Bd -literal nvlist_t *nvl; const char *command; char *filename; int fd; nvl = nvlist_recv(sock, 0); if (nvl == NULL) err(1, "nvlist_recv() failed"); /* For command we take pointer to nvlist's buffer. */ command = nvlist_get_string(nvl, "command"); /* * For filename we remove it from the nvlist and take * ownership of the buffer. */ filename = nvlist_take_string(nvl, "filename"); /* The same for the descriptor. */ fd = nvlist_take_descriptor(nvl, "fd"); printf("command=%s filename=%s fd=%d\n", command, filename, fd); nvlist_destroy(nvl); free(filename); close(fd); /* command was freed by nvlist_destroy() */ .Ed .Pp Iterating over nvlist: .Bd -literal nvlist_t *nvl; const char *name; void *cookie; int type; nvl = nvlist_recv(sock, 0); if (nvl == NULL) err(1, "nvlist_recv() failed"); cookie = NULL; while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) { printf("%s=", name); switch (type) { case NV_TYPE_NUMBER: printf("%ju", (uintmax_t)nvlist_get_number(nvl, name)); break; case NV_TYPE_STRING: printf("%s", nvlist_get_string(nvl, name)); break; default: printf("N/A"); break; } printf("\\n"); } .Ed .Pp Iterating over every nested nvlist: .Bd -literal nvlist_t *nvl; const char *name; void *cookie; int type; nvl = nvlist_recv(sock, 0); if (nvl == NULL) err(1, "nvlist_recv() failed"); cookie = NULL; do { while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) { if (type == NV_TYPE_NVLIST) { nvl = nvlist_get_nvlist(nvl, name); cookie = NULL; } } } while ((nvl = nvlist_get_parent(nvl, &cookie)) != NULL); .Ed .Pp Iterating over every nested nvlist and every nvlist element: .Bd -literal nvlist_t *nvl; const nvlist_t * const *array; const char *name; void *cookie; int type; nvl = nvlist_recv(sock, 0); if (nvl == null) err(1, "nvlist_recv() failed"); cookie = null; do { while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) { if (type == NV_TYPE_NVLIST) { nvl = nvlist_get_nvlist(nvl, name); cookie = NULL; } else if (type == NV_TYPE_NVLIST_ARRAY) { nvl = nvlist_get_nvlist_array(nvl, name, NULL)[0]; cookie = NULL; } } } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL); .Ed .Pp Or alternatively: .Bd -literal nvlist_t *nvl, *tmp; const nvlist_t * const *array; const char *name; void *cookie; int type; nvl = nvlist_recv(sock, 0); if (nvl == null) err(1, "nvlist_recv() failed"); cooke = NULL; tmp = nvl; do { do { nvl = tmp; while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) { if (type == NV_TYPE_NVLIST) { nvl = nvlist_get_nvlist(nvl, name); cookie = NULL; } else if (type == NV_TYPE_NVLIST_ARRAY) { nvl = nvlist_get_nvlist_array(nvl, name, NULL)[0]; cookie = NULL; } } cookie = NULL; } while ((tmp = nvlist_get_array_next(nvl)) != NULL); } while ((tmp = nvlist_get_parent(nvl, &cookie)) != NULL); .Ed .Sh SEE ALSO .Xr close 2 , .Xr dup 2 , .Xr open 2 , .Xr err 3 , .Xr free 3 , .Xr printf 3 , .Xr unix 4 .Sh HISTORY The .Nm libnv library appeared in .Fx 11.0 . .Sh AUTHORS .An -nosplit The .Nm libnv library was implemented by .An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net under sponsorship from the FreeBSD Foundation. Index: stable/11/share/man/man9/owll.9 =================================================================== --- stable/11/share/man/man9/owll.9 (revision 336345) +++ stable/11/share/man/man9/owll.9 (revision 336346) @@ -1,93 +1,93 @@ .\" .\" Copyright (c) 2015 M. Warner Losh .\" 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. .\" 2. 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 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 AUTHOR 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$ .\" .Dd July 20, 2015 .Dt OWLL 9 .Os .Sh NAME .Nm owll -.Nm OWLL_WRITE_ONE, -.Nm OWLL_WRITE_ZERO, -.Nm OWLL_READ_DATA, +.Nm OWLL_WRITE_ONE , +.Nm OWLL_WRITE_ZERO , +.Nm OWLL_READ_DATA , .Nm OWLL_REASET_AND_PRESENCE .Nd Dallas Semiconductor 1-Wire Link Layer Interface .Sh SYNOPSIS .Ft int .Fn OWLL_WRITE_ONE "device_t lldev" "struct ow_timing *timing" .Ft int .Fn OWLL_WRITE_ZERO "device_t lldev" "struct ow_timing *timing" .Ft int .Fn OWLL_READ_DATA "device_t lldev" "struct ow_timing *timing" "int *bit" .Ft int .Fn OWLL_RESET_AND_PRESENCE "device_t lldev" "struct ow_timing *timing" "int *bit" .Sh DESCRIPTION The .Nm interface provides access to the link layer of the Dallas Semiconductor 1-Wire from upper layers of the protocol. .Pp .Fn OWLL_WRITE_ONE and .Fn OWLL_WRITE_ZERO writes a one bitor a zero bit respectively on the 1-Wire bus. .Pp .Fn OWLL_READ_DATA reads one bit from the 1-Wire bus. This is often referred to as a .Dq Read Time Slot in the 1-Wire device data sheets. .Pp The .Fn OWLL_RESET_AND_PRESENCE function starts a reset sequence and detects if any device(s) are present on the bus. This is the beginning of all 1-Wire transactions. .Sh NOTES This interface is intended to be used only by the .Xr ow 4 device to talk to the low-level bus. By convention, the device that implements this interface is called .Xr owc 4 . Only devices that implement .Xr own 9 should call these interfaces. .Sh SEE ALSO .Xr ow 4 , .Xr owc 4 , .Xr own 9 .Sh LEGAL .Tn 1-Wire is a registered trademark of Maxim Integrated Products, Inc. .Sh HISTORY The .Nm driver first appeared in .Fx 11.0 . .Sh AUTHORS The .Nm device driver and this manual page were written by .An Warner Losh . Index: stable/11/share/man/man9/rwlock.9 =================================================================== --- stable/11/share/man/man9/rwlock.9 (revision 336345) +++ stable/11/share/man/man9/rwlock.9 (revision 336346) @@ -1,337 +1,337 @@ .\" Copyright (c) 2006 Gleb Smirnoff .\" 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. .\" 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 AUTHOR 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 AUTHOR 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$ .\" .Dd November 11, 2017 .Dt RWLOCK 9 .Os .Sh NAME .Nm rwlock , .Nm rw_init , -.Nm rw_init_flags, +.Nm rw_init_flags , .Nm rw_destroy , .Nm rw_rlock , .Nm rw_wlock , .Nm rw_runlock , .Nm rw_wunlock , .Nm rw_unlock , .Nm rw_try_rlock , .Nm rw_try_upgrade , .Nm rw_try_wlock , .Nm rw_downgrade , .Nm rw_sleep , .Nm rw_initialized , .Nm rw_wowned , .Nm rw_assert , .Nm RW_SYSINIT , .Nm RW_SYSINIT_FLAGS .Nd kernel reader/writer lock .Sh SYNOPSIS .In sys/param.h .In sys/lock.h .In sys/rwlock.h .Ft void .Fn rw_init "struct rwlock *rw" "const char *name" .Ft void .Fn rw_init_flags "struct rwlock *rw" "const char *name" "int opts" .Ft void .Fn rw_destroy "struct rwlock *rw" .Ft void .Fn rw_rlock "struct rwlock *rw" .Ft void .Fn rw_wlock "struct rwlock *rw" .Ft int .Fn rw_try_rlock "struct rwlock *rw" .Ft int .Fn rw_try_wlock "struct rwlock *rw" .Ft void .Fn rw_runlock "struct rwlock *rw" .Ft void .Fn rw_wunlock "struct rwlock *rw" .Ft void .Fn rw_unlock "struct rwlock *rw" .Ft int .Fn rw_try_upgrade "struct rwlock *rw" .Ft void .Fn rw_downgrade "struct rwlock *rw" .Ft int .Fn rw_sleep "void *chan" "struct rwlock *rw" "int priority" "const char *wmesg" "int timo" .Ft int .Fn rw_initialized "const struct rwlock *rw" .Ft int .Fn rw_wowned "const struct rwlock *rw" .Pp .Cd "options INVARIANTS" .Cd "options INVARIANT_SUPPORT" .Ft void .Fn rw_assert "const struct rwlock *rw" "int what" .In sys/kernel.h .Fn RW_SYSINIT "name" "struct rwlock *rw" "const char *desc" .Fn RW_SYSINIT_FLAGS "name" "struct rwlock *rw" "const char *desc" "int flags" .Sh DESCRIPTION Reader/writer locks allow shared access to protected data by multiple threads, or exclusive access by a single thread. The threads with shared access are known as .Em readers since they only read the protected data. A thread with exclusive access is known as a .Em writer since it can modify protected data. .Pp Although reader/writer locks look very similar to .Xr sx 9 locks, their usage pattern is different. Reader/writer locks can be treated as mutexes (see .Xr mutex 9 ) with shared/exclusive semantics. Unlike .Xr sx 9 , an .Nm can be locked while holding a non-spin mutex, and an .Nm cannot be held while sleeping. The .Nm locks have priority propagation like mutexes, but priority can be propagated only to writers. This limitation comes from the fact that readers are anonymous. Another important property is that readers can always recurse, and exclusive locks can be made recursive selectively. .Ss Macros and Functions .Bl -tag -width indent .It Fn rw_init "struct rwlock *rw" "const char *name" Initialize structure located at .Fa rw as reader/writer lock, described by name .Fa name . The description is used solely for debugging purposes. This function must be called before any other operations on the lock. .It Fn rw_init_flags "struct rwlock *rw" "const char *name" "int opts" Initialize the rw lock just like the .Fn rw_init function, but specifying a set of optional flags to alter the behaviour of .Fa rw , through the .Fa opts argument. It contains one or more of the following flags: .Bl -tag -width ".Dv RW_NOPROFILE" .It Dv RW_DUPOK Witness should not log messages about duplicate locks being acquired. .It Dv RW_NOPROFILE Do not profile this lock. .It Dv RW_NOWITNESS Instruct .Xr witness 4 to ignore this lock. .It Dv RW_QUIET Do not log any operations for this lock via .Xr ktr 4 . .It Dv RW_RECURSE Allow threads to recursively acquire exclusive locks for .Fa rw . .It Dv RW_NEW If the kernel has been compiled with .Cd "option INVARIANTS" , .Fn rw_init_flags will assert that the .Fa rw has not been initialized multiple times without intervening calls to .Fn rw_destroy unless this option is specified. .El .It Fn rw_rlock "struct rwlock *rw" Lock .Fa rw as a reader. If any thread holds this lock exclusively, the current thread blocks, and its priority is propagated to the exclusive holder. The .Fn rw_rlock function can be called when the thread has already acquired reader access on .Fa rw . This is called .Dq "recursing on a lock" . .It Fn rw_wlock "struct rwlock *rw" Lock .Fa rw as a writer. If there are any shared owners of the lock, the current thread blocks. The .Fn rw_wlock function can be called recursively only if .Fa rw has been initialized with the .Dv RW_RECURSE option enabled. .It Fn rw_try_rlock "struct rwlock *rw" Try to lock .Fa rw as a reader. This function will return true if the operation succeeds, otherwise 0 will be returned. .It Fn rw_try_wlock "struct rwlock *rw" Try to lock .Fa rw as a writer. This function will return true if the operation succeeds, otherwise 0 will be returned. .It Fn rw_runlock "struct rwlock *rw" This function releases a shared lock previously acquired by .Fn rw_rlock . .It Fn rw_wunlock "struct rwlock *rw" This function releases an exclusive lock previously acquired by .Fn rw_wlock . .It Fn rw_unlock "struct rwlock *rw" This function releases a shared lock previously acquired by .Fn rw_rlock or an exclusive lock previously acquired by .Fn rw_wlock . .It Fn rw_try_upgrade "struct rwlock *rw" Attempt to upgrade a single shared lock to an exclusive lock. The current thread must hold a shared lock of .Fa rw . This will only succeed if the current thread holds the only shared lock on .Fa rw , and it only holds a single shared lock. If the attempt succeeds .Fn rw_try_upgrade will return a non-zero value, and the current thread will hold an exclusive lock. If the attempt fails .Fn rw_try_upgrade will return zero, and the current thread will still hold a shared lock. .It Fn rw_downgrade "struct rwlock *rw" Convert an exclusive lock into a single shared lock. The current thread must hold an exclusive lock of .Fa rw . .It Fn rw_sleep "void *chan" "struct rwlock *rw" "int priority" "const char *wmesg" "int timo" Atomically release .Fa rw while waiting for an event. For more details on the parameters to this function, see .Xr sleep 9 . .It Fn rw_initialized "const struct rwlock *rw" This function returns non-zero if .Fa rw has been initialized, and zero otherwise. .It Fn rw_destroy "struct rwlock *rw" This functions destroys a lock previously initialized with .Fn rw_init . The .Fa rw lock must be unlocked. .It Fn rw_wowned "const struct rwlock *rw" This function returns a non-zero value if the current thread owns an exclusive lock on .Fa rw . .It Fn rw_assert "const struct rwlock *rw" "int what" This function allows assertions specified in .Fa what to be made about .Fa rw . If the assertions are not true and the kernel is compiled with .Cd "options INVARIANTS" and .Cd "options INVARIANT_SUPPORT" , the kernel will panic. Currently the following base assertions are supported: .Bl -tag -width ".Dv RA_UNLOCKED" .It Dv RA_LOCKED Assert that current thread holds either a shared or exclusive lock of .Fa rw . .It Dv RA_RLOCKED Assert that current thread holds a shared lock of .Fa rw . .It Dv RA_WLOCKED Assert that current thread holds an exclusive lock of .Fa rw . .It Dv RA_UNLOCKED Assert that current thread holds neither a shared nor exclusive lock of .Fa rw . .El .Pp In addition, one of the following optional flags may be specified with .Dv RA_LOCKED , .Dv RA_RLOCKED , or .Dv RA_WLOCKED : .Bl -tag -width ".Dv RA_NOTRECURSED" .It Dv RA_RECURSED Assert that the current thread holds a recursive lock of .Fa rw . .It Dv RA_NOTRECURSED Assert that the current thread does not hold a recursive lock of .Fa rw . .El .El .Sh SEE ALSO .Xr locking 9 , .Xr mutex 9 , .Xr panic 9 , .Xr sema 9 , .Xr sx 9 .Sh HISTORY These functions appeared in .Fx 7.0 . .Sh AUTHORS .An -nosplit The .Nm facility was written by .An "John Baldwin" . This manual page was written by .An "Gleb Smirnoff" . .Sh BUGS A kernel without .Dv WITNESS cannot assert whether the current thread does or does not hold a read lock. .Dv RA_LOCKED and .Dv RA_RLOCKED can only assert that .Em any thread holds a read lock. They cannot ensure that the current thread holds a read lock. Further, .Dv RA_UNLOCKED can only assert that the current thread does not hold a write lock. .Pp Reader/writer is a bit of an awkward name. An .Nm can also be called a .Dq Robert Watson lock if desired. Index: stable/11/share/man/man9/zone.9 =================================================================== --- stable/11/share/man/man9/zone.9 (revision 336345) +++ stable/11/share/man/man9/zone.9 (revision 336346) @@ -1,374 +1,374 @@ .\"- .\" Copyright (c) 2001 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. .\" 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 AUTHOR 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 AUTHOR 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$ .\" .Dd April 26, 2017 .Dt ZONE 9 .Os .Sh NAME .Nm uma_zcreate , .Nm uma_zalloc , .Nm uma_zalloc_arg , .Nm uma_zfree , .Nm uma_zfree_arg , .Nm uma_zdestroy , -.Nm uma_zone_set_max, -.Nm uma_zone_get_max, -.Nm uma_zone_get_cur, -.Nm uma_zone_set_warning, +.Nm uma_zone_set_max , +.Nm uma_zone_get_max , +.Nm uma_zone_get_cur , +.Nm uma_zone_set_warning , .Nm uma_zone_set_maxaction .Nd zone allocator .Sh SYNOPSIS .In sys/param.h .In sys/queue.h .In vm/uma.h .Ft uma_zone_t .Fo uma_zcreate .Fa "char *name" "int size" .Fa "uma_ctor ctor" "uma_dtor dtor" "uma_init uminit" "uma_fini fini" .Fa "int align" "uint16_t flags" .Fc .Ft "void *" .Fn uma_zalloc "uma_zone_t zone" "int flags" .Ft "void *" .Fn uma_zalloc_arg "uma_zone_t zone" "void *arg" "int flags" .Ft void .Fn uma_zfree "uma_zone_t zone" "void *item" .Ft void .Fn uma_zfree_arg "uma_zone_t zone" "void *item" "void *arg" .Ft void .Fn uma_zdestroy "uma_zone_t zone" .Ft int .Fn uma_zone_set_max "uma_zone_t zone" "int nitems" .Ft int .Fn uma_zone_get_max "uma_zone_t zone" .Ft int .Fn uma_zone_get_cur "uma_zone_t zone" .Ft void .Fn uma_zone_set_warning "uma_zone_t zone" "const char *warning" .Ft void .Fn uma_zone_set_maxaction "uma_zone_t zone" "void (*maxaction)(uma_zone_t)" .In sys/sysctl.h .Fn SYSCTL_UMA_MAX parent nbr name access zone descr .Fn SYSCTL_ADD_UMA_MAX ctx parent nbr name access zone descr .Fn SYSCTL_UMA_CUR parent nbr name access zone descr .Fn SYSCTL_ADD_UMA_CUR ctx parent nbr name access zone descr .Sh DESCRIPTION The zone allocator provides an efficient interface for managing dynamically-sized collections of items of similar size. The zone allocator can work with preallocated zones as well as with runtime-allocated ones, and is therefore available much earlier in the boot process than other memory management routines. .Pp A zone is an extensible collection of items of identical size. The zone allocator keeps track of which items are in use and which are not, and provides functions for allocating items from the zone and for releasing them back (which makes them available for later use). .Pp After the first allocation of an item, it will have been cleared to zeroes, however subsequent allocations will retain the contents as of the last free. .Pp The .Fn uma_zcreate function creates a new zone from which items may then be allocated from. The .Fa name argument is a text name of the zone for debugging and stats; this memory should not be freed until the zone has been deallocated. .Pp The .Fa ctor and .Fa dtor arguments are callback functions that are called by the uma subsystem at the time of the call to .Fn uma_zalloc and .Fn uma_zfree respectively. Their purpose is to provide hooks for initializing or destroying things that need to be done at the time of the allocation or release of a resource. A good usage for the .Fa ctor and .Fa dtor callbacks might be to adjust a global count of the number of objects allocated. .Pp The .Fa uminit and .Fa fini arguments are used to optimize the allocation of objects from the zone. They are called by the uma subsystem whenever it needs to allocate or free several items to satisfy requests or memory pressure. A good use for the .Fa uminit and .Fa fini callbacks might be to initialize and destroy mutexes contained within the object. This would allow one to re-use already initialized mutexes when an object is returned from the uma subsystem's object cache. They are not called on each call to .Fn uma_zalloc and .Fn uma_zfree but rather in a batch mode on several objects. .Pp The .Fa flags argument of the .Fn uma_zcreate is a subset of the following flags: .Bl -tag -width "foo" .It Dv UMA_ZONE_NOFREE Slabs of the zone are never returned back to VM. .It Dv UMA_ZONE_NODUMP Pages belonging to the zone will not be included into mini-dumps. .It Dv UMA_ZONE_PCPU An allocation from zone would have .Va mp_ncpu shadow copies, that are privately assigned to CPUs. A CPU can address its private copy using base allocation address plus multiple of current CPU id and .Fn sizeof "struct pcpu" : .Bd -literal -offset indent foo_zone = uma_zcreate(..., UMA_ZONE_PCPU); ... foo_base = uma_zalloc(foo_zone, ...); ... critical_enter(); foo_pcpu = (foo_t *)zpcpu_get(foo_base); /* do something with foo_pcpu */ critical_exit(); .Ed .It Dv UMA_ZONE_OFFPAGE By default book-keeping of items within a slab is done in the slab page itself. This flag explicitly tells subsystem that book-keeping structure should be allocated separately from special internal zone. This flag requires either .Dv UMA_ZONE_VTOSLAB or .Dv UMA_ZONE_HASH , since subsystem requires a mechanism to find a book-keeping structure to an item being freed. The subsystem may choose to prefer offpage book-keeping for certain zones implicitly. .It Dv UMA_ZONE_ZINIT The zone will have its .Ft uma_init method set to internal method that initializes a new allocated slab to all zeros. Do not mistake .Ft uma_init method with .Ft uma_ctor . A zone with .Dv UMA_ZONE_ZINIT flag would not return zeroed memory on every .Fn uma_zalloc . .It Dv UMA_ZONE_HASH The zone should use an internal hash table to find slab book-keeping structure where an allocation being freed belongs to. .It Dv UMA_ZONE_VTOSLAB The zone should use special field of .Vt vm_page_t to find slab book-keeping structure where an allocation being freed belongs to. .It Dv UMA_ZONE_MALLOC The zone is for the .Xr malloc 9 subsystem. .It Dv UMA_ZONE_VM The zone is for the VM subsystem. .El .Pp To allocate an item from a zone, simply call .Fn uma_zalloc with a pointer to that zone and set the .Fa flags argument to selected flags as documented in .Xr malloc 9 . It will return a pointer to an item if successful, or .Dv NULL in the rare case where all items in the zone are in use and the allocator is unable to grow the zone and .Dv M_NOWAIT is specified. .Pp Items are released back to the zone from which they were allocated by calling .Fn uma_zfree with a pointer to the zone and a pointer to the item. If .Fa item is .Dv NULL , then .Fn uma_zfree does nothing. .Pp The variations .Fn uma_zalloc_arg and .Fn uma_zfree_arg allow to specify an argument for the .Dv ctor and .Dv dtor functions, respectively. .Pp Created zones, which are empty, can be destroyed using .Fn uma_zdestroy , freeing all memory that was allocated for the zone. All items allocated from the zone with .Fn uma_zalloc must have been freed with .Fn uma_zfree before. .Pp The .Fn uma_zone_set_max function limits the number of items .Pq and therefore memory that can be allocated to .Fa zone . The .Fa nitems argument specifies the requested upper limit number of items. The effective limit is returned to the caller, as it may end up being higher than requested due to the implementation rounding up to ensure all memory pages allocated to the zone are utilised to capacity. The limit applies to the total number of items in the zone, which includes allocated items, free items and free items in the per-cpu caches. On systems with more than one CPU it may not be possible to allocate the specified number of items even when there is no shortage of memory, because all of the remaining free items may be in the caches of the other CPUs when the limit is hit. .Pp The .Fn uma_zone_get_max function returns the effective upper limit number of items for a zone. .Pp The .Fn uma_zone_get_cur function returns the approximate current occupancy of the zone. The returned value is approximate because appropriate synchronisation to determine an exact value is not performed by the implementation. This ensures low overhead at the expense of potentially stale data being used in the calculation. .Pp The .Fn uma_zone_set_warning function sets a warning that will be printed on the system console when the given zone becomes full and fails to allocate an item. The warning will be printed no more often than every five minutes. Warnings can be turned off globally by setting the .Va vm.zone_warnings sysctl tunable to .Va 0 . .Pp The .Fn uma_zone_set_maxaction function sets a function that will be called when the given zone becomes full and fails to allocate an item. The function will be called with the zone locked. Also, the function that called the allocation function may have held additional locks. Therefore, this function should do very little work (similar to a signal handler). .Pp The .Fn SYSCTL_UMA_MAX parent nbr name access zone descr macro declares a static .Xr sysctl oid that exports the effective upper limit number of items for a zone. The .Fa zone argument should be a pointer to .Vt uma_zone_t . A read of the oid returns value obtained through .Fn uma_zone_get_max . A write to the oid sets new value via .Fn uma_zone_set_max . The .Fn SYSCTL_ADD_UMA_MAX ctx parent nbr name access zone descr macro is provided to create this type of oid dynamically. .Pp The .Fn SYSCTL_UMA_CUR parent nbr name access zone descr macro declares a static read-only .Xr sysctl oid that exports the approximate current occupancy of the zone. The .Fa zone argument should be a pointer to .Vt uma_zone_t . A read of the oid returns value obtained through .Fn uma_zone_get_cur . The .Fn SYSCTL_ADD_UMA_CUR ctx parent nbr name zone descr macro is provided to create this type of oid dynamically. .Sh RETURN VALUES The .Fn uma_zalloc function returns a pointer to an item, or .Dv NULL if the zone ran out of unused items and .Dv M_NOWAIT was specified. .Sh SEE ALSO .Xr malloc 9 .Sh HISTORY The zone allocator first appeared in .Fx 3.0 . It was radically changed in .Fx 5.0 to function as a slab allocator. .Sh AUTHORS .An -nosplit The zone allocator was written by .An John S. Dyson . The zone allocator was rewritten in large parts by .An Jeff Roberson Aq Mt jeff@FreeBSD.org to function as a slab allocator. .Pp This manual page was written by .An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org . Changes for UMA by .An Jeroen Ruigrok van der Werven Aq Mt asmodai@FreeBSD.org . Index: stable/11/sys/contrib/libnv/cnvlist.c =================================================================== --- stable/11/sys/contrib/libnv/cnvlist.c (revision 336345) +++ stable/11/sys/contrib/libnv/cnvlist.c (revision 336346) @@ -1,197 +1,217 @@ /*- * Copyright (c) 2016 Adam Starak * 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. * 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$ */ #include __FBSDID("$FreeBSD$"); #ifdef _KERNEL #include #include #include #include #include #include #else #include #include #include #include #endif #include #include #include "nv_impl.h" #include "nvlist_impl.h" #include "nvpair_impl.h" +const char * +cnvlist_name(const void *cookie) +{ + + return (nvpair_name(cookie)); +} + +int +cnvlist_type(const void *cookie) +{ + + return (nvpair_type(cookie)); +} + #define CNVLIST_GET(ftype, type, NVTYPE) \ ftype \ -cnvlist_get_##type(void *cookiep) \ +cnvlist_get_##type(const void *cookie) \ { \ \ - if (nvpair_type(cookiep) != NV_TYPE_##NVTYPE) { \ + if (nvpair_type(cookie) != NV_TYPE_##NVTYPE) { \ nvlist_report_missing(NV_TYPE_##NVTYPE, \ - nvpair_name(cookiep)); \ + nvpair_name(cookie)); \ } \ - return (nvpair_get_##type(cookiep)); \ + return (nvpair_get_##type(cookie)); \ } CNVLIST_GET(bool, bool, BOOL) CNVLIST_GET(uint64_t, number, NUMBER) CNVLIST_GET(const char *, string, STRING) CNVLIST_GET(const nvlist_t *, nvlist, NVLIST) #ifndef _KERNEL CNVLIST_GET(int, descriptor, DESCRIPTOR) #endif #undef CNVLIST_GET #define CNVLIST_GET_ARRAY(ftype, type, NVTYPE) \ ftype \ -cnvlist_get_##type(void *cookiep, size_t *nitemsp) \ +cnvlist_get_##type(const void *cookie, size_t *nitemsp) \ { \ \ - if (nvpair_type(cookiep) != NV_TYPE_##NVTYPE) { \ + if (nvpair_type(cookie) != NV_TYPE_##NVTYPE) { \ nvlist_report_missing(NV_TYPE_##NVTYPE, \ - nvpair_name(cookiep)); \ + nvpair_name(cookie)); \ } \ - return (nvpair_get_##type(cookiep, nitemsp)); \ + return (nvpair_get_##type(cookie, nitemsp)); \ } CNVLIST_GET_ARRAY(const bool *, bool_array, BOOL_ARRAY) CNVLIST_GET_ARRAY(const uint64_t *, number_array, NUMBER_ARRAY) CNVLIST_GET_ARRAY(const char * const *, string_array, STRING_ARRAY) CNVLIST_GET_ARRAY(const nvlist_t * const *, nvlist_array, NVLIST_ARRAY) #ifndef _KERNEL CNVLIST_GET_ARRAY(const int *, descriptor_array, DESCRIPTOR_ARRAY) #endif #undef CNVLIST_GET_ARRAY const void * -cnvlist_get_binary(void *cookiep, size_t *sizep) +cnvlist_get_binary(const void *cookie, size_t *sizep) { - if (nvpair_type(cookiep) != NV_TYPE_BINARY) - nvlist_report_missing(NV_TYPE_BINARY, nvpair_name(cookiep)); - return (nvpair_get_binary(cookiep, sizep)); + if (nvpair_type(cookie) != NV_TYPE_BINARY) + nvlist_report_missing(NV_TYPE_BINARY, nvpair_name(cookie)); + return (nvpair_get_binary(cookie, sizep)); } #define CNVLIST_TAKE(ftype, type, NVTYPE) \ ftype \ -cnvlist_take_##type(nvlist_t *nvl, void *cookiep) \ +cnvlist_take_##type(void *cookie) \ { \ ftype value; \ + nvlist_t *nvl; \ \ - if (nvpair_type(cookiep) != NV_TYPE_##NVTYPE) { \ + if (nvpair_type(cookie) != NV_TYPE_##NVTYPE) { \ nvlist_report_missing(NV_TYPE_##NVTYPE, \ - nvpair_name(cookiep)); \ + nvpair_name(cookie)); \ } \ - value = (ftype)(intptr_t)nvpair_get_##type(cookiep); \ - nvlist_remove_nvpair(nvl, cookiep); \ - nvpair_free_structure(cookiep); \ + nvl = nvpair_nvlist(cookie); \ + value = (ftype)(intptr_t)nvpair_get_##type(cookie); \ + nvlist_remove_nvpair(nvl, cookie); \ + nvpair_free_structure(cookie); \ return (value); \ } CNVLIST_TAKE(bool, bool, BOOL) CNVLIST_TAKE(uint64_t, number, NUMBER) CNVLIST_TAKE(char *, string, STRING) CNVLIST_TAKE(nvlist_t *, nvlist, NVLIST) #ifndef _KERNEL CNVLIST_TAKE(int, descriptor, DESCRIPTOR) #endif #undef CNVLIST_TAKE #define CNVLIST_TAKE_ARRAY(ftype, type, NVTYPE) \ ftype \ -cnvlist_take_##type(nvlist_t *nvl, void *cookiep, size_t *nitemsp) \ +cnvlist_take_##type(void *cookie, size_t *nitemsp) \ { \ ftype value; \ + nvlist_t *nvl; \ \ - if (nvpair_type(cookiep) != NV_TYPE_##NVTYPE) { \ + if (nvpair_type(cookie) != NV_TYPE_##NVTYPE) { \ nvlist_report_missing(NV_TYPE_##NVTYPE, \ - nvpair_name(cookiep)); \ + nvpair_name(cookie)); \ } \ - value = (ftype)(intptr_t)nvpair_get_##type(cookiep, nitemsp); \ - nvlist_remove_nvpair(nvl, cookiep); \ - nvpair_free_structure(cookiep); \ + nvl = nvpair_nvlist(cookie); \ + value = (ftype)(intptr_t)nvpair_get_##type(cookie, nitemsp); \ + nvlist_remove_nvpair(nvl, cookie); \ + nvpair_free_structure(cookie); \ return (value); \ } CNVLIST_TAKE_ARRAY(bool *, bool_array, BOOL_ARRAY) CNVLIST_TAKE_ARRAY(uint64_t *, number_array, NUMBER_ARRAY) CNVLIST_TAKE_ARRAY(char **, string_array, STRING_ARRAY) CNVLIST_TAKE_ARRAY(nvlist_t **, nvlist_array, NVLIST_ARRAY) #ifndef _KERNEL CNVLIST_TAKE_ARRAY(int *, descriptor_array, DESCRIPTOR_ARRAY); #endif #undef CNVLIST_TAKE_ARRAY void * -cnvlist_take_binary(nvlist_t *nvl, void *cookiep, size_t *sizep) +cnvlist_take_binary(void *cookie, size_t *sizep) { void *value; + nvlist_t *nvl; - if (nvpair_type(cookiep) != NV_TYPE_BINARY) - nvlist_report_missing(NV_TYPE_BINARY, nvpair_name(cookiep)); - value = (void *)(intptr_t)nvpair_get_binary(cookiep, sizep); - nvlist_remove_nvpair(nvl, cookiep); - nvpair_free_structure(cookiep); + if (nvpair_type(cookie) != NV_TYPE_BINARY) + nvlist_report_missing(NV_TYPE_BINARY, nvpair_name(cookie)); + nvl = nvpair_nvlist(cookie); + value = (void *)(intptr_t)nvpair_get_binary(cookie, sizep); + nvlist_remove_nvpair(nvl, cookie); + nvpair_free_structure(cookie); return (value); } #define CNVLIST_FREE(type) \ void \ -cnvlist_free_##type(nvlist_t *nvl, void *cookiep) \ +cnvlist_free_##type(void *cookie) \ { \ \ - nvlist_free_nvpair(nvl, cookiep); \ + nvlist_free_nvpair(nvpair_nvlist(cookie), cookie); \ } CNVLIST_FREE(bool) CNVLIST_FREE(number) CNVLIST_FREE(string) CNVLIST_FREE(nvlist) CNVLIST_FREE(binary); CNVLIST_FREE(bool_array) CNVLIST_FREE(number_array) CNVLIST_FREE(string_array) CNVLIST_FREE(nvlist_array) #ifndef _KERNEL CNVLIST_FREE(descriptor) CNVLIST_FREE(descriptor_array) #endif #undef CNVLIST_FREE Index: stable/11/sys/contrib/libnv/nv_impl.h =================================================================== --- stable/11/sys/contrib/libnv/nv_impl.h (revision 336345) +++ stable/11/sys/contrib/libnv/nv_impl.h (revision 336346) @@ -1,158 +1,164 @@ /*- * Copyright (c) 2013 The FreeBSD Foundation * Copyright (c) 2013-2015 Mariusz Zaborski * 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_ARRAY_NEXT 254 #define NV_TYPE_NVLIST_UP 255 #define NV_TYPE_FIRST NV_TYPE_NULL #define NV_TYPE_LAST NV_TYPE_DESCRIPTOR_ARRAY #define NV_FLAG_BIG_ENDIAN 0x080 #define NV_FLAG_IN_ARRAY 0x100 #ifdef _KERNEL #define nv_malloc(size) malloc((size), M_NVLIST, M_WAITOK) -#define nv_calloc(n, size) malloc((n) * (size), M_NVLIST, \ +#define nv_calloc(n, size) mallocarray((n), (size), M_NVLIST, \ M_WAITOK | M_ZERO) #define nv_realloc(buf, size) realloc((buf), (size), M_NVLIST, \ M_WAITOK) #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 ERRNO_SET(var) do { } while (0) #define ERRNO_SAVE() do { do { } while(0) #define ERRNO_RESTORE() } while (0) #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 ERRNO_SET(var) do { errno = (var); } while (0) #define ERRNO_SAVE() do { \ int _serrno; \ \ _serrno = errno #define ERRNO_RESTORE() errno = _serrno; \ } while (0) #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); void nvlist_set_flags(nvlist_t *nvl, int flags); 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); bool nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp); void nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent); void nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele); const nvpair_t *nvlist_get_nvpair(const nvlist_t *nvl, const char *name); nvpair_t *nvlist_take_nvpair(nvlist_t *nvl, const char *name); /* Function removes the given nvpair from the nvlist. */ void nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp); void nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp); int nvpair_type(const nvpair_t *nvp); const char *nvpair_name(const nvpair_t *nvp); nvpair_t *nvpair_clone(const nvpair_t *nvp); nvpair_t *nvpair_create_null(const char *name); nvpair_t *nvpair_create_bool(const char *name, bool value); nvpair_t *nvpair_create_number(const char *name, uint64_t value); nvpair_t *nvpair_create_string(const char *name, const char *value); nvpair_t *nvpair_create_stringf(const char *name, const char *valuefmt, ...) __printflike(2, 3); nvpair_t *nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap) __printflike(2, 0); nvpair_t *nvpair_create_nvlist(const char *name, const nvlist_t *value); nvpair_t *nvpair_create_descriptor(const char *name, int value); nvpair_t *nvpair_create_binary(const char *name, const void *value, size_t size); nvpair_t *nvpair_create_bool_array(const char *name, const bool *value, size_t nitems); nvpair_t *nvpair_create_number_array(const char *name, const uint64_t *value, size_t nitems); nvpair_t *nvpair_create_string_array(const char *name, const char * const *value, size_t nitems); nvpair_t *nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value, size_t nitems); nvpair_t *nvpair_create_descriptor_array(const char *name, const int *value, size_t nitems); nvpair_t *nvpair_move_string(const char *name, char *value); nvpair_t *nvpair_move_nvlist(const char *name, nvlist_t *value); nvpair_t *nvpair_move_descriptor(const char *name, int value); nvpair_t *nvpair_move_binary(const char *name, void *value, size_t size); nvpair_t *nvpair_move_bool_array(const char *name, bool *value, size_t nitems); nvpair_t *nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems); nvpair_t *nvpair_move_descriptor_array(const char *name, int *value, size_t nitems); nvpair_t *nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems); nvpair_t *nvpair_move_string_array(const char *name, char **value, size_t nitems); + +int nvpair_append_bool_array(nvpair_t *nvp, const bool value); +int nvpair_append_number_array(nvpair_t *nvp, const uint64_t value); +int nvpair_append_string_array(nvpair_t *nvp, const char *value); +int nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value); +int nvpair_append_descriptor_array(nvpair_t *nvp, const int 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 bool *nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitemsp); const uint64_t *nvpair_get_number_array(const nvpair_t *nvp, size_t *nitemsp); const char * const *nvpair_get_string_array(const nvpair_t *nvp, size_t *nitemsp); const nvlist_t * const *nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitemsp); const int *nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitemsp); void nvpair_free(nvpair_t *nvp); #endif /* !_NV_IMPL_H_ */ Index: stable/11/sys/contrib/libnv/nvlist.c =================================================================== --- stable/11/sys/contrib/libnv/nvlist.c (revision 336345) +++ stable/11/sys/contrib/libnv/nvlist.c (revision 336346) @@ -1,2027 +1,2058 @@ /*- * Copyright (c) 2009-2013 The FreeBSD Foundation * Copyright (c) 2013-2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #ifdef _KERNEL #include #include #include #include #include #include #else #include #include #include #include #include #define _WITH_DPRINTF #include #include #include #include #include "msgio.h" #endif #ifdef HAVE_PJDLOG #include #endif #include #include "nv_impl.h" #include "nvlist_impl.h" #include "nvpair_impl.h" #ifndef HAVE_PJDLOG #ifdef _KERNEL #define PJDLOG_ASSERT(...) MPASS(__VA_ARGS__) #define PJDLOG_RASSERT(expr, ...) KASSERT(expr, (__VA_ARGS__)) #define PJDLOG_ABORT(...) panic(__VA_ARGS__) #else #include #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) #define PJDLOG_RASSERT(expr, ...) assert(expr) #define PJDLOG_ABORT(...) do { \ fprintf(stderr, "%s:%u: ", __FILE__, __LINE__); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ abort(); \ } while (0) #endif #endif #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN | NV_FLAG_IN_ARRAY) #define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE) #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK) #define NVLIST_MAGIC 0x6e766c /* "nvl" */ struct nvlist { int nvl_magic; int nvl_error; int nvl_flags; nvpair_t *nvl_parent; nvpair_t *nvl_array_next; struct nvl_head nvl_head; }; #define NVLIST_ASSERT(nvl) do { \ PJDLOG_ASSERT((nvl) != NULL); \ PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC); \ } while (0) #ifdef _KERNEL MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist"); #endif #define NVPAIR_ASSERT(nvp) nvpair_assert(nvp) #define NVLIST_HEADER_MAGIC 0x6c #define NVLIST_HEADER_VERSION 0x00 struct nvlist_header { uint8_t nvlh_magic; uint8_t nvlh_version; uint8_t nvlh_flags; uint64_t nvlh_descriptors; uint64_t nvlh_size; } __packed; nvlist_t * nvlist_create(int flags) { nvlist_t *nvl; PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); nvl = nv_malloc(sizeof(*nvl)); if (nvl == NULL) return (NULL); nvl->nvl_error = 0; nvl->nvl_flags = flags; nvl->nvl_parent = NULL; nvl->nvl_array_next = NULL; TAILQ_INIT(&nvl->nvl_head); nvl->nvl_magic = NVLIST_MAGIC; return (nvl); } void nvlist_destroy(nvlist_t *nvl) { nvpair_t *nvp; if (nvl == NULL) return; ERRNO_SAVE(); NVLIST_ASSERT(nvl); while ((nvp = nvlist_first_nvpair(nvl)) != NULL) { nvlist_remove_nvpair(nvl, nvp); nvpair_free(nvp); } if (nvl->nvl_array_next != NULL) nvpair_free_structure(nvl->nvl_array_next); nvl->nvl_array_next = NULL; nvl->nvl_parent = NULL; nvl->nvl_magic = 0; nv_free(nvl); ERRNO_RESTORE(); } 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; } void nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele) { NVLIST_ASSERT(nvl); if (ele != NULL) { nvl->nvl_flags |= NV_FLAG_IN_ARRAY; } else { nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY; nv_free(nvl->nvl_array_next); } nvl->nvl_array_next = ele; } bool nvlist_in_array(const nvlist_t *nvl) { NVLIST_ASSERT(nvl); return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0); } const nvlist_t * nvlist_get_array_next(const nvlist_t *nvl) { nvpair_t *nvp; NVLIST_ASSERT(nvl); nvp = nvl->nvl_array_next; if (nvp == NULL) return (NULL); return (nvpair_get_nvlist(nvp)); } const nvlist_t * nvlist_get_pararr(const nvlist_t *nvl, void **cookiep) { const nvlist_t *ret; ret = nvlist_get_array_next(nvl); if (ret != NULL) { if (cookiep != NULL) *cookiep = NULL; return (ret); } return (nvlist_get_parent(nvl, cookiep)); } bool nvlist_empty(const nvlist_t *nvl) { NVLIST_ASSERT(nvl); PJDLOG_ASSERT(nvl->nvl_error == 0); return (nvlist_first_nvpair(nvl) == NULL); } int nvlist_flags(const nvlist_t *nvl) { NVLIST_ASSERT(nvl); PJDLOG_ASSERT(nvl->nvl_error == 0); return (nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); } void nvlist_set_flags(nvlist_t *nvl, int flags) { NVLIST_ASSERT(nvl); PJDLOG_ASSERT(nvl->nvl_error == 0); nvl->nvl_flags = flags; } void nvlist_report_missing(int type, const char *name) { PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", name, nvpair_type_string(type)); } static nvpair_t * nvlist_find(const nvlist_t *nvl, int type, const char *name) { nvpair_t *nvp; NVLIST_ASSERT(nvl); PJDLOG_ASSERT(nvl->nvl_error == 0); PJDLOG_ASSERT(type == NV_TYPE_NONE || (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) { if (type != NV_TYPE_NONE && nvpair_type(nvp) != type) continue; if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) { if (strcasecmp(nvpair_name(nvp), name) != 0) continue; } else { if (strcmp(nvpair_name(nvp), name) != 0) continue; } break; } if (nvp == NULL) ERRNO_SET(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); } 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); } nvlist_t * nvlist_clone(const nvlist_t *nvl) { nvlist_t *newnvl; nvpair_t *nvp, *newnvp; NVLIST_ASSERT(nvl); if (nvl->nvl_error != 0) { ERRNO_SET(nvl->nvl_error); return (NULL); } newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK); for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) { newnvp = nvpair_clone(nvp); if (newnvp == NULL) break; (void)nvlist_move_nvpair(newnvl, newnvp); } if (nvp != NULL) { nvlist_destroy(newnvl); return (NULL); } return (newnvl); } #ifndef _KERNEL static bool nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level) { if (nvlist_error(nvl) != 0) { dprintf(fd, "%*serror: %d\n", level * 4, "", nvlist_error(nvl)); return (true); } return (false); } /* * Dump content of nvlist. */ void nvlist_dump(const nvlist_t *nvl, int fd) { const nvlist_t *tmpnvl; nvpair_t *nvp, *tmpnvp; void *cookie; int level; level = 0; if (nvlist_dump_error_check(nvl, fd, level)) return; nvp = nvlist_first_nvpair(nvl); while (nvp != NULL) { dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp), nvpair_type_string(nvpair_type(nvp))); switch (nvpair_type(nvp)) { case NV_TYPE_NULL: dprintf(fd, " null\n"); break; case NV_TYPE_BOOL: dprintf(fd, " %s\n", nvpair_get_bool(nvp) ? "TRUE" : "FALSE"); break; case NV_TYPE_NUMBER: dprintf(fd, " %ju (%jd) (0x%jx)\n", (uintmax_t)nvpair_get_number(nvp), (intmax_t)nvpair_get_number(nvp), (uintmax_t)nvpair_get_number(nvp)); break; case NV_TYPE_STRING: dprintf(fd, " [%s]\n", nvpair_get_string(nvp)); break; case NV_TYPE_NVLIST: dprintf(fd, "\n"); tmpnvl = nvpair_get_nvlist(nvp); if (nvlist_dump_error_check(tmpnvl, fd, level + 1)) break; tmpnvp = nvlist_first_nvpair(tmpnvl); if (tmpnvp != NULL) { nvl = tmpnvl; nvp = tmpnvp; level++; continue; } break; case NV_TYPE_DESCRIPTOR: dprintf(fd, " %d\n", nvpair_get_descriptor(nvp)); break; case NV_TYPE_BINARY: { const unsigned char *binary; unsigned int ii; size_t size; binary = nvpair_get_binary(nvp, &size); dprintf(fd, " %zu ", size); for (ii = 0; ii < size; ii++) dprintf(fd, "%02hhx", binary[ii]); dprintf(fd, "\n"); break; } case NV_TYPE_BOOL_ARRAY: { const bool *value; unsigned int ii; size_t nitems; value = nvpair_get_bool_array(nvp, &nitems); dprintf(fd, " [ "); for (ii = 0; ii < nitems; ii++) { dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE"); if (ii != nitems - 1) dprintf(fd, ", "); } dprintf(fd, " ]\n"); break; } case NV_TYPE_STRING_ARRAY: { const char * const *value; unsigned int ii; size_t nitems; value = nvpair_get_string_array(nvp, &nitems); dprintf(fd, " [ "); for (ii = 0; ii < nitems; ii++) { if (value[ii] == NULL) dprintf(fd, "NULL"); else dprintf(fd, "\"%s\"", value[ii]); if (ii != nitems - 1) dprintf(fd, ", "); } dprintf(fd, " ]\n"); break; } case NV_TYPE_NUMBER_ARRAY: { const uint64_t *value; unsigned int ii; size_t nitems; value = nvpair_get_number_array(nvp, &nitems); dprintf(fd, " [ "); for (ii = 0; ii < nitems; ii++) { dprintf(fd, "%ju (%jd) (0x%jx)", value[ii], value[ii], value[ii]); if (ii != nitems - 1) dprintf(fd, ", "); } dprintf(fd, " ]\n"); break; } case NV_TYPE_DESCRIPTOR_ARRAY: { const int *value; unsigned int ii; size_t nitems; value = nvpair_get_descriptor_array(nvp, &nitems); dprintf(fd, " [ "); for (ii = 0; ii < nitems; ii++) { dprintf(fd, "%d", value[ii]); if (ii != nitems - 1) dprintf(fd, ", "); } dprintf(fd, " ]\n"); break; } case NV_TYPE_NVLIST_ARRAY: { const nvlist_t * const *value; unsigned int ii; size_t nitems; value = nvpair_get_nvlist_array(nvp, &nitems); dprintf(fd, " %zu\n", nitems); tmpnvl = NULL; tmpnvp = NULL; for (ii = 0; ii < nitems; ii++) { if (nvlist_dump_error_check(value[ii], fd, level + 1)) { break; } if (tmpnvl == NULL) { tmpnvp = nvlist_first_nvpair(value[ii]); if (tmpnvp != NULL) { tmpnvl = value[ii]; } else { dprintf(fd, "%*s,\n", (level + 1) * 4, ""); } } } if (tmpnvp != NULL) { nvl = tmpnvl; nvp = tmpnvp; level++; continue; } break; } default: PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp)); } while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { do { cookie = NULL; if (nvlist_in_array(nvl)) dprintf(fd, "%*s,\n", level * 4, ""); nvl = nvlist_get_pararr(nvl, &cookie); if (nvl == NULL) return; if (nvlist_in_array(nvl) && cookie == NULL) { nvp = nvlist_first_nvpair(nvl); } else { nvp = cookie; level--; } } while (nvp == NULL); if (nvlist_in_array(nvl) && cookie == NULL) break; } } } 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 nvlist_t * const *nvlarray; const nvpair_t *nvp, *tmpnvp; void *cookie; size_t size, nitems; unsigned int ii; NVLIST_ASSERT(nvl); PJDLOG_ASSERT(nvl->nvl_error == 0); size = sizeof(struct nvlist_header); nvp = nvlist_first_nvpair(nvl); while (nvp != NULL) { size += nvpair_header_size(); size += strlen(nvpair_name(nvp)) + 1; if (nvpair_type(nvp) == NV_TYPE_NVLIST) { size += sizeof(struct nvlist_header); size += nvpair_header_size() + 1; tmpnvl = nvpair_get_nvlist(nvp); PJDLOG_ASSERT(tmpnvl->nvl_error == 0); tmpnvp = nvlist_first_nvpair(tmpnvl); if (tmpnvp != NULL) { nvl = tmpnvl; nvp = tmpnvp; continue; } } else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) { nvlarray = nvpair_get_nvlist_array(nvp, &nitems); PJDLOG_ASSERT(nitems > 0); size += (nvpair_header_size() + 1) * nitems; size += sizeof(struct nvlist_header) * nitems; tmpnvl = NULL; tmpnvp = NULL; for (ii = 0; ii < nitems; ii++) { PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0); tmpnvp = nvlist_first_nvpair(nvlarray[ii]); if (tmpnvp != NULL) { tmpnvl = nvlarray[ii]; break; } } if (tmpnvp != NULL) { nvp = tmpnvp; nvl = tmpnvl; continue; } } else { size += nvpair_size(nvp); } while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { do { cookie = NULL; nvl = nvlist_get_pararr(nvl, &cookie); if (nvl == NULL) goto out; if (nvlist_in_array(nvl) && cookie == NULL) { nvp = nvlist_first_nvpair(nvl); } else { nvp = cookie; } } while (nvp == NULL); if (nvlist_in_array(nvl) && cookie == NULL) break; } } out: return (size); } #ifndef _KERNEL static int * nvlist_xdescriptors(const nvlist_t *nvl, int *descs) { void *cookie; nvpair_t *nvp; int type; NVLIST_ASSERT(nvl); PJDLOG_ASSERT(nvl->nvl_error == 0); cookie = NULL; do { while (nvlist_next(nvl, &type, &cookie) != NULL) { nvp = cookie; switch (type) { case NV_TYPE_DESCRIPTOR: *descs = nvpair_get_descriptor(nvp); descs++; break; case NV_TYPE_DESCRIPTOR_ARRAY: { const int *value; size_t nitems; unsigned int ii; value = nvpair_get_descriptor_array(nvp, &nitems); for (ii = 0; ii < nitems; ii++) { *descs = value[ii]; descs++; } break; } case NV_TYPE_NVLIST: nvl = nvpair_get_nvlist(nvp); cookie = NULL; break; case NV_TYPE_NVLIST_ARRAY: { const nvlist_t * const *value; size_t nitems; value = nvpair_get_nvlist_array(nvp, &nitems); PJDLOG_ASSERT(value != NULL); PJDLOG_ASSERT(nitems > 0); nvl = value[0]; cookie = NULL; break; } } } } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL); 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); fds[nitems] = -1; if (nitemsp != NULL) *nitemsp = nitems; return (fds); } #endif size_t nvlist_ndescriptors(const nvlist_t *nvl) { #ifndef _KERNEL void *cookie; nvpair_t *nvp; size_t ndescs; int type; NVLIST_ASSERT(nvl); PJDLOG_ASSERT(nvl->nvl_error == 0); ndescs = 0; cookie = NULL; do { while (nvlist_next(nvl, &type, &cookie) != NULL) { nvp = cookie; switch (type) { case NV_TYPE_DESCRIPTOR: ndescs++; break; case NV_TYPE_NVLIST: nvl = nvpair_get_nvlist(nvp); cookie = NULL; break; case NV_TYPE_NVLIST_ARRAY: { const nvlist_t * const *value; size_t nitems; value = nvpair_get_nvlist_array(nvp, &nitems); PJDLOG_ASSERT(value != NULL); PJDLOG_ASSERT(nitems > 0); nvl = value[0]; cookie = NULL; break; } case NV_TYPE_DESCRIPTOR_ARRAY: { size_t nitems; (void)nvpair_get_descriptor_array(nvp, &nitems); ndescs += nitems; break; } } } } while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL); return (ndescs); #else return (0); #endif } static unsigned char * nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp) { struct nvlist_header nvlhdr; NVLIST_ASSERT(nvl); nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC; nvlhdr.nvlh_version = NVLIST_HEADER_VERSION; nvlhdr.nvlh_flags = nvl->nvl_flags; #if BYTE_ORDER == BIG_ENDIAN nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN; #endif nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl); nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr); PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr)); memcpy(ptr, &nvlhdr, sizeof(nvlhdr)); ptr += sizeof(nvlhdr); *leftp -= sizeof(nvlhdr); return (ptr); } static void * nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep) { unsigned char *buf, *ptr; size_t left, size; const nvlist_t *tmpnvl; nvpair_t *nvp, *tmpnvp; void *cookie; NVLIST_ASSERT(nvl); if (nvl->nvl_error != 0) { ERRNO_SET(nvl->nvl_error); return (NULL); } size = nvlist_size(nvl); buf = nv_malloc(size); if (buf == NULL) return (NULL); ptr = buf; left = size; ptr = nvlist_pack_header(nvl, ptr, &left); nvp = nvlist_first_nvpair(nvl); while (nvp != NULL) { NVPAIR_ASSERT(nvp); nvpair_init_datasize(nvp); ptr = nvpair_pack_header(nvp, ptr, &left); if (ptr == NULL) goto fail; switch (nvpair_type(nvp)) { case NV_TYPE_NULL: ptr = nvpair_pack_null(nvp, ptr, &left); break; case NV_TYPE_BOOL: ptr = nvpair_pack_bool(nvp, ptr, &left); break; case NV_TYPE_NUMBER: ptr = nvpair_pack_number(nvp, ptr, &left); break; case NV_TYPE_STRING: ptr = nvpair_pack_string(nvp, ptr, &left); break; case NV_TYPE_NVLIST: tmpnvl = nvpair_get_nvlist(nvp); ptr = nvlist_pack_header(tmpnvl, ptr, &left); if (ptr == NULL) goto fail; 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; case NV_TYPE_DESCRIPTOR_ARRAY: ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp, &left); break; #endif case NV_TYPE_BINARY: ptr = nvpair_pack_binary(nvp, ptr, &left); break; case NV_TYPE_BOOL_ARRAY: ptr = nvpair_pack_bool_array(nvp, ptr, &left); break; case NV_TYPE_NUMBER_ARRAY: ptr = nvpair_pack_number_array(nvp, ptr, &left); break; case NV_TYPE_STRING_ARRAY: ptr = nvpair_pack_string_array(nvp, ptr, &left); break; case NV_TYPE_NVLIST_ARRAY: { const nvlist_t * const * value; size_t nitems; unsigned int ii; tmpnvl = NULL; value = nvpair_get_nvlist_array(nvp, &nitems); for (ii = 0; ii < nitems; ii++) { ptr = nvlist_pack_header(value[ii], ptr, &left); if (ptr == NULL) goto out; tmpnvp = nvlist_first_nvpair(value[ii]); if (tmpnvp != NULL) { tmpnvl = value[ii]; break; } ptr = nvpair_pack_nvlist_array_next(ptr, &left); if (ptr == NULL) goto out; } if (tmpnvl != NULL) { nvl = tmpnvl; nvp = tmpnvp; continue; } break; } default: PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); } if (ptr == NULL) goto fail; while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { do { cookie = NULL; if (nvlist_in_array(nvl)) { ptr = nvpair_pack_nvlist_array_next(ptr, &left); if (ptr == NULL) goto fail; } nvl = nvlist_get_pararr(nvl, &cookie); if (nvl == NULL) goto out; if (nvlist_in_array(nvl) && cookie == NULL) { nvp = nvlist_first_nvpair(nvl); ptr = nvlist_pack_header(nvl, ptr, &left); if (ptr == NULL) goto fail; } else if (nvpair_type((nvpair_t *)cookie) != NV_TYPE_NVLIST_ARRAY) { ptr = nvpair_pack_nvlist_up(ptr, &left); if (ptr == NULL) goto fail; nvp = cookie; } else { nvp = cookie; } } while (nvp == NULL); if (nvlist_in_array(nvl) && cookie == NULL) break; } } out: if (sizep != NULL) *sizep = size; return (buf); fail: nv_free(buf); return (NULL); } void * nvlist_pack(const nvlist_t *nvl, size_t *sizep) { NVLIST_ASSERT(nvl); if (nvl->nvl_error != 0) { ERRNO_SET(nvl->nvl_error); return (NULL); } if (nvlist_ndescriptors(nvl) > 0) { ERRNO_SET(EOPNOTSUPP); return (NULL); } return (nvlist_xpack(nvl, NULL, sizep)); } static bool nvlist_check_header(struct nvlist_header *nvlhdrp) { if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) { ERRNO_SET(EINVAL); return (false); } if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) { ERRNO_SET(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; int inarrayf; if (*leftp < sizeof(nvlhdr)) goto fail; memcpy(&nvlhdr, ptr, sizeof(nvlhdr)); if (!nvlist_check_header(&nvlhdr)) goto fail; if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr)) goto fail; /* * nvlh_descriptors might be smaller than nfds in embedded nvlists. */ if (nvlhdr.nvlh_descriptors > nfds) goto fail; if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) goto fail; inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY); nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf; ptr += sizeof(nvlhdr); if (isbep != NULL) *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0); *leftp -= sizeof(nvlhdr); return (ptr); fail: ERRNO_SET(EINVAL); return (NULL); } static nvlist_t * nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds, int flags) { const unsigned char *ptr; nvlist_t *nvl, *retnvl, *tmpnvl, *array; nvpair_t *nvp; size_t left; bool isbe; PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0); left = size; ptr = buf; tmpnvl = array = NULL; nvl = retnvl = nvlist_create(0); if (nvl == NULL) goto fail; ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); if (ptr == NULL) goto fail; if (nvl->nvl_flags != flags) { ERRNO_SET(EILSEQ); goto fail; } while (left > 0) { ptr = nvpair_unpack(isbe, ptr, &left, &nvp); if (ptr == NULL) goto fail; switch (nvpair_type(nvp)) { case NV_TYPE_NULL: ptr = nvpair_unpack_null(isbe, nvp, ptr, &left); break; case NV_TYPE_BOOL: ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left); break; case NV_TYPE_NUMBER: ptr = nvpair_unpack_number(isbe, nvp, ptr, &left); break; case NV_TYPE_STRING: ptr = nvpair_unpack_string(isbe, nvp, ptr, &left); break; case NV_TYPE_NVLIST: ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds, &tmpnvl); if (tmpnvl == NULL || ptr == NULL) goto fail; nvlist_set_parent(tmpnvl, nvp); break; #ifndef _KERNEL case NV_TYPE_DESCRIPTOR: ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left, fds, nfds); break; case NV_TYPE_DESCRIPTOR_ARRAY: ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr, &left, fds, nfds); break; #endif case NV_TYPE_BINARY: ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left); break; case NV_TYPE_NVLIST_UP: if (nvl->nvl_parent == NULL) goto fail; nvl = nvpair_nvlist(nvl->nvl_parent); nvpair_free_structure(nvp); continue; case NV_TYPE_NVLIST_ARRAY_NEXT: if (nvl->nvl_array_next == NULL) { if (nvl->nvl_parent == NULL) goto fail; nvl = nvpair_nvlist(nvl->nvl_parent); } else { nvl = __DECONST(nvlist_t *, nvlist_get_array_next(nvl)); ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left); if (ptr == NULL) goto fail; } nvpair_free_structure(nvp); continue; case NV_TYPE_BOOL_ARRAY: ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left); break; case NV_TYPE_NUMBER_ARRAY: ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left); break; case NV_TYPE_STRING_ARRAY: ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left); break; case NV_TYPE_NVLIST_ARRAY: ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left, &array); if (ptr == NULL) goto fail; PJDLOG_ASSERT(array != NULL); tmpnvl = array; do { nvlist_set_parent(array, nvp); array = __DECONST(nvlist_t *, nvlist_get_array_next(array)); } while (array != NULL); ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe, &left); break; default: PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp)); } if (ptr == NULL) goto fail; if (!nvlist_move_nvpair(nvl, nvp)) goto fail; if (tmpnvl != NULL) { nvl = tmpnvl; tmpnvl = NULL; } } return (retnvl); fail: nvlist_destroy(retnvl); return (NULL); } nvlist_t * nvlist_unpack(const void *buf, size_t size, int flags) { return (nvlist_xunpack(buf, size, NULL, 0, flags)); } #ifndef _KERNEL int nvlist_send(int sock, const nvlist_t *nvl) { size_t datasize, nfds; int *fds; void *data; int64_t fdidx; int ret; if (nvlist_error(nvl) != 0) { ERRNO_SET(nvlist_error(nvl)); return (-1); } fds = nvlist_descriptors(nvl, &nfds); if (fds == NULL) return (-1); ret = -1; fdidx = 0; data = nvlist_xpack(nvl, &fdidx, &datasize); if (data == NULL) goto out; if (buf_send(sock, data, datasize) == -1) goto out; if (nfds > 0) { if (fd_send(sock, fds, nfds) == -1) goto out; } ret = 0; out: ERRNO_SAVE(); nv_free(fds); nv_free(data); ERRNO_RESTORE(); return (ret); } nvlist_t * nvlist_recv(int sock, int flags) { struct nvlist_header nvlhdr; nvlist_t *nvl, *ret; unsigned char *buf; size_t nfds, size, i; int *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 = nv_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 = nv_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, flags); if (nvl == NULL) { ERRNO_SAVE(); for (i = 0; i < nfds; i++) close(fds[i]); ERRNO_RESTORE(); goto out; } ret = nvl; out: ERRNO_SAVE(); nv_free(buf); nv_free(fds); ERRNO_RESTORE(); return (ret); } nvlist_t * nvlist_xfer(int sock, nvlist_t *nvl, int flags) { if (nvlist_send(sock, nvl) < 0) { nvlist_destroy(nvl); return (NULL); } nvlist_destroy(nvl); return (nvlist_recv(sock, flags)); } #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); if (cookiep == NULL || *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); if (cookiep != NULL) *cookiep = nvp; return (nvpair_name(nvp)); } bool nvlist_exists(const nvlist_t *nvl, const char *name) { return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL); } #define NVLIST_EXISTS(type, TYPE) \ bool \ nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ { \ \ return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \ } NVLIST_EXISTS(null, NULL) NVLIST_EXISTS(bool, BOOL) NVLIST_EXISTS(number, NUMBER) NVLIST_EXISTS(string, STRING) NVLIST_EXISTS(nvlist, NVLIST) NVLIST_EXISTS(binary, BINARY) NVLIST_EXISTS(bool_array, BOOL_ARRAY) NVLIST_EXISTS(number_array, NUMBER_ARRAY) NVLIST_EXISTS(string_array, STRING_ARRAY) NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY) #ifndef _KERNEL NVLIST_EXISTS(descriptor, DESCRIPTOR) NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY) #endif #undef NVLIST_EXISTS void nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) { nvpair_t *newnvp; NVPAIR_ASSERT(nvp); if (nvlist_error(nvl) != 0) { ERRNO_SET(nvlist_error(nvl)); return; } if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { if (nvlist_exists(nvl, nvpair_name(nvp))) { nvl->nvl_error = EEXIST; ERRNO_SET(nvlist_error(nvl)); return; } } newnvp = nvpair_clone(nvp); if (newnvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvlist_error(nvl)); return; } nvpair_insert(&nvl->nvl_head, newnvp, nvl); } void nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) { va_list valueap; va_start(valueap, valuefmt); nvlist_add_stringv(nvl, name, valuefmt, valueap); va_end(valueap); } void nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, va_list valueap) { nvpair_t *nvp; if (nvlist_error(nvl) != 0) { ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_create_stringv(name, valuefmt, valueap); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } void nvlist_add_null(nvlist_t *nvl, const char *name) { nvpair_t *nvp; if (nvlist_error(nvl) != 0) { ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_create_null(name); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } void nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, size_t size) { nvpair_t *nvp; if (nvlist_error(nvl) != 0) { ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_create_binary(name, value, size); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } #define NVLIST_ADD(vtype, type) \ void \ nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value) \ { \ nvpair_t *nvp; \ \ if (nvlist_error(nvl) != 0) { \ ERRNO_SET(nvlist_error(nvl)); \ return; \ } \ \ nvp = nvpair_create_##type(name, value); \ if (nvp == NULL) { \ nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ ERRNO_SET(nvl->nvl_error); \ } else { \ (void)nvlist_move_nvpair(nvl, nvp); \ } \ } NVLIST_ADD(bool, bool) NVLIST_ADD(uint64_t, number) NVLIST_ADD(const char *, string) NVLIST_ADD(const nvlist_t *, nvlist) #ifndef _KERNEL NVLIST_ADD(int, descriptor); #endif #undef NVLIST_ADD #define NVLIST_ADD_ARRAY(vtype, type) \ void \ nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value, \ size_t nitems) \ { \ nvpair_t *nvp; \ \ if (nvlist_error(nvl) != 0) { \ ERRNO_SET(nvlist_error(nvl)); \ return; \ } \ \ nvp = nvpair_create_##type##_array(name, value, nitems); \ if (nvp == NULL) { \ nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ ERRNO_SET(nvl->nvl_error); \ } else { \ (void)nvlist_move_nvpair(nvl, nvp); \ } \ } NVLIST_ADD_ARRAY(const bool *, bool) NVLIST_ADD_ARRAY(const uint64_t *, number) NVLIST_ADD_ARRAY(const char * const *, string) NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist) #ifndef _KERNEL NVLIST_ADD_ARRAY(const int *, descriptor) #endif #undef NVLIST_ADD_ARRAY +#define NVLIST_APPEND_ARRAY(vtype, type, TYPE) \ +void \ +nvlist_append_##type##_array(nvlist_t *nvl, const char *name, vtype value)\ +{ \ + nvpair_t *nvp; \ + \ + if (nvlist_error(nvl) != 0) { \ + ERRNO_SET(nvlist_error(nvl)); \ + return; \ + } \ + nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ + if (nvp == NULL) { \ + nvlist_add_##type##_array(nvl, name, &value, 1); \ + return; \ + } \ + if (nvpair_append_##type##_array(nvp, value) == -1) { \ + nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ + ERRNO_SET(nvl->nvl_error); \ + } \ +} + +NVLIST_APPEND_ARRAY(const bool, bool, BOOL) +NVLIST_APPEND_ARRAY(const uint64_t, number, NUMBER) +NVLIST_APPEND_ARRAY(const char *, string, STRING) +NVLIST_APPEND_ARRAY(const nvlist_t *, nvlist, NVLIST) +#ifndef _KERNEL +NVLIST_APPEND_ARRAY(const int, descriptor, DESCRIPTOR) +#endif + +#undef NVLIST_APPEND_ARRAY + bool nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL); if (nvlist_error(nvl) != 0) { nvpair_free(nvp); ERRNO_SET(nvlist_error(nvl)); return (false); } if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { if (nvlist_exists(nvl, nvpair_name(nvp))) { nvpair_free(nvp); nvl->nvl_error = EEXIST; ERRNO_SET(nvl->nvl_error); return (false); } } nvpair_insert(&nvl->nvl_head, nvp, nvl); return (true); } void nvlist_move_string(nvlist_t *nvl, const char *name, char *value) { nvpair_t *nvp; if (nvlist_error(nvl) != 0) { nv_free(value); ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_move_string(name, value); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } void nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value) { nvpair_t *nvp; if (nvlist_error(nvl) != 0) { if (value != NULL && nvlist_get_nvpair_parent(value) != NULL) nvlist_destroy(value); ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_move_nvlist(name, value); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } #ifndef _KERNEL void nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value) { nvpair_t *nvp; if (nvlist_error(nvl) != 0) { close(value); ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_move_descriptor(name, value); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } #endif void nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size) { nvpair_t *nvp; if (nvlist_error(nvl) != 0) { nv_free(value); ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_move_binary(name, value, size); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } void nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value, size_t nitems) { nvpair_t *nvp; if (nvlist_error(nvl) != 0) { nv_free(value); ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_move_bool_array(name, value, nitems); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } void nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value, size_t nitems) { nvpair_t *nvp; size_t i; if (nvlist_error(nvl) != 0) { if (value != NULL) { for (i = 0; i < nitems; i++) nv_free(value[i]); nv_free(value); } ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_move_string_array(name, value, nitems); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } void nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value, size_t nitems) { nvpair_t *nvp; size_t i; if (nvlist_error(nvl) != 0) { if (value != NULL) { for (i = 0; i < nitems; i++) { if (nvlist_get_pararr(value[i], NULL) == NULL) nvlist_destroy(value[i]); } } nv_free(value); ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_move_nvlist_array(name, value, nitems); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } void nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value, size_t nitems) { nvpair_t *nvp; if (nvlist_error(nvl) != 0) { nv_free(value); ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_move_number_array(name, value, nitems); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } #ifndef _KERNEL void nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value, size_t nitems) { nvpair_t *nvp; size_t i; if (nvlist_error(nvl) != 0) { if (value != 0) { for (i = 0; i < nitems; i++) close(value[i]); nv_free(value); } ERRNO_SET(nvlist_error(nvl)); return; } nvp = nvpair_move_descriptor_array(name, value, nitems); if (nvp == NULL) { nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); ERRNO_SET(nvl->nvl_error); } else { (void)nvlist_move_nvpair(nvl, nvp); } } #endif const nvpair_t * nvlist_get_nvpair(const nvlist_t *nvl, const char *name) { return (nvlist_find(nvl, NV_TYPE_NONE, name)); } #define NVLIST_GET(ftype, type, TYPE) \ ftype \ nvlist_get_##type(const nvlist_t *nvl, const char *name) \ { \ const nvpair_t *nvp; \ \ nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ if (nvp == NULL) \ nvlist_report_missing(NV_TYPE_##TYPE, name); \ return (nvpair_get_##type(nvp)); \ } NVLIST_GET(bool, bool, BOOL) NVLIST_GET(uint64_t, number, NUMBER) NVLIST_GET(const char *, string, STRING) NVLIST_GET(const nvlist_t *, nvlist, NVLIST) #ifndef _KERNEL NVLIST_GET(int, descriptor, DESCRIPTOR) #endif #undef NVLIST_GET const void * nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) { nvpair_t *nvp; nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); if (nvp == NULL) nvlist_report_missing(NV_TYPE_BINARY, name); return (nvpair_get_binary(nvp, sizep)); } #define NVLIST_GET_ARRAY(ftype, type, TYPE) \ ftype \ nvlist_get_##type##_array(const nvlist_t *nvl, const char *name, \ size_t *nitems) \ { \ const nvpair_t *nvp; \ \ nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ if (nvp == NULL) \ nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ return (nvpair_get_##type##_array(nvp, nitems)); \ } NVLIST_GET_ARRAY(const bool *, bool, BOOL) NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER) NVLIST_GET_ARRAY(const char * const *, string, STRING) NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST) #ifndef _KERNEL NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR) #endif #undef NVLIST_GET_ARRAY #define NVLIST_TAKE(ftype, type, TYPE) \ ftype \ nvlist_take_##type(nvlist_t *nvl, const char *name) \ { \ nvpair_t *nvp; \ ftype value; \ \ nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ if (nvp == NULL) \ nvlist_report_missing(NV_TYPE_##TYPE, name); \ value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ nvlist_remove_nvpair(nvl, nvp); \ nvpair_free_structure(nvp); \ return (value); \ } NVLIST_TAKE(bool, bool, BOOL) NVLIST_TAKE(uint64_t, number, NUMBER) NVLIST_TAKE(char *, string, STRING) NVLIST_TAKE(nvlist_t *, nvlist, NVLIST) #ifndef _KERNEL NVLIST_TAKE(int, descriptor, DESCRIPTOR) #endif #undef NVLIST_TAKE void * nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) { nvpair_t *nvp; void *value; nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); if (nvp == NULL) nvlist_report_missing(NV_TYPE_BINARY, name); value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); nvlist_remove_nvpair(nvl, nvp); nvpair_free_structure(nvp); return (value); } #define NVLIST_TAKE_ARRAY(ftype, type, TYPE) \ ftype \ nvlist_take_##type##_array(nvlist_t *nvl, const char *name, \ size_t *nitems) \ { \ nvpair_t *nvp; \ ftype value; \ \ nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name); \ if (nvp == NULL) \ nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name); \ value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\ nvlist_remove_nvpair(nvl, nvp); \ nvpair_free_structure(nvp); \ return (value); \ } NVLIST_TAKE_ARRAY(bool *, bool, BOOL) NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER) NVLIST_TAKE_ARRAY(char **, string, STRING) NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST) #ifndef _KERNEL NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR) #endif void nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) { NVLIST_ASSERT(nvl); NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); nvpair_remove(&nvl->nvl_head, nvp, nvl); } void nvlist_free(nvlist_t *nvl, const char *name) { nvlist_free_type(nvl, name, NV_TYPE_NONE); } #define NVLIST_FREE(type, TYPE) \ void \ nvlist_free_##type(nvlist_t *nvl, const char *name) \ { \ \ nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ } NVLIST_FREE(null, NULL) NVLIST_FREE(bool, BOOL) NVLIST_FREE(number, NUMBER) NVLIST_FREE(string, STRING) NVLIST_FREE(nvlist, NVLIST) NVLIST_FREE(binary, BINARY) NVLIST_FREE(bool_array, BOOL_ARRAY) NVLIST_FREE(number_array, NUMBER_ARRAY) NVLIST_FREE(string_array, STRING_ARRAY) NVLIST_FREE(nvlist_array, NVLIST_ARRAY) #ifndef _KERNEL NVLIST_FREE(descriptor, DESCRIPTOR) NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY) #endif #undef NVLIST_FREE void nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp) { NVLIST_ASSERT(nvl); NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); nvlist_remove_nvpair(nvl, nvp); nvpair_free(nvp); } Index: stable/11/sys/contrib/libnv/nvpair.c =================================================================== --- stable/11/sys/contrib/libnv/nvpair.c (revision 336345) +++ stable/11/sys/contrib/libnv/nvpair.c (revision 336346) @@ -1,2006 +1,2146 @@ /*- * Copyright (c) 2009-2013 The FreeBSD Foundation * Copyright (c) 2013-2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #ifdef _KERNEL #include #include #include #include #include #else #include #include #include #include #include #include #include #include #include "common_impl.h" #endif #ifdef HAVE_PJDLOG #include #endif #include #include "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; size_t nvp_nitems; /* Used only for array types. */ 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; uint64_t nvph_nitems; } __packed; void nvpair_assert(const nvpair_t *nvp) { NVPAIR_ASSERT(nvp); } static nvpair_t * nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize, size_t nitems) { nvpair_t *nvp; size_t namelen; PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST); namelen = strlen(name); if (namelen >= NV_NAME_MAX) { ERRNO_SET(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); nvp->nvp_name[namelen] = '\0'; nvp->nvp_type = type; nvp->nvp_data = data; nvp->nvp_datasize = datasize; nvp->nvp_nitems = nitems; nvp->nvp_magic = NVPAIR_MAGIC; } return (nvp); } +static int +nvpair_append(nvpair_t *nvp, const void *value, size_t valsize, size_t datasize) +{ + void *olddata, *data, *valp; + size_t oldlen; + + oldlen = nvp->nvp_nitems * valsize; + olddata = (void *)(uintptr_t)nvp->nvp_data; + data = nv_realloc(olddata, oldlen + valsize); + if (data == NULL) { + ERRNO_SET(ENOMEM); + return (-1); + } + valp = (unsigned char *)data + oldlen; + memcpy(valp, value, valsize); + + nvp->nvp_data = (uint64_t)(uintptr_t)data; + nvp->nvp_datasize += datasize; + nvp->nvp_nitems++; + return (0); +} + 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_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 || !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); } static void nvpair_remove_nvlist_array(nvpair_t *nvp) { nvlist_t **nvlarray; size_t count, i; /* XXX: DECONST is bad, mkay? */ nvlarray = __DECONST(nvlist_t **, nvpair_get_nvlist_array(nvp, &count)); - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { nvlist_set_array_next(nvlarray[i], NULL); + nvlist_set_parent(nvlarray[i], NULL); + } } void nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_list == nvl); if (nvpair_type(nvp) == NV_TYPE_NVLIST) nvpair_remove_nvlist(nvp); else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) nvpair_remove_nvlist_array(nvp); TAILQ_REMOVE(head, nvp, nvp_next); nvp->nvp_list = NULL; } nvpair_t * nvpair_clone(const nvpair_t *nvp) { nvpair_t *newnvp; const char *name; const void *data; size_t datasize; NVPAIR_ASSERT(nvp); name = nvpair_name(nvp); switch (nvpair_type(nvp)) { case NV_TYPE_NULL: newnvp = nvpair_create_null(name); break; case NV_TYPE_BOOL: newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp)); break; case NV_TYPE_NUMBER: newnvp = nvpair_create_number(name, nvpair_get_number(nvp)); break; case NV_TYPE_STRING: newnvp = nvpair_create_string(name, nvpair_get_string(nvp)); break; case NV_TYPE_NVLIST: newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp)); break; case NV_TYPE_BINARY: data = nvpair_get_binary(nvp, &datasize); newnvp = nvpair_create_binary(name, data, datasize); break; case NV_TYPE_BOOL_ARRAY: data = nvpair_get_bool_array(nvp, &datasize); newnvp = nvpair_create_bool_array(name, data, datasize); break; case NV_TYPE_NUMBER_ARRAY: data = nvpair_get_number_array(nvp, &datasize); newnvp = nvpair_create_number_array(name, data, datasize); break; case NV_TYPE_STRING_ARRAY: data = nvpair_get_string_array(nvp, &datasize); newnvp = nvpair_create_string_array(name, data, datasize); break; case NV_TYPE_NVLIST_ARRAY: data = nvpair_get_nvlist_array(nvp, &datasize); newnvp = nvpair_create_nvlist_array(name, data, datasize); break; #ifndef _KERNEL case NV_TYPE_DESCRIPTOR: newnvp = nvpair_create_descriptor(name, nvpair_get_descriptor(nvp)); break; case NV_TYPE_DESCRIPTOR_ARRAY: data = nvpair_get_descriptor_array(nvp, &datasize); newnvp = nvpair_create_descriptor_array(name, data, datasize); break; #endif 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; nvphdr.nvph_nitems = nvp->nvp_nitems; PJDLOG_ASSERT(*leftp >= sizeof(nvphdr)); memcpy(ptr, &nvphdr, sizeof(nvphdr)); ptr += sizeof(nvphdr); *leftp -= sizeof(nvphdr); PJDLOG_ASSERT(*leftp >= namesize); memcpy(ptr, nvp->nvp_name, namesize); ptr += namesize; *leftp -= namesize; return (ptr); } unsigned char * nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp __unused) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); return (ptr); } unsigned char * nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) { uint8_t value; NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); value = (uint8_t)nvp->nvp_data; PJDLOG_ASSERT(*leftp >= sizeof(value)); memcpy(ptr, &value, sizeof(value)); ptr += sizeof(value); *leftp -= sizeof(value); return (ptr); } unsigned char * nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) { uint64_t value; NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); value = (uint64_t)nvp->nvp_data; PJDLOG_ASSERT(*leftp >= sizeof(value)); memcpy(ptr, &value, sizeof(value)); ptr += sizeof(value); *leftp -= sizeof(value); return (ptr); } unsigned char * nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize); ptr += nvp->nvp_datasize; *leftp -= nvp->nvp_datasize; return (ptr); } unsigned char * nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp) { struct nvpair_header nvphdr; size_t namesize; const char *name = ""; namesize = 1; nvphdr.nvph_type = NV_TYPE_NVLIST_UP; nvphdr.nvph_namesize = namesize; nvphdr.nvph_datasize = 0; nvphdr.nvph_nitems = 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); } unsigned char * nvpair_pack_nvlist_array_next(unsigned char *ptr, size_t *leftp) { struct nvpair_header nvphdr; size_t namesize; const char *name = ""; namesize = 1; nvphdr.nvph_type = NV_TYPE_NVLIST_ARRAY_NEXT; nvphdr.nvph_namesize = namesize; nvphdr.nvph_datasize = 0; nvphdr.nvph_nitems = 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); } unsigned char * nvpair_pack_bool_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); 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_number_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); 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_string_array(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp) { unsigned int ii; size_t size, len; const char * const *array; NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); size = 0; array = nvpair_get_string_array(nvp, NULL); PJDLOG_ASSERT(array != NULL); for (ii = 0; ii < nvp->nvp_nitems; ii++) { len = strlen(array[ii]) + 1; PJDLOG_ASSERT(*leftp >= len); memcpy(ptr, (const void *)array[ii], len); size += len; ptr += len; *leftp -= len; } PJDLOG_ASSERT(size == nvp->nvp_datasize); return (ptr); } #ifndef _KERNEL unsigned char * nvpair_pack_descriptor_array(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, size_t *leftp) { int64_t value; const int *array; unsigned int ii; NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize); array = nvpair_get_descriptor_array(nvp, NULL); PJDLOG_ASSERT(array != NULL); for (ii = 0; ii < nvp->nvp_nitems; ii++) { PJDLOG_ASSERT(*leftp >= sizeof(value)); value = array[ii]; 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)++; } memcpy(ptr, &value, sizeof(value)); ptr += sizeof(value); *leftp -= sizeof(value); } return (ptr); } #endif void nvpair_init_datasize(nvpair_t *nvp) { NVPAIR_ASSERT(nvp); if (nvp->nvp_type == NV_TYPE_NVLIST) { if (nvp->nvp_data == 0) { nvp->nvp_datasize = 0; } else { nvp->nvp_datasize = nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data); } } } const unsigned char * nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp) { struct nvpair_header nvphdr; if (*leftp < sizeof(nvphdr)) goto fail; memcpy(&nvphdr, ptr, sizeof(nvphdr)); ptr += sizeof(nvphdr); *leftp -= sizeof(nvphdr); #if NV_TYPE_FIRST > 0 if (nvphdr.nvph_type < NV_TYPE_FIRST) goto fail; #endif if (nvphdr.nvph_type > NV_TYPE_LAST && nvphdr.nvph_type != NV_TYPE_NVLIST_UP && nvphdr.nvph_type != NV_TYPE_NVLIST_ARRAY_NEXT) { goto fail; } #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 fail; if (*leftp < nvphdr.nvph_namesize) goto fail; if (nvphdr.nvph_namesize < 1) goto fail; if (strnlen((const char *)ptr, nvphdr.nvph_namesize) != (size_t)(nvphdr.nvph_namesize - 1)) { goto fail; } memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize); ptr += nvphdr.nvph_namesize; *leftp -= nvphdr.nvph_namesize; if (*leftp < nvphdr.nvph_datasize) goto fail; nvp->nvp_type = nvphdr.nvph_type; nvp->nvp_data = 0; nvp->nvp_datasize = nvphdr.nvph_datasize; nvp->nvp_nitems = nvphdr.nvph_nitems; return (ptr); fail: ERRNO_SET(EINVAL); return (NULL); } const unsigned char * nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp __unused) { PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL); if (nvp->nvp_datasize != 0) { ERRNO_SET(EINVAL); return (NULL); } return (ptr); } const unsigned char * nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp) { uint8_t value; PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL); if (nvp->nvp_datasize != sizeof(value)) { ERRNO_SET(EINVAL); return (NULL); } if (*leftp < sizeof(value)) { ERRNO_SET(EINVAL); return (NULL); } memcpy(&value, ptr, sizeof(value)); ptr += sizeof(value); *leftp -= sizeof(value); if (value != 0 && value != 1) { ERRNO_SET(EINVAL); return (NULL); } nvp->nvp_data = (uint64_t)value; return (ptr); } const unsigned char * nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp) { PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER); if (nvp->nvp_datasize != sizeof(uint64_t)) { ERRNO_SET(EINVAL); return (NULL); } if (*leftp < sizeof(uint64_t)) { ERRNO_SET(EINVAL); return (NULL); } if (isbe) nvp->nvp_data = be64dec(ptr); else nvp->nvp_data = le64dec(ptr); ptr += sizeof(uint64_t); *leftp -= sizeof(uint64_t); return (ptr); } const unsigned char * nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp) { PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { ERRNO_SET(EINVAL); return (NULL); } if (strnlen((const char *)ptr, nvp->nvp_datasize) != nvp->nvp_datasize - 1) { ERRNO_SET(EINVAL); return (NULL); } nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr); if (nvp->nvp_data == 0) return (NULL); ptr += nvp->nvp_datasize; *leftp -= nvp->nvp_datasize; return (ptr); } const unsigned char * nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child) { nvlist_t *value; PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { ERRNO_SET(EINVAL); return (NULL); } value = nvlist_create(0); if (value == NULL) return (NULL); ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp); if (ptr == NULL) return (NULL); nvp->nvp_data = (uint64_t)(uintptr_t)value; *child = value; return (ptr); } #ifndef _KERNEL const unsigned char * nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds) { int64_t idx; PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); if (nvp->nvp_datasize != sizeof(idx)) { ERRNO_SET(EINVAL); return (NULL); } if (*leftp < sizeof(idx)) { ERRNO_SET(EINVAL); return (NULL); } if (isbe) idx = be64dec(ptr); else idx = le64dec(ptr); if (idx < 0) { ERRNO_SET(EINVAL); return (NULL); } if ((size_t)idx >= nfds) { ERRNO_SET(EINVAL); return (NULL); } nvp->nvp_data = (uint64_t)fds[idx]; ptr += sizeof(idx); *leftp -= sizeof(idx); return (ptr); } #endif const unsigned char * nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp) { void *value; PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) { ERRNO_SET(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_array(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp) { uint8_t *value; size_t size; unsigned int i; PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); size = sizeof(*value) * nvp->nvp_nitems; if (nvp->nvp_datasize != size || *leftp < size || nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { ERRNO_SET(EINVAL); return (NULL); } value = nv_malloc(size); if (value == NULL) return (NULL); for (i = 0; i < nvp->nvp_nitems; i++) { value[i] = *(const uint8_t *)ptr; ptr += sizeof(*value); *leftp -= sizeof(*value); } nvp->nvp_data = (uint64_t)(uintptr_t)value; return (ptr); } const unsigned char * nvpair_unpack_number_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp) { uint64_t *value; size_t size; unsigned int i; PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); size = sizeof(*value) * nvp->nvp_nitems; if (nvp->nvp_datasize != size || *leftp < size || nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { ERRNO_SET(EINVAL); return (NULL); } value = nv_malloc(size); if (value == NULL) return (NULL); for (i = 0; i < nvp->nvp_nitems; i++) { if (isbe) value[i] = be64dec(ptr); else value[i] = le64dec(ptr); ptr += sizeof(*value); *leftp -= sizeof(*value); } nvp->nvp_data = (uint64_t)(uintptr_t)value; return (ptr); } const unsigned char * nvpair_unpack_string_array(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp) { ssize_t size; size_t len; const char *tmp; char **value; unsigned int ii, j; PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0 || nvp->nvp_nitems == 0) { ERRNO_SET(EINVAL); return (NULL); } size = nvp->nvp_datasize; tmp = (const char *)ptr; for (ii = 0; ii < nvp->nvp_nitems; ii++) { len = strnlen(tmp, size - 1) + 1; size -= len; if (size < 0) { ERRNO_SET(EINVAL); return (NULL); } tmp += len; } if (size != 0) { ERRNO_SET(EINVAL); return (NULL); } value = nv_malloc(sizeof(*value) * nvp->nvp_nitems); if (value == NULL) return (NULL); for (ii = 0; ii < nvp->nvp_nitems; ii++) { value[ii] = nv_strdup((const char *)ptr); if (value[ii] == NULL) goto out; len = strlen(value[ii]) + 1; ptr += len; *leftp -= len; } nvp->nvp_data = (uint64_t)(uintptr_t)value; return (ptr); out: for (j = 0; j < ii; j++) nv_free(value[j]); nv_free(value); return (NULL); } #ifndef _KERNEL const unsigned char * nvpair_unpack_descriptor_array(bool isbe, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds) { int64_t idx; size_t size; unsigned int ii; int *array; PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); size = sizeof(idx) * nvp->nvp_nitems; if (nvp->nvp_datasize != size || *leftp < size || nvp->nvp_nitems == 0 || size < nvp->nvp_nitems) { ERRNO_SET(EINVAL); return (NULL); } array = (int *)nv_malloc(size); if (array == NULL) return (NULL); for (ii = 0; ii < nvp->nvp_nitems; ii++) { if (isbe) idx = be64dec(ptr); else idx = le64dec(ptr); if (idx < 0) { ERRNO_SET(EINVAL); nv_free(array); return (NULL); } if ((size_t)idx >= nfds) { ERRNO_SET(EINVAL); nv_free(array); return (NULL); } array[ii] = (uint64_t)fds[idx]; ptr += sizeof(idx); *leftp -= sizeof(idx); } nvp->nvp_data = (uint64_t)(uintptr_t)array; return (ptr); } #endif const unsigned char * nvpair_unpack_nvlist_array(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr, size_t *leftp, nvlist_t **firstel) { nvlist_t **value; nvpair_t *tmpnvp; unsigned int ii, j; size_t sizeup; PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); sizeup = sizeof(struct nvpair_header) * nvp->nvp_nitems; if (nvp->nvp_nitems == 0 || sizeup < nvp->nvp_nitems || sizeup > *leftp) { ERRNO_SET(EINVAL); return (NULL); } value = nv_malloc(nvp->nvp_nitems * sizeof(*value)); if (value == NULL) return (NULL); for (ii = 0; ii < nvp->nvp_nitems; ii++) { value[ii] = nvlist_create(0); if (value[ii] == NULL) goto fail; if (ii > 0) { tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value[ii], 0, 0); if (tmpnvp == NULL) goto fail; nvlist_set_array_next(value[ii - 1], tmpnvp); } } nvlist_set_flags(value[nvp->nvp_nitems - 1], NV_FLAG_IN_ARRAY); nvp->nvp_data = (uint64_t)(uintptr_t)value; *firstel = value[0]; return (ptr); fail: ERRNO_SAVE(); for (j = 0; j <= ii; j++) nvlist_destroy(value[j]); nv_free(value); ERRNO_RESTORE(); return (NULL); } 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 fail; tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1); if (tmp == NULL) goto fail; 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); fail: 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); } 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_null(const char *name) { return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0, 0)); } nvpair_t * nvpair_create_bool(const char *name, bool value) { return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0, sizeof(uint8_t), 0)); } nvpair_t * nvpair_create_number(const char *name, uint64_t value) { return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value), 0)); } nvpair_t * nvpair_create_string(const char *name, const char *value) { nvpair_t *nvp; size_t size; char *data; if (value == NULL) { ERRNO_SET(EINVAL); return (NULL); } data = nv_strdup(value); if (data == NULL) return (NULL); size = strlen(value) + 1; nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data, size, 0); if (nvp == NULL) nv_free(data); return (nvp); } nvpair_t * nvpair_create_nvlist(const char *name, const nvlist_t *value) { nvlist_t *nvl; nvpair_t *nvp; if (value == NULL) { ERRNO_SET(EINVAL); return (NULL); } nvl = nvlist_clone(value); if (nvl == NULL) return (NULL); nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0, 0); if (nvp == NULL) nvlist_destroy(nvl); else nvlist_set_parent(nvl, nvp); return (nvp); } #ifndef _KERNEL nvpair_t * nvpair_create_descriptor(const char *name, int value) { nvpair_t *nvp; if (value < 0 || !fd_is_valid(value)) { ERRNO_SET(EBADF); return (NULL); } value = fcntl(value, F_DUPFD_CLOEXEC, 0); if (value < 0) return (NULL); nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, sizeof(int64_t), 0); if (nvp == NULL) { ERRNO_SAVE(); close(value); ERRNO_RESTORE(); } return (nvp); } #endif nvpair_t * nvpair_create_binary(const char *name, const void *value, size_t size) { nvpair_t *nvp; void *data; if (value == NULL || size == 0) { ERRNO_SET(EINVAL); return (NULL); } data = nv_malloc(size); if (data == NULL) return (NULL); memcpy(data, value, size); nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data, size, 0); if (nvp == NULL) nv_free(data); return (nvp); } nvpair_t * nvpair_create_bool_array(const char *name, const bool *value, size_t nitems) { nvpair_t *nvp; size_t size; void *data; if (value == NULL || nitems == 0) { ERRNO_SET(EINVAL); return (NULL); } size = sizeof(value[0]) * nitems; data = nv_malloc(size); if (data == NULL) return (NULL); memcpy(data, value, size); nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)data, size, nitems); if (nvp == NULL) { ERRNO_SAVE(); nv_free(data); ERRNO_RESTORE(); } return (nvp); } nvpair_t * nvpair_create_number_array(const char *name, const uint64_t *value, size_t nitems) { nvpair_t *nvp; size_t size; void *data; if (value == NULL || nitems == 0) { ERRNO_SET(EINVAL); return (NULL); } size = sizeof(value[0]) * nitems; data = nv_malloc(size); if (data == NULL) return (NULL); memcpy(data, value, size); nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, (uint64_t)(uintptr_t)data, size, nitems); if (nvp == NULL) { ERRNO_SAVE(); nv_free(data); ERRNO_RESTORE(); } return (nvp); } nvpair_t * nvpair_create_string_array(const char *name, const char * const *value, size_t nitems) { nvpair_t *nvp; unsigned int ii; size_t datasize, size; char **data; if (value == NULL || nitems == 0) { ERRNO_SET(EINVAL); return (NULL); } nvp = NULL; datasize = 0; data = nv_malloc(sizeof(value[0]) * nitems); if (data == NULL) return (NULL); for (ii = 0; ii < nitems; ii++) { if (value[ii] == NULL) { ERRNO_SET(EINVAL); goto fail; } size = strlen(value[ii]) + 1; datasize += size; data[ii] = nv_strdup(value[ii]); if (data[ii] == NULL) goto fail; } nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, (uint64_t)(uintptr_t)data, datasize, nitems); fail: if (nvp == NULL) { ERRNO_SAVE(); for (; ii > 0; ii--) nv_free(data[ii - 1]); nv_free(data); ERRNO_RESTORE(); } return (nvp); } nvpair_t * nvpair_create_nvlist_array(const char *name, const nvlist_t * const *value, size_t nitems) { unsigned int ii; nvlist_t **nvls; nvpair_t *parent; int flags; nvls = NULL; if (value == NULL || nitems == 0) { ERRNO_SET(EINVAL); return (NULL); } nvls = nv_malloc(sizeof(value[0]) * nitems); if (nvls == NULL) return (NULL); for (ii = 0; ii < nitems; ii++) { if (value[ii] == NULL) { ERRNO_SET(EINVAL); goto fail; } nvls[ii] = nvlist_clone(value[ii]); if (nvls[ii] == NULL) goto fail; if (ii > 0) { nvpair_t *nvp; nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvls[ii], 0, 0); if (nvp == NULL) { ERRNO_SAVE(); nvlist_destroy(nvls[ii]); ERRNO_RESTORE(); goto fail; } nvlist_set_array_next(nvls[ii - 1], nvp); } } flags = nvlist_flags(nvls[nitems - 1]) | NV_FLAG_IN_ARRAY; nvlist_set_flags(nvls[nitems - 1], flags); parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, (uint64_t)(uintptr_t)nvls, 0, nitems); if (parent == NULL) goto fail; for (ii = 0; ii < nitems; ii++) nvlist_set_parent(nvls[ii], parent); return (parent); fail: ERRNO_SAVE(); for (; ii > 0; ii--) nvlist_destroy(nvls[ii - 1]); nv_free(nvls); ERRNO_RESTORE(); return (NULL); } #ifndef _KERNEL nvpair_t * nvpair_create_descriptor_array(const char *name, const int *value, size_t nitems) { unsigned int ii; nvpair_t *nvp; int *fds; if (value == NULL) { ERRNO_SET(EINVAL); return (NULL); } nvp = NULL; fds = nv_malloc(sizeof(value[0]) * nitems); if (fds == NULL) return (NULL); for (ii = 0; ii < nitems; ii++) { if (value[ii] == -1) { fds[ii] = -1; } else { if (!fd_is_valid(value[ii])) { ERRNO_SET(EBADF); goto fail; } fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0); if (fds[ii] == -1) goto fail; } } nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, (uint64_t)(uintptr_t)fds, sizeof(int64_t) * nitems, nitems); fail: if (nvp == NULL) { ERRNO_SAVE(); for (; ii > 0; ii--) { if (fds[ii - 1] != -1) close(fds[ii - 1]); } nv_free(fds); ERRNO_RESTORE(); } return (nvp); } #endif nvpair_t * nvpair_move_string(const char *name, char *value) { nvpair_t *nvp; if (value == NULL) { ERRNO_SET(EINVAL); return (NULL); } nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value, strlen(value) + 1, 0); if (nvp == NULL) { ERRNO_SAVE(); nv_free(value); ERRNO_RESTORE(); } return (nvp); } nvpair_t * nvpair_move_nvlist(const char *name, nvlist_t *value) { nvpair_t *nvp; if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) { ERRNO_SET(EINVAL); return (NULL); } if (nvlist_error(value) != 0) { ERRNO_SET(nvlist_error(value)); nvlist_destroy(value); return (NULL); } nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value, 0, 0); if (nvp == NULL) nvlist_destroy(value); else nvlist_set_parent(value, nvp); return (nvp); } #ifndef _KERNEL nvpair_t * nvpair_move_descriptor(const char *name, int value) { nvpair_t *nvp; if (value < 0 || !fd_is_valid(value)) { ERRNO_SET(EBADF); return (NULL); } nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value, sizeof(int64_t), 0); if (nvp == NULL) { ERRNO_SAVE(); close(value); ERRNO_RESTORE(); } return (nvp); } #endif nvpair_t * nvpair_move_binary(const char *name, void *value, size_t size) { nvpair_t *nvp; if (value == NULL || size == 0) { ERRNO_SET(EINVAL); return (NULL); } nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size, 0); if (nvp == NULL) { ERRNO_SAVE(); nv_free(value); ERRNO_RESTORE(); } return (nvp); } nvpair_t * nvpair_move_bool_array(const char *name, bool *value, size_t nitems) { nvpair_t *nvp; if (value == NULL || nitems == 0) { ERRNO_SET(EINVAL); return (NULL); } nvp = nvpair_allocv(name, NV_TYPE_BOOL_ARRAY, (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); if (nvp == NULL) { ERRNO_SAVE(); nv_free(value); ERRNO_RESTORE(); } return (nvp); } nvpair_t * nvpair_move_string_array(const char *name, char **value, size_t nitems) { nvpair_t *nvp; size_t i, size; if (value == NULL || nitems == 0) { ERRNO_SET(EINVAL); return (NULL); } size = 0; for (i = 0; i < nitems; i++) { if (value[i] == NULL) { ERRNO_SET(EINVAL); return (NULL); } size += strlen(value[i]) + 1; } nvp = nvpair_allocv(name, NV_TYPE_STRING_ARRAY, (uint64_t)(uintptr_t)value, size, nitems); if (nvp == NULL) { ERRNO_SAVE(); for (i = 0; i < nitems; i++) nv_free(value[i]); nv_free(value); ERRNO_RESTORE(); } return (nvp); } nvpair_t * nvpair_move_number_array(const char *name, uint64_t *value, size_t nitems) { nvpair_t *nvp; if (value == NULL || nitems == 0) { ERRNO_SET(EINVAL); return (NULL); } nvp = nvpair_allocv(name, NV_TYPE_NUMBER_ARRAY, (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); if (nvp == NULL) { ERRNO_SAVE(); nv_free(value); ERRNO_RESTORE(); } return (nvp); } nvpair_t * nvpair_move_nvlist_array(const char *name, nvlist_t **value, size_t nitems) { nvpair_t *parent; unsigned int ii; int flags; if (value == NULL || nitems == 0) { ERRNO_SET(EINVAL); return (NULL); } for (ii = 0; ii < nitems; ii++) { if (value == NULL || nvlist_error(value[ii]) != 0 || nvlist_get_pararr(value[ii], NULL) != NULL) { ERRNO_SET(EINVAL); goto fail; } if (ii > 0) { nvpair_t *nvp; nvp = nvpair_allocv(" ", NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value[ii], 0, 0); if (nvp == NULL) goto fail; nvlist_set_array_next(value[ii - 1], nvp); } } flags = nvlist_flags(value[nitems - 1]) | NV_FLAG_IN_ARRAY; nvlist_set_flags(value[nitems - 1], flags); parent = nvpair_allocv(name, NV_TYPE_NVLIST_ARRAY, (uint64_t)(uintptr_t)value, 0, nitems); if (parent == NULL) goto fail; for (ii = 0; ii < nitems; ii++) nvlist_set_parent(value[ii], parent); return (parent); fail: ERRNO_SAVE(); for (ii = 0; ii < nitems; ii++) { if (value[ii] != NULL && nvlist_get_pararr(value[ii], NULL) != NULL) { nvlist_destroy(value[ii]); } } nv_free(value); ERRNO_RESTORE(); return (NULL); } #ifndef _KERNEL nvpair_t * nvpair_move_descriptor_array(const char *name, int *value, size_t nitems) { nvpair_t *nvp; size_t i; if (value == NULL || nitems == 0) { ERRNO_SET(EINVAL); return (NULL); } for (i = 0; i < nitems; i++) { if (value[i] != -1 && !fd_is_valid(value[i])) { ERRNO_SET(EBADF); goto fail; } } nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR_ARRAY, (uint64_t)(uintptr_t)value, sizeof(value[0]) * nitems, nitems); if (nvp == NULL) goto fail; return (nvp); fail: ERRNO_SAVE(); for (i = 0; i < nitems; i++) { if (fd_is_valid(value[i])) close(value[i]); } nv_free(value); ERRNO_RESTORE(); return (NULL); } #endif bool nvpair_get_bool(const nvpair_t *nvp) { NVPAIR_ASSERT(nvp); return (nvp->nvp_data == 1); } uint64_t nvpair_get_number(const nvpair_t *nvp) { NVPAIR_ASSERT(nvp); return (nvp->nvp_data); } const char * nvpair_get_string(const nvpair_t *nvp) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING); return ((const char *)(intptr_t)nvp->nvp_data); } const nvlist_t * nvpair_get_nvlist(const nvpair_t *nvp) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST); return ((const nvlist_t *)(intptr_t)nvp->nvp_data); } #ifndef _KERNEL int nvpair_get_descriptor(const nvpair_t *nvp) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR); return ((int)nvp->nvp_data); } #endif const void * nvpair_get_binary(const nvpair_t *nvp, size_t *sizep) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY); if (sizep != NULL) *sizep = nvp->nvp_datasize; return ((const void *)(intptr_t)nvp->nvp_data); } const bool * nvpair_get_bool_array(const nvpair_t *nvp, size_t *nitems) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); if (nitems != NULL) *nitems = nvp->nvp_nitems; return ((const bool *)(intptr_t)nvp->nvp_data); } const uint64_t * nvpair_get_number_array(const nvpair_t *nvp, size_t *nitems) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); if (nitems != NULL) *nitems = nvp->nvp_nitems; return ((const uint64_t *)(intptr_t)nvp->nvp_data); } const char * const * nvpair_get_string_array(const nvpair_t *nvp, size_t *nitems) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); if (nitems != NULL) *nitems = nvp->nvp_nitems; return ((const char * const *)(intptr_t)nvp->nvp_data); } const nvlist_t * const * nvpair_get_nvlist_array(const nvpair_t *nvp, size_t *nitems) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); if (nitems != NULL) *nitems = nvp->nvp_nitems; return ((const nvlist_t * const *)((intptr_t)nvp->nvp_data)); } #ifndef _KERNEL const int * nvpair_get_descriptor_array(const nvpair_t *nvp, size_t *nitems) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); if (nitems != NULL) *nitems = nvp->nvp_nitems; return ((const int *)(intptr_t)nvp->nvp_data); +} +#endif + +int +nvpair_append_bool_array(nvpair_t *nvp, const bool value) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL_ARRAY); + return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); +} + +int +nvpair_append_number_array(nvpair_t *nvp, const uint64_t value) +{ + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER_ARRAY); + return (nvpair_append(nvp, &value, sizeof(value), sizeof(value))); +} + +int +nvpair_append_string_array(nvpair_t *nvp, const char *value) +{ + char *str; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING_ARRAY); + if (value == NULL) { + ERRNO_SET(EINVAL); + return (-1); + } + str = nv_strdup(value); + if (str == NULL) { + return (-1); + } + if (nvpair_append(nvp, &str, sizeof(str), strlen(str) + 1) == -1) { + nv_free(str); + return (-1); + } + return (0); +} + +int +nvpair_append_nvlist_array(nvpair_t *nvp, const nvlist_t *value) +{ + nvpair_t *tmpnvp; + nvlist_t *nvl, *prev; + int flags; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST_ARRAY); + if (value == NULL || nvlist_error(value) != 0 || + nvlist_get_pararr(value, NULL) != NULL) { + ERRNO_SET(EINVAL); + return (-1); + } + nvl = nvlist_clone(value); + if (nvl == NULL) { + return (-1); + } + flags = nvlist_flags(nvl) | NV_FLAG_IN_ARRAY; + nvlist_set_flags(nvl, flags); + + tmpnvp = NULL; + prev = NULL; + if (nvp->nvp_nitems > 0) { + nvlist_t **nvls = (void *)(uintptr_t)nvp->nvp_data; + + prev = nvls[nvp->nvp_nitems - 1]; + PJDLOG_ASSERT(prev != NULL); + + tmpnvp = nvpair_allocv(" ", NV_TYPE_NVLIST, + (uint64_t)(uintptr_t)nvl, 0, 0); + if (tmpnvp == NULL) { + goto fail; + } + } + if (nvpair_append(nvp, &nvl, sizeof(nvl), 0) == -1) { + goto fail; + } + if (tmpnvp) { + NVPAIR_ASSERT(tmpnvp); + nvlist_set_array_next(prev, tmpnvp); + } + nvlist_set_parent(nvl, nvp); + return (0); +fail: + if (tmpnvp) { + nvpair_free(tmpnvp); + } + nvlist_destroy(nvl); + return (-1); +} + +#ifndef _KERNEL +int +nvpair_append_descriptor_array(nvpair_t *nvp, const int value) +{ + int fd; + + NVPAIR_ASSERT(nvp); + PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY); + if (value < 0 || !fd_is_valid(value)) { + ERRNO_SET(EBADF); + return -1; + } + fd = fcntl(value, F_DUPFD_CLOEXEC, 0); + if (fd == -1) { + return (-1); + } + if (nvpair_append(nvp, &fd, sizeof(fd), sizeof(fd)) == -1) { + close(fd); + return (-1); + } + return (0); } #endif void nvpair_free(nvpair_t *nvp) { size_t i; 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; case NV_TYPE_DESCRIPTOR_ARRAY: for (i = 0; i < nvp->nvp_nitems; i++) close(((int *)(intptr_t)nvp->nvp_data)[i]); break; #endif case NV_TYPE_NVLIST: nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data); break; case NV_TYPE_STRING: nv_free((char *)(intptr_t)nvp->nvp_data); break; case NV_TYPE_BINARY: nv_free((void *)(intptr_t)nvp->nvp_data); break; case NV_TYPE_NVLIST_ARRAY: for (i = 0; i < nvp->nvp_nitems; i++) { nvlist_destroy( ((nvlist_t **)(intptr_t)nvp->nvp_data)[i]); } nv_free(((nvlist_t **)(intptr_t)nvp->nvp_data)); break; case NV_TYPE_NUMBER_ARRAY: nv_free((uint64_t *)(intptr_t)nvp->nvp_data); break; case NV_TYPE_BOOL_ARRAY: nv_free((bool *)(intptr_t)nvp->nvp_data); break; case NV_TYPE_STRING_ARRAY: for (i = 0; i < nvp->nvp_nitems; i++) nv_free(((char **)(intptr_t)nvp->nvp_data)[i]); nv_free((char **)(intptr_t)nvp->nvp_data); break; } nv_free(nvp); } void nvpair_free_structure(nvpair_t *nvp) { NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_list == NULL); nvp->nvp_magic = 0; nv_free(nvp); } const char * nvpair_type_string(int type) { switch (type) { case NV_TYPE_NULL: return ("NULL"); case NV_TYPE_BOOL: return ("BOOL"); case NV_TYPE_NUMBER: return ("NUMBER"); case NV_TYPE_STRING: return ("STRING"); case NV_TYPE_NVLIST: return ("NVLIST"); case NV_TYPE_DESCRIPTOR: return ("DESCRIPTOR"); case NV_TYPE_BINARY: return ("BINARY"); case NV_TYPE_BOOL_ARRAY: return ("BOOL ARRAY"); case NV_TYPE_NUMBER_ARRAY: return ("NUMBER ARRAY"); case NV_TYPE_STRING_ARRAY: return ("STRING ARRAY"); case NV_TYPE_NVLIST_ARRAY: return ("NVLIST ARRAY"); case NV_TYPE_DESCRIPTOR_ARRAY: return ("DESCRIPTOR ARRAY"); default: return (""); } } Index: stable/11/sys/sys/cnv.h =================================================================== --- stable/11/sys/sys/cnv.h (nonexistent) +++ stable/11/sys/sys/cnv.h (revision 336346) @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 2016 Adam Starak + * 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. + * 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 _CNV_H_ +#define _CNV_H_ + +#include + +#ifndef _KERNEL +#include +#include +#include +#include +#endif + +#ifndef _NVLIST_T_DECLARED +#define _NVLIST_T_DECLARED +struct nvlist; + +typedef struct nvlist nvlist_t; +#endif + +__BEGIN_DECLS + +/* + * Functions which returns information about the given cookie. + */ +const char *cnvlist_name(const void *cookie); +int cnvlist_type(const void *cookie); + +/* + * The cnvlist_get functions returns value associated with the given cookie. + * If it returns a pointer, the pointer represents internal buffer and should + * not be freed by the caller. + */ + +bool cnvlist_get_bool(const void *cookie); +uint64_t cnvlist_get_number(const void *cookie); +const char *cnvlist_get_string(const void *cookie); +const nvlist_t *cnvlist_get_nvlist(const void *cookie); +const void *cnvlist_get_binary(const void *cookie, size_t *sizep); +const bool *cnvlist_get_bool_array(const void *cookie, size_t *nitemsp); +const uint64_t *cnvlist_get_number_array(const void *cookie, size_t *nitemsp); +const char * const *cnvlist_get_string_array(const void *cookie, size_t *nitemsp); +const nvlist_t * const *cnvlist_get_nvlist_array(const void *cookie, size_t *nitemsp); +#ifndef _KERNEL +int cnvlist_get_descriptor(const void *cookie); +const int *cnvlist_get_descriptor_array(const void *cookie, size_t *nitemsp); +#endif + + +/* + * The cnvlist_take functions returns value associated with the given cookie and + * remove the given entry from the nvlist. + * The caller is responsible for freeing received data. + */ + +bool cnvlist_take_bool(void *cookie); +uint64_t cnvlist_take_number(void *cookie); +char *cnvlist_take_string(void *cookie); +nvlist_t *cnvlist_take_nvlist(void *cookie); +void *cnvlist_take_binary(void *cookie, size_t *sizep); +bool *cnvlist_take_bool_array(void *cookie, size_t *nitemsp); +uint64_t *cnvlist_take_number_array(void *cookie, size_t *nitemsp); +char **cnvlist_take_string_array(void *cookie, size_t *nitemsp); +nvlist_t **cnvlist_take_nvlist_array(void *cookie, size_t *nitemsp); +#ifndef _KERNEL +int cnvlist_take_descriptor(void *cookie); +int *cnvlist_take_descriptor_array(void *cookie, size_t *nitemsp); +#endif + +/* + * The cnvlist_free functions removes the given name/value pair from the nvlist based on cookie + * and frees memory associated with it. + */ + +void cnvlist_free_bool(void *cookie); +void cnvlist_free_number(void *cookie); +void cnvlist_free_string(void *cookie); +void cnvlist_free_nvlist(void *cookie); +void cnvlist_free_binary(void *cookie); +void cnvlist_free_bool_array(void *cookie); +void cnvlist_free_number_array(void *cookie); +void cnvlist_free_string_array(void *cookie); +void cnvlist_free_nvlist_array(void *cookie); +#ifndef _KERNEL +void cnvlist_free_descriptor(void *cookie); +void cnvlist_free_descriptor_array(void *cookie); +#endif + +__END_DECLS + +#endif /* !_CNV_H_ */ Property changes on: stable/11/sys/sys/cnv.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/sys/nv.h =================================================================== --- stable/11/sys/sys/nv.h (revision 336345) +++ stable/11/sys/sys/nv.h (revision 336346) @@ -1,246 +1,254 @@ /*- * Copyright (c) 2009-2013 The FreeBSD Foundation * Copyright (c) 2013-2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _NV_H_ #define _NV_H_ #include #ifndef _KERNEL #include #include #include #include #endif #ifndef _NVLIST_T_DECLARED #define _NVLIST_T_DECLARED struct nvlist; typedef struct nvlist nvlist_t; #endif #define NV_NAME_MAX 2048 #define NV_TYPE_NONE 0 #define NV_TYPE_NULL 1 #define NV_TYPE_BOOL 2 #define NV_TYPE_NUMBER 3 #define NV_TYPE_STRING 4 #define NV_TYPE_NVLIST 5 #define NV_TYPE_DESCRIPTOR 6 #define NV_TYPE_BINARY 7 #define NV_TYPE_BOOL_ARRAY 8 #define NV_TYPE_NUMBER_ARRAY 9 #define NV_TYPE_STRING_ARRAY 10 #define NV_TYPE_NVLIST_ARRAY 11 #define NV_TYPE_DESCRIPTOR_ARRAY 12 /* * 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); 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); nvlist_t *nvlist_unpack(const void *buf, size_t size, int flags); int nvlist_send(int sock, const nvlist_t *nvl); nvlist_t *nvlist_recv(int sock, int flags); nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl, int flags); const char *nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep); const nvlist_t *nvlist_get_parent(const nvlist_t *nvl, void **cookiep); const nvlist_t *nvlist_get_array_next(const nvlist_t *nvl); bool nvlist_in_array(const nvlist_t *nvl); const nvlist_t *nvlist_get_pararr(const nvlist_t *nvl, void **cookiep); /* * The nvlist_exists functions check if the given name (optionally of the given * type) exists on nvlist. */ bool nvlist_exists(const nvlist_t *nvl, const char *name); bool nvlist_exists_type(const nvlist_t *nvl, const char *name, int type); bool nvlist_exists_null(const nvlist_t *nvl, const char *name); bool nvlist_exists_bool(const nvlist_t *nvl, const char *name); bool nvlist_exists_number(const nvlist_t *nvl, const char *name); bool nvlist_exists_string(const nvlist_t *nvl, const char *name); bool nvlist_exists_nvlist(const nvlist_t *nvl, const char *name); bool nvlist_exists_binary(const nvlist_t *nvl, const char *name); bool nvlist_exists_bool_array(const nvlist_t *nvl, const char *name); bool nvlist_exists_number_array(const nvlist_t *nvl, const char *name); bool nvlist_exists_string_array(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); bool nvlist_exists_descriptor_array(const nvlist_t *nvl, const char *name); #endif /* * The nvlist_add functions add the given name/value pair. * If a pointer is provided, nvlist_add will internally allocate memory for the * given data (in other words it won't consume provided buffer). */ void nvlist_add_null(nvlist_t *nvl, const char *name); void nvlist_add_bool(nvlist_t *nvl, const char *name, bool value); void nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value); void nvlist_add_string(nvlist_t *nvl, const char *name, const char *value); void nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) __printflike(3, 4); #if !defined(_KERNEL) || defined(_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_binary(nvlist_t *nvl, const char *name, const void *value, size_t size); void nvlist_add_bool_array(nvlist_t *nvl, const char *name, const bool *value, size_t nitems); void nvlist_add_number_array(nvlist_t *nvl, const char *name, const uint64_t *value, size_t nitems); void nvlist_add_string_array(nvlist_t *nvl, const char *name, const char * const *value, size_t nitems); void nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, const nvlist_t * const *value, size_t nitems); #ifndef _KERNEL void nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value); void nvlist_add_descriptor_array(nvlist_t *nvl, const char *name, const int *value, size_t nitems); #endif +void nvlist_append_bool_array(nvlist_t *nvl, const char *name, const bool value); +void nvlist_append_number_array(nvlist_t *nvl, const char *name, const uint64_t value); +void nvlist_append_string_array(nvlist_t *nvl, const char *name, const char * const value); +void nvlist_append_nvlist_array(nvlist_t *nvl, const char *name, const nvlist_t * const value); +#ifndef _KERNEL +void nvlist_append_descriptor_array(nvlist_t *nvl, const char *name, int value); +#endif + /* * 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_binary(nvlist_t *nvl, const char *name, void *value, size_t size); void nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value, size_t nitems); void nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value, size_t nitems); void nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value, size_t nitems); void nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value, size_t nitems); #ifndef _KERNEL void nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value); void nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value, size_t nitems); #endif /* * The nvlist_get functions returns value associated with the given name. * If it returns a pointer, the pointer represents internal buffer and should * not be freed by the caller. */ bool nvlist_get_bool(const nvlist_t *nvl, const char *name); uint64_t nvlist_get_number(const nvlist_t *nvl, const char *name); const char *nvlist_get_string(const nvlist_t *nvl, const char *name); const nvlist_t *nvlist_get_nvlist(const nvlist_t *nvl, const char *name); const void *nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep); const bool *nvlist_get_bool_array(const nvlist_t *nvl, const char *name, size_t *nitemsp); const uint64_t *nvlist_get_number_array(const nvlist_t *nvl, const char *name, size_t *nitemsp); const char * const *nvlist_get_string_array(const nvlist_t *nvl, const char *name, size_t *nitemsp); const nvlist_t * const *nvlist_get_nvlist_array(const nvlist_t *nvl, const char *name, size_t *nitemsp); #ifndef _KERNEL int nvlist_get_descriptor(const nvlist_t *nvl, const char *name); const int *nvlist_get_descriptor_array(const nvlist_t *nvl, const char *name, size_t *nitemsp); #endif /* * The nvlist_take functions returns value associated with the given name and * remove the given entry from the nvlist. * The caller is responsible for freeing received data. */ bool nvlist_take_bool(nvlist_t *nvl, const char *name); uint64_t nvlist_take_number(nvlist_t *nvl, const char *name); char *nvlist_take_string(nvlist_t *nvl, const char *name); nvlist_t *nvlist_take_nvlist(nvlist_t *nvl, const char *name); void *nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep); bool *nvlist_take_bool_array(nvlist_t *nvl, const char *name, size_t *nitemsp); uint64_t *nvlist_take_number_array(nvlist_t *nvl, const char *name, size_t *nitemsp); char **nvlist_take_string_array(nvlist_t *nvl, const char *name, size_t *nitemsp); nvlist_t **nvlist_take_nvlist_array(nvlist_t *nvl, const char *name, size_t *nitemsp); #ifndef _KERNEL int nvlist_take_descriptor(nvlist_t *nvl, const char *name); int *nvlist_take_descriptor_array(nvlist_t *nvl, const char *name, size_t *nitemsp); #endif /* * The nvlist_free functions removes the given name/value pair from the nvlist * and frees memory associated with it. */ void nvlist_free(nvlist_t *nvl, const char *name); void nvlist_free_type(nvlist_t *nvl, const char *name, int type); void nvlist_free_null(nvlist_t *nvl, const char *name); void nvlist_free_bool(nvlist_t *nvl, const char *name); void nvlist_free_number(nvlist_t *nvl, const char *name); void nvlist_free_string(nvlist_t *nvl, const char *name); void nvlist_free_nvlist(nvlist_t *nvl, const char *name); void nvlist_free_binary(nvlist_t *nvl, const char *name); void nvlist_free_bool_array(nvlist_t *nvl, const char *name); void nvlist_free_number_array(nvlist_t *nvl, const char *name); void nvlist_free_string_array(nvlist_t *nvl, const char *name); void nvlist_free_nvlist_array(nvlist_t *nvl, const char *name); void nvlist_free_binary_array(nvlist_t *nvl, const char *name); #ifndef _KERNEL void nvlist_free_descriptor(nvlist_t *nvl, const char *name); void nvlist_free_descriptor_array(nvlist_t *nvl, const char *name); #endif __END_DECLS #endif /* !_NV_H_ */ Index: stable/11 =================================================================== --- stable/11 (revision 336345) +++ stable/11 (revision 336346) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r304910,304912,304915,304952,325019,328164,331094,332664,335341-335345,335347,335379-335380,335382