diff mbox series

[v2] stream_interface: Keep reading the cpio padding, if any, up to 512 bytes from the socket until the client stops writing.

Message ID 20200224090840.4589-1-pedro.aguilar@vimar.com
State Changes Requested
Headers show
Series [v2] stream_interface: Keep reading the cpio padding, if any, up to 512 bytes from the socket until the client stops writing. | expand

Commit Message

Pedro Aguilar Feb. 24, 2020, 9:08 a.m. UTC
This avoids that the streaming client gets an EPIPE error when trying to write the padding to the IPC socket. This can happen when the streaming client is downloading very slowly and swupdate, after reading the trailer, closes the pipe.
The cpio utility always adds a 512 bytes alignment after the file trailer, independently of the given format.

Signed-off-by: Pedro Aguilar <pedro.aguilar@vimar.com>
Signed-off-by: Luca Pesce <luca.pesce@vimar.com>
---
 core/cpio_utils.c       | 27 ++++++++++++++++++++++++++-
 core/stream_interface.c |  5 +++++
 include/cpiohdr.h       |  1 +
 3 files changed, 32 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/core/cpio_utils.c b/core/cpio_utils.c
index 03776e2..8cf4713 100644
--- a/core/cpio_utils.c
+++ b/core/cpio_utils.c
@@ -79,6 +79,32 @@  static int fill_buffer(int fd, unsigned char *buf, unsigned int nbytes, unsigned
 	return count;
 }
 
+/*
+ * Read padding that could exists between the cpio trailer and the end-of-file.
+ * cpio aligns the file to 512 bytes
+ */
+void extract_padding(int fd, unsigned long *offset)
+{
+    int padding;
+    ssize_t len;
+	unsigned char buf[512];
+
+    if (fd < 0 || !offset)
+        return;
+
+    padding = (512 - (*offset % 512)) % 512;
+    if (padding) {
+        TRACE("Expecting %d padding bytes at end-of-file", padding);
+        len = read(fd, buf, padding);
+        if (len < 0) {
+            DEBUG("Failure while reading padding %d: %s", fd, strerror(errno));
+            return;
+        }
+    }
+
+    return;
+}
+
 /*
  * Export the copy_write{,_*} functions to be used in other modules
  * for copying a buffer to a file.
@@ -760,7 +786,6 @@  int cpio_scan(int fd, struct swupdate_cfg *cfg, off_t start)
 	int file_listed;
 	uint32_t checksum;
 
-
 	while (1) {
 		file_listed = 0;
 		start = offset;
diff --git a/core/stream_interface.c b/core/stream_interface.c
index ff2f6d0..824c51a 100644
--- a/core/stream_interface.c
+++ b/core/stream_interface.c
@@ -174,6 +174,11 @@  static int extract_files(int fd, struct swupdate_cfg *software)
 				return -1;
 			}
 			if (strcmp("TRAILER!!!", fdh.filename) == 0) {
+                /*
+                 * Keep reading the cpio padding, if any, up to 512 bytes from
+                 * the socket until the client stops writing
+                 */
+                extract_padding(fd, &offset);
 				status = STREAM_END;
 				break;
 			}
diff --git a/include/cpiohdr.h b/include/cpiohdr.h
index 855d5e8..aa1c9b1 100644
--- a/include/cpiohdr.h
+++ b/include/cpiohdr.h
@@ -53,5 +53,6 @@  int get_cpiohdr(unsigned char *buf, unsigned long *size,
 			unsigned long *namesize, unsigned long *chksum);
 int extract_cpio_header(int fd, struct filehdr *fhdr, unsigned long *offset);
 int extract_img_from_cpio(int fd, unsigned long offset, struct filehdr *fdh);
+void extract_padding(int fd, unsigned long *offset);
 
 #endif