@@ -64,12 +64,13 @@ static int read_sw_version_file(struct swupdate_cfg *sw)
return -ENOMEM;
}
strlcpy(swcomp->name, name, sizeof(swcomp->name));
- strlcpy(swcomp->version, version, sizeof(swcomp->version));
+ strlcpy(swcomp->config_version, version, sizeof(swcomp->config_version));
+ swcomp->runtime_version[0] = '\0';
LIST_INSERT_HEAD(&sw->installed_sw_list, swcomp, next);
TRACE("Installed %s: Version %s",
swcomp->name,
- swcomp->version);
+ swcomp->config_version);
free(name);
free(version);
} else {
@@ -115,12 +116,13 @@ static int versions_settings(void *setting, void *data)
}
GET_FIELD_STRING(LIBCFG_PARSER, elem, "name", swcomp->name);
- GET_FIELD_STRING(LIBCFG_PARSER, elem, "version", swcomp->version);
+ GET_FIELD_STRING(LIBCFG_PARSER, elem, "version", swcomp->config_version);
+ swcomp->runtime_version[0] = '\0';
LIST_INSERT_HEAD(&sw->installed_sw_list, swcomp, next);
TRACE("Installed %s: Version %s",
swcomp->name,
- swcomp->version);
+ swcomp->config_version);
}
return 0;
@@ -261,3 +263,37 @@ int compare_versions(const char* left_version, const char* right_version)
DEBUG("Comparing lexicographically '%s' <-> '%s'", left_version, right_version);
return strcmp(left_version, right_version);
}
+
+int backup_artifacts_versions(struct swver *dest, struct swver *src)
+{
+ struct sw_version *swcomp, *swcomp_copy;
+
+ LIST_INIT(dest);
+
+ LIST_FOREACH(swcomp, src, next) {
+ swcomp_copy = (struct sw_version *)calloc(1, sizeof(struct sw_version));
+ if (!swcomp_copy) {
+ ERROR("Could not create new version entry.");
+ free_image(swcomp_copy);
+ return -ENOMEM;
+ }
+
+ strlcpy(swcomp_copy->name, swcomp->name, sizeof(swcomp_copy->name));
+ strlcpy(swcomp_copy->runtime_version, swcomp->runtime_version,
+ sizeof(swcomp_copy->runtime_version));
+ strlcpy(swcomp_copy->config_version, swcomp->config_version,
+ sizeof(swcomp_copy->config_version));
+ LIST_INSERT_HEAD(dest, swcomp_copy, next);
+ }
+
+ return 0;
+}
+
+void restore_artifacts_versions(struct swver *dest, struct swver *src)
+{
+ struct swver tmp;
+
+ LIST_MOVE(src, &tmp, next);
+ LIST_MOVE(dest, src, next);
+ LIST_MOVE(&tmp, dest, next);
+}
\ No newline at end of file
@@ -205,13 +205,23 @@ static int generate_swversions(struct swupdate_cfg *cfg)
FILE *fp;
struct sw_version *swver;
struct swver *sw_ver_list = &cfg->installed_sw_list;
+ char *selected_version[SWUPDATE_GENERAL_STRING_SIZE];
fp = fopen(cfg->output_swversions, "w");
if (!fp)
return -EACCES;
LIST_FOREACH(swver, sw_ver_list, next) {
- fprintf(fp, "%s\t\t%s\n", swver->name, swver->version);
+ if (!strlen(swver->runtime_version))
+ {
+ strncpy(selected_version, swver->config_version, sizeof(selected_version));
+ }
+ else
+ {
+ strncpy(selected_version, swver->runtime_version, sizeof(selected_version));
+ }
+
+ fprintf(fp, "%s\t\t%s\n", swver->name, selected_version);
}
fclose(fp);
@@ -324,12 +334,12 @@ static int update_installed_image_version(struct swver *sw_ver_list,
* If component is already installed, update the version
*/
if (!strncmp(img->id.name, swver->name, sizeof(img->id.name))) {
- strncpy(swver->version, img->id.version, sizeof(img->id.version));
+ strncpy(swver->runtime_version, img->id.runtime_version, sizeof(swver->runtime_version));
return true;
}
}
- if (!strlen(img->id.version))
+ if (!strlen(img->id.runtime_version))
return false;
/*
@@ -342,7 +352,7 @@ static int update_installed_image_version(struct swver *sw_ver_list,
}
strlcpy(swcomp->name, img->id.name, sizeof(swcomp->name));
- strlcpy(swcomp->version, img->id.version, sizeof(swcomp->version));
+ strlcpy(swcomp->runtime_version, img->id.runtime_version, sizeof(swcomp->runtime_version));
LIST_INSERT_HEAD(sw_ver_list, swcomp, next);
return true;
@@ -364,6 +374,13 @@ int install_images(struct swupdate_cfg *sw)
bool dry_run = sw->parms.dry_run;
bool dropimg;
+ /* In case of failure, we must restore the previous versions */
+ ret = backup_artifacts_versions(&sw->installed_sw_list_backup, &sw->installed_sw_list);
+ if (ret) {
+ ERROR("Could not backup current installed software versions");
+ return ret;
+ }
+
/* Extract all scripts, preinstall scripts must be run now */
const char* tmpdir_scripts = get_tmpdirscripts();
ret = extract_scripts(&sw->scripts);
@@ -526,6 +543,8 @@ void cleanup_files(struct swupdate_cfg *software) {
struct img_type *img_tmp;
struct hw_type *hw;
struct hw_type *hw_tmp;
+ struct sw_version *swver;
+ struct sw_version *swver_tmp;
const char* TMPDIR = get_tmpdir();
struct imglist *list[] = {&software->scripts};
@@ -557,6 +576,14 @@ void cleanup_files(struct swupdate_cfg *software) {
dict_drop_db(&software->bootloader);
dict_drop_db(&software->vars);
+ /*
+ * Cleanup backup of installed software versions
+ */
+ LIST_FOREACH_SAFE(swver, &software->installed_sw_list_backup, next, swver_tmp) {
+ LIST_REMOVE(swver, next);
+ free(swver);
+ }
+
/*
* Drop Lua State if instantiated
*/
@@ -760,6 +760,13 @@ void *network_initializer(void *data)
WARN("execute POST FAILURE scripts return error, ignoring..");
}
}
+
+ /*
+ * Restore the previous software versions list
+ * if the installation failed
+ */
+ restore_artifacts_versions(&software->installed_sw_list,
+ &software->installed_sw_list_backup);
} else {
/*
* Clear the recovery variable to indicate to bootloader
@@ -297,8 +297,8 @@ static void lua_string_to_img(struct img_type *img, const char *key,
sizeof(img->id.name));
}
if (!strcmp(key, "version")) {
- strncpy(img->id.version, value,
- sizeof(img->id.version));
+ strncpy(img->id.runtime_version, value,
+ sizeof(img->id.runtime_version));
}
if (!strcmp(key, "filename")) {
strncpy(img->fname, value,
@@ -506,7 +506,7 @@ static void update_table(lua_State* L, struct img_type *img)
luaL_checktype(L, -1, LUA_TTABLE);
LUA_PUSH_IMG_STRING(img, "name", id.name);
- LUA_PUSH_IMG_STRING(img, "version", id.version);
+ LUA_PUSH_IMG_STRING(img, "version", id.runtime_version);
LUA_PUSH_IMG_STRING(img, "filename", fname);
LUA_PUSH_IMG_STRING(img, "volume", volname);
LUA_PUSH_IMG_STRING(img, "type", type);
@@ -98,6 +98,7 @@ struct swupdate_cfg {
struct hw_type hw;
struct hwlist hardware;
struct swver installed_sw_list;
+ struct swver installed_sw_list_backup;
struct swupdate_type_list swupdate_types;
struct imglist images;
struct imglist scripts;
@@ -32,7 +32,8 @@ typedef enum {
struct sw_version {
char name[SWUPDATE_GENERAL_STRING_SIZE];
- char version[SWUPDATE_GENERAL_STRING_SIZE];
+ char runtime_version[SWUPDATE_GENERAL_STRING_SIZE]; /*Version installed since swupdate is running*/
+ char config_version[SWUPDATE_GENERAL_STRING_SIZE]; /*Version referenced into versions config files*/
bool install_if_different;
bool install_if_higher;
LIST_ENTRY(sw_version) next;
@@ -9,4 +9,6 @@
#include "swupdate_settings.h"
void get_sw_versions(swupdate_cfg_handle *handle, struct swupdate_cfg *sw);
+int backup_artifacts_versions(struct swver *dest, struct swver *src);
+void restore_artifacts_versions(struct swver *dest, struct swver *src);
@@ -47,8 +47,8 @@ static void sw_append_stream(struct img_type *img, const char *key,
sizeof(img->id.name));
}
if (!strcmp(key, "version")) {
- strlcpy(img->id.version, value,
- sizeof(img->id.version));
+ strlcpy(img->id.runtime_version, value,
+ sizeof(img->id.runtime_version));
}
if (!strcmp(key, "mtdname") || !strcmp(key, "dest"))
strlcpy(img->mtdname, value,
@@ -349,7 +349,7 @@ static int is_image_installed(struct swver *sw_ver_list,
if (!sw_ver_list)
return false;
- if (!strlen(img->id.name) || !strlen(img->id.version) ||
+ if (!strlen(img->id.name) || !strlen(img->id.runtime_version) ||
!img->id.install_if_different)
return false;
@@ -358,10 +358,10 @@ static int is_image_installed(struct swver *sw_ver_list,
* Check if name and version are identical
*/
if (!strncmp(img->id.name, swver->name, sizeof(img->id.name)) &&
- !compare_versions(img->id.version, swver->version)) {
+ !compare_versions(img->id.runtime_version, swver->config_version)) {
TRACE("%s(%s) already installed, skipping...",
img->id.name,
- img->id.version);
+ img->id.runtime_version);
return true;
}
@@ -378,13 +378,13 @@ static int is_image_higher(struct swver *sw_ver_list,
if (!sw_ver_list)
return false;
- if (!strlen(img->id.name) || !strlen(img->id.version) ||
+ if (!strlen(img->id.name) || !strlen(img->id.runtime_version) ||
!img->id.install_if_higher)
return false;
LIST_FOREACH(swver, sw_ver_list, next) {
- const char* current_version = swver->version;
- const char* proposed_version = img->id.version;
+ const char* current_version = swver->config_version;
+ const char* proposed_version = img->id.runtime_version;
/*
* Check if name are identical and the new version is lower
@@ -394,7 +394,7 @@ static int is_image_higher(struct swver *sw_ver_list,
(compare_versions(proposed_version, current_version) <= 0)) {
TRACE("%s(%s) has a higher or same version installed, skipping...",
img->id.name,
- img->id.version);
+ img->id.runtime_version);
return true;
}
@@ -472,7 +472,7 @@ static int parse_common_attributes(parsertype p, void *elem, struct img_type *im
seek_str[0] = '\0';
GET_FIELD_STRING(p, elem, "name", image->id.name);
- GET_FIELD_STRING(p, elem, "version", image->id.version);
+ GET_FIELD_STRING(p, elem, "version", image->id.runtime_version);
GET_FIELD_STRING(p, elem, "filename", image->fname);
GET_FIELD_STRING(p, elem, "path", image->path);
GET_FIELD_STRING(p, elem, "volume", image->volname);
@@ -757,13 +757,13 @@ static int _parse_bootloader(parsertype p, void *cfg, void *setting, const char
* to let allocate the place for the strings
*/
GET_FIELD_STRING(p, elem, "name", dummy.id.name);
- GET_FIELD_STRING(p, elem, "value", dummy.id.version);
+ GET_FIELD_STRING(p, elem, "value", dummy.id.runtime_version);
skip = run_embscript(p, elem, &dummy, L, swcfg->embscript);
if (skip < 0) {
return -1;
}
if (!skip) {
- dict_set_value(&swcfg->bootloader, dummy.id.name, dummy.id.version);
+ dict_set_value(&swcfg->bootloader, dummy.id.name, dummy.id.runtime_version);
TRACE("Bootloader var: %s = %s",
dummy.id.name,
dict_get_value(&swcfg->bootloader, dummy.id.name));
@@ -832,7 +832,7 @@ static int _parse_vars(parsertype p, void *cfg, void *setting, const char **node
* to let allocate the place for the strings
*/
GET_FIELD_STRING(p, elem, "name", dummy.id.name);
- GET_FIELD_STRING(p, elem, "value", dummy.id.version);
+ GET_FIELD_STRING(p, elem, "value", dummy.id.runtime_version);
skip = run_embscript(p, elem, &dummy, L, swcfg->embscript);
if (skip < 0)
return -1;
@@ -842,7 +842,7 @@ static int _parse_vars(parsertype p, void *cfg, void *setting, const char **node
/*
* Store the variable in dictionary
*/
- dict_set_value(&swcfg->vars, dummy.id.name, dummy.id.version);
+ dict_set_value(&swcfg->vars, dummy.id.name, dummy.id.runtime_version);
TRACE("SWUpdate var: %s = %s",
dummy.id.name,
@@ -929,7 +929,7 @@ static int _parse_images(parsertype p, void *cfg, void *setting, const char **no
skip ? "Skip" : "Found",
image->compressed ? "compressed " : "",
strlen(image->id.name) ? " " : "", image->id.name,
- strlen(image->id.version) ? " " : "", image->id.version,
+ strlen(image->id.runtime_version) ? " " : "", image->id.runtime_version,
image->fname,
strlen(image->volname) ? "volume" : "device",
strlen(image->volname) ? image->volname :
@@ -1025,7 +1025,7 @@ static int _parse_files(parsertype p, void *cfg, void *setting, const char **nod
skip ? "Skip" : "Found",
file->compressed ? "compressed " : "",
strlen(file->id.name) ? " " : "", file->id.name,
- strlen(file->id.version) ? " " : "", file->id.version,
+ strlen(file->id.runtime_version) ? " " : "", file->id.runtime_version,
file->fname,
file->path,
strlen(file->device) ? file->device : "ROOTFS",