aboutsummaryrefslogtreecommitdiffstats
path: root/minzip
diff options
context:
space:
mode:
authorDoug Zongker <dougz@android.com>2009-04-29 16:52:04 -0700
committerDoug Zongker <dougz@android.com>2009-04-29 17:35:34 -0700
commit596271fa71d79e3eec03c7cf6ac76cb026dd8578 (patch)
tree3a78f4d9d0b3694d4a75b7dd3d086b0249de8b5e /minzip
parentf554ceb0500f75c425b37c74a0d65d138c0fbdd0 (diff)
downloadbootable_recovery-596271fa71d79e3eec03c7cf6ac76cb026dd8578.zip
bootable_recovery-596271fa71d79e3eec03c7cf6ac76cb026dd8578.tar.gz
bootable_recovery-596271fa71d79e3eec03c7cf6ac76cb026dd8578.tar.bz2
handle short writes when unzipping files
minzip fails if write() doesn't write all the data in one call. Apparently this was good enough before, but it causes OTAs to fail all the time now (maybe due to the recently-submitted kernel)? Change code to attempt continuing after short writes.
Diffstat (limited to 'minzip')
-rw-r--r--minzip/Zip.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/minzip/Zip.c b/minzip/Zip.c
index 100c833..ead8993 100644
--- a/minzip/Zip.c
+++ b/minzip/Zip.c
@@ -41,7 +41,7 @@ enum {
CENSIZ = 20,
CENLEN = 24,
CENNAM = 28,
- CENEXT = 30,
+ CENEXT = 30,
CENCOM = 32,
CENDSK = 34,
CENATT = 36,
@@ -66,13 +66,13 @@ enum {
LOCSIG = 0x04034b50, // PK34
LOCHDR = 30,
-
+
LOCVER = 4,
LOCFLG = 6,
LOCHOW = 8,
LOCTIM = 10,
LOCCRC = 14,
- LOCSIZ = 18,
+ LOCSIZ = 18,
LOCLEN = 22,
LOCNAM = 26,
LOCEXT = 28,
@@ -757,7 +757,7 @@ bool mzReadZipEntry(const ZipArchive* pArchive, const ZipEntry* pEntry,
{
CopyProcessArgs args;
bool ret;
-
+
args.buf = buf;
args.bufLen = bufLen;
ret = mzProcessZipEntryContents(pArchive, pEntry, copyProcessFunction,
@@ -772,13 +772,29 @@ bool mzReadZipEntry(const ZipArchive* pArchive, const ZipEntry* pEntry,
static bool writeProcessFunction(const unsigned char *data, int dataLen,
void *fd)
{
- ssize_t n = write((int)fd, data, dataLen);
- if (n != dataLen) {
- LOGE("Can't write %d bytes (only %ld) from zip file: %s\n",
- dataLen, n, strerror(errno));
- return false;
- }
- return true;
+ int zeroWrites = 0;
+ ssize_t soFar = 0;
+ do {
+ ssize_t n = write((int)fd, data+soFar, dataLen-soFar);
+ if (n < 0) {
+ LOGE("Error writing %ld bytes from zip file: %s\n",
+ dataLen-soFar, strerror(errno));
+ return false;
+ } else if (n > 0) {
+ soFar += n;
+ if (soFar == dataLen) return true;
+ if (soFar > dataLen) {
+ LOGE("write overrun? (%ld bytes instead of %d)\n",
+ soFar, dataLen);
+ return false;
+ }
+ zeroWrites = 0;
+ } else {
+ ++zeroWrites;
+ }
+ } while (zeroWrites < 5);
+ LOGE("too many consecutive zero-length writes\n");
+ return false;
}
/*