From patchwork Wed Nov 14 16:02:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Babic X-Patchwork-Id: 997813 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=googlegroups.com (client-ip=2a00:1450:4864:20::23e; helo=mail-lj1-x23e.google.com; envelope-from=swupdate+bncbcxploxj6ikrbiuowhpqkgqehn3vykq@googlegroups.com; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.b="nRkbHMbm"; dkim-atps=neutral Received: from mail-lj1-x23e.google.com (mail-lj1-x23e.google.com [IPv6:2a00:1450:4864:20::23e]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42w8Qt1rD2z9sB7 for ; Thu, 15 Nov 2018 03:02:46 +1100 (AEDT) Received: by mail-lj1-x23e.google.com with SMTP id e8-v6sf5965865ljg.22 for ; Wed, 14 Nov 2018 08:02:46 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1542211363; cv=pass; d=google.com; s=arc-20160816; b=TGgiMI6sg8XXakWLr57rAQwnEcym7WArU7Uv3DxA2meE3mX6WGvJE0G0TwcvApz5qV PirMXTRkm8mA+EDEKO9f2qAlluq4A7ijJBh1tlD325OPRWGQvEEGCCqkAyaLrzq395bD 5Ed7g2kvaCGWsbOmclKEJkoeNyHDiXaLXbdJMPaTQuH6/ShNscEznlPljLl28sTRcyIX ATyOCEr2q8va/Qy3L6og64KZoyyuECDO90Tj/i4tV4VZ1xm4eQtSQ7Ch4m30ntpGZyhu JDUiA6o/uHcoQdPsc1+lk+PMTgcizkZBgj7IyvosFHQO6JSnDzKPACd6kcBE/szZ5bPL OWhg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:mime-version:sender:dkim-signature; bh=H9dKpJnsbUYHym93tjNc0rG+mlk2+d5CnZNZYuc2Sx0=; b=WIzhnYpOZg+ttOTBPV2dP1m4eLuCV8J79pnHqstiNbDoKYfAEoY+vuqV36WNlOKtfG 4JemiFlCdiBqMPd2WEg7WfyEts/GZz/0eOqxeBtBN3+pHHkbjt4GuDZPfHZCi+KBLYA7 eUdSEv++kcMv1/+34KcY3329LY7xKrEYlU/wGEfBpVVG3nWl2XPsdX2/EMpNLPrSPVtk jU+yrKNqc9T1oDZOkDouieOJbmVcJ738cwGnf7DSUmq+s4tI267YqDTFy875dAzH9Z4P 364F/TdHPu0ZccclwWIlgzkQunb2joMYJlp7K8msveza5UXc++qgG9xmUhLUt1xKN0N4 9yjg== ARC-Authentication-Results: i=2; gmr-mx.google.com; spf=neutral (google.com: 212.18.0.9 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20161025; h=sender:mime-version:from:to:cc:subject:date:message-id:in-reply-to :references:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=H9dKpJnsbUYHym93tjNc0rG+mlk2+d5CnZNZYuc2Sx0=; b=nRkbHMbm9ZGRQdRvbGMjWQtCIg90Ke2wH4wbvjczGUBux3CsGLF2lQ3n6ft80tfy2t DNdqeP10GjGJBED9f2EdltFt4+lRMQG4uoEF0F6EuMMXu85d8ePGXIbyj61LCTPCNUAI zmtI6/T6uVLNp6xOh7q8IFyyMNbV0CDisfb2aYoVJb/TPd/WGL0RfewCK7WlJ1e3Twzw 6OR0QdAKgY/clSvv2xgj2M2OH6Ee443ZNVfQ6tw9ADSuX3+Q/uJd237wsKzBv2Mx/EA+ tbwS2/m9c4u6IeiScrs5MayFRm+bs2OX31W9j2jEQdc//E2rGLI04iR6gn4gKtaUuIoU E4SQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=sender:x-gm-message-state:mime-version:from:to:cc:subject:date :message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=H9dKpJnsbUYHym93tjNc0rG+mlk2+d5CnZNZYuc2Sx0=; b=QmcaZhoIIjk/N9rAodeqJTATsTVWpvTu6nyQ4OM9nPydVb8xXICOPOeD1SDsfpZqIW JGr5hK6cQ5S/8LkdLk8c3NChRf9WXvP5FzCeJKFz3aUaD7a2dsDfiO+5xeF+sxSSbJqE 9V6M9JVK5+JrDSos/1XRzvcFfm43biSItxQ8CCpUS45Ir5c9qSaYtoEOBUbcvAL3fAae IjtoOslqlCtfpZdtDy1UTdunS23BIHwUyiEAvlwj0Ik0LZyDvPwH4yK6ukZrZ0ZMyo3j sKoeO1E5IAvtfSgYSOfjlWKxyb+hYx3HYynHh7Jfvsy7HFIO6YIhZ++kRBXfA37Bk9w5 oAFQ== Sender: swupdate@googlegroups.com X-Gm-Message-State: AGRZ1gK2JskaMyrvwurcXRGMwtJoW/AwfzQsK6zLgdDSu1YPUz2e0kyF jDXBtsj/OcZccBZUqab97M0= X-Google-Smtp-Source: AJdET5eb1CmqrDZpXQeD2ZSHCtukIN2o5FlTt0fM1uJSTyr0XJG6QxYANS+2xlPDTAMewxQZxXwnvQ== X-Received: by 2002:a19:d819:: with SMTP id p25mr13980lfg.6.1542211362902; Wed, 14 Nov 2018 08:02:42 -0800 (PST) MIME-Version: 1.0 X-BeenThere: swupdate@googlegroups.com Received: by 2002:a2e:9d05:: with SMTP id t5-v6ls1341955lji.23.gmail; Wed, 14 Nov 2018 08:02:42 -0800 (PST) X-Received: by 2002:a2e:42ce:: with SMTP id h75-v6mr268178ljf.27.1542211362229; Wed, 14 Nov 2018 08:02:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542211362; cv=none; d=google.com; s=arc-20160816; b=sG1CIOB5Iq3cn04A3ctcSaKy7W/tbgCXpYmunDimvfCf3ejCqZxFxZTlKM+p/OtfhM WJFT/LnLpAKOhfY1BsAIzyaOOmLmBsiGBF2WDyoNq+CC8PaY/alLpbEcUQ4LYrc4bNEz NIt/gpP2/e55v3jFdAwuZZ6f6ntwbwHjCAykrl6Pc0BLxc2r6K8WRsXILCVTG9dG7b2I LJa5bvBoi1i2XUAOzdwCA1eHcEhADwQFcSJUSSdKPESjCSrYhCsZ0roWWmRLD7B9hiTv ZVfo3xqz8135xcvsmsXo3oywn54Sd+039RQyIYHCncLm5PBJoIvxY2hzWFPid4VKjSOT Xm5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from; bh=IvAMmCW2EnzjteE8wKbLahYU9rJAZlttqPPr16FkjgA=; b=uWXQWrpnMdw9nG+87WHM7la6YWJkcvvXAsN5zVuIpEpjwPmD1clRh96N5iZnSBM3mq 7ySvDIyAHkVM4adFT7Q1iB8ZqC61yoXFBn5P6q6Tr57ppWsrxhxMNz+I822cRg5rVyhB sV8SqjqKeT5NOi30bMdWUQU4tf9+OtbcC6G2M8FSRFKvPjIEEuxjrwDTewHTKu9nd3vQ zA/eAqblDs6HJ7ivvoclrdduIKXKJqmxV7RPpJkUR0sjIJ/HN2y6JKbGROZO4GjYUWwt 2ky4xG6WtZFRUi67uO3rRQZSslbnXaaRqWqDDb7ZFm92XTxjBG3DihbBidd5E/1obcyu vpxw== ARC-Authentication-Results: i=1; gmr-mx.google.com; spf=neutral (google.com: 212.18.0.9 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de Received: from mail-out.m-online.net (mail-out.m-online.net. [212.18.0.9]) by gmr-mx.google.com with ESMTPS id t5-v6si913999lje.3.2018.11.14.08.02.42 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Nov 2018 08:02:42 -0800 (PST) Received-SPF: neutral (google.com: 212.18.0.9 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) client-ip=212.18.0.9; Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 42w8Qn4P8Hz1r01W; Wed, 14 Nov 2018 17:02:41 +0100 (CET) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 42w8Qn4Cpzz1qsJK; Wed, 14 Nov 2018 17:02:41 +0100 (CET) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id k1-GzhlCE37a; Wed, 14 Nov 2018 17:02:35 +0100 (CET) Received: from babic.homelinux.org (host-88-217-136-221.customer.m-online.net [88.217.136.221]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPS; Wed, 14 Nov 2018 17:02:35 +0100 (CET) Received: from localhost (mail.babic.homelinux.org [127.0.0.1]) by babic.homelinux.org (Postfix) with ESMTP id A79B94540471; Wed, 14 Nov 2018 17:02:34 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at babic.homelinux.org Received: from babic.homelinux.org ([127.0.0.1]) by localhost (mail.babic.homelinux.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id uR6N5abS1S8M; Wed, 14 Nov 2018 17:02:30 +0100 (CET) Received: from papero.fritz.box (papero.fritz.box [192.168.178.132]) by babic.homelinux.org (Postfix) with ESMTP id 23399454065E; Wed, 14 Nov 2018 17:02:24 +0100 (CET) From: Stefano Babic To: swupdate@googlegroups.com Cc: Stefano Babic Subject: [swupdate] [PATCH v2 4/5] parser: introduce links in sw-description Date: Wed, 14 Nov 2018 17:02:20 +0100 Message-Id: <20181114160221.18242-5-sbabic@denx.de> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181114160221.18242-1-sbabic@denx.de> References: <20181114160221.18242-1-sbabic@denx.de> X-Original-Sender: sbabic@denx.de X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 212.18.0.9 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de Precedence: list Mailing-list: list swupdate@googlegroups.com; contact swupdate+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: swupdate@googlegroups.com X-Google-Group-Id: 605343134186 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , There are a lot of use cases when special configurations are needed. Current sw-description requires that each entry is full described and does not allow to factorize some parts. This means that in most cases entries are duplicated multiple times even if changes are minimal between sections. This patch introduce links for the root node. If the node is a string instead of an object, it is interpreted as new link to be follow. The parser tries to follow the links recursively (a maximum number of 10 links is introduce to avoid deadlocks). The patch factorizes how to call find_node() for the specific parser. Instead of using two mechanism (a formatted sting and an array of strings) for libconfig and json, use an array of strings for both. Signed-off-by: Stefano Babic --- Changes in v2: None corelib/parsing_library.c | 137 ++++++++++++----- corelib/parsing_library_libconfig.c | 71 +++++++++ corelib/parsing_library_libjson.c | 37 +++++ include/parselib.h | 10 +- parser/parser.c | 219 +++++++++++++--------------- 5 files changed, 320 insertions(+), 154 deletions(-) diff --git a/corelib/parsing_library.c b/corelib/parsing_library.c index 00463a7..fd451ac 100644 --- a/corelib/parsing_library.c +++ b/corelib/parsing_library.c @@ -153,6 +153,39 @@ int exist_field_string(parsertype p, void *e, const char *path) return 0; } +void *find_root(parsertype p, void *root, const char **nodes) +{ + + switch (p) { + case LIBCFG_PARSER: + return find_root_libconfig((config_t *)root, nodes, MAX_LINKS_DEPTH); + + case JSON_PARSER: + return find_root_json((json_object *)root, nodes, MAX_LINKS_DEPTH); + default: + (void)root; + (void)nodes; + } + + return NULL; +} + +void *get_node(parsertype p, void *root, const char **nodes) +{ + + switch (p) { + case LIBCFG_PARSER: + return get_node_libconfig((config_t *)root, nodes); + case JSON_PARSER: + return get_node_json((json_object *)root, nodes); + default: + (void)root; + (void)nodes; + } + + return NULL; +} + void get_hash_value(parsertype p, void *elem, unsigned char *hash) { char hash_ascii[80]; @@ -165,52 +198,86 @@ void get_hash_value(parsertype p, void *elem, unsigned char *hash) bool set_find_path(const char **nodes, const char *newpath, char **tmp) { - unsigned int nleading; - char **iter, **paths; - unsigned int count = count_string_array(nodes); - unsigned int countpaths; - - if (!newpath) - return false; + char **paths; + unsigned int count; + char *saveptr; + char *token, *ref; + bool first = true; + int allocstr = 0; /* - * Check if we have to traverse back + * Include of files is not supported, + * each reference should start with '#' */ - for (nleading = 0; newpath[nleading] == '.'; nleading++); - - /* - * delimiter at the beginning indicates a relative path - * exactly as in Unix, that mean .. for the upper directory - * .. = parent - * .... = parent of parent - * The number of leading "." must be even, else - * it is a malformed path - */ - if (nleading % 2) + if (!newpath || (newpath[0] != '#') || (strlen(newpath) < 3)) return false; - nleading /= 2; - if ((count - nleading) <= 0) + ref = strdup(newpath); + if (!ref) { + ERROR("No memory: failed for %lu bytes", + strlen(newpath) + 1); return false; - - count -= nleading; - if (count > 0) count--; - - paths = string_split(newpath, '.'); + } /* - * check if there is enough space in nodes + * First find how many strings should be stored + * Each token is stored temporarily on the heap */ - countpaths = count_string_array((const char **)paths); - if (count + countpaths >= MAX_PARSED_NODES) + count = 0; + token = strtok_r(&ref[1], "/", &saveptr); + while (token) { + count++; + token = strtok_r(NULL, "/", &saveptr); + } + free(ref); /* string was changed, clean and copy again */ + + if (!count) + return false; + + paths = calloc(count + 1, sizeof(char*) * count); + if (!paths) { + ERROR("No memory: calloc failed for %lu bytes", + sizeof(char*) * count); + return false; + } + count = count_string_array(nodes); + ref = strdup(newpath); + if (!ref) { + ERROR("No memory: failed for %lu bytes", + strlen(newpath) + 1); + free(paths); return false; - if (!countpaths) - nodes[count++] = newpath; - else - for (iter = paths; *iter != NULL; iter++, count++) - nodes[count] = *iter; - nodes[count] = NULL; + } + + token = strtok_r(&ref[1], "/", &saveptr); + while (token) { + if (!strcmp(token, "..")) { + if (!count) { + free(ref); + free_string_array(paths); + return false; + } + count--; + } else if (strcmp(token, ".")) { + if (first) { + count = 0; + } + paths[allocstr] = strdup(token); + nodes[count++] = paths[allocstr++]; + paths[allocstr] = NULL; + nodes[count] = NULL; + if (count >= MAX_PARSED_NODES) { + ERROR("Big depth in link, giving up..."); + free_string_array(paths); + free(ref); + return false; + } + } + token = strtok_r(NULL, "/", &saveptr); + first = false; + } + free(ref); tmp = paths; return true; diff --git a/corelib/parsing_library_libconfig.c b/corelib/parsing_library_libconfig.c index 415116b..d3fc3c2 100644 --- a/corelib/parsing_library_libconfig.c +++ b/corelib/parsing_library_libconfig.c @@ -13,12 +13,34 @@ #include #include #include +#include #include "generated/autoconf.h" #include "bsdqueue.h" #include "util.h" #include "swupdate.h" #include "parselib.h" +static void path_libconfig(const char **nodes, char *root, unsigned int rootsize) +{ + const char **node; + int nbytes, left; + char *buf; + const char *concat; + bool first=true; + + root[0] = '\0'; + + for (node = nodes, buf = root, left = rootsize; *node != NULL; node++) { + concat = first ? "" : "."; + nbytes = snprintf(buf, left, "%s%s", concat, *node); + buf += nbytes; + left -= nbytes; + first = false; + if (left ==0) + break; + } +} + void get_value_libconfig(const config_setting_t *e, void *dest) { int type = config_setting_type(e); @@ -108,3 +130,52 @@ const char *get_field_string_libconfig(config_setting_t *e, const char *path) return NULL; } + +void *get_node_libconfig(config_t *cfg, const char **nodes) +{ + config_setting_t *setting; + char root[1024]; + + path_libconfig(nodes, root, sizeof(root)); + setting = config_lookup(cfg, root); + if (setting) + return setting; + + return NULL; +} + +void *find_root_libconfig(config_t *cfg, const char **nodes, unsigned int depth) +{ + config_setting_t *elem; + char root[1024]; + const char *ref; + char **tmp = NULL; + + /* + * check for deadlock links, block recursion + */ + if (!(--depth)) + return NULL; + + path_libconfig(nodes, root, sizeof(root)); + + /* + * If this is root node for the device, + * it is a group and lenght is not 0. + * If it is a link, follow it + */ + elem = config_lookup(cfg, root); + + if (elem && config_setting_is_group(elem) == CONFIG_TRUE) { + ref = get_field_string_libconfig(elem, "ref"); + if (ref) { + if (!set_find_path(nodes, ref, tmp)) + return NULL; + elem = find_root_libconfig(cfg, nodes, depth); + free_string_array(tmp); + } + } + + return elem; + +} diff --git a/corelib/parsing_library_libjson.c b/corelib/parsing_library_libjson.c index b1f5775..0322a4f 100644 --- a/corelib/parsing_library_libjson.c +++ b/corelib/parsing_library_libjson.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -179,4 +180,40 @@ char *json_get_data_url(json_object *json_root, const char *key) : strndup(json_object_get_string(json_data), MAX_URL_LENGTH); } +void *find_root_json(json_object *root, const char **nodes, unsigned int depth) +{ + json_object *node; + enum json_type type; + char **tmp = NULL; + const char *str; + + /* + * check for deadlock links, block recursion + */ + if (!(--depth)) + return false; + + node = find_json_recursive_node(root, nodes); + + if (node) { + type = json_object_get_type(node); + + if (type == json_type_object || type == json_type_array) { + str = get_field_string_json(node, "ref"); + if (str) { + if (!set_find_path(nodes, str, tmp)) + return NULL; + node = find_root_json(root, nodes, depth); + free_string_array(tmp); + } + } + } + return node; +} + +void *get_node_json(json_object *root, const char **nodes) +{ + return find_json_recursive_node(root, nodes); +} + diff --git a/include/parselib.h b/include/parselib.h index 2fca3b5..5cbc255 100644 --- a/include/parselib.h +++ b/include/parselib.h @@ -39,6 +39,8 @@ void *get_child_libconfig(void *e, const char *name); void iterate_field_libconfig(config_setting_t *e, iterate_callback cb, void *data); const char *get_field_string_libconfig(config_setting_t *e, const char *path); +void *find_root_libconfig(config_t *cfg, const char **nodes, unsigned int depth); +void *get_node_libconfig(config_t *cfg, const char **nodes); #else #define config_setting_get_elem(a,b) (NULL) @@ -49,6 +51,8 @@ const char *get_field_string_libconfig(config_setting_t *e, const char *path); #define get_child_libconfig(e, name) (NULL) #define iterate_field_libconfig(e, cb, data) { } #define get_field_cfg(e, path, dest) +#define find_root_libconfig(cfg, nodes, depth) (NULL) +#define get_node_libconfig(cfg, nodes) (NULL) #endif #ifdef CONFIG_JSON @@ -65,6 +69,8 @@ const char *json_get_value(struct json_object *json_root, const char *key); json_object *json_get_path_key(json_object *json_root, const char **json_path); char *json_get_data_url(json_object *json_root, const char *key); +void *find_root_json(json_object *root, const char **nodes, unsigned int depth); +void *get_node_json(json_object *root, const char **nodes); #else #define find_node_json(a, b, c) (NULL) @@ -75,6 +81,8 @@ char *json_get_data_url(json_object *json_root, const char *key); #define json_object_object_get_ex(a,b,c) (0) #define json_object_array_get_idx(a, b) (0) #define json_object_array_length(a) (0) +#define find_root_json(root, nodes, depth) (NULL) +#define get_node_json(root, nodes) (NULL) #endif typedef int (*settings_callback)(void *elem, void *data); @@ -90,7 +98,7 @@ void get_field(parsertype p, void *e, const char *path, void *dest); int exist_field_string(parsertype p, void *e, const char *path); void get_hash_value(parsertype p, void *elem, unsigned char *hash); void check_field_string(const char *src, char *dst, const size_t max_len); -bool find_root(parsertype p, void *root, const char **nodes); +void *find_root(parsertype p, void *root, const char **nodes); void *get_node(parsertype p, void *root, const char **nodes); bool set_find_path(const char **nodes, const char *newpath, char **tmp); diff --git a/parser/parser.c b/parser/parser.c index 19181d1..bc89b9d 100644 --- a/parser/parser.c +++ b/parser/parser.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -29,115 +30,125 @@ #define NODEROOT (!strlen(CONFIG_PARSERROOT) ? \ "software" : CONFIG_PARSERROOT) -#ifdef CONFIG_LIBCONFIG -static config_setting_t *find_node_libconfig(config_t *cfg, - const char *field, struct swupdate_cfg *swcfg) +#if defined(CONFIG_LIBCONFIG) || defined(CONFIG_JSON) + +static bool path_append(const char **nodes, const char *field) { - config_setting_t *setting; - struct hw_type *hardware; + unsigned int count = 0; - char node[1024]; + count = count_string_array(nodes); - if (!field) - return NULL; + if (count >= MAX_PARSED_NODES) + return false; - hardware = &swcfg->hw; + nodes[count++] = field; + nodes[count] = NULL; - if (strlen(swcfg->running_mode) && strlen(swcfg->software_set)) { - /* Try with both software set and board name */ - if (strlen(hardware->boardname)) { - snprintf(node, sizeof(node), "%s.%s.%s.%s.%s", - NODEROOT, - hardware->boardname, - swcfg->software_set, - swcfg->running_mode, - field); - setting = config_lookup(cfg, node); - if (setting) - return setting; - } - /* still here, try with software set and mode */ - snprintf(node, sizeof(node), "%s.%s.%s.%s", - NODEROOT, - swcfg->software_set, - swcfg->running_mode, - field); - setting = config_lookup(cfg, node); - if (setting) - return setting; - - } - - /* Try with board name */ - if (strlen(hardware->boardname)) { - snprintf(node, sizeof(node), "%s.%s.%s", - NODEROOT, - hardware->boardname, - field); - setting = config_lookup(cfg, node); - if (setting) - return setting; - } - /* Fall back without board entry */ - snprintf(node, sizeof(node), "%s.%s", - NODEROOT, - field); - return config_lookup(cfg, node); + return true; } -#endif - -#ifdef CONFIG_JSON -static json_object *find_node_json(json_object *root, const char *node, +static void *find_node(parsertype p, void *root, const char *field, struct swupdate_cfg *swcfg) { - json_object *jnode = NULL; - const char *simple_nodes[] = {NODEROOT, node, NULL}; + struct hw_type *hardware; + const char **nodes; + int i; + + if (!field) + return NULL; hardware = &swcfg->hw; - if (strlen(swcfg->running_mode) && strlen(swcfg->software_set)) { - if (strlen(hardware->boardname)) { - const char *nodes[] = {NODEROOT, hardware->boardname, - swcfg->software_set, swcfg->running_mode, - node, NULL}; - jnode = find_json_recursive_node(root, nodes); - if (jnode) - return jnode; - } else { - const char *nodes[] = {NODEROOT, swcfg->software_set, - swcfg->running_mode, node, NULL}; - jnode = find_json_recursive_node(root, nodes); - if (jnode) - return jnode; + nodes = (const char **)calloc(MAX_PARSED_NODES, sizeof(*nodes)); + + for (i = 0; i < 4; i++) { + nodes[0] = NULL; + switch(i) { + case 0: + if (strlen(swcfg->running_mode) && strlen(swcfg->software_set) && + strlen(hardware->boardname)) { + nodes[0] = NODEROOT; + nodes[1] = hardware->boardname; + nodes[2] = swcfg->software_set; + nodes[3] = swcfg->running_mode; + nodes[4] = NULL; + } + break; + case 1: + /* try with software set and mode */ + if (strlen(swcfg->running_mode) && strlen(swcfg->software_set)) { + nodes[0] = NODEROOT; + nodes[1] = swcfg->software_set; + nodes[2] = swcfg->running_mode; + nodes[3] = NULL; + } + break; + case 2: + /* Try with board name */ + if (strlen(hardware->boardname)) { + nodes[0] = NODEROOT; + nodes[1] = hardware->boardname; + nodes[2] = NULL; + } + break; + case 3: + /* Fall back without board entry */ + nodes[0] = NODEROOT; + nodes[1] = NULL; + break; } - } - if (strlen(hardware->boardname)) { - const char *nodes[] = {NODEROOT, hardware->boardname, node, - NULL}; - jnode = find_json_recursive_node(root, nodes); - if (jnode) - return jnode; + /* + * If conditions are not set, + * skip to the next option + */ + if (!nodes[0]) + continue; + + /* + * The first find_root() search for + * the root element from board, selection + * The second one starts from root and follow the tree + * to search for element + */ + if (find_root(p, root, nodes)) { + void *node = NULL; + if (!path_append(nodes, field)) + return NULL; + node = find_root(p, root, nodes); + + if (node) { + free(nodes); + return node; + } + } } - return find_json_recursive_node(root, simple_nodes); + free(nodes); + + return NULL; } -#endif -#if defined(CONFIG_LIBCONFIG) || defined(CONFIG_JSON) -static void *find_node(parsertype p, void *root, const char *node, - struct swupdate_cfg *swcfg) +static bool get_common_fields(parsertype p, void *cfg, struct swupdate_cfg *swcfg) { - switch (p) { - case LIBCFG_PARSER: - return find_node_libconfig((config_t *)root, node, swcfg); - case JSON_PARSER: - return find_node_json((json_object *)root, node, swcfg); + + void *setting; + + if((setting = find_node(p, cfg, "version", swcfg)) == NULL) { + ERROR("Missing version in configuration file"); + return false; } + + GET_FIELD_STRING(p, setting, NULL, swcfg->version); + TRACE("Version %s", swcfg->version); - return NULL; + if((setting = find_node(p, cfg, "description", swcfg)) != NULL) { + GET_FIELD_STRING(p, setting, NULL, swcfg->description); + TRACE("Description %s", swcfg->description); + } + + return true; } static void add_properties_cb(const char *name, const char *value, void *data) @@ -672,11 +683,8 @@ static int parser(parsertype p, void *cfg, struct swupdate_cfg *swcfg) int parse_cfg (struct swupdate_cfg *swcfg, const char *filename) { config_t cfg; - const char *str; - char node[128]; parsertype p = LIBCFG_PARSER; int ret; - config_setting_t *setting; memset(&cfg, 0, sizeof(cfg)); config_init(&cfg); @@ -694,24 +702,8 @@ int parse_cfg (struct swupdate_cfg *swcfg, const char *filename) return -1; } - if((setting = find_node(p, &cfg, "version", swcfg)) == NULL) { - ERROR("Missing version in configuration file"); + if (!get_common_fields(p, &cfg, swcfg)) return -1; - } else { - GET_FIELD_STRING(p, setting, NULL, swcfg->version); - TRACE("Version %s", swcfg->version); - } - - if((setting = find_node(p, &cfg, "description", swcfg)) != NULL) { - GET_FIELD_STRING(p, setting, NULL, swcfg->description); - TRACE("Description %s", swcfg->description); - } - - snprintf(node, sizeof(node), "%s.embedded-script", - NODEROOT); - if (config_lookup_string(&cfg, node, &str)) { - TRACE("Found Lua Software:\n%s", str); - } ret = parser(p, &cfg, swcfg); @@ -734,7 +726,7 @@ int parse_json(struct swupdate_cfg *swcfg, const char *filename) struct stat stbuf; unsigned int size; char *string; - json_object *cfg, *setting; + json_object *cfg; parsertype p = JSON_PARSER; /* Read the file. If there is an error, report it and exit. */ @@ -764,18 +756,9 @@ int parse_json(struct swupdate_cfg *swcfg, const char *filename) return -1; } - if((setting = find_node(p, cfg, "version", swcfg)) == NULL) { - ERROR("Missing version in configuration file"); + if (!get_common_fields(p, cfg, swcfg)) { free(string); return -1; - } else { - GET_FIELD_STRING(p, setting, NULL, swcfg->version); - TRACE("Version %s", swcfg->version); - } - - if((setting = find_node(p, cfg, "description", swcfg)) != NULL) { - GET_FIELD_STRING(p, setting, NULL, swcfg->description); - TRACE("Description %s", swcfg->description); } ret = parser(p, cfg, swcfg);