diff mbox series

[1/2] Introduce --gen-swversions parameter

Message ID 20240419063311.601172-1-marcus.folkesson@gmail.com
State Superseded
Headers show
Series [1/2] Introduce --gen-swversions parameter | expand

Commit Message

Marcus Folkesson April 19, 2024, 6:33 a.m. UTC
After a successful update, --gen-swversions generates a file with
the installed software and their versions.

The file is compatible with CONFIG_SW_VERSIONS_FILE and could replace
that file if the end user want swupdate to maintain that file entirely.

Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
---
 core/installer.c   | 64 ++++++++++++++++++++++++++++++++++++++++++++++
 core/swupdate.c    |  7 ++++-
 include/swupdate.h |  1 +
 3 files changed, 71 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/core/installer.c b/core/installer.c
index 48c7fe5e..83122388 100644
--- a/core/installer.c
+++ b/core/installer.c
@@ -187,6 +187,24 @@  static int prepare_var_script(struct dict *dict, const char *script)
 	return 0;
 }
 
+static int generate_swversions(struct swupdate_cfg *cfg)
+{
+	FILE *fp;
+	struct sw_version *swver;
+	struct swver *sw_ver_list = &cfg->installed_sw_list;
+
+	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);
+	}
+	fclose(fp);
+
+	return 0;
+}
+
 static int update_bootloader_env(struct swupdate_cfg *cfg, const char *script)
 {
 	int ret = 0;
@@ -279,6 +297,41 @@  int install_single_image(struct img_type *img, bool dry_run)
 	return ret;
 }
 
+static int update_installed_image_version(struct swver *sw_ver_list,
+		struct img_type *img)
+{
+	struct sw_version *swver;
+	struct sw_version *swcomp;
+
+	if (!sw_ver_list)
+		return false;
+
+	LIST_FOREACH(swver, sw_ver_list, next) {
+		/*
+		 * 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));
+			return true;
+		}
+	}
+
+	/*
+	 * No previous version of this component is installed. Create a new entry.
+	 */
+	swcomp = (struct sw_version *)calloc(1, sizeof(struct sw_version));
+	if (!swcomp) {
+		ERROR("Could not create new version entry.");
+		return false;
+	}
+
+	strlcpy(swcomp->name, img->id.name, sizeof(swcomp->name));
+	strlcpy(swcomp->version, img->id.version, sizeof(swcomp->version));
+	LIST_INSERT_HEAD(sw_ver_list, swcomp, next);
+
+	return true;
+}
+
 /*
  * streamfd: file descriptor if it is required to extract
  *           images from the stream (update from file)
@@ -370,6 +423,8 @@  int install_images(struct swupdate_cfg *sw)
 
 		close(img->fdin);
 
+		update_installed_image_version(&sw->installed_sw_list, img);
+
 		if (dropimg)
 			free_image(img);
 
@@ -409,6 +464,15 @@  int install_images(struct swupdate_cfg *sw)
 
 	ret |= run_prepost_scripts(&sw->bootscripts, POSTINSTALL);
 
+	/*
+	 * Should we generate a list with installed software?
+	 */
+	if (strlen(sw->output_swversions)) {
+		if (!generate_swversions(sw)) {
+			ERROR("%s cannot be opened", sw->output_swversions);
+		}
+	}
+
 	return ret;
 }
 
diff --git a/core/swupdate.c b/core/swupdate.c
index a421e888..5cfec3d6 100644
--- a/core/swupdate.c
+++ b/core/swupdate.c
@@ -111,6 +111,7 @@  static struct option long_options[] = {
 	{"no-state-marker", no_argument, NULL, 'm'},
 	{"no-transaction-marker", no_argument, NULL, 'M'},
 	{"output", required_argument, NULL, 'o'},
+	{"gen-swversions", required_argument, NULL, 's'},
 	{"preupdate", required_argument, NULL, 'P'},
 	{"postupdate", required_argument, NULL, 'p'},
 	{"select", required_argument, NULL, 'e'},
@@ -173,6 +174,7 @@  static void usage(char *programname)
 		" -M, --no-transaction-marker    : disable setting bootloader transaction marker\n"
 		" -m, --no-state-marker          : disable setting update state in bootloader\n"
 		" -o, --output <filename>        : saves the incoming stream\n"
+		" -s, --gen-swversions <filename>: generate sw-versions file after successful installation\n"
 		" -v, --verbose                  : be verbose, set maximum loglevel\n"
 		"     --version                  : print SWUpdate version and exit\n"
 #ifdef CONFIG_HW_COMPATIBILITY
@@ -475,7 +477,7 @@  int main(int argc, char **argv)
 #endif
 	memset(main_options, 0, sizeof(main_options));
 	memset(image_url, 0, sizeof(image_url));
-	strcpy(main_options, "vhni:e:gq:l:Lcf:p:P:o:N:R:MmB:");
+	strcpy(main_options, "vhni:e:gq:l:Lcf:p:P:o:s:N:R:MmB:");
 #ifdef CONFIG_MTD
 	strcat(main_options, "b:");
 #endif
@@ -623,6 +625,9 @@  int main(int argc, char **argv)
 		case 'o':
 			strlcpy(swcfg.output, optarg, sizeof(swcfg.output));
 			break;
+		case 's':
+			strlcpy(swcfg.output_swversions, optarg, sizeof(swcfg.output_swversions));
+			break;
 		case 'B':
 			if (set_bootloader(optarg) != 0) {
 				ERROR("Bootloader interface '%s' could not be initialized.", optarg);
diff --git a/include/swupdate.h b/include/swupdate.h
index e18de8d3..ecad2d82 100644
--- a/include/swupdate.h
+++ b/include/swupdate.h
@@ -49,6 +49,7 @@  struct swupdate_cfg {
 	bool bootloader_transaction_marker;
 	bool bootloader_state_marker;
 	char output[SWUPDATE_GENERAL_STRING_SIZE];
+	char output_swversions[SWUPDATE_GENERAL_STRING_SIZE];
 	char publickeyfname[SWUPDATE_GENERAL_STRING_SIZE];
 	char aeskeyfname[SWUPDATE_GENERAL_STRING_SIZE];
 	char postupdatecmd[SWUPDATE_GENERAL_STRING_SIZE];