From patchwork Wed Jan 17 14:34:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stefan Herbrechtsmeier X-Patchwork-Id: 862291 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:4010:c07::23d; helo=mail-lf0-x23d.google.com; envelope-from=swupdate+bncbdn7dbh5yqibbqn67xjakgqedxqdvvq@googlegroups.com; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.b="juSVrOfm"; dkim-atps=neutral Received: from mail-lf0-x23d.google.com (mail-lf0-x23d.google.com [IPv6:2a00:1450:4010:c07::23d]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zM8lT0wBsz9s71 for ; Thu, 18 Jan 2018 01:35:48 +1100 (AEDT) Received: by mail-lf0-x23d.google.com with SMTP id q21sf5986350lfa.14 for ; Wed, 17 Jan 2018 06:35:48 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1516199745; cv=pass; d=google.com; s=arc-20160816; b=XoYLqOVNVclBKMaLK5ElcryJWU1wcTZSnjT7qz1nasetgfyhL/NjY4OjxdJ7rw0TGK v1YRjtu7buIOoad3dVC72Czr1N4BV9F5jPV1r1qZiPtCiLCN33v24gQvERoQtfCehDMu eMqJjiGYOyMlIoJKd8/TkehDIgtT0BZYShpkMyQ6xkawQ0lKk1b9mUQ+CVRPZhmR52sj c/jojXrjT+r3spOpUlZmjmZezUcVz6UnGOymmKGefxaPxqXWDQ5IxMtP3ImCuqZoF0UH wywFCbd6yYGB09mSD038x7HyIvkId/8YZrYHHNdQp27DcSs6bREh29yob7gmMgI2G8lV 2v7g== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:arc-authentication-results:arc-message-signature:sender :dkim-signature:arc-authentication-results; bh=ZmWXSgLcoKegOqA7uXbkgSLbfA21ju2l3rqRv6T19Zc=; b=m8BP0oVqQLPmkYx83hsGl68CDcFCnK5hYVUKqVc+61Bg3RZPcCj1ixoWHcSWcLO/lM Q1xax3y7JkpEswzp9aEnUQoQQmXuC4Y8jI3jTc7OVFQSAvG01uqfLnr6RbgbnJCxU5kL VQmI1YL+Z3M2wr0bJlu9qO8hLy/of7nSf1fMMEIc9+9590oRDui/rDvYtIlf7iCL5v96 ey5q7pcdO+3xhYjlqIaHR4N93OWRZQ4zhimlWhK1FBki4jb20Q522NrVCaqguSJvTeoJ olsvczlNm2KQeiO2BAt4qm29yBaq9l4/Lkb6QmpnrE8G1+6VdGTbysUmfbkIXmDgWsJR xQ0w== ARC-Authentication-Results: i=2; gmr-mx.google.com; spf=neutral (google.com: 85.13.157.12 is neither permitted nor denied by best guess record for domain of stefan@herbrechtsmeier.net) smtp.mailfrom=stefan@herbrechtsmeier.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-subscribe:list-unsubscribe; bh=ZmWXSgLcoKegOqA7uXbkgSLbfA21ju2l3rqRv6T19Zc=; b=juSVrOfmVRBx8bvwlac1uRbrDt1ppCs9pxAfPUCNi2mzr3X6CA5zDpp6r4VwN1iuAy xtd3DrAuxhOqyK6O70MXeqmRLIYaf9FOrTAnObinz1jq9yajqyZ1c8SqLnvatXgfK6pj duAZNveaOxNrlJhW5M9gnrHADIRfZJQW9j19GKy+Mh19FsO8n68RTguPGEMnIdJt4Yaz +Ay5mt6iznWGv2314T1l5FaxVhRd7WXLyjlgyZI2dHzeMqM/V2xa6yw5/UOmDz8aDvrm ok/0LKfEQeawn1li3wmSutFrDY3xArjQt9R76viEcBLeIrofam2C9PjQ2nCZd+odFEF/ SYYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=sender:x-gm-message-state:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding :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=ZmWXSgLcoKegOqA7uXbkgSLbfA21ju2l3rqRv6T19Zc=; b=TgS6qcwXqsfUUJXDgcJE/bykz4ElxLMB2rdZneGD/BGDjRRmbACSvuLTHUdsuIA6/L XFnSwbwswUnYra6oWsll5I6rQ8Cn5O31aRBpQaGeWQYoEx5mOZe9yGU3pnBFKpNt+NGC evNS4AoIRqkdme0V2PxImKjVwJ3oZ8HcqnUnBI4hdZzEemEA4v+vATcNL1EDoT1vKeMN 3AU67wEfV1aeNZAABL2amUWjrtpiV3MSj8wsC1J4PvOlhPQD9f+TzQIAU9w3vLYS/cjR lbE8rT0FVBeZCoCfAqsGOARWuHX1yyvrLC2jo4AaFrJRE0bqgUwlTdrzSPemmNdfs4W0 IocQ== Sender: swupdate@googlegroups.com X-Gm-Message-State: AKGB3mIoI/S7OI+xcdtVTKLeFQliCShSNCgLVqIQotodrdQcderROVJZ TJC6k78lGuPvATl0Xjv14mY= X-Google-Smtp-Source: ACJfBotB9heSJboEZ8nGs7TTY2QbPN+wGmaOE1Hcjz3hf0mKpPIMMoqC4olBUy6i55/QASOTuMN0sw== X-Received: by 10.46.55.17 with SMTP id e17mr117555lja.13.1516199745581; Wed, 17 Jan 2018 06:35:45 -0800 (PST) X-BeenThere: swupdate@googlegroups.com Received: by 10.25.151.15 with SMTP id z15ls140455lfd.14.gmail; Wed, 17 Jan 2018 06:35:44 -0800 (PST) X-Received: by 10.46.87.24 with SMTP id l24mr1111935ljb.30.1516199744170; Wed, 17 Jan 2018 06:35:44 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516199744; cv=none; d=google.com; s=arc-20160816; b=Z3GfjNH0asfP6HHXUhlTsRzs69URSziJ3MYIPD7OK5JTJscrZXIuLX5hDeCPePoCeO OvGZbP6/rz94RThMbQ+gV7LpiQrHbjQZrxFr+PsDwW4hHLvibIsOmCe6BAcCj2jfUk9g ybHIDKWuNPlaxSeki5DE+Kn7vGZiJItL2y0Mnkq3hNvsL/HjO5TQTFt5hsDUOZk2KCL6 zhxakZaeRI/1ynjlLOfpyfPFQbNMS9UlnswV5xUQxOC5im1dP1Zm0kBZ3IFlbTjQUUiC vc2Fk63XLxJvk+YaLoAhSfCQ+hmXl/wh5RX1SUj9Q/SoGkmiSn5K5jUvDkHZxgW9/8cx J2eA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=FhCmygC9Ytf5j0f2YPtR4ukvaCB2z4ePGSdy7+6x7kA=; b=nRZQZ7JG9tRg0gW98NlN1r4oMcup/BY9DxWvqtzrB1ug7nmF8aW3laL2jS3Qx15euG f5bjC8hb1ZqWDmHyfjUeXIU8eeW5UcG8QGVgWHB5XJcIKT/GKNByaiJkPAGwkKtoW7j8 vBtA7jIcedD7zzVOy+GMUzE1J7t16Ad1nsd9gCv07dgeI40oR99KRNWaVp/bRqJcpyvT jOnfKTo3h0dEq2zhf3zAB4r76LyOXGFZK/BqTEMfHaK5C6FeXWhftBCbD8Ezbr7My08K wvlHL4WFC7Gv7Ga6J9cdupw0eac+LUj2X/BX5TTl2rh4iuMSLH9jbSYG9L5tGpsUVJtz jv/w== ARC-Authentication-Results: i=1; gmr-mx.google.com; spf=neutral (google.com: 85.13.157.12 is neither permitted nor denied by best guess record for domain of stefan@herbrechtsmeier.net) smtp.mailfrom=stefan@herbrechtsmeier.net Received: from dd41138.kasserver.com (dd41138.kasserver.com. [85.13.157.12]) by gmr-mx.google.com with ESMTPS id l26si208266lja.0.2018.01.17.06.35.43 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 17 Jan 2018 06:35:43 -0800 (PST) Received-SPF: neutral (google.com: 85.13.157.12 is neither permitted nor denied by best guess record for domain of stefan@herbrechtsmeier.net) client-ip=85.13.157.12; Received: from WS08941.weidmueller.com (unknown [217.244.7.16]) by dd41138.kasserver.com (Postfix) with ESMTPSA id 3AA3211A0698; Wed, 17 Jan 2018 15:35:43 +0100 (CET) From: stefan@herbrechtsmeier.net To: swupdate@googlegroups.com Cc: Stefan Herbrechtsmeier Subject: [swupdate] [PATCH v2 2/5] corelib: Rework dictionary to support multiple values per key Date: Wed, 17 Jan 2018 15:34:03 +0100 Message-Id: <1516199646-5607-2-git-send-email-stefan@herbrechtsmeier.net> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1516199646-5607-1-git-send-email-stefan@herbrechtsmeier.net> References: <1516199646-5607-1-git-send-email-stefan@herbrechtsmeier.net> MIME-Version: 1.0 X-Original-Sender: stefan@herbrechtsmeier.net X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 85.13.157.12 is neither permitted nor denied by best guess record for domain of stefan@herbrechtsmeier.net) smtp.mailfrom=stefan@herbrechtsmeier.net 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: , From: Stefan Herbrechtsmeier Signed-off-by: Stefan Herbrechtsmeier Reviewed-by: Stefano Babic Tested-by: Stefano Babic --- Changes in v3: - Add const to all dict key and value parameters - Update swuforward to iterate over the value list Changes in v2: None bootloader/grub.c | 20 +++---- corelib/installer.c | 9 +-- corelib/swupdate_dict.c | 130 ++++++++++++++++++++++++++++++++---------- handlers/swuforward_handler.c | 11 +--- include/swupdate_dict.h | 22 +++++-- parser/parser.c | 2 +- suricatta/server_hawkbit.c | 14 +++-- 7 files changed, 143 insertions(+), 65 deletions(-) diff --git a/bootloader/grub.c b/bootloader/grub.c index 2f6172e..dc35718 100644 --- a/bootloader/grub.c +++ b/bootloader/grub.c @@ -153,8 +153,10 @@ static inline void grubenv_update_size(struct grubenv_t *grubenv) /* lengths of strings + '=' and '\n' characters */ LIST_FOREACH(grubvar, &grubenv->vars, next) { - size = size + strlen(grubvar->key) + - strlen(grubvar->value) + 2; + char *key = dict_entry_get_key(grubvar); + char *value = dict_entry_get_value(grubvar); + + size = size + strlen(key) + strlen(value) + 2; } size += strlen(GRUBENV_HEADER); grubenv->size = size; @@ -194,10 +196,12 @@ static int grubenv_write(struct grubenv_t *grubenv) strncpy(buf, GRUBENV_HEADER, strlen(GRUBENV_HEADER) + 1); LIST_FOREACH(grubvar, &grubenv->vars, next) { - llen = strlen(grubvar->key) + strlen(grubvar->value) + 2; + char *key = dict_entry_get_key(grubvar); + char *value = dict_entry_get_value(grubvar); + + llen = strlen(key) + strlen(value) + 2; /* +1 for null termination */ - snprintf(line, llen + 1, "%s=%s\n", grubvar->key, - grubvar->value); + snprintf(line, llen + 1, "%s=%s\n", key, value); strncat(buf, line, llen); } @@ -237,11 +241,7 @@ cleanup: * allocation */ static inline void grubenv_close(struct grubenv_t *grubenv) { - struct dict_entry *grubvar; - - LIST_FOREACH(grubvar, &grubenv->vars, next) { - dict_remove(&grubenv->vars, grubvar->key); - } + dict_drop_db(&grubenv->vars); } /* I feel that '#' and '=' characters should be forbidden. Although it's not diff --git a/corelib/installer.c b/corelib/installer.c index e5bf895..f778d8b 100644 --- a/corelib/installer.c +++ b/corelib/installer.c @@ -206,11 +206,12 @@ static int prepare_boot_script(struct swupdate_cfg *cfg, const char *script) return -1; LIST_FOREACH(bootvar, &cfg->bootloader, next) { - if (!bootvar->key || !bootvar->value) + char *key = dict_entry_get_key(bootvar); + char *value = dict_entry_get_value(bootvar); + + if (!key || !value) continue; - snprintf(buf, sizeof(buf), "%s %s\n", - bootvar->key, - bootvar->value); + snprintf(buf, sizeof(buf), "%s %s\n", key, value); if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) { TRACE("Error saving temporary file"); ret = -1; diff --git a/corelib/swupdate_dict.c b/corelib/swupdate_dict.c index 2cdad47..be21ff2 100644 --- a/corelib/swupdate_dict.c +++ b/corelib/swupdate_dict.c @@ -2,6 +2,9 @@ * (C) Copyright 2016 * Stefano Babic, DENX Software Engineering, sbabic@denx.de. * + * Copyright (C) 2018 Weidmüller Interface GmbH & Co. KG + * Stefan Herbrechtsmeier + * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -19,7 +22,52 @@ #include "util.h" #include "swupdate_dict.h" -static struct dict_entry *get_entry(struct dict *dictionary, char *key) +static int insert_list_elem(struct dict_list *list, const char *value) +{ + struct dict_list_elem *elem = (struct dict_list_elem *)malloc(sizeof(*elem)); + + if (!elem) + return -ENOMEM; + + memset(elem, 0, sizeof(*elem)); + elem->value = strdup(value); + + LIST_INSERT_HEAD(list, elem, next); + + return 0; +} + +static void remove_list_elem(struct dict_list_elem *elem) +{ + LIST_REMOVE(elem, next); + free(elem->value); + free(elem); +} + +static void remove_list(struct dict_list *list) +{ + struct dict_list_elem *elem; + + LIST_FOREACH(elem, list, next) { + remove_list_elem(elem); + } +} + +static struct dict_entry *insert_entry(struct dict *dictionary, const char *key) +{ + struct dict_entry *entry = (struct dict_entry *)malloc(sizeof(*entry)); + if (!entry) + return NULL; + + memset(entry, 0, sizeof(*entry)); + entry->key = strdup(key); + + LIST_INSERT_HEAD(dictionary, entry, next); + + return entry; +} + +static struct dict_entry *get_entry(struct dict *dictionary, const char *key) { struct dict_entry *entry; @@ -31,72 +79,92 @@ static struct dict_entry *get_entry(struct dict *dictionary, char *key) return NULL; } -int dict_insert_entry(struct dict *dictionary, char *key, char *value) +static void remove_entry(struct dict_entry *entry) { - struct dict_entry *entry = (struct dict_entry *)malloc(sizeof(*entry)); + LIST_REMOVE(entry, next); + free(entry->key); + remove_list(&entry->list); + free(entry); +} +char *dict_entry_get_key(struct dict_entry *entry) +{ if (!entry) - return -ENOMEM; + return NULL; - memset(entry, 0, sizeof(*entry)); - entry->key = strdup(key); - entry->value = strdup(value); + return entry->key; +} - LIST_INSERT_HEAD(dictionary, entry, next); +char *dict_entry_get_value(struct dict_entry *entry) +{ + if (!entry || !LIST_FIRST(&entry->list)) + return NULL; - return 0; + return LIST_FIRST(&entry->list)->value; } -char *dict_get_value(struct dict *dictionary, char *key) +struct dict_list *dict_get_list(struct dict *dictionary, const char *key) { struct dict_entry *entry = get_entry(dictionary, key); if (!entry) return NULL; - return entry->value; + return &entry->list; } -int dict_set_value(struct dict *dictionary, char *key, char *value) +char *dict_get_value(struct dict *dictionary, const char *key) { struct dict_entry *entry = get_entry(dictionary, key); - /* - * Set to new value if key is already in - * dictionary - */ - if (entry) { - LIST_REMOVE(entry, next); - free(entry); - } + if (!entry) + return NULL; - return dict_insert_entry(dictionary, key, value); + return dict_entry_get_value(entry); } -void dict_remove_entry(struct dict_entry *entry) +int dict_insert_value(struct dict *dictionary, const char *key, const char *value) { - LIST_REMOVE(entry, next); - free(entry->key); - free(entry->value); - free(entry); + struct dict_entry *entry = get_entry(dictionary, key); + + if (!entry) { + entry = insert_entry(dictionary, key); + if (!entry) + return -ENOMEM; + } + + return insert_list_elem(&entry->list, value); } -void dict_remove(struct dict *dictionary, char *key) +int dict_set_value(struct dict *dictionary, const char *key, const char *value) { + struct dict_entry *entry = get_entry(dictionary, key); + + if (entry) + remove_entry(entry); + entry = insert_entry(dictionary, key); + if (!entry) + return -ENOMEM; + + return insert_list_elem(&entry->list, value); +} + +void dict_remove(struct dict *dictionary, const char *key) +{ struct dict_entry *entry = get_entry(dictionary, key); if (!entry) return; - dict_remove_entry(entry); + remove_entry(entry); } void dict_drop_db(struct dict *dictionary) { - struct dict_entry *var; + struct dict_entry *entry; - LIST_FOREACH(var, dictionary, next) { - dict_remove_entry(var); + LIST_FOREACH(entry, dictionary, next) { + remove_entry(entry); } } diff --git a/handlers/swuforward_handler.c b/handlers/swuforward_handler.c index c804628..8b0c17f 100644 --- a/handlers/swuforward_handler.c +++ b/handlers/swuforward_handler.c @@ -292,7 +292,7 @@ static int install_remote_swu(struct img_type *img, struct hnd_priv priv; struct curlconn *conn; int ret, still_running = 0; - struct dict_entry *url; + struct dict_list_elem *url; struct curl_slist *headerlist; CURLMsg *msg = NULL; @@ -320,16 +320,9 @@ static int install_remote_swu(struct img_type *img, priv.maxwaitms = MAX_WAIT_MS; priv.size = img->size; - /* - * Parse handler properties to get URLs for destination - * - */ - LIST_FOREACH(url, &img->properties, next) { + LIST_FOREACH(url, dict_get_list(&img->properties, "url"), next) { char curlheader[SWUPDATE_GENERAL_STRING_SIZE + strlen(CUSTOM_HEADER)]; - if (!url->key || !url->value || strcmp(url->key, "url")) - continue; - conn = (struct curlconn *)calloc(1, sizeof(struct curlconn)); if (!conn) { ERROR("FAULT: no memory"); diff --git a/include/swupdate_dict.h b/include/swupdate_dict.h index 2cae5ca..82988ac 100644 --- a/include/swupdate_dict.h +++ b/include/swupdate_dict.h @@ -10,19 +10,29 @@ #include +struct dict_list_elem { + char *value; + LIST_ENTRY(dict_list_elem) next; +}; + +LIST_HEAD(dict_list, dict_list_elem); + struct dict_entry { char *key; - char *value; + struct dict_list list; LIST_ENTRY(dict_entry) next; }; LIST_HEAD(dict, dict_entry); -char *dict_get_value(struct dict *dictionary, char *key); -int dict_set_value(struct dict *dictionary, char *key, char *value); -int dict_insert_entry(struct dict *dictionary, char *key, char *value); -void dict_remove(struct dict *dictionary, char *key); -void dict_remove_entry(struct dict_entry *entry); +char *dict_entry_get_key(struct dict_entry *entry); +char *dict_entry_get_value(struct dict_entry *entry); + +struct dict_list *dict_get_list(struct dict *dictionary, const char *key); +char *dict_get_value(struct dict *dictionary, const char *key); +int dict_set_value(struct dict *dictionary, const char *key, const char *value); +int dict_insert_value(struct dict *dictionary, const char *key, const char *value); +void dict_remove(struct dict *dictionary, const char *key); void dict_drop_db(struct dict *dictionary); #endif diff --git a/parser/parser.c b/parser/parser.c index 04cd549..2e9208d 100644 --- a/parser/parser.c +++ b/parser/parser.c @@ -162,7 +162,7 @@ static void add_properties(parsertype p, void *node, struct img_type *image) key, value ); - if (dict_insert_entry(&image->properties, key, value)) + if (dict_insert_value(&image->properties, key, value)) ERROR("Property not stored, skipping..."); } diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c index c84de65..02ffb3a 100644 --- a/suricatta/server_hawkbit.c +++ b/suricatta/server_hawkbit.c @@ -1336,7 +1336,10 @@ int get_target_data_length(void) struct dict_entry *entry; LIST_FOREACH(entry, &server_hawkbit.configdata, next) { - len += strlen(entry->key) + strlen(entry->value) + strlen (" : ") + 6; + char *key = dict_entry_get_key(entry); + char *value = dict_entry_get_value(entry); + + len += strlen(key) + strlen(value) + strlen (" : ") + 6; } return len; @@ -1367,17 +1370,20 @@ server_op_res_t server_send_target_data(void) char *keyvalue = NULL; LIST_FOREACH(entry, &server_hawkbit.configdata, next) { + char *key = dict_entry_get_key(entry); + char *value = dict_entry_get_value(entry); + if (ENOMEM_ASPRINTF == asprintf(&keyvalue, config_data, ((first) ? ' ' : ','), - entry->key, - entry->value)) { + key, + value)) { ERROR("hawkBit server reply cannot be sent because of OOM.\n"); result = SERVER_EINIT; goto cleanup; } first = false; - TRACE("KEYVALUE=%s %s %s", keyvalue, entry->key, entry->value); + TRACE("KEYVALUE=%s %s %s", keyvalue, key, value); strcat(configData, keyvalue); free(keyvalue);