libgluonutil: merge domain and site configs

[Matthias Schiffer: rebase and simplify]
This commit is contained in:
lemoer 2017-10-28 17:05:53 +02:00 committed by Matthias Schiffer
parent a2f45d0d32
commit 146787fa5c
No known key found for this signature in database
GPG Key ID: 16EF3F64CB201D9C
4 changed files with 108 additions and 4 deletions

View File

@ -16,7 +16,7 @@ define Package/libgluonutil
SECTION:=libs
CATEGORY:=Libraries
TITLE:=Gluon utility library
DEPENDS:=+libjson-c
DEPENDS:=+libjson-c +libuci
endef
CMAKE_OPTIONS += \

View File

@ -6,7 +6,7 @@ set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS _GNU_SOURCE)
add_library(gluonutil SHARED libgluonutil.c)
set_property(TARGET gluonutil PROPERTY COMPILE_FLAGS "-Wall -std=c99")
target_link_libraries(gluonutil json-c)
target_link_libraries(gluonutil json-c uci)
install(TARGETS gluonutil
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib

View File

@ -27,11 +27,44 @@
#include "libgluonutil.h"
#include <json-c/json.h>
#include <uci.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
/**
* Merges two JSON objects
*
* Both objects are consumed. On conflicts, object b will be preferred.
*/
static struct json_object * merge_json(struct json_object *a, struct json_object *b) {
if (!json_object_is_type(a, json_type_object) || !json_object_is_type(b, json_type_object)) {
json_object_put(a);
return b;
}
json_object *m = json_object_new_object();
json_object_object_foreach(a, key_a, val_a)
json_object_object_add(m, key_a, json_object_get(val_a));
json_object_put(a);
json_object_object_foreach(b, key_b, val_b) {
struct json_object *val_m;
if (json_object_object_get_ex(m, key_b, &val_m))
val_m = merge_json(json_object_get(val_m), json_object_get(val_b));
else
val_m = json_object_get(val_b);
json_object_object_add(m, key_b, val_m);
}
json_object_put(b);
return m;
}
char * gluonutil_read_line(const char *filename) {
FILE *f = fopen(filename, "r");
@ -141,6 +174,75 @@ bool gluonutil_get_node_prefix6(struct in6_addr *prefix) {
}
struct json_object * gluonutil_load_site_config(void) {
return json_object_from_file("/lib/gluon/site.json");
bool gluonutil_has_domains(void) {
return (access("/lib/gluon/domains/", F_OK) == 0);
}
char * gluonutil_get_domain(void) {
if (!gluonutil_has_domains())
return NULL;
char *ret = NULL;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
goto uci_fail;
ctx->flags &= ~UCI_FLAG_STRICT;
struct uci_package *p;
if (uci_load(ctx, "gluon", &p))
goto uci_fail;
struct uci_section *s = uci_lookup_section(ctx, p, "core");
if (!s)
goto uci_fail;
const char *domain_code = uci_lookup_option_string(ctx, s, "domain");
if (!domain_code)
goto uci_fail;
ret = strdup(domain_code);
uci_fail:
if (ctx)
uci_free_context(ctx);
return ret;
}
struct json_object * gluonutil_load_site_config(void) {
char *domain_code = NULL;
struct json_object *site = NULL, *domain = NULL;
site = json_object_from_file("/lib/gluon/site.json");
if (!site)
return NULL;
if (!gluonutil_has_domains())
return site;
domain_code = gluonutil_get_domain();
if (!domain_code)
goto err;
{
const char *domain_path_fmt = "/lib/gluon/domains/%s.json";
char domain_path[strlen(domain_path_fmt) + strlen(domain_code)];
snprintf(domain_path, sizeof(domain_path), domain_path_fmt, domain_code);
free(domain_code);
domain = json_object_from_file(domain_path);
}
if (!domain)
goto err;
return merge_json(site, domain);
err:
json_object_put(site);
free(domain_code);
return NULL;
}

View File

@ -40,6 +40,8 @@ bool gluonutil_get_node_prefix6(struct in6_addr *prefix);
struct json_object * gluonutil_wrap_string(const char *str);
struct json_object * gluonutil_wrap_and_free_string(char *str);
bool gluonutil_has_domains(void);
char * gluonutil_get_domain(void);
struct json_object * gluonutil_load_site_config(void);
#endif /* _LIBGLUON_LIBGLUON_H_ */