[1/2] Add command line for output image

Message ID 1520605496-19708-1-git-send-email-sbabic@denx.de
State Accepted
Headers show
Series
  • [1/2] Add command line for output image
Related show

Commit Message

Stefano Babic March 9, 2018, 2:24 p.m.
Some use cases require to save the incoming stream to a local file.
Add command line parameter (-o or --output)

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 core/cpio_utils.c          |  6 +++++-
 core/swupdate.c            | 13 ++++++++++++-
 corelib/stream_interface.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++
 include/swupdate.h         |  1 +
 include/util.h             |  1 +
 5 files changed, 66 insertions(+), 2 deletions(-)

Comments

Christian Storm May 2, 2018, 11:23 a.m. | #1
Hi Stefano,

> Some use cases require to save the incoming stream to a local file.
> Add command line parameter (-o or --output)

Hm, this new switch doesn't show up in 
$ ./swupdate --help

Is that intended?



Kind regards,
   Christian
Stefano Babic May 2, 2018, 11:27 a.m. | #2
On 02/05/2018 13:23, Christian Storm wrote:
> Hi Stefano,
> 
>> Some use cases require to save the incoming stream to a local file.
>> Add command line parameter (-o or --output)
> 
> Hm, this new switch doesn't show up in 
> $ ./swupdate --help
> 
> Is that intended?

Of course, not. I prepare a patch.

Thanks,
Stefano

Patch

diff --git a/core/cpio_utils.c b/core/cpio_utils.c
index 15c1374..79d1c79 100644
--- a/core/cpio_utils.c
+++ b/core/cpio_utils.c
@@ -76,7 +76,11 @@  static int fill_buffer(int fd, unsigned char *buf, unsigned int nbytes, unsigned
 	return count;
 }
 
-static int copy_write(void *out, const void *buf, unsigned int len)
+/*
+ * Export this to be used in other modules
+ * It just copy a buffer to a file
+ */
+int copy_write(void *out, const void *buf, unsigned int len)
 {
 	int ret;
 	int fd = (out != NULL) ? *(int *)out : -1;
diff --git a/core/swupdate.c b/core/swupdate.c
index c5511dc..e08659e 100644
--- a/core/swupdate.c
+++ b/core/swupdate.c
@@ -76,6 +76,7 @@  static struct option long_options[] = {
 	{"loglevel", required_argument, NULL, 'l'},
 	{"syslog", no_argument, NULL, 'L' },
 	{"select", required_argument, NULL, 'e'},
+	{"output", required_argument, NULL, 'o'},
 #ifdef CONFIG_SIGNED_IMAGES
 	{"key", required_argument, NULL, 'k'},
 #endif
@@ -548,7 +549,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, "vhi:e:l:Lcf:p:");
+	strcpy(main_options, "vhi:e:l:Lcf:p:o:");
 #ifdef CONFIG_MTD
 	strcat(main_options, "b:");
 #endif
@@ -658,6 +659,9 @@  int main(int argc, char **argv)
 			strncpy(fname, optarg, sizeof(fname));
 			opt_i = 1;
 			break;
+		case 'o':
+			strncpy(swcfg.output, optarg, sizeof(swcfg.output));
+			break;
 		case 'l':
 			loglevel = strtoul(optarg, NULL, 10);
 			break;
@@ -750,6 +754,13 @@  int main(int argc, char **argv)
 		exit(1);
 	}
 
+	if (opt_i && strlen(swcfg.output)) {
+		fprintf(stderr,
+			"Output just from network - do you know cp ?\n");
+		usage(argv[0]);
+		exit(1);
+	}
+
 #ifdef CONFIG_SURICATTA
 	if (opt_u && (opt_c || opt_i)) {
 		fprintf(stderr, "invalid mode combination with suricatta.\n");
diff --git a/corelib/stream_interface.c b/corelib/stream_interface.c
index 91f523f..adc6363 100644
--- a/corelib/stream_interface.c
+++ b/corelib/stream_interface.c
@@ -17,6 +17,7 @@ 
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/socket.h>
 #include <ctype.h>
 #include <fcntl.h>
 #include <dirent.h>
@@ -281,6 +282,32 @@  static int extract_files(int fd, struct swupdate_cfg *software)
 	}
 }
 
+static int save_stream(int fdin, const char *output)
+{
+	char *buf;
+	int fdout, ret, len;
+	const int bufsize = 16 * 1024;
+
+	fdout = openfileoutput(output);
+	if (fdout < 0)
+		return -1;
+
+	buf = (char *)malloc(bufsize);
+	if (!buf)
+		return -ENOMEM;
+
+	for (;;) {
+		len = read(fdin, buf, bufsize);
+		if (len == 0)
+			break;
+		ret = copy_write(&fdout, buf, len);
+		if (ret < 0)
+			return -EIO;
+	}
+
+	return 0;
+}
+
 void *network_initializer(void *data)
 {
 	int ret;
@@ -306,6 +333,26 @@  void *network_initializer(void *data)
 		pthread_mutex_unlock(&stream_mutex);
 		notify(START, RECOVERY_NO_ERROR, INFOLEVEL, "Software Update started !");
 
+		/*
+		 * Check if the stream should be saved
+		 */
+		if (strlen(software->output)) {
+			ret = save_stream(inst.fd, software->output);
+			if (ret < 0) {
+				notify(FAILURE, RECOVERY_ERROR, ERRORLEVEL,
+					"Image invalid or corrupted. Not installing ...");
+				continue;
+			}
+
+			/*
+			 * now replace the file descriptor with
+			 * the saved file
+			 */
+			close(inst.fd);
+			inst.fd = open(software->output, O_RDONLY,  S_IRUSR);
+		}
+
+
 #ifdef CONFIG_MTD
 		mtd_cleanup();
 		scan_mtd_devices();
diff --git a/include/swupdate.h b/include/swupdate.h
index 7de096a..10010f5 100644
--- a/include/swupdate.h
+++ b/include/swupdate.h
@@ -116,6 +116,7 @@  struct swupdate_cfg {
 	char version[SWUPDATE_GENERAL_STRING_SIZE];
 	char software_set[SWUPDATE_GENERAL_STRING_SIZE];
 	char running_mode[SWUPDATE_GENERAL_STRING_SIZE];
+	char output[SWUPDATE_GENERAL_STRING_SIZE];
 	struct hw_type hw;
 	struct hwlist hardware;
 	struct swver installed_sw_list;
diff --git a/include/util.h b/include/util.h
index bff9436..2ac4139 100644
--- a/include/util.h
+++ b/include/util.h
@@ -131,6 +131,7 @@  char *sdup(const char *str);
 typedef int (*writeimage) (void *out, const void *buf, unsigned int len);
 
 int openfile(const char *filename);
+int copy_write(void *out, const void *buf, unsigned int len);
 int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs,
 	unsigned long long seek,
 	int skip_file, int compressed, uint32_t *checksum,