From patchwork Wed Dec 23 13:40:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Babic X-Patchwork-Id: 1420130 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=googlegroups.com (client-ip=2a00:1450:4864:20::43d; helo=mail-wr1-x43d.google.com; envelope-from=swupdate+bncbcxploxj6ikrby4rrx7qkgqegzjlb7q@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.a=rsa-sha256 header.s=20161025 header.b=TK2HlLWV; dkim-atps=neutral Received: from mail-wr1-x43d.google.com (mail-wr1-x43d.google.com [IPv6:2a00:1450:4864:20::43d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4D1Dqt5PYCz9sVH for ; Thu, 24 Dec 2020 00:40:55 +1100 (AEDT) Received: by mail-wr1-x43d.google.com with SMTP id b8sf12374841wrv.14 for ; Wed, 23 Dec 2020 05:40:55 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1608730851; cv=pass; d=google.com; s=arc-20160816; b=y3rMBP+fmUd4IZaKXRIlZHVvzgj8RQFO6TCoEKNeBX+n/PltG/eJADDExulImlKCtK 7cx/lV3dJ4eiaZIAUFIExUkG2w2/uTs5ewJlQBlfEbnwtGdIC7emZi7erNFwCx0KV/2p txPVbcAhkGoq4msNg7cqzHofAOdGmPihK/v/znKAkXtmVM6pn6LKL9ngXnFe8uBc1HYl qT/tyS7H3s+r6VC+xjPy0w4XBMgqeEVavlV11JOHsBbeIUhk7/5M0nSLo7+XWDaxGQe2 CnAI1+Hqx5wB9Gb8eB4E3slaN5HK1wlFrhwuJ8J92cx2QFoUpYA0ESHbEtPC3ot5cvBT OzZQ== 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:mime-version:message-id:date :subject:cc:to:from:sender:dkim-signature; bh=YXFrg6vUqxTAtdwFxmjvQPMOmDKxtXNDuXSW8wzIWuc=; b=b4epjpug4TOx217CrjMt31VFRNnJ26Ke2GiOrY26iH9dnSJlozfwNnarP1i1ORJpyt C55wfpdhuuoy8UKIyTlbtINkQRtd7YCilwvYMU9wVdOyU+zgOXF3S4tCJHg3OL5nRRnY JmtCRZ+6QKYje7tZcyrd08FEAstAJHtMCXbNKwy3MJFYJKCR3ZRd0Qp17FLj4ARRaNwo p5zjzNWSe8G3tzuqIkK0I+h21H63XoxmDWWm94EXVoH7GPwtgQYilgLX30Ek6Ll1dKVp GU7XN8NLvOr2034H/JDhsdT6Cmtho3Hz98KCGufjy+ujxpSDm0PpPLtuj1FocPVa9pqh w4nQ== 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:from:to:cc:subject:date:message-id:mime-version :x-original-sender:x-original-authentication-results:precedence :mailing-list:list-id:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=YXFrg6vUqxTAtdwFxmjvQPMOmDKxtXNDuXSW8wzIWuc=; b=TK2HlLWV5mcynIYmud2OCY3sqRfHNvA92XTAlwwAjwl0U1mZDtqPRwwnlbc1gjhfmR mlUUXgaxhqwzQr7DTf6UkuYZxx49rePEXk2bt+9ryzQcY5e8uxMhr6Q+vJY16J/9/xDu kiEHZyVnh10bZFzLJwxptdrZODRdHmvxBT1gJLBfxLjfjT4AiDthYuG9MncoOaWtgU1x Kx4NbgcCR8Rf4sN79inNTa4j8qWkIO8pOvzQ46IxIJuRkQHEJrxQhIoxN5RnkK4H7wH4 kGTqY/5K2PbUgDVHhkcgGk8mfnoJWKSuAKGnWDEfkyzq1maw6ttSU+sf6NOxavHv7DN2 AVow== 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 :mime-version: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=YXFrg6vUqxTAtdwFxmjvQPMOmDKxtXNDuXSW8wzIWuc=; b=Kpnrwi7SxF2l56/NnXoQePYO4vO2wd/VlhykaK0osnTxTC4L85m7B0ZSt6c6zghp39 QkMBZmTyMkux5NkPNO3GoSZLtI1O7cJN9AqqU5tp03RXtRf9cxrd587S5tmGSg+IgqgE ntjDgpGkGwT+WejOg5MxDGUstdMIm5pXJKDG0RlwGGCTpVGO1RN0yY5eGTct54h0+lQ4 JmfjlZbRq1BxAtFA4X53k+/9jxgIPqlxBMEupqtvRZmM8pMO4vOliyYC2HcdWJi6aPKA 3mwHk4kTjGz/MRjemmdLTUcB3rly+nM4pQZnZ9F2lO0OVLhkXDs0A6Untw7jkHxcd5+C 7TLw== Sender: swupdate@googlegroups.com X-Gm-Message-State: AOAM531QpT1usuK3tdlQjvhFg8UJKDU9KH2BACv2gWoTs6oHY185EOn6 +A4wFzye5Pf8V4GIJX3aeM0= X-Google-Smtp-Source: ABdhPJw6kgaSJaN0Qnc0GdXMevqWb0vICb5FxCU52tezkSJyc/TPULg6Ootqtt80pC69YLpV5T6Xkg== X-Received: by 2002:a5d:6845:: with SMTP id o5mr29115763wrw.421.1608730851612; Wed, 23 Dec 2020 05:40:51 -0800 (PST) X-BeenThere: swupdate@googlegroups.com Received: by 2002:a5d:6812:: with SMTP id w18ls8261215wru.1.gmail; Wed, 23 Dec 2020 05:40:50 -0800 (PST) X-Received: by 2002:a05:6000:1624:: with SMTP id v4mr14858401wrb.210.1608730850442; Wed, 23 Dec 2020 05:40:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1608730850; cv=none; d=google.com; s=arc-20160816; b=d+/oXisUc9Y/Y0ytb9OqiiiE1Sl3Ud0xLvzpvkdnWywrSci0G7hx3Yis9LnDxLpIob vaIsfpNyokHGKNAcO3n+p31fJNu5w/845ULFPSa+uuOGdiQKzre5tjTY2ns/5YHybLs0 ochughQJPUOYksRhXkFA9mFCQcFR6YKxSMQ4bP/D+Y7xJ2ANf84WrUVkI0haszNT3t+k ufAUnFtdCUoDtrwDrlRsAluhhV8kJ0XeEtZbXBvHA7eO/qeHo2aqf6HKmXe5ZA/hoMfF DOFrCUhIMJsLJ/frS7jKl1A/iDW9fcpStkyC2MKwMXsei5y6t7z2xjsH/u5WmHSXnR8m ZY7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from; bh=Tu0esQCRRMRa7xnkpGfqK78IsnrY3/oRbAIUZZb28Lk=; b=0ZbF89apV9Rfi6mycLxk7vuxgzBlxzMFX6j7JNIrNck3mOEFjEo49KbCQNE2XXomqB KNBwX1QJiHkrlREAi/JOH3A3+OlkcxpkXisGKaQazunYqY5y4dx6+k6BlwP3VwKMVx4g 464c9jverEqRQfqKyUWd90wlLnJSHf57yxYGGDZ02qX8gE5LTrOzN7+Pe6nMgn72erMD 8cA/pgKQG6qeGefpF3emrwkMRb4cxL4esUDU3/INywoK36QtJoYp3WvB9/0naB4jq5+z DFh4sdLN3HTDmst5kPCTBWXWb81WFGUj8/kvrmIspX+tS7UFgCHd6LXC5VAxD7iQrDPS qETQ== 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 y1si877931wrl.4.2020.12.23.05.40.50 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 23 Dec 2020 05:40:50 -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 4D1Dqk1VQNz1qs0h; Wed, 23 Dec 2020 14:40:50 +0100 (CET) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 4D1Dqk1FvWz1tSQl; Wed, 23 Dec 2020 14:40:50 +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 XNiOdgU9f_WP; Wed, 23 Dec 2020 14:40:48 +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, 23 Dec 2020 14:40:48 +0100 (CET) Received: from localhost (mail.babic.homelinux.org [127.0.0.1]) by babic.homelinux.org (Postfix) with ESMTP id 30F4D4540700; Wed, 23 Dec 2020 14:40:48 +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 WjBnJlVdhiRc; Wed, 23 Dec 2020 14:40:45 +0100 (CET) Received: from paperino.fritz.box (paperino.fritz.box [192.168.178.64]) by babic.homelinux.org (Postfix) with ESMTP id 239B44540559; Wed, 23 Dec 2020 14:40:45 +0100 (CET) From: Stefano Babic To: swupdate@googlegroups.com Cc: Stefano Babic Subject: [swupdate] [PATCH] Drop separate installation path for local file Date: Wed, 23 Dec 2020 14:40:43 +0100 Message-Id: <20201223134043.787666-1-sbabic@denx.de> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 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 currently two separate paths for installing, via network thread (used by OTA / IPC library) and from a local file. This increases efforts during regression tests because both paths must be tested. In case of local path, no network thread is created and file is scanned via seek(), adding an implicit "installed-directly" to all artifacts. Nevertheless, it happened to find dicrepancies between OTA and local file update. This patch is a big cleanup and drops the path from local file. The network thread is always generated, andcode from swupdate-client is integrated into SWUpdate to use the generic update path. Specific functions duplicated for local path are dropped, and it is not requested to forward in all steps if an updated is coming from local file or from OTA. These changes are thought to be compatible with the past, and updating via -i (local file) is still supported. Indeed, the following different behaviors are introduced: - SWU check via -c is the same as dry-run mode. Not just sw-description is parsed, but the whole update is checked without installing. This extends the check's functionality and verifies the whole SWU. - before these changes, -i results in an implicit "installed-drirectly" for all artifacts. This is not maintained, and users should add the attribute to own sw-description to avoid temporary copies on tmpdir. Signed-off-by: Stefano Babic --- core/Makefile | 1 + core/install_from_file.c | 113 ++++++++++++++++ core/installer.c | 109 +++++++--------- core/stream_interface.c | 2 +- core/swupdate.c | 275 +++++---------------------------------- include/installer.h | 4 +- 6 files changed, 200 insertions(+), 304 deletions(-) create mode 100644 core/install_from_file.c diff --git a/core/Makefile b/core/Makefile index ad94120..11bc183 100644 --- a/core/Makefile +++ b/core/Makefile @@ -12,6 +12,7 @@ obj-y += swupdate.o \ cpio_utils.o \ notifier.o \ handler.o \ + install_from_file.o \ util.o \ parser.o \ pctl.o \ diff --git a/core/install_from_file.c b/core/install_from_file.c new file mode 100644 index 0000000..a595c30 --- /dev/null +++ b/core/install_from_file.c @@ -0,0 +1,113 @@ +/* + * (C) Copyright 2020 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "network_ipc.h" +#include "util.h" +#include "installer.h" + +static pthread_mutex_t mymutex; + +static char buf[16 * 1024]; +static int fd = STDIN_FILENO; +static int end_status = EXIT_SUCCESS; +/* + * this is the callback to get a new chunk of the + * image. + * It is called by a thread generated by the library and + * can block. + */ +static int readimage(char **p, int *size) { + int ret; + + ret = read(fd, buf, sizeof(buf)); + + *p = buf; + + *size = ret; + + return ret; +} + +/* + * this is called at the end reporting the status + * of the upgrade and running any post-update actions + * if successful + */ +static int endupdate(RECOVERY_STATUS status) +{ + end_status = (status == SUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE; + + INFO("Swupdate %s\n", + status == FAILURE ? "*failed* !" : + "was successful !"); + + pthread_mutex_unlock(&mymutex); + + return 0; +} + +int install_from_file(const char *filename, bool check) +{ + int rc; + int timeout_cnt = 3; + + if (filename && (fd = open(filename, O_RDONLY)) < 0) { + fprintf(stderr, "Unable to open %s\n", filename); + return EXIT_FAILURE; + } + + pthread_mutex_init(&mymutex, NULL); + + /* synchronize with a mutex */ + pthread_mutex_lock(&mymutex); + + + /* May be set non-zero by end() function on failure */ + end_status = EXIT_SUCCESS; + + struct swupdate_request req; + swupdate_prepare_req(&req); + if (check) + req.dry_run = RUN_DRYRUN; + + while (timeout_cnt > 0) { + rc = swupdate_async_start(readimage, NULL, + endupdate, &req, sizeof(req)); + if (rc >= 0) + break; + timeout_cnt--; + sleep(1); + } + + /* return if we've hit an error scenario */ + if (rc < 0) { + ERROR ("swupdate_async_start returns %d\n", rc); + pthread_mutex_unlock(&mymutex); + close(fd); + return EXIT_FAILURE; + } + + /* Now block */ + pthread_mutex_lock(&mymutex); + + /* End called, unlock and exit */ + pthread_mutex_unlock(&mymutex); + + if (filename) + close(fd); + + return end_status; +} diff --git a/core/installer.c b/core/installer.c index 981a21d..d830dae 100644 --- a/core/installer.c +++ b/core/installer.c @@ -92,7 +92,7 @@ int check_if_required(struct imglist *list, struct filehdr *pfdh, * Extract all scripts from a list from the image * and save them on the filesystem to be executed later */ -static int extract_scripts(int fd, struct imglist *head, int fromfile) +static int extract_scripts(struct imglist *head) { struct img_type *script; int fdout; @@ -100,6 +100,11 @@ static int extract_scripts(int fd, struct imglist *head, int fromfile) const char* tmpdir_scripts = get_tmpdirscripts(); LIST_FOREACH(script, head, next) { + int fdin; + char *tmpfile; + unsigned long offset = 0; + uint32_t checksum; + if (!script->fname[0] && (script->provided == 0)) { TRACE("No script provided for script of type %s", script->type); @@ -118,40 +123,31 @@ static int extract_scripts(int fd, struct imglist *head, int fromfile) if (fdout < 0) return fdout; - if (fromfile) - ret = extract_next_file(fd, fdout, script->offset, 0, - script->is_encrypted, script->ivt_ascii, script->sha256); - else { - int fdin; - char *tmpfile; - unsigned long offset = 0; - uint32_t checksum; - if (asprintf(&tmpfile, "%s%s", get_tmpdir(), script->fname) == - ENOMEM_ASPRINTF) { - ERROR("Path too long: %s%s", get_tmpdir(), script->fname); - close(fdout); - return -ENOMEM; - } - - fdin = open(tmpfile, O_RDONLY); - free(tmpfile); - if (fdin < 0) { - ERROR("Extracted script not found in %s: %s %d", - get_tmpdir(), script->extract_file, errno); - close(fdout); - return -ENOENT; - } + if (asprintf(&tmpfile, "%s%s", get_tmpdir(), script->fname) == + ENOMEM_ASPRINTF) { + ERROR("Path too long: %s%s", get_tmpdir(), script->fname); + close(fdout); + return -ENOMEM; + } - ret = copyfile(fdin, &fdout, script->size, &offset, 0, 0, - script->compressed, - &checksum, - script->sha256, - script->is_encrypted, - script->ivt_ascii, - NULL); - close(fdin); + fdin = open(tmpfile, O_RDONLY); + free(tmpfile); + if (fdin < 0) { + ERROR("Extracted script not found in %s: %s %d", + get_tmpdir(), script->extract_file, errno); + close(fdout); + return -ENOENT; } + + ret = copyfile(fdin, &fdout, script->size, &offset, 0, 0, + script->compressed, + &checksum, + script->sha256, + script->is_encrypted, + script->ivt_ascii, + NULL); + close(fdin); close(fdout); if (ret < 0) @@ -252,12 +248,11 @@ int install_single_image(struct img_type *img, int dry_run) * extract : boolean, true to enable extraction */ -int install_images(struct swupdate_cfg *sw, int fdsw, int fromfile) +int install_images(struct swupdate_cfg *sw) { int ret; struct img_type *img, *tmp; char *filename; - struct filehdr fdh; struct stat buf; const char* TMPDIR = get_tmpdir(); int dry_run = sw->globals.dry_run; @@ -265,8 +260,8 @@ int install_images(struct swupdate_cfg *sw, int fdsw, int fromfile) /* Extract all scripts, preinstall scripts must be run now */ const char* tmpdir_scripts = get_tmpdirscripts(); - ret = extract_scripts(fdsw, &sw->scripts, fromfile); - ret |= extract_scripts(fdsw, &sw->bootscripts, fromfile); + ret = extract_scripts(&sw->scripts); + ret |= extract_scripts(&sw->bootscripts); if (ret) { ERROR("extracting script to %s failed", tmpdir_scripts); return ret; @@ -292,37 +287,28 @@ int install_images(struct swupdate_cfg *sw, int fdsw, int fromfile) * This does not make sense when installed from file, * because images are seekd (no streaming) */ - if (!fromfile && img->install_directly) + if (img->install_directly) continue; - if (!fromfile) { - if (asprintf(&filename, "%s%s", TMPDIR, img->fname) == + if (asprintf(&filename, "%s%s", TMPDIR, img->fname) == ENOMEM_ASPRINTF) { ERROR("Path too long: %s%s", TMPDIR, img->fname); return -1; - } - - ret = stat(filename, &buf); - if (ret) { - TRACE("%s not found or wrong", filename); - free(filename); - return -1; - } - img->size = buf.st_size; + } - img->fdin = open(filename, O_RDONLY); + ret = stat(filename, &buf); + if (ret) { + TRACE("%s not found or wrong", filename); free(filename); - if (img->fdin < 0) { - ERROR("Image %s cannot be opened", - img->fname); - return -1; - } - } else { - if (extract_img_from_cpio(fdsw, img->offset, &fdh) < 0) - return -1; - img->size = fdh.size; - img->checksum = fdh.chksum; - img->fdin = fdsw; + return -1; + } + img->size = buf.st_size; + img->fdin = open(filename, O_RDONLY); + free(filename); + if (img->fdin < 0) { + ERROR("Image %s cannot be opened", + img->fname); + return -1; } if ((strlen(img->path) > 0) && @@ -345,8 +331,7 @@ int install_images(struct swupdate_cfg *sw, int fdsw, int fromfile) ret = install_single_image(img, dry_run); } - if (!fromfile) - close(img->fdin); + close(img->fdin); if (dropimg) free_image(img); diff --git a/core/stream_interface.c b/core/stream_interface.c index 6d32998..c5073fd 100644 --- a/core/stream_interface.c +++ b/core/stream_interface.c @@ -587,7 +587,7 @@ void *network_initializer(void *data) } notify(RUN, RECOVERY_NO_ERROR, INFOLEVEL, "Installation in progress"); - ret = install_images(software, 0, 0); + ret = install_images(software); if (ret != 0) { if (!software->globals.dry_run && software->bootloader_transaction_marker) { save_state_string((char*)BOOTVAR_TRANSACTION, STATE_FAILED); diff --git a/core/swupdate.c b/core/swupdate.c index 9adafa8..318a245 100644 --- a/core/swupdate.c +++ b/core/swupdate.c @@ -178,23 +178,6 @@ static void usage(char *programname) #endif } -static int check_provided(struct imglist *list) -{ - int ret = 0; - struct img_type *p; - - for (p = list->lh_first; p != NULL; - p = p->next.le_next) { - if (!p->provided && !(get_handler_mask(p) & NO_DATA_HANDLER)) { - ERROR("Requested file not found in image: %s", \ - p->fname); - ret = -1; - } - } - - return ret; -} - struct swupdate_cfg *get_swupdate_cfg(void) { return &swcfg; } @@ -229,191 +212,6 @@ static int opt_to_hwrev(char *param, struct hw_type *hw) return 0; } -static int searching_for_image(char *name) -{ - char *dir, *dirc, *basec; - char *fpattern; - DIR *path; - struct dirent *dp; - int fd = -1; - int found; - char fname[MAX_IMAGE_FNAME]; - char *buf; - char hex[4]; - - dirc = strdup(name); - basec = strdup(name); - dir = dirname(dirc); - fpattern = basename(basec); - path = opendir(dir); - - TRACE("Searching image: check %s into %s", - basec, dirc); - if (!path) { - free(dirc); - free(basec); - return -EBADF; - } - - dp = readdir(path); - do { - if (!dp) - break; - if (!strcmp(dp->d_name, ".") || - !strcmp(dp->d_name, "..") || - !strlen(dp->d_name)) - continue; - found = !fnmatch(fpattern, dp->d_name, FNM_CASEFOLD); - - if (found) { - TRACE("File found: %s :", dp->d_name); - /* Buffer for hexa output */ - buf = (char *)malloc(3 * strlen(dp->d_name) + 1); - if (buf) { - for (size_t i = 0; i < strlen(dp->d_name); i++) { - snprintf(hex, sizeof(hex), "%x ", dp->d_name[i]); - memcpy(&buf[3 * i], hex, 3); - } - buf[3 * strlen(dp->d_name)] = '\0'; - TRACE("\nFile name (hex): %s", buf); - } - /* Take the first one as image */ - if (fd < 0) { - if (snprintf(fname, sizeof(fname), "%s/%s", - dirc, dp->d_name) >= (int)sizeof(fname)) { - ERROR("Path too long: %s/%s", dirc, dp->d_name); - } - fd = open(fname, O_RDONLY); - if (fd > 0) - TRACE("\t\t**Used for upgrade"); - } - free(buf); - } - - } while ((dp = readdir(path)) !=NULL); - - free(dirc); - free(basec); - closedir(path); - - return fd; -} - -static int install_from_file(char *fname, int check) -{ - int fdsw; - off_t pos; - int ret; - bool encrypted_sw_desc = false; - -#ifdef CONFIG_ENCRYPTED_SW_DESCRIPTION - encrypted_sw_desc = true; -#endif - if (!strlen(fname)) { - ERROR("Image not found...please reboot"); - exit(EXIT_FAILURE); - } - - fdsw = open(fname, O_RDONLY); - if (fdsw < 0) { - fdsw = searching_for_image(fname); - if (fdsw < 0) { - ERROR("Image Software cannot be read...exiting !"); - exit(EXIT_FAILURE); - } - } - - pos = 0; - ret = extract_sw_description(fdsw, SW_DESCRIPTION_FILENAME, &pos, encrypted_sw_desc); -#ifdef CONFIG_SIGNED_IMAGES - ret |= extract_sw_description(fdsw, SW_DESCRIPTION_FILENAME ".sig", - &pos, false); -#endif - /* - * Check if files could be extracted - */ - if (ret) { - ERROR("Failed to extract meta information"); - exit(EXIT_FAILURE); - } - - char* swdescfilename = alloca(strlen(get_tmpdir())+strlen(SW_DESCRIPTION_FILENAME)+1); - sprintf(swdescfilename, "%s%s", get_tmpdir(), SW_DESCRIPTION_FILENAME); - ret = parse(&swcfg, swdescfilename); - if (ret) { - ERROR("failed to parse " SW_DESCRIPTION_FILENAME "!"); - exit(EXIT_FAILURE); - } - - if (check_hw_compatibility(&swcfg)) { - ERROR("SW not compatible with hardware"); - exit(EXIT_FAILURE); - } - - if (cpio_scan(fdsw, &swcfg, pos) < 0) { - ERROR("failed to scan for pos '%lld'!", (long long)pos); - close(fdsw); - exit(EXIT_FAILURE); - } - - /* - * Check if all files described in sw-description - * are in the image - */ - ret = check_provided(&swcfg.images); - if (ret) { - ERROR("failed to check images!"); - exit(EXIT_FAILURE); - } - ret = check_provided(&swcfg.scripts); - if (ret) { - ERROR("failed to check scripts!"); - exit(EXIT_FAILURE); - } - - if (check) { - fprintf(stdout, "successfully checked '%s'\n", fname); - exit(EXIT_SUCCESS); - } - - ret = preupdatecmd(&swcfg); - if (ret) { - ERROR("Failed pre-update command!"); - exit(EXIT_FAILURE); - } - -#ifdef CONFIG_MTD - mtd_cleanup(); - scan_mtd_devices(); -#endif - /* - * Set "recovery_status" as begin of the transaction" - */ - if (!swcfg.globals.dry_run && swcfg.bootloader_transaction_marker) { - save_state_string((char*)BOOTVAR_TRANSACTION, STATE_IN_PROGRESS); - } - - swcfg.globals.dry_run = swcfg.globals.default_dry_run; - ret = install_images(&swcfg, fdsw, 1); - - swupdate_progress_end(ret == 0 ? SUCCESS : FAILURE); - - close(fdsw); - - if (ret) { - fprintf(stdout, "Software update failed\n"); - return EXIT_FAILURE; - } - - if (!swcfg.globals.dry_run && swcfg.bootloader_transaction_marker) { - unset_state((char*)BOOTVAR_TRANSACTION); - } - fprintf(stdout, "Software updated successfully\n"); - fprintf(stdout, "Please reboot the device to start the new software\n"); - - return EXIT_SUCCESS; -} - static int parse_image_selector(const char *selector, struct swupdate_cfg *sw) { char *pos; @@ -641,7 +439,7 @@ int main(int argc, char **argv) const char *software_select = NULL; int opt_i = 0; int opt_e = 0; - int opt_c = 0; + bool opt_c = false; char image_url[MAX_URL]; char main_options[256]; unsigned int public_key_mandatory = 0; @@ -896,7 +694,7 @@ int main(int argc, char **argv) break; #endif case 'c': - opt_c = 1; + opt_c = true; break; case 'p': strlcpy(swcfg.globals.postupdatecmd, optarg, @@ -1012,63 +810,60 @@ int main(int argc, char **argv) get_sw_versions(cfgfname, &swcfg); /* - * Do not start daemon if just a check is required + * Start daemon if just a check is required * SWUpdate will exit after the check */ - if (!opt_c) { - network_daemon = start_thread(network_initializer, &swcfg); + network_daemon = start_thread(network_initializer, &swcfg); - start_thread(progress_bar_thread, NULL); + start_thread(progress_bar_thread, NULL); - /* Start embedded web server */ + /* Start embedded web server */ #if defined(CONFIG_MONGOOSE) - if (opt_w) { - start_subprocess(SOURCE_WEBSERVER, "webserver", - cfgfname, ac, av, - start_mongoose); - freeargs(av); - } + if (opt_w) { + start_subprocess(SOURCE_WEBSERVER, "webserver", + cfgfname, ac, av, + start_mongoose); + freeargs(av); + } #endif #if defined(CONFIG_SURICATTA) - if (opt_u) { - start_subprocess(SOURCE_SURICATTA, "suricatta", - cfgfname, argcount, - argvalues, start_suricatta); + if (opt_u) { + start_subprocess(SOURCE_SURICATTA, "suricatta", + cfgfname, argcount, + argvalues, start_suricatta); - freeargs(argvalues); - } + freeargs(argvalues); + } #endif #ifdef CONFIG_DOWNLOAD - if (opt_d) { - start_subprocess(SOURCE_DOWNLOADER, "download", - cfgfname, dwlac, - dwlav, start_download); - freeargs(dwlav); - } + if (opt_d) { + start_subprocess(SOURCE_DOWNLOADER, "download", + cfgfname, dwlac, + dwlav, start_download); + freeargs(dwlav); + } #endif - /* - * Start all processes added in the config file - */ - struct extproc *proc; + /* + * Start all processes added in the config file + */ + struct extproc *proc; - LIST_FOREACH(proc, &swcfg.extprocs, next) { - dwlav = splitargs(proc->exec, &dwlac); + LIST_FOREACH(proc, &swcfg.extprocs, next) { + dwlav = splitargs(proc->exec, &dwlac); - dwlav[dwlac] = NULL; + dwlav[dwlac] = NULL; - start_subprocess_from_file(SOURCE_UNKNOWN, proc->name, - cfgfname, dwlac, - dwlav, dwlav[0]); + start_subprocess_from_file(SOURCE_UNKNOWN, proc->name, + cfgfname, dwlac, + dwlav, dwlav[0]); - freeargs(dwlav); - } + freeargs(dwlav); } if (opt_i) { - result = install_from_file(fname, opt_c); switch (result) { case EXIT_FAILURE: diff --git a/include/installer.h b/include/installer.h index 1351603..9fe5f2b 100644 --- a/include/installer.h +++ b/include/installer.h @@ -9,6 +9,7 @@ #ifndef _INSTALLER_H #define _INSTALLER_H +#include #include "swupdate.h" #include "handler.h" #include "cpiohdr.h" @@ -16,8 +17,9 @@ int check_if_required(struct imglist *list, struct filehdr *pfdh, const char *destdir, struct img_type **pimg); -int install_images(struct swupdate_cfg *sw, int fdsw, int fromfile); +int install_images(struct swupdate_cfg *sw); int install_single_image(struct img_type *img, int dry_run); +int install_from_file(const char *filename, bool check); int postupdate(struct swupdate_cfg *swcfg, const char *info); int preupdatecmd(struct swupdate_cfg *swcfg); void cleanup_files(struct swupdate_cfg *software);