[PATCH BlueZ 7/9] mesh: Implement config read/write for mesh json format

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This adds implementation of
mesh_config_create_config(), mesh_config_release_config(),
mesh_config_get_config(), mesh_config_get_config_backup(),
mesh_config_restore_backup() and mesh_config_save_config()
for the JSON based node configuration storage.
---
 mesh/mesh-config-json.c | 171 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 171 insertions(+)

diff --git a/mesh/mesh-config-json.c b/mesh/mesh-config-json.c
index 5ca086ad0..3c65b3846 100644
--- a/mesh/mesh-config-json.c
+++ b/mesh/mesh-config-json.c
@@ -22,9 +22,14 @@
 #endif
 
 #define _GNU_SOURCE
+
+#include <dirent.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <ftw.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <ell/ell.h>
 #include <json-c/json.h>
@@ -35,6 +40,10 @@
 
 #define CHECK_KEY_IDX_RANGE(x) (((x) >= 0) && ((x) <= 4095))
 
+static const char *cfg_name = "/node.json";
+static const char *bak_name = "/node.json.bak";
+static const char *tmp_name = "/node.json.tmp";
+
 static bool get_int(json_object *jobj, const char *keyword, int *value)
 {
 	json_object *jvalue;
@@ -1827,3 +1836,165 @@ bool mesh_config_model_sub_del_all(void *cfg, uint16_t addr, uint32_t mod_id,
 
 	return delete_model_property(jnode, addr, mod_id, vendor, "subscribe");
 }
+
+static char *create_filename(const char *dir, const char *fname)
+{
+	size_t path_len = strlen(dir) + strlen(fname);
+
+	if (path_len + 1 >= PATH_MAX)
+		return NULL;
+
+	return l_strdup_printf("%s%s", dir, fname);
+}
+
+static void *get_node_config(const char *dir, const char *fname)
+{
+	int fd;
+	char *str = NULL, *fname_full;
+	struct stat st;
+	ssize_t sz;
+	json_object *jconfig = NULL;
+
+	fname_full = create_filename(dir, fname);
+	if (!fname)
+		return NULL;
+
+	l_info("Loading configuration from %s", fname_full);
+
+	fd = open(fname_full, O_RDONLY);
+	if (fd < 0)
+		goto done;
+
+	if (fstat(fd, &st) == -1)
+		goto done;
+
+	str = (char *) l_new(char, st.st_size + 1);
+	if (!str)
+		goto done;
+
+	sz = read(fd, str, st.st_size);
+	if (sz != st.st_size) {
+		l_error("Failed to read configuration file %s", fname_full);
+		goto done;
+	}
+
+	jconfig = json_tokener_parse(str);
+
+done:
+	if (fd >= 0)
+		close(fd);
+
+	l_free(str);
+	l_free(fname_full);
+
+	return jconfig;
+}
+
+void *mesh_config_get_config(const char *dir)
+{
+	if (!dir)
+		return NULL;
+
+	return get_node_config(dir, cfg_name);
+}
+
+void *mesh_config_get_config_backup(const char *dir)
+{
+	if (!dir)
+		return NULL;
+
+	return get_node_config(cfg_name, bak_name);
+}
+
+bool mesh_config_restore_backup(const char *dir)
+{
+	char *fname_cfg = NULL, *fname_bak = NULL;
+	bool res = false;
+
+	fname_cfg = create_filename(dir, cfg_name);
+	fname_bak = create_filename(dir, bak_name);
+
+	if (fname_cfg && fname_bak) {
+		remove(fname_cfg);
+		rename(fname_bak, fname_cfg);
+		res = true;
+	}
+
+	l_free(fname_bak);
+	l_free(fname_cfg);
+
+	return res;
+}
+
+static bool save_config(void *cfg, const char *fname)
+{
+	FILE *outfile;
+	const char *str;
+	bool result = false;
+	json_object *jnode = cfg;
+
+	outfile = fopen(fname, "w");
+
+	if (!outfile)
+		return false;
+
+	str = json_object_to_json_string_ext(jnode, JSON_C_TO_STRING_PRETTY);
+
+	if (fwrite(str, sizeof(char), strlen(str), outfile) < strlen(str))
+		l_warn("Incomplete write of mesh configuration");
+	else
+		result = true;
+
+	fclose(outfile);
+
+	return result;
+}
+
+void *mesh_config_create_config(void)
+{
+	return json_object_new_object();
+}
+
+void mesh_config_release_config(void *cfg)
+{
+	json_object *jnode = cfg;
+
+	if (!cfg)
+		return;
+
+	json_object_put(jnode);
+}
+
+bool mesh_config_save_config(const char *dir, void *cfg)
+{
+	char *fname_cfg;
+	char *fname_bak;
+	char *fname_tmp;
+	bool result = false;
+
+	fname_cfg = create_filename(dir, cfg_name);
+	fname_bak = create_filename(dir, bak_name);
+	fname_tmp = create_filename(dir, tmp_name);
+
+	if (!fname_cfg || !fname_bak || !fname_tmp)
+		goto done;
+
+	result = save_config(cfg, fname_tmp);
+
+	if (result) {
+		remove(fname_bak);
+		rename(fname_cfg, fname_bak);
+		rename(fname_tmp, fname_cfg);
+	} else {
+		l_error("Failed to save configuration to %s", fname_tmp);
+	}
+
+	remove(fname_tmp);
+
+done:
+	l_free(fname_cfg);
+	l_free(fname_bak);
+	l_free(fname_tmp);
+
+	return result;
+}
-- 
2.21.0




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux