diff options
author | Timo Teras <timo.teras@iki.fi> | 2009-07-31 10:50:15 +0300 |
---|---|---|
committer | Timo Teras <timo.teras@iki.fi> | 2009-07-31 10:50:55 +0300 |
commit | 67108bf07a67811ea91fc965f3f1592a4a70044e (patch) | |
tree | f020cc21b7100152e7e10344d4df70d692ab83c4 | |
parent | fe43d8ab1d8aab0f0fba0a1ea6c0bf96c358478f (diff) | |
download | apk-tools-67108bf07a67811ea91fc965f3f1592a4a70044e.tar.gz apk-tools-67108bf07a67811ea91fc965f3f1592a4a70044e.tar.bz2 apk-tools-67108bf07a67811ea91fc965f3f1592a4a70044e.tar.xz apk-tools-67108bf07a67811ea91fc965f3f1592a4a70044e.zip |
io: fix corruption of big files on mmap write
remember to increment destination pointer; and munmap the proper
base address.
-rw-r--r-- | src/io.c | 27 |
1 files changed, 13 insertions, 14 deletions
@@ -114,21 +114,19 @@ size_t apk_istream_splice(void *stream, int fd, size_t size, { static void *splice_buffer = NULL; struct apk_istream *is = (struct apk_istream *) stream; - unsigned char *buf = MAP_FAILED; - size_t bufsz, done = 0, r, togo, mmapped = 0; + unsigned char *buf, *mmapbase = MAP_FAILED; + size_t bufsz, done = 0, r, togo; bufsz = size; if (size > 128 * 1024) { if (ftruncate(fd, size) == 0) - buf = mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (buf != MAP_FAILED) { - mmapped = 1; - if (bufsz > 2*1024*1024) - bufsz = 2*1024*1024; - } + mmapbase = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + if (bufsz > 2*1024*1024) + bufsz = 2*1024*1024; + buf = mmapbase; } - if (!mmapped) { + if (mmapbase == MAP_FAILED) { if (splice_buffer == NULL) splice_buffer = malloc(256*1024); buf = splice_buffer; @@ -149,13 +147,14 @@ size_t apk_istream_splice(void *stream, int fd, size_t size, if (r < 0) goto err; - if (!mmapped) { + if (mmapbase == MAP_FAILED) { if (write(fd, buf, r) != r) { if (r < 0) r = -errno; goto err; } - } + } else + buf += r; done += r; if (r != togo) @@ -163,8 +162,8 @@ size_t apk_istream_splice(void *stream, int fd, size_t size, } r = done; err: - if (mmapped) - munmap(buf, size); + if (mmapbase != MAP_FAILED) + munmap(mmapbase, size); return r; } |