diff --git a/package/libgluonutil/Makefile b/package/libgluonutil/Makefile index 489a9ba9..2536727c 100644 --- a/package/libgluonutil/Makefile +++ b/package/libgluonutil/Makefile @@ -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 += \ diff --git a/package/libgluonutil/src/CMakeLists.txt b/package/libgluonutil/src/CMakeLists.txt index 7df17b1a..41dd038a 100644 --- a/package/libgluonutil/src/CMakeLists.txt +++ b/package/libgluonutil/src/CMakeLists.txt @@ -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 diff --git a/package/libgluonutil/src/libgluonutil.c b/package/libgluonutil/src/libgluonutil.c index db46b9c9..0f4bfe4a 100644 --- a/package/libgluonutil/src/libgluonutil.c +++ b/package/libgluonutil/src/libgluonutil.c @@ -27,11 +27,44 @@ #include "libgluonutil.h" #include +#include #include #include #include #include +#include +/** + * 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; } diff --git a/package/libgluonutil/src/libgluonutil.h b/package/libgluonutil/src/libgluonutil.h index b2f90d69..39b253ba 100644 --- a/package/libgluonutil/src/libgluonutil.h +++ b/package/libgluonutil/src/libgluonutil.h @@ -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_ */