Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 18 Jun 2018 22:57:32 +0000 (UTC)
From:      Mariusz Zaborski <oshogbo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r335347 - in head: lib/libnv/tests share/man/man9 sys/contrib/libnv sys/sys
Message-ID:  <201806182257.w5IMvWH7036479@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: oshogbo
Date: Mon Jun 18 22:57:32 2018
New Revision: 335347
URL: https://svnweb.freebsd.org/changeset/base/335347

Log:
  libnv: Add nvlist_append_*_array() family of functions.
  
  The nvlist_append_{bool,number,string,nvlist,descriptor}_array() functions
  allows to dynamically extend array stored in the nvlist.
  
  Submitted by:	Mindaugas Rasiukevicius <rmind@netbsd.org>

Added:
  head/lib/libnv/tests/nvlist_append_test.c   (contents, props changed)
Modified:
  head/lib/libnv/tests/Makefile
  head/share/man/man9/nv.9
  head/sys/contrib/libnv/nv_impl.h
  head/sys/contrib/libnv/nvlist.c
  head/sys/contrib/libnv/nvpair.c
  head/sys/sys/nv.h

Modified: head/lib/libnv/tests/Makefile
==============================================================================
--- head/lib/libnv/tests/Makefile	Mon Jun 18 22:27:29 2018	(r335346)
+++ head/lib/libnv/tests/Makefile	Mon Jun 18 22:57:32 2018	(r335347)
@@ -7,6 +7,7 @@ ATF_TESTS_CXX=	\
 	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

Added: head/lib/libnv/tests/nvlist_append_test.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libnv/tests/nvlist_append_test.c	Mon Jun 18 22:57:32 2018	(r335347)
@@ -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 <sys/nv.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+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);
+}

Modified: head/share/man/man9/nv.9
==============================================================================
--- head/share/man/man9/nv.9	Mon Jun 18 22:27:29 2018	(r335346)
+++ head/share/man/man9/nv.9	Mon Jun 18 22:57:32 2018	(r335347)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 16, 2017
+.Dd June 19, 2018
 .Dt NV 9
 .Os
 .Sh NAME
@@ -55,7 +55,8 @@
 .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
@@ -239,6 +240,17 @@
 .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"
@@ -708,6 +720,20 @@ 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_<type>_array
+function.
+The internal error is set on append failure.
 .Pp
 The
 .Fn nvlist_free

Modified: head/sys/contrib/libnv/nv_impl.h
==============================================================================
--- head/sys/contrib/libnv/nv_impl.h	Mon Jun 18 22:27:29 2018	(r335346)
+++ head/sys/contrib/libnv/nv_impl.h	Mon Jun 18 22:57:32 2018	(r335347)
@@ -143,6 +143,12 @@ nvpair_t *nvpair_move_descriptor_array(const char *nam
 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);

Modified: head/sys/contrib/libnv/nvlist.c
==============================================================================
--- head/sys/contrib/libnv/nvlist.c	Mon Jun 18 22:27:29 2018	(r335346)
+++ head/sys/contrib/libnv/nvlist.c	Mon Jun 18 22:57:32 2018	(r335347)
@@ -1607,6 +1607,37 @@ NVLIST_ADD_ARRAY(const int *, descriptor)
 
 #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)
 {

Modified: head/sys/contrib/libnv/nvpair.c
==============================================================================
--- head/sys/contrib/libnv/nvpair.c	Mon Jun 18 22:27:29 2018	(r335346)
+++ head/sys/contrib/libnv/nvpair.c	Mon Jun 18 22:57:32 2018	(r335347)
@@ -144,6 +144,28 @@ nvpair_allocv(const char *name, int type, uint64_t dat
 	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)
 {
@@ -1910,6 +1932,121 @@ nvpair_get_descriptor_array(const nvpair_t *nvp, size_
 		*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;
+	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
 

Modified: head/sys/sys/nv.h
==============================================================================
--- head/sys/sys/nv.h	Mon Jun 18 22:27:29 2018	(r335346)
+++ head/sys/sys/nv.h	Mon Jun 18 22:57:32 2018	(r335347)
@@ -162,6 +162,14 @@ void nvlist_add_descriptor(nvlist_t *nvl, const char *
 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.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201806182257.w5IMvWH7036479>