From 9d8e1fe4857c1c3e8f1a2e2ae59ef9c4790adb39 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 10 Jun 2013 14:00:02 +0200 Subject: [PATCH] blob: add uci<->blob conversion library code Signed-off-by: Felix Fietkau --- CMakeLists.txt | 5 +- blob.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++++ uci_blob.h | 41 ++++++++++ 3 files changed, 255 insertions(+), 2 deletions(-) create mode 100644 blob.c create mode 100644 uci_blob.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a72012..e846ceb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,9 +13,10 @@ CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/uci_config.h.in ${CMAKE_SOURCE_DIR}/uci_conf INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) -SET(LIB_SOURCES libuci.c file.c util.c delta.c parse.c) +SET(LIB_SOURCES libuci.c file.c util.c delta.c parse.c blob.c) ADD_LIBRARY(uci SHARED ${LIB_SOURCES}) +TARGET_LINK_LIBRARIES(uci ubox) SET_TARGET_PROPERTIES(uci PROPERTIES OUTPUT_NAME uci) ADD_EXECUTABLE(cli cli.c) @@ -29,7 +30,7 @@ TARGET_LINK_LIBRARIES(ucimap-example uci ucimap) ADD_SUBDIRECTORY(lua) -INSTALL(FILES uci.h uci_config.h ucimap.h +INSTALL(FILES uci.h uci_config.h uci_blob.h ucimap.h DESTINATION include ) diff --git a/blob.c b/blob.c new file mode 100644 index 0000000..6fdaa47 --- /dev/null +++ b/blob.c @@ -0,0 +1,211 @@ +/* + * blob.c - uci <-> blobmsg conversion layer + * Copyright (C) 2012-2013 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ +#include +#include +#include + +#include +#include "uci.h" +#include "uci_blob.h" + +static bool +uci_attr_to_blob(struct blob_buf *b, const char *str, + const char *name, enum blobmsg_type type) +{ + char *err; + int intval; + + switch (type) { + case BLOBMSG_TYPE_STRING: + blobmsg_add_string(b, name, str); + break; + case BLOBMSG_TYPE_BOOL: + if (!strcmp(str, "true") || !strcmp(str, "1")) + intval = 1; + else if (!strcmp(str, "false") || !strcmp(str, "0")) + intval = 0; + else + return false; + + blobmsg_add_u8(b, name, intval); + break; + case BLOBMSG_TYPE_INT32: + intval = strtol(str, &err, 0); + if (*err) + return false; + + blobmsg_add_u32(b, name, intval); + break; + default: + return false; + } + return true; +} + +static void +uci_array_to_blob(struct blob_buf *b, struct uci_option *o, + enum blobmsg_type type) +{ + struct uci_element *e; + char *str, *next, *word; + + if (o->type == UCI_TYPE_LIST) { + uci_foreach_element(&o->v.list, e) { + uci_attr_to_blob(b, e->name, NULL, type); + } + return; + } + + str = strdup(o->v.string); + next = str; + + while ((word = strsep(&next, " \t")) != NULL) { + if (!*word) + continue; + + uci_attr_to_blob(b, word, NULL, type); + } + + free(str); +} + +static int +__uci_to_blob(struct blob_buf *b, struct uci_section *s, + const struct uci_blob_param_list *p) +{ + const struct blobmsg_policy *attr = NULL; + struct uci_element *e; + struct uci_option *o; + void *array; + int i, ret = 0; + + uci_foreach_element(&s->options, e) { + for (i = 0; i < p->n_params; i++) { + attr = &p->params[i]; + if (!strcmp(attr->name, e->name)) + break; + } + + if (i == p->n_params) + continue; + + o = uci_to_option(e); + + if (attr->type == BLOBMSG_TYPE_ARRAY) { + if (!p->info) + continue; + + array = blobmsg_open_array(b, attr->name); + uci_array_to_blob(b, o, p->info[i].type); + blobmsg_close_array(b, array); + ret++; + continue; + } + + if (o->type == UCI_TYPE_LIST) + continue; + + ret += uci_attr_to_blob(b, o->v.string, attr->name, attr->type); + } + + return ret; +} + +int +uci_to_blob(struct blob_buf *b, struct uci_section *s, + const struct uci_blob_param_list *p) +{ + int ret = 0; + int i; + + ret += __uci_to_blob(b, s, p); + for (i = 0; i < p->n_next; i++) + ret += uci_to_blob(b, s, p->next[i]); + + return ret; +} + +bool +uci_blob_diff(struct blob_attr **tb1, struct blob_attr **tb2, + const struct uci_blob_param_list *config, unsigned long *diff) +{ + bool ret = false; + int i; + + for (i = 0; i < config->n_params; i++) { + if (!tb1[i] && !tb2[i]) + continue; + + if (!!tb1[i] != !!tb2[i]) + goto mark; + + if (blob_len(tb1[i]) != blob_len(tb2[i])) + goto mark; + + if (memcmp(tb1[i], tb2[i], blob_raw_len(tb1[i])) != 0) + goto mark; + + continue; + +mark: + ret = true; + if (diff) + bitfield_set(diff, i); + else + return ret; + } + + return ret; +} + + +static bool +__uci_blob_check_equal(struct blob_attr *c1, struct blob_attr *c2, + const struct uci_blob_param_list *config) +{ + struct blob_attr **tb1, **tb2; + + if (!!c1 ^ !!c2) + return false; + + if (!c1 && !c2) + return true; + + tb1 = alloca(config->n_params * sizeof(struct blob_attr *)); + blobmsg_parse(config->params, config->n_params, tb1, + blob_data(c1), blob_len(c1)); + + tb2 = alloca(config->n_params * sizeof(struct blob_attr *)); + blobmsg_parse(config->params, config->n_params, tb2, + blob_data(c2), blob_len(c2)); + + return !uci_blob_diff(tb1, tb2, config, NULL); +} + +bool +uci_blob_check_equal(struct blob_attr *c1, struct blob_attr *c2, + const struct uci_blob_param_list *config) +{ + int i; + + if (!__uci_blob_check_equal(c1, c2, config)) + return false; + + for (i = 0; i < config->n_next; i++) { + if (!__uci_blob_check_equal(c1, c2, config->next[i])) + return false; + } + + return true; +} diff --git a/uci_blob.h b/uci_blob.h new file mode 100644 index 0000000..d2294d8 --- /dev/null +++ b/uci_blob.h @@ -0,0 +1,41 @@ +/* + * blob.c - uci <-> blobmsg conversion layer + * Copyright (C) 2012-2013 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ +#ifndef __UCI_BLOB_H +#define __UCI_BLOB_H + +#include +#include "uci.h" + +struct uci_blob_param_info { + enum blobmsg_type type; +}; + +struct uci_blob_param_list { + int n_params; + const struct blobmsg_policy *params; + const struct uci_blob_param_info *info; + + int n_next; + const struct uci_blob_param_list *next[]; +}; + +int uci_to_blob(struct blob_buf *b, struct uci_section *s, + const struct uci_blob_param_list *p); +bool uci_blob_check_equal(struct blob_attr *c1, struct blob_attr *c2, + const struct uci_blob_param_list *config); +bool uci_blob_diff(struct blob_attr **tb1, struct blob_attr **tb2, + const struct uci_blob_param_list *config, + unsigned long *diff_bits); + +#endif -- 2.30.2