All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vishal Verma <vishal.l.verma@intel.com>
To: <nvdimm@lists.linux.dev>
Cc: Dan Williams <dan.j.williams@intel.com>,
	QI Fuli <qi.fuli@jp.fujitsu.com>,
	fenghua.hu@intel.com, QI Fuli <qi.fuli@fujitsu.com>,
	Vishal Verma <vishal.l.verma@intel.com>
Subject: [ndctl PATCH v3 01/11] ndctl, util: add parse-configs helper
Date: Fri, 10 Dec 2021 15:34:30 -0700	[thread overview]
Message-ID: <20211210223440.3946603-2-vishal.l.verma@intel.com> (raw)
In-Reply-To: <20211210223440.3946603-1-vishal.l.verma@intel.com>

From: QI Fuli <qi.fuli@fujitsu.com>

Add parse-config util to help ndctl commands parse ndctl global
configuration files. This provides a parse_configs_prefix() helper which
uses the iniparser APIs to read all applicable config files, and either
return a 'value' for a requested 'key', or perform a callback if
requested. The operation is defined by a 'struct config' which
encapsulates the key to search for, the location to store the value, and
any callbacks to be executed.

Signed-off-by: QI Fuli <qi.fuli@fujitsu.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 configure.ac         |   4 ++
 Makefile.am          |   2 +
 util/parse-configs.h |  38 ++++++++++++++++
 util/parse-configs.c | 105 +++++++++++++++++++++++++++++++++++++++++++
 ndctl/Makefile.am    |   3 +-
 5 files changed, 151 insertions(+), 1 deletion(-)
 create mode 100644 util/parse-configs.h
 create mode 100644 util/parse-configs.c

diff --git a/configure.ac b/configure.ac
index dc39dbe..cbd5a6f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -199,6 +199,10 @@ ndctl_keysreadme=keys.readme
 AC_SUBST([ndctl_keysdir])
 AC_SUBST([ndctl_keysreadme])
 
+AC_CHECK_HEADERS([iniparser.h],,[
+		  AC_MSG_ERROR([iniparser.h not found, install iniparser-devel, libiniparser-dev, or so])
+		 ])
+
 my_CFLAGS="\
 -Wall \
 -Wchar-subscripts \
diff --git a/Makefile.am b/Makefile.am
index 60a1998..c547459 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -70,6 +70,8 @@ noinst_LIBRARIES += libutil.a
 libutil_a_SOURCES = \
 	util/parse-options.c \
 	util/parse-options.h \
+	util/parse-configs.c \
+	util/parse-configs.h \
 	util/usage.c \
 	util/size.c \
 	util/main.c \
diff --git a/util/parse-configs.h b/util/parse-configs.h
new file mode 100644
index 0000000..32783b5
--- /dev/null
+++ b/util/parse-configs.h
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2021, FUJITSU LIMITED. ALL rights reserved.
+
+#include <dirent.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <util/util.h>
+
+enum parse_conf_type {
+	CONFIG_STRING,
+	CONFIG_END,
+	MONITOR_CALLBACK,
+};
+
+int filter_conf_files(const struct dirent *dir);
+
+struct config;
+typedef int parse_conf_cb(const struct config *, const char *config_file);
+
+struct config {
+	enum parse_conf_type type;
+	const char *key;
+	void *value;
+	void *defval;
+	parse_conf_cb *callback;
+};
+
+#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v )
+
+#define CONF_END() { .type = CONFIG_END }
+#define CONF_STR(k,v,d) \
+	{ .type = CONFIG_STRING, .key = (k), .value = check_vtype(v, const char **), .defval = (d) }
+#define CONF_MONITOR(k,f) \
+	{ .type = MONITOR_CALLBACK, .key = (k), .callback = (f)}
+
+int parse_configs_prefix(const char *config_path, const char *prefix,
+			 const struct config *configs);
diff --git a/util/parse-configs.c b/util/parse-configs.c
new file mode 100644
index 0000000..61352d8
--- /dev/null
+++ b/util/parse-configs.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2021, FUJITSU LIMITED. ALL rights reserved.
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <iniparser/iniparser.h>
+#include <sys/stat.h>
+#include <util/parse-configs.h>
+#include <util/strbuf.h>
+
+int filter_conf_files(const struct dirent *dir)
+{
+	if (!dir)
+		return 0;
+
+	if (dir->d_type == DT_REG) {
+		const char *ext = strrchr(dir->d_name, '.');
+
+		if ((!ext) || (ext == dir->d_name))
+			return 0;
+		if (strcmp(ext, ".conf") == 0)
+			return 1;
+	}
+
+	return 0;
+}
+
+static void set_str_val(const char **value, const char *val)
+{
+	struct strbuf buf = STRBUF_INIT;
+	size_t len = *value ? strlen(*value) : 0;
+
+	if (!val)
+		return;
+
+	if (len) {
+		strbuf_add(&buf, *value, len);
+		strbuf_addstr(&buf, " ");
+	}
+	strbuf_addstr(&buf, val);
+	*value = strbuf_detach(&buf, NULL);
+}
+
+static int parse_config_file(const char *config_file,
+			const struct config *configs)
+{
+	dictionary *dic;
+
+	if ((configs->type == MONITOR_CALLBACK) &&
+			(strcmp(config_file, configs->key) == 0))
+		return configs->callback(configs, configs->key);
+
+	dic = iniparser_load(config_file);
+	if (!dic)
+		return -errno;
+
+	for (; configs->type != CONFIG_END; configs++) {
+		switch (configs->type) {
+		case CONFIG_STRING:
+			set_str_val((const char **)configs->value,
+					iniparser_getstring(dic,
+					configs->key, configs->defval));
+			break;
+		case MONITOR_CALLBACK:
+		case CONFIG_END:
+			break;
+		}
+	}
+
+	iniparser_freedict(dic);
+	return 0;
+}
+
+int parse_configs_prefix(const char *config_path, const char *prefix,
+			 const struct config *configs)
+{
+	const char *config_file = NULL;
+	struct dirent **namelist;
+	int rc, count;
+
+	if (configs->type == MONITOR_CALLBACK)
+		return parse_config_file(config_path, configs);
+
+	count = scandir(config_path, &namelist, filter_conf_files, alphasort);
+	if (count == -1)
+		return -errno;
+
+	while (count--) {
+		char *conf_abspath;
+
+		config_file = namelist[count]->d_name;
+		rc = asprintf(&conf_abspath, "%s/%s", config_path, config_file);
+		if (rc < 0)
+			return -ENOMEM;
+
+		rc = parse_config_file(conf_abspath, configs);
+
+		free(conf_abspath);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am
index a63b1e0..afdd03c 100644
--- a/ndctl/Makefile.am
+++ b/ndctl/Makefile.am
@@ -56,7 +56,8 @@ ndctl_LDADD =\
 	../libutil.a \
 	$(UUID_LIBS) \
 	$(KMOD_LIBS) \
-	$(JSON_LIBS)
+	$(JSON_LIBS) \
+	-liniparser
 
 if ENABLE_KEYUTILS
 ndctl_LDADD += -lkeyutils
-- 
2.33.1


  reply	other threads:[~2021-12-10 22:34 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-10 22:34 [ndctl PATCH v3 00/11] Policy based reconfiguration for daxctl Vishal Verma
2021-12-10 22:34 ` Vishal Verma [this message]
2021-12-16 21:42   ` [ndctl PATCH v3 01/11] ndctl, util: add parse-configs helper Dan Williams
2021-12-17 21:31     ` Verma, Vishal L
2021-12-21 12:54   ` Joao Martins
2021-12-10 22:34 ` [ndctl PATCH v3 02/11] ndctl: make ndctl support configuration files Vishal Verma
2021-12-16 21:47   ` Dan Williams
2021-12-10 22:34 ` [ndctl PATCH v3 03/11] ndctl, config: add the default ndctl configuration file Vishal Verma
2021-12-10 22:34 ` [ndctl PATCH v3 04/11] ndctl, monitor: refator monitor for supporting multiple config files Vishal Verma
2021-12-10 22:34 ` [ndctl PATCH v3 05/11] ndctl: Update ndctl.spec.in for 'ndctl.conf' Vishal Verma
2021-12-10 22:34 ` [ndctl PATCH v3 06/11] daxctl: Documentation updates for persistent reconfiguration Vishal Verma
2021-12-10 22:34 ` [ndctl PATCH v3 07/11] daxctl: add basic config parsing support Vishal Verma
2021-12-16 22:37   ` Dan Williams
2021-12-10 22:34 ` [ndctl PATCH v3 08/11] util/parse-configs: add a key/value search helper Vishal Verma
2021-12-16 22:44   ` Dan Williams
2021-12-10 22:34 ` [ndctl PATCH v3 09/11] daxctl/device.c: add an option for getting params from a config file Vishal Verma
2021-12-16 22:45   ` Dan Williams
2021-12-10 22:34 ` [ndctl PATCH v3 10/11] daxctl: add systemd service and udev rule for automatic reconfiguration Vishal Verma
2021-12-16 23:03   ` Dan Williams
2021-12-10 22:34 ` [ndctl PATCH v3 11/11] daxctl: add and install an example config file Vishal Verma

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211210223440.3946603-2-vishal.l.verma@intel.com \
    --to=vishal.l.verma@intel.com \
    --cc=dan.j.williams@intel.com \
    --cc=fenghua.hu@intel.com \
    --cc=nvdimm@lists.linux.dev \
    --cc=qi.fuli@fujitsu.com \
    --cc=qi.fuli@jp.fujitsu.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.