auc: update to version 0.0.9
* use full package list when checking for upgrades * verify sha256sums and usign signature of sha256sums.sig * introduce '-c' option to only check if system is up-to-date * introduce '-F' option to ignore the signature verification result * return -1 on locally caused and -2 on server-side errors * don't include locally appended attributes in debug output of a server reply * output bug report note on 412 target not found * use content-length header instead of filesize field in JSON content * suppress duplicate error messages * drop unused attributes * make debug messages optional at compile-time Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
parent
2be807285a
commit
8162fecb37
2 changed files with 302 additions and 122 deletions
|
@ -5,8 +5,8 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=auc
|
PKG_NAME:=auc
|
||||||
PKG_VERSION:=0.0.8
|
PKG_VERSION:=0.0.9
|
||||||
PKG_RELEASE=1
|
PKG_RELEASE:=1
|
||||||
PKG_LICENSE:=GPL-3.0
|
PKG_LICENSE:=GPL-3.0
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
@ -24,6 +24,12 @@ define Package/auc/description
|
||||||
CLI client for attended-sysupgrade
|
CLI client for attended-sysupgrade
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
# set to 1 to enable debugging
|
||||||
|
DEBUG:=1
|
||||||
|
|
||||||
|
EXTRA_CFLAGS += \
|
||||||
|
$(if $(DEBUG),-DAUC_DEBUG=ON)
|
||||||
|
|
||||||
define Package/auc/install
|
define Package/auc/install
|
||||||
$(INSTALL_DIR) $(1)/usr/sbin
|
$(INSTALL_DIR) $(1)/usr/sbin
|
||||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/auc $(1)/usr/sbin/
|
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/auc $(1)/usr/sbin/
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#define AUC_VERSION "0.0.8"
|
#define AUC_VERSION "0.0.9"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
@ -39,6 +39,16 @@
|
||||||
#define APIOBJ_CHECK "api/upgrade-check"
|
#define APIOBJ_CHECK "api/upgrade-check"
|
||||||
#define APIOBJ_REQUEST "api/upgrade-request"
|
#define APIOBJ_REQUEST "api/upgrade-request"
|
||||||
|
|
||||||
|
#define PUBKEY_PATH "/etc/opkg/keys"
|
||||||
|
|
||||||
|
#ifdef AUC_DEBUG
|
||||||
|
#define DPRINTF(...) if (debug) fprintf(stderr, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DPRINTF(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char server_issues[]="https://github.com/aparcar/attendedsysupgrade-server/issues";
|
||||||
|
|
||||||
static char user_agent[80];
|
static char user_agent[80];
|
||||||
static char *serverurl;
|
static char *serverurl;
|
||||||
static int upgrade_packages;
|
static int upgrade_packages;
|
||||||
|
@ -52,30 +62,26 @@ static int output_fd = -1;
|
||||||
static int retry, imagebuilder, building, ibready;
|
static int retry, imagebuilder, building, ibready;
|
||||||
static char *board_name = NULL;
|
static char *board_name = NULL;
|
||||||
static char *target = NULL, *subtarget = NULL;
|
static char *target = NULL, *subtarget = NULL;
|
||||||
static char *distribution = NULL, *version = NULL, *revision = NULL;
|
static char *distribution = NULL, *version = NULL;
|
||||||
static int uptodate;
|
static int uptodate;
|
||||||
static char *filename = NULL;
|
static char *filename = NULL;
|
||||||
|
static int rc;
|
||||||
|
|
||||||
|
#ifdef AUC_DEBUG
|
||||||
static int debug = 0;
|
static int debug = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* policy for ubus call system board
|
* policy for ubus call system board
|
||||||
* see procd/system.c
|
* see procd/system.c
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
BOARD_KERNEL,
|
|
||||||
BOARD_HOSTNAME,
|
|
||||||
BOARD_SYSTEM,
|
|
||||||
BOARD_MODEL,
|
|
||||||
BOARD_BOARD_NAME,
|
BOARD_BOARD_NAME,
|
||||||
BOARD_RELEASE,
|
BOARD_RELEASE,
|
||||||
__BOARD_MAX,
|
__BOARD_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct blobmsg_policy board_policy[__BOARD_MAX] = {
|
static const struct blobmsg_policy board_policy[__BOARD_MAX] = {
|
||||||
[BOARD_KERNEL] = { .name = "kernel", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
[BOARD_HOSTNAME] = { .name = "hostname", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
[BOARD_SYSTEM] = { .name = "system", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
[BOARD_MODEL] = { .name = "model", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
[BOARD_BOARD_NAME] = { .name = "board_name", .type = BLOBMSG_TYPE_STRING },
|
[BOARD_BOARD_NAME] = { .name = "board_name", .type = BLOBMSG_TYPE_STRING },
|
||||||
[BOARD_RELEASE] = { .name = "release", .type = BLOBMSG_TYPE_TABLE },
|
[BOARD_RELEASE] = { .name = "release", .type = BLOBMSG_TYPE_TABLE },
|
||||||
};
|
};
|
||||||
|
@ -87,20 +93,14 @@ static const struct blobmsg_policy board_policy[__BOARD_MAX] = {
|
||||||
enum {
|
enum {
|
||||||
RELEASE_DISTRIBUTION,
|
RELEASE_DISTRIBUTION,
|
||||||
RELEASE_VERSION,
|
RELEASE_VERSION,
|
||||||
RELEASE_REVISION,
|
|
||||||
RELEASE_CODENAME,
|
|
||||||
RELEASE_TARGET,
|
RELEASE_TARGET,
|
||||||
RELEASE_DESCRIPTION,
|
|
||||||
__RELEASE_MAX,
|
__RELEASE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct blobmsg_policy release_policy[__RELEASE_MAX] = {
|
static const struct blobmsg_policy release_policy[__RELEASE_MAX] = {
|
||||||
[RELEASE_DISTRIBUTION] = { .name = "distribution", .type = BLOBMSG_TYPE_STRING },
|
[RELEASE_DISTRIBUTION] = { .name = "distribution", .type = BLOBMSG_TYPE_STRING },
|
||||||
[RELEASE_VERSION] = { .name = "version", .type = BLOBMSG_TYPE_STRING },
|
[RELEASE_VERSION] = { .name = "version", .type = BLOBMSG_TYPE_STRING },
|
||||||
[RELEASE_REVISION] = { .name = "revision", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
[RELEASE_CODENAME] = { .name = "codename", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
[RELEASE_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
|
[RELEASE_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
|
||||||
[RELEASE_DESCRIPTION] = { .name = "description", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -146,6 +146,11 @@ static const struct blobmsg_policy check_policy[__CHECK_MAX] = {
|
||||||
[CHECK_UPGRADES] = { .name = "upgrades", .type = BLOBMSG_TYPE_TABLE },
|
[CHECK_UPGRADES] = { .name = "upgrades", .type = BLOBMSG_TYPE_TABLE },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct blobmsg_policy pkg_upgrades_policy[2] = {
|
||||||
|
{ .type = BLOBMSG_TYPE_STRING },
|
||||||
|
{ .type = BLOBMSG_TYPE_STRING },
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* policy for upgrade-request response
|
* policy for upgrade-request response
|
||||||
* parse download information for the ready image.
|
* parse download information for the ready image.
|
||||||
|
@ -162,19 +167,37 @@ enum {
|
||||||
|
|
||||||
static const struct blobmsg_policy image_policy[__IMAGE_MAX] = {
|
static const struct blobmsg_policy image_policy[__IMAGE_MAX] = {
|
||||||
[IMAGE_REQHASH] = { .name = "request_hash", .type = BLOBMSG_TYPE_STRING },
|
[IMAGE_REQHASH] = { .name = "request_hash", .type = BLOBMSG_TYPE_STRING },
|
||||||
[IMAGE_FILESIZE] = { .name = "filesize", .type = BLOBMSG_TYPE_INT32 },
|
|
||||||
[IMAGE_URL] = { .name = "url", .type = BLOBMSG_TYPE_STRING },
|
[IMAGE_URL] = { .name = "url", .type = BLOBMSG_TYPE_STRING },
|
||||||
[IMAGE_CHECKSUM] = { .name = "checksum", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
[IMAGE_FILES] = { .name = "files", .type = BLOBMSG_TYPE_STRING },
|
[IMAGE_FILES] = { .name = "files", .type = BLOBMSG_TYPE_STRING },
|
||||||
[IMAGE_SYSUPGRADE] = { .name = "sysupgrade", .type = BLOBMSG_TYPE_STRING },
|
[IMAGE_SYSUPGRADE] = { .name = "sysupgrade", .type = BLOBMSG_TYPE_STRING },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* policy for HTTP headers received from server
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
H_RANGE,
|
||||||
|
H_LEN,
|
||||||
|
H_IBSTATUS,
|
||||||
|
H_IBQUEUEPOS,
|
||||||
|
H_UNKNOWN_PACKAGE,
|
||||||
|
__H_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct blobmsg_policy policy[__H_MAX] = {
|
||||||
|
[H_RANGE] = { .name = "content-range", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[H_LEN] = { .name = "content-length", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[H_IBSTATUS] = { .name = "x-imagebuilder-status", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[H_IBQUEUEPOS] = { .name = "x-build-queue-position", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[H_UNKNOWN_PACKAGE] = { .name = "x-unknown-package", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* load serverurl from UCI
|
* load serverurl from UCI
|
||||||
*/
|
*/
|
||||||
static int load_config() {
|
static int load_config() {
|
||||||
static struct uci_context *uci_ctx;
|
struct uci_context *uci_ctx;
|
||||||
static struct uci_package *uci_attendedsysupgrade;
|
struct uci_package *uci_attendedsysupgrade;
|
||||||
struct uci_section *uci_s;
|
struct uci_section *uci_s;
|
||||||
|
|
||||||
uci_ctx = uci_alloc_context();
|
uci_ctx = uci_alloc_context();
|
||||||
|
@ -217,20 +240,47 @@ static int load_config() {
|
||||||
* rpc-sys packagelist
|
* rpc-sys packagelist
|
||||||
* append packagelist response to blobbuf given in req->priv
|
* append packagelist response to blobbuf given in req->priv
|
||||||
*/
|
*/
|
||||||
static void pkglist_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
|
static void pkglist_check_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
|
||||||
struct blob_buf *buf = (struct blob_buf *)req->priv;
|
struct blob_buf *buf = (struct blob_buf *)req->priv;
|
||||||
struct blob_attr *tb[__PACKAGELIST_MAX];
|
struct blob_attr *tb[__PACKAGELIST_MAX];
|
||||||
|
|
||||||
blobmsg_parse(packagelist_policy, __PACKAGELIST_MAX, tb, blob_data(msg), blob_len(msg));
|
blobmsg_parse(packagelist_policy, __PACKAGELIST_MAX, tb, blob_data(msg), blob_len(msg));
|
||||||
|
|
||||||
|
if (!tb[PACKAGELIST_PACKAGES]) {
|
||||||
|
fprintf(stderr, "No packagelist received\n");
|
||||||
|
rc=-1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
blobmsg_add_field(buf, BLOBMSG_TYPE_TABLE, "packages", blobmsg_data(tb[PACKAGELIST_PACKAGES]), blobmsg_data_len(tb[PACKAGELIST_PACKAGES]));
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rpc-sys packagelist
|
||||||
|
* append array of package names to blobbuf given in req->priv
|
||||||
|
*/
|
||||||
|
static void pkglist_req_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
|
||||||
|
struct blob_buf *buf = (struct blob_buf *)req->priv;
|
||||||
|
struct blob_attr *tb[__PACKAGELIST_MAX];
|
||||||
|
struct blob_attr *cur;
|
||||||
|
int rem;
|
||||||
|
void *array;
|
||||||
|
|
||||||
|
blobmsg_parse(packagelist_policy, __PACKAGELIST_MAX, tb, blob_data(msg), blob_len(msg));
|
||||||
|
|
||||||
if (!tb[PACKAGELIST_PACKAGES]) {
|
if (!tb[PACKAGELIST_PACKAGES]) {
|
||||||
fprintf(stderr, "No packagelist received\n");
|
fprintf(stderr, "No packagelist received\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blobmsg_add_field(buf, BLOBMSG_TYPE_TABLE, "packages", blobmsg_data(tb[PACKAGELIST_PACKAGES]), blobmsg_data_len(tb[PACKAGELIST_PACKAGES]));
|
array = blobmsg_open_array(buf, "packages");
|
||||||
|
blobmsg_for_each_attr(cur, tb[PACKAGELIST_PACKAGES], rem)
|
||||||
|
blobmsg_add_string(buf, NULL, blobmsg_name(cur));
|
||||||
|
|
||||||
|
blobmsg_close_array(buf, array);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* system board
|
* system board
|
||||||
* append append board information to blobbuf given in req->priv
|
* append append board information to blobbuf given in req->priv
|
||||||
|
@ -245,12 +295,14 @@ static void board_cb(struct ubus_request *req, int type, struct blob_attr *msg)
|
||||||
|
|
||||||
if (!tb[BOARD_BOARD_NAME]) {
|
if (!tb[BOARD_BOARD_NAME]) {
|
||||||
fprintf(stderr, "No board name received\n");
|
fprintf(stderr, "No board name received\n");
|
||||||
|
rc=-1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
board_name = strdup(blobmsg_get_string(tb[BOARD_BOARD_NAME]));
|
board_name = strdup(blobmsg_get_string(tb[BOARD_BOARD_NAME]));
|
||||||
|
|
||||||
if (!tb[BOARD_RELEASE]) {
|
if (!tb[BOARD_RELEASE]) {
|
||||||
fprintf(stderr, "No release received\n");
|
fprintf(stderr, "No release received\n");
|
||||||
|
rc=-1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,6 +311,7 @@ static void board_cb(struct ubus_request *req, int type, struct blob_attr *msg)
|
||||||
|
|
||||||
if (!rel[RELEASE_TARGET]) {
|
if (!rel[RELEASE_TARGET]) {
|
||||||
fprintf(stderr, "No target received\n");
|
fprintf(stderr, "No target received\n");
|
||||||
|
rc=-1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +321,6 @@ static void board_cb(struct ubus_request *req, int type, struct blob_attr *msg)
|
||||||
|
|
||||||
distribution = strdup(blobmsg_get_string(rel[RELEASE_DISTRIBUTION]));
|
distribution = strdup(blobmsg_get_string(rel[RELEASE_DISTRIBUTION]));
|
||||||
version = strdup(blobmsg_get_string(rel[RELEASE_VERSION]));
|
version = strdup(blobmsg_get_string(rel[RELEASE_VERSION]));
|
||||||
revision = strdup(blobmsg_get_string(rel[RELEASE_REVISION]));
|
|
||||||
|
|
||||||
blobmsg_add_string(buf, "distro", distribution);
|
blobmsg_add_string(buf, "distro", distribution);
|
||||||
blobmsg_add_string(buf, "target", target);
|
blobmsg_add_string(buf, "target", target);
|
||||||
|
@ -354,19 +406,6 @@ static void request_done(struct uclient *cl)
|
||||||
|
|
||||||
static void header_done_cb(struct uclient *cl)
|
static void header_done_cb(struct uclient *cl)
|
||||||
{
|
{
|
||||||
enum {
|
|
||||||
H_RANGE,
|
|
||||||
H_LEN,
|
|
||||||
H_IBSTATUS,
|
|
||||||
H_IBQUEUEPOS,
|
|
||||||
__H_MAX
|
|
||||||
};
|
|
||||||
static const struct blobmsg_policy policy[__H_MAX] = {
|
|
||||||
[H_RANGE] = { .name = "content-range", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
[H_LEN] = { .name = "content-length", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
[H_IBSTATUS] = { .name = "x-imagebuilder-status", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
[H_IBQUEUEPOS] = { .name = "x-build-queue-position", .type = BLOBMSG_TYPE_STRING },
|
|
||||||
};
|
|
||||||
struct blob_attr *tb[__H_MAX];
|
struct blob_attr *tb[__H_MAX];
|
||||||
uint64_t resume_offset = 0, resume_end, resume_size;
|
uint64_t resume_offset = 0, resume_end, resume_size;
|
||||||
char *ibstatus;
|
char *ibstatus;
|
||||||
|
@ -385,21 +424,24 @@ static void header_done_cb(struct uclient *cl)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug)
|
DPRINTF("headers:\n%s\n", blobmsg_format_json_indent(cl->meta, true, 0));
|
||||||
fprintf(stderr, "headers:\n%s\n", blobmsg_format_json_indent(cl->meta, true, 0));
|
|
||||||
|
|
||||||
blobmsg_parse(policy, __H_MAX, tb, blob_data(cl->meta), blob_len(cl->meta));
|
blobmsg_parse(policy, __H_MAX, tb, blob_data(cl->meta), blob_len(cl->meta));
|
||||||
|
|
||||||
switch (cl->status_code) {
|
switch (cl->status_code) {
|
||||||
case 400:
|
case 400:
|
||||||
request_done(cl);
|
request_done(cl);
|
||||||
|
rc=-1;
|
||||||
break;
|
break;
|
||||||
case 412:
|
case 412:
|
||||||
fprintf(stderr, "target not found.\n");
|
fprintf(stderr, "%s target %s/%s (%s) not found. Please report this at %s\n",
|
||||||
|
distribution, target, subtarget, board_name, server_issues);
|
||||||
request_done(cl);
|
request_done(cl);
|
||||||
|
rc=-2;
|
||||||
break;
|
break;
|
||||||
case 413:
|
case 413:
|
||||||
fprintf(stderr, "image too big.\n");
|
fprintf(stderr, "image too big.\n");
|
||||||
|
rc=-1;
|
||||||
request_done(cl);
|
request_done(cl);
|
||||||
break;
|
break;
|
||||||
case 416:
|
case 416:
|
||||||
|
@ -407,16 +449,20 @@ static void header_done_cb(struct uclient *cl)
|
||||||
request_done(cl);
|
request_done(cl);
|
||||||
break;
|
break;
|
||||||
case 422:
|
case 422:
|
||||||
fprintf(stderr, "unknown package requested.\n");
|
fprintf(stderr, "unknown package '%s' requested.\n",
|
||||||
|
blobmsg_get_string(tb[H_UNKNOWN_PACKAGE]));
|
||||||
|
rc=-1;
|
||||||
request_done(cl);
|
request_done(cl);
|
||||||
break;
|
break;
|
||||||
case 501:
|
case 501:
|
||||||
fprintf(stderr, "ImageBuilder didn't produce sysupgrade file.\n");
|
fprintf(stderr, "ImageBuilder didn't produce sysupgrade file.\n");
|
||||||
|
rc=-2;
|
||||||
request_done(cl);
|
request_done(cl);
|
||||||
break;
|
break;
|
||||||
case 204:
|
case 204:
|
||||||
fprintf(stderr, "system is up to date.\n");
|
fprintf(stdout, "system is up to date.\n");
|
||||||
uptodate=1;
|
uptodate=1;
|
||||||
|
request_done(cl);
|
||||||
break;
|
break;
|
||||||
case 206:
|
case 206:
|
||||||
if (!cur_resume) {
|
if (!cur_resume) {
|
||||||
|
@ -467,6 +513,7 @@ static void header_done_cb(struct uclient *cl)
|
||||||
retry=1;
|
retry=1;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "unrecognized remote imagebuilder status '%s'\n", ibstatus);
|
fprintf(stderr, "unrecognized remote imagebuilder status '%s'\n", ibstatus);
|
||||||
|
rc=-2;
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 200:
|
case 200:
|
||||||
|
@ -657,45 +704,95 @@ static int init_ustream_ssl(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* use busybox md5sum (from jow's luci-ng)
|
* use busybox sha256sum to verify sha256sums file
|
||||||
*/
|
*/
|
||||||
static char *md5sum(const char *file) {
|
static int sha256sum_v(const char *sha256file, const char *msgfile) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int fds[2];
|
int fds[2];
|
||||||
static char md5[33];
|
int status;
|
||||||
|
FILE *f = fopen(sha256file, "r");
|
||||||
|
char sumline[512] = {};
|
||||||
|
char *fname;
|
||||||
|
unsigned int fnlen;
|
||||||
|
unsigned int cnt = 0;
|
||||||
|
|
||||||
if (pipe(fds))
|
if (pipe(fds))
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
switch ((pid = fork()))
|
if (!f)
|
||||||
{
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
switch (pid) {
|
||||||
case -1:
|
case -1:
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
uloop_done();
|
uloop_done();
|
||||||
|
|
||||||
dup2(fds[1], 1);
|
dup2(fds[0], 0);
|
||||||
|
close(1);
|
||||||
close(0);
|
|
||||||
close(2);
|
close(2);
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
|
if (execl("/bin/busybox", "/bin/busybox", "sha256sum", "-s", "-c", NULL));
|
||||||
if (execl("/bin/busybox", "/bin/busybox", "md5sum", file, NULL));
|
return -1;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
memset(md5, 0, sizeof(md5));
|
while (fgets(sumline, sizeof(sumline), f)) {
|
||||||
read(fds[0], md5, 32);
|
fname = &sumline[66];
|
||||||
waitpid(pid, NULL, 0);
|
fnlen = strlen(fname);
|
||||||
close(fds[0]);
|
fname[fnlen-1] = '\0';
|
||||||
|
if (!strcmp(fname, msgfile)) {
|
||||||
|
fname[fnlen-1] = '\n';
|
||||||
|
write(fds[1], sumline, strlen(sumline));
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
close(fds[0]);
|
||||||
|
|
||||||
|
if (cnt == 1)
|
||||||
|
return WEXITSTATUS(status);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return md5;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* use usign to verify sha256sums.sig
|
||||||
|
*/
|
||||||
|
static int usign_v(const char *file) {
|
||||||
|
pid_t pid;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
switch (pid) {
|
||||||
|
case -1:
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
uloop_done();
|
||||||
|
|
||||||
|
if (execl("/usr/bin/usign", "/usr/bin/usign",
|
||||||
|
"-V", "-q", "-P", PUBKEY_PATH, "-m", file, NULL));
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
return WEXITSTATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ask_user(void)
|
static int ask_user(void)
|
||||||
|
@ -711,13 +808,8 @@ static void print_package_updates(struct blob_attr *upgrades) {
|
||||||
struct blob_attr *tb[2];
|
struct blob_attr *tb[2];
|
||||||
int rem;
|
int rem;
|
||||||
|
|
||||||
static struct blobmsg_policy policy[2] = {
|
|
||||||
{ .type = BLOBMSG_TYPE_STRING },
|
|
||||||
{ .type = BLOBMSG_TYPE_STRING },
|
|
||||||
};
|
|
||||||
|
|
||||||
blobmsg_for_each_attr(cur, upgrades, rem) {
|
blobmsg_for_each_attr(cur, upgrades, rem) {
|
||||||
blobmsg_parse_array(policy, ARRAY_SIZE(policy), tb, blobmsg_data(cur), blobmsg_data_len(cur));
|
blobmsg_parse_array(pkg_upgrades_policy, ARRAY_SIZE(policy), tb, blobmsg_data(cur), blobmsg_data_len(cur));
|
||||||
if (!tb[0] || !tb[1])
|
if (!tb[0] || !tb[1])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -728,19 +820,19 @@ static void print_package_updates(struct blob_attr *upgrades) {
|
||||||
|
|
||||||
/* this main function is too big... todo: split */
|
/* this main function is too big... todo: split */
|
||||||
int main(int args, char *argv[]) {
|
int main(int args, char *argv[]) {
|
||||||
unsigned char argc=1;
|
static struct blob_buf allpkg, checkbuf, infobuf, reqbuf, imgbuf, upgbuf;
|
||||||
static struct blob_buf checkbuf, reqbuf, imgbuf, upgbuf;
|
|
||||||
struct ubus_context *ctx = ubus_connect(NULL);
|
struct ubus_context *ctx = ubus_connect(NULL);
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
int rc;
|
int valid, use_get;
|
||||||
int queuepos, valid, use_get;
|
|
||||||
char url[256];
|
char url[256];
|
||||||
char *newversion = NULL;
|
char *newversion = NULL;
|
||||||
struct blob_attr *tb[__IMAGE_MAX];
|
struct blob_attr *tb[__IMAGE_MAX];
|
||||||
struct blob_attr *tbc[__CHECK_MAX];
|
struct blob_attr *tbc[__CHECK_MAX];
|
||||||
unsigned int filesize;
|
char *tmp;
|
||||||
char *checksum = NULL;
|
|
||||||
struct stat imgstat;
|
struct stat imgstat;
|
||||||
|
int check_only = 0;
|
||||||
|
int ignore_sig = 0;
|
||||||
|
unsigned char argc = 1;
|
||||||
|
|
||||||
snprintf(user_agent, sizeof(user_agent), "%s (%s)", argv[0], AUC_VERSION);
|
snprintf(user_agent, sizeof(user_agent), "%s (%s)", argv[0], AUC_VERSION);
|
||||||
fprintf(stdout, "%s\n", user_agent);
|
fprintf(stdout, "%s\n", user_agent);
|
||||||
|
@ -750,12 +842,25 @@ int main(int args, char *argv[]) {
|
||||||
!strncmp(argv[argc], "--help", 7)) {
|
!strncmp(argv[argc], "--help", 7)) {
|
||||||
fprintf(stdout, "%s: Attended sysUpgrade CLI client\n", argv[0]);
|
fprintf(stdout, "%s: Attended sysUpgrade CLI client\n", argv[0]);
|
||||||
fprintf(stdout, "Usage: auc [-d] [-h]\n");
|
fprintf(stdout, "Usage: auc [-d] [-h]\n");
|
||||||
|
fprintf(stdout, " -c\tonly check if system is up-to-date\n");
|
||||||
|
fprintf(stdout, " -F\tignore result of signature verification\n");
|
||||||
|
#ifdef AUC_DEBUG
|
||||||
fprintf(stdout, " -d\tenable debugging output\n");
|
fprintf(stdout, " -d\tenable debugging output\n");
|
||||||
|
#endif
|
||||||
fprintf(stdout, " -h\toutput help\n");
|
fprintf(stdout, " -h\toutput help\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef AUC_DEBUG
|
||||||
if (!strncmp(argv[argc], "-d", 3))
|
if (!strncmp(argv[argc], "-d", 3))
|
||||||
debug = 1;
|
debug = 1;
|
||||||
|
#endif
|
||||||
|
if (!strncmp(argv[argc], "-c", 3))
|
||||||
|
check_only = 1;
|
||||||
|
|
||||||
|
if (!strncmp(argv[argc], "-F", 3))
|
||||||
|
ignore_sig = 1;
|
||||||
|
|
||||||
argc++;
|
argc++;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -787,9 +892,12 @@ int main(int args, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
blobmsg_buf_init(&checkbuf);
|
blobmsg_buf_init(&checkbuf);
|
||||||
|
blobmsg_buf_init(&infobuf);
|
||||||
blobmsg_buf_init(&reqbuf);
|
blobmsg_buf_init(&reqbuf);
|
||||||
blobmsg_buf_init(&imgbuf);
|
blobmsg_buf_init(&imgbuf);
|
||||||
blobmsg_buf_init(&upgbuf);
|
/* ubus requires BLOBMSG_TYPE_UNSPEC */
|
||||||
|
blob_buf_init(&allpkg, 0);
|
||||||
|
blob_buf_init(&upgbuf, 0);
|
||||||
|
|
||||||
if (ubus_lookup_id(ctx, "system", &id) ||
|
if (ubus_lookup_id(ctx, "system", &id) ||
|
||||||
ubus_invoke(ctx, id, "board", NULL, board_cb, &checkbuf, 3000)) {
|
ubus_invoke(ctx, id, "board", NULL, board_cb, &checkbuf, 3000)) {
|
||||||
|
@ -798,34 +906,37 @@ int main(int args, char *argv[]) {
|
||||||
goto freebufs;
|
goto freebufs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
goto freebufs;
|
||||||
|
|
||||||
|
blobmsg_add_u8(&allpkg, "all", 1);
|
||||||
|
blobmsg_add_string(&allpkg, "dummy", "foo");
|
||||||
if (ubus_lookup_id(ctx, "rpc-sys", &id) ||
|
if (ubus_lookup_id(ctx, "rpc-sys", &id) ||
|
||||||
ubus_invoke(ctx, id, "packagelist", NULL, pkglist_cb, &checkbuf, 3000)) {
|
ubus_invoke(ctx, id, "packagelist", allpkg.head, pkglist_check_cb, &checkbuf, 3000)) {
|
||||||
fprintf(stderr, "cannot request packagelist from rpcd\n");
|
fprintf(stderr, "cannot request packagelist from rpcd\n");
|
||||||
rc=-1;
|
rc=-1;
|
||||||
goto freeboard;
|
goto freeboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
goto freeboard;
|
||||||
|
|
||||||
blobmsg_add_u32(&checkbuf, "upgrade_packages", upgrade_packages);
|
blobmsg_add_u32(&checkbuf, "upgrade_packages", upgrade_packages);
|
||||||
|
|
||||||
fprintf(stdout, "running %s %s %s on %s/%s (%s)\n", distribution,
|
fprintf(stdout, "running %s %s on %s/%s (%s)\n", distribution,
|
||||||
version, revision, target, subtarget, board_name);
|
version, target, subtarget, board_name);
|
||||||
|
|
||||||
fprintf(stdout, "checking %s for release upgrade%s\n", serverurl,
|
fprintf(stdout, "checking %s for release upgrade%s\n", serverurl,
|
||||||
upgrade_packages?" or updated packages":"");
|
upgrade_packages?" or updated packages":"");
|
||||||
|
|
||||||
blobmsg_add_string(&reqbuf, "distro", distribution);
|
|
||||||
blobmsg_add_string(&reqbuf, "target", target);
|
|
||||||
blobmsg_add_string(&reqbuf, "subtarget", subtarget);
|
|
||||||
blobmsg_add_string(&reqbuf, "board", board_name);
|
|
||||||
|
|
||||||
snprintf(url, sizeof(url), "%s/%s", serverurl, APIOBJ_CHECK);
|
snprintf(url, sizeof(url), "%s/%s", serverurl, APIOBJ_CHECK);
|
||||||
uptodate=0;
|
uptodate=0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
retry=0;
|
retry=0;
|
||||||
if (debug)
|
DPRINTF("requesting:\n%s\n", blobmsg_format_json_indent(checkbuf.head, true, 0));
|
||||||
fprintf(stderr, "requesting:\n%s\n", blobmsg_format_json_indent(checkbuf.head, true, 0));
|
if (server_request(url, &checkbuf, &infobuf)) {
|
||||||
if (server_request(url, &checkbuf, &reqbuf)) {
|
|
||||||
fprintf(stderr, "failed to connect to server\n");
|
fprintf(stderr, "failed to connect to server\n");
|
||||||
rc=-1;
|
rc=-1;
|
||||||
goto freeboard;
|
goto freeboard;
|
||||||
|
@ -835,20 +946,20 @@ int main(int args, char *argv[]) {
|
||||||
sleep(3);
|
sleep(3);
|
||||||
} while(retry);
|
} while(retry);
|
||||||
|
|
||||||
if (debug)
|
DPRINTF("reply:\n%s\n", blobmsg_format_json_indent(infobuf.head, true, 0));
|
||||||
fprintf(stderr, "reply:\n%s\n", blobmsg_format_json_indent(reqbuf.head, true, 0));
|
|
||||||
|
|
||||||
blobmsg_parse(check_policy, __CHECK_MAX, tbc, blob_data(reqbuf.head), blob_len(reqbuf.head));
|
blobmsg_parse(check_policy, __CHECK_MAX, tbc, blob_data(infobuf.head), blob_len(infobuf.head));
|
||||||
|
|
||||||
if (!tbc[CHECK_VERSION] && !tbc[CHECK_UPGRADES]) {
|
if (!tbc[CHECK_VERSION] && !tbc[CHECK_UPGRADES]) {
|
||||||
if (!uptodate) {
|
if (uptodate) {
|
||||||
|
rc=0;
|
||||||
|
} else if (!rc) {
|
||||||
fprintf(stderr, "server reply invalid.\n");
|
fprintf(stderr, "server reply invalid.\n");
|
||||||
rc=-1;
|
rc=-2;
|
||||||
goto freeboard;
|
|
||||||
}
|
}
|
||||||
rc=0;
|
|
||||||
goto freeboard;
|
goto freeboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tbc[CHECK_VERSION]) {
|
if (tbc[CHECK_VERSION]) {
|
||||||
newversion = blobmsg_get_string(tbc[CHECK_VERSION]);
|
newversion = blobmsg_get_string(tbc[CHECK_VERSION]);
|
||||||
fprintf(stdout, "new %s release %s found.\n", distribution, newversion);
|
fprintf(stdout, "new %s release %s found.\n", distribution, newversion);
|
||||||
|
@ -862,10 +973,29 @@ int main(int args, char *argv[]) {
|
||||||
print_package_updates(tbc[CHECK_UPGRADES]);
|
print_package_updates(tbc[CHECK_UPGRADES]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_only) {
|
||||||
|
rc=1;
|
||||||
|
goto freeboard;
|
||||||
|
};
|
||||||
|
|
||||||
rc = ask_user();
|
rc = ask_user();
|
||||||
if (rc)
|
if (rc)
|
||||||
goto freeboard;
|
goto freeboard;
|
||||||
|
|
||||||
|
blobmsg_add_string(&reqbuf, "distro", distribution);
|
||||||
|
blobmsg_add_string(&reqbuf, "target", target);
|
||||||
|
blobmsg_add_string(&reqbuf, "subtarget", subtarget);
|
||||||
|
blobmsg_add_string(&reqbuf, "board", board_name);
|
||||||
|
|
||||||
|
blob_buf_init(&allpkg, 0);
|
||||||
|
blobmsg_add_u8(&allpkg, "all", 0);
|
||||||
|
blobmsg_add_string(&allpkg, "dummy", "foo");
|
||||||
|
if (ubus_invoke(ctx, id, "packagelist", allpkg.head, pkglist_req_cb, &reqbuf, 3000)) {
|
||||||
|
fprintf(stderr, "cannot request packagelist from rpcd\n");
|
||||||
|
rc=-1;
|
||||||
|
goto freeboard;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(url, sizeof(url), "%s/%s", serverurl, APIOBJ_REQUEST);
|
snprintf(url, sizeof(url), "%s/%s", serverurl, APIOBJ_REQUEST);
|
||||||
|
|
||||||
imagebuilder = 0;
|
imagebuilder = 0;
|
||||||
|
@ -875,8 +1005,7 @@ int main(int args, char *argv[]) {
|
||||||
do {
|
do {
|
||||||
retry = 0;
|
retry = 0;
|
||||||
|
|
||||||
if (debug && !use_get)
|
DPRINTF("requesting:\n%s\n", use_get?"":blobmsg_format_json_indent(reqbuf.head, true, 0));
|
||||||
fprintf(stderr, "requesting:\n%s\n", blobmsg_format_json_indent(reqbuf.head, true, 0));
|
|
||||||
|
|
||||||
server_request(url, use_get?NULL:&reqbuf, &imgbuf);
|
server_request(url, use_get?NULL:&reqbuf, &imgbuf);
|
||||||
blobmsg_parse(image_policy, __IMAGE_MAX, tb, blob_data(imgbuf.head), blob_len(imgbuf.head));
|
blobmsg_parse(image_policy, __IMAGE_MAX, tb, blob_data(imgbuf.head), blob_len(imgbuf.head));
|
||||||
|
@ -885,9 +1014,7 @@ int main(int args, char *argv[]) {
|
||||||
snprintf(url, sizeof(url), "%s/%s/%s", serverurl,
|
snprintf(url, sizeof(url), "%s/%s/%s", serverurl,
|
||||||
APIOBJ_REQUEST,
|
APIOBJ_REQUEST,
|
||||||
blobmsg_get_string(tb[IMAGE_REQHASH]));
|
blobmsg_get_string(tb[IMAGE_REQHASH]));
|
||||||
if (debug)
|
DPRINTF("polling via GET %s\n", url);
|
||||||
fprintf(stderr, "polling via GET %s\n", url);
|
|
||||||
|
|
||||||
retry=1;
|
retry=1;
|
||||||
use_get=1;
|
use_get=1;
|
||||||
}
|
}
|
||||||
|
@ -897,35 +1024,22 @@ int main(int args, char *argv[]) {
|
||||||
blobmsg_buf_init(&imgbuf);
|
blobmsg_buf_init(&imgbuf);
|
||||||
sleep(3);
|
sleep(3);
|
||||||
}
|
}
|
||||||
} while(retry || queuepos);
|
} while(retry);
|
||||||
|
|
||||||
if (debug)
|
DPRINTF("reply:\n%s\n", blobmsg_format_json_indent(imgbuf.head, true, 0));
|
||||||
fprintf(stderr, "reply:\n%s\n", blobmsg_format_json_indent(imgbuf.head, true, 0));
|
|
||||||
|
|
||||||
if (!tb[IMAGE_SYSUPGRADE]) {
|
if (!tb[IMAGE_SYSUPGRADE]) {
|
||||||
fprintf(stderr, "no sysupgrade image returned\n");
|
if (!rc) {
|
||||||
rc=-1;
|
fprintf(stderr, "no sysupgrade image returned\n");
|
||||||
|
rc=-1;
|
||||||
|
}
|
||||||
goto freeboard;
|
goto freeboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(url, blobmsg_get_string(tb[IMAGE_SYSUPGRADE]), sizeof(url));
|
strncpy(url, blobmsg_get_string(tb[IMAGE_SYSUPGRADE]), sizeof(url));
|
||||||
|
|
||||||
if (!tb[IMAGE_FILESIZE]) {
|
|
||||||
fprintf(stderr, "no image size returned\n");
|
|
||||||
rc=-1;
|
|
||||||
goto freeboard;
|
|
||||||
}
|
|
||||||
filesize = blobmsg_get_u32(tb[IMAGE_FILESIZE]);
|
|
||||||
|
|
||||||
if (!tb[IMAGE_CHECKSUM]) {
|
|
||||||
fprintf(stderr, "no image checksum returned\n");
|
|
||||||
rc=-1;
|
|
||||||
goto freeboard;
|
|
||||||
}
|
|
||||||
checksum = blobmsg_get_string(tb[IMAGE_CHECKSUM]);
|
|
||||||
server_request(url, NULL, NULL);
|
server_request(url, NULL, NULL);
|
||||||
/* usign signature is not yet implemented! */
|
|
||||||
// strncat(url, ".sig", sizeof(url));
|
|
||||||
// server_request(url, NULL, NULL);
|
|
||||||
filename = uclient_get_url_filename(url, "firmware.bin");
|
filename = uclient_get_url_filename(url, "firmware.bin");
|
||||||
|
|
||||||
if (stat(filename, &imgstat)) {
|
if (stat(filename, &imgstat)) {
|
||||||
|
@ -934,18 +1048,78 @@ int main(int args, char *argv[]) {
|
||||||
goto freeboard;
|
goto freeboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((intmax_t)imgstat.st_size != filesize) {
|
if ((intmax_t)imgstat.st_size != out_len) {
|
||||||
fprintf(stderr, "file size mismatch\n");
|
fprintf(stderr, "file size mismatch\n");
|
||||||
unlink(filename);
|
unlink(filename);
|
||||||
rc=-1;
|
rc=-1;
|
||||||
goto freeboard;
|
goto freeboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(checksum, md5sum(filename), 33)) {
|
tmp=strrchr(url, '/');
|
||||||
fprintf(stderr, "image checksum mismatch\n");
|
|
||||||
unlink(filename);
|
strcpy(tmp, "/sha256sums");
|
||||||
|
server_request(url, NULL, NULL);
|
||||||
|
|
||||||
|
if (stat("sha256sums", &imgstat)) {
|
||||||
|
fprintf(stderr, "sha256sums download failed\n");
|
||||||
rc=-1;
|
rc=-1;
|
||||||
goto freeboard;
|
goto freeboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((intmax_t)imgstat.st_size != out_len) {
|
||||||
|
fprintf(stderr, "sha256sums download incomplete\n");
|
||||||
|
unlink("sha256sums");
|
||||||
|
rc=-1;
|
||||||
|
goto freeboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_len < 68) {
|
||||||
|
fprintf(stderr, "sha256sums size mismatch\n");
|
||||||
|
unlink("sha256sums");
|
||||||
|
rc=-1;
|
||||||
|
goto freeboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sha256sum_v("sha256sums", filename)) {
|
||||||
|
fprintf(stderr, "checksum verification failed\n");
|
||||||
|
unlink(filename);
|
||||||
|
unlink("sha256sums");
|
||||||
|
rc=-1;
|
||||||
|
goto freeboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(tmp, "/sha256sums.sig");
|
||||||
|
server_request(url, NULL, NULL);
|
||||||
|
|
||||||
|
if (stat("sha256sums.sig", &imgstat)) {
|
||||||
|
fprintf(stderr, "sha256sums.sig download failed\n");
|
||||||
|
rc=-1;
|
||||||
|
goto freeboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((intmax_t)imgstat.st_size != out_len) {
|
||||||
|
fprintf(stderr, "sha256sums.sig download incomplete\n");
|
||||||
|
unlink("sha256sums.sig");
|
||||||
|
rc=-1;
|
||||||
|
goto freeboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_len < 16) {
|
||||||
|
fprintf(stderr, "sha256sums.sig size mismatch\n");
|
||||||
|
unlink("sha256sums.sig");
|
||||||
|
rc=-1;
|
||||||
|
goto freeboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usign_v("sha256sums")) {
|
||||||
|
fprintf(stderr, "signature verification failed\n");
|
||||||
|
if (!ignore_sig) {
|
||||||
|
unlink(filename);
|
||||||
|
unlink("sha256sums");
|
||||||
|
unlink("sha256sums.sig");
|
||||||
|
rc=-1;
|
||||||
|
goto freeboard;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (strcmp(filename, "firmware.bin")) {
|
if (strcmp(filename, "firmware.bin")) {
|
||||||
|
@ -974,10 +1148,10 @@ freeboard:
|
||||||
/* subtarget is a pointer within target, don't free */
|
/* subtarget is a pointer within target, don't free */
|
||||||
free(distribution);
|
free(distribution);
|
||||||
free(version);
|
free(version);
|
||||||
free(revision);
|
|
||||||
|
|
||||||
freebufs:
|
freebufs:
|
||||||
blob_buf_free(&checkbuf);
|
blob_buf_free(&checkbuf);
|
||||||
|
blob_buf_free(&infobuf);
|
||||||
blob_buf_free(&reqbuf);
|
blob_buf_free(&reqbuf);
|
||||||
blob_buf_free(&imgbuf);
|
blob_buf_free(&imgbuf);
|
||||||
blob_buf_free(&upgbuf);
|
blob_buf_free(&upgbuf);
|
||||||
|
|
Loading…
Reference in a new issue