@@ -11,6 +11,8 @@
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
#ifdef CONFIG_GUNZIP
#include <zlib.h>
#endif
@@ -96,25 +98,48 @@ static int fill_buffer(int fd, unsigned char *buf, unsigned int nbytes, unsigned
* 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)
+void extract_padding(int fd)
{
int padding;
ssize_t len;
unsigned char buf[512];
+ int old_flags;
+ struct pollfd pfd;
+ int retval;
- if (fd < 0 || !offset)
+ if (fd < 0)
return;
- padding = (512 - (*offset % 512)) % 512;
- if (padding) {
- TRACE("Expecting %d padding bytes at end-of-file", padding);
+ old_flags = fcntl(fd, F_GETFL);
+ if (old_flags < 0)
+ return;
+
+ if (fcntl(fd, F_SETFL, old_flags | O_NONBLOCK) < 0)
+ return
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+
+ padding = 512;
+
+ TRACE("Expecting up to 512 padding bytes at end-of-file");
+ do {
+ retval = poll(&pfd, 1, 1000);
+ if (retval < 0) {
+ DEBUG("Failure while waiting on fd %d: %s", fd, strerror(errno));
+ (void)fcntl(fd, F_SETFL, old_flags);
+ return;
+ }
len = read(fd, buf, padding);
if (len < 0) {
DEBUG("Failure while reading padding %d: %s", fd, strerror(errno));
+ (void)fcntl(fd, F_SETFL, old_flags);
return;
}
- }
+ padding -= len;
+ } while (len > 0 && padding > 0);
+ (void)fcntl(fd, F_SETFL, old_flags);
return;
}
@@ -205,7 +205,7 @@ static int extract_files(int fd, struct swupdate_cfg *software)
* to 512 bytes from the socket until the
* client stops writing
*/
- extract_padding(fd, &offset);
+ extract_padding(fd);
status = STREAM_END;
break;
}
@@ -59,7 +59,7 @@ struct filehdr {
int get_cpiohdr(unsigned char *buf, struct filehdr *fhdr);
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);
+void extract_padding(int fd);
bool swupdate_verify_chksum(const uint32_t chk1, struct filehdr *fhdr);
#endif
The stream interface may not read all data from the socket which could cause swupdate to close the socket fd before a client has written all data, resulting in an EPIPE on the client. Instead of trying to calculate and expect a specific number of padding bytes, perform best effort to read up to 512 bytes or until an error or timeout is encountered. Signed-off-by: Nick Potenski <nick.potenski@garmin.com> --- core/cpio_utils.c | 37 +++++++++++++++++++++++++++++++------ core/stream_interface.c | 2 +- include/cpiohdr.h | 2 +- 3 files changed, 33 insertions(+), 8 deletions(-)