summaryrefslogtreecommitdiff
path: root/src/io.c
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2009-07-29 19:33:52 +0300
committerTimo Teras <timo.teras@iki.fi>2009-07-29 19:33:52 +0300
commit2ff4059b9a4073459cb75406df1a6f2d7717e72e (patch)
tree228c7a835fdd069ac6f8f20c0e94f106f3b4d1f4 /src/io.c
parent7b05eef61f08f0f34266ac3af4ae22fc72dbc269 (diff)
downloadapk-tools-2ff4059b9a4073459cb75406df1a6f2d7717e72e.tar.gz
apk-tools-2ff4059b9a4073459cb75406df1a6f2d7717e72e.tar.bz2
apk-tools-2ff4059b9a4073459cb75406df1a6f2d7717e72e.tar.xz
apk-tools-2ff4059b9a4073459cb75406df1a6f2d7717e72e.zip
io: use mmap to write archive entries to disk
avoids some copying and system calls.
Diffstat (limited to 'src/io.c')
-rw-r--r--src/io.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/src/io.c b/src/io.c
index da0e66f..c78cda8 100644
--- a/src/io.c
+++ b/src/io.c
@@ -114,15 +114,25 @@ size_t apk_istream_splice(void *stream, int fd, size_t size,
{
struct apk_istream *is = (struct apk_istream *) stream;
unsigned char *buf;
- size_t bufsz, done = 0, r, togo;
+ size_t bufsz, done = 0, r, togo, mmapped = 0;
bufsz = size;
- if (bufsz > 256*1024)
- bufsz = 256*1024;
+ if (size > 256 * 1024) {
+ buf = mmap(NULL, size, PROT_WRITE, 0, fd, 0);
+ if (buf != NULL) {
+ mmapped = 1;
+ if (bufsz > 2*1024*1024)
+ bufsz = 2*1024*1024;
+ }
+ }
+ if (!mmapped) {
+ if (bufsz > 256*1024)
+ bufsz = 256*1024;
- buf = malloc(bufsz);
- if (buf == NULL)
- return -ENOMEM;
+ buf = malloc(bufsz);
+ if (buf == NULL)
+ return -ENOMEM;
+ }
while (done < size) {
if (done != 0 && cb != NULL)
@@ -134,18 +144,25 @@ size_t apk_istream_splice(void *stream, int fd, size_t size,
r = is->read(is, buf, togo);
if (r < 0)
goto err;
- if (write(fd, buf, r) != r) {
- if (r < 0)
- r = -errno;
- goto err;
+
+ if (!mmapped) {
+ if (write(fd, buf, r) != r) {
+ if (r < 0)
+ r = -errno;
+ goto err;
+ }
}
+
done += r;
if (r != togo)
break;
}
r = done;
err:
- free(buf);
+ if (mmapped)
+ munmap(buf, size);
+ else
+ free(buf);
return r;
}