diff options
author | Timo Teräs <timo.teras@iki.fi> | 2020-01-10 11:02:48 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2020-01-11 03:44:23 +0200 |
commit | 7ca0d146ecaf2f99781653d1203bd3db7afc85ba (patch) | |
tree | 0b167bd627a174be8e0d24f2af0f3697904ad5de /src/io.c | |
parent | 9dda2d3c21d1116077257caafa065b659ffe419b (diff) | |
download | apk-tools-7ca0d146ecaf2f99781653d1203bd3db7afc85ba.tar.gz apk-tools-7ca0d146ecaf2f99781653d1203bd3db7afc85ba.tar.bz2 apk-tools-7ca0d146ecaf2f99781653d1203bd3db7afc85ba.tar.xz apk-tools-7ca0d146ecaf2f99781653d1203bd3db7afc85ba.zip |
istream: add buffering capability
Convert all implementations to do buffering. This is in preparation
to remove bstream interface as redundant.
istream_read() will return full reads unless end-of-file. The backends
can return short reads to optimize buffering or due to other reasons
like boundary change for gz.
Diffstat (limited to 'src/io.c')
-rw-r--r-- | src/io.c | 80 |
1 files changed, 47 insertions, 33 deletions
@@ -35,6 +35,8 @@ #define HAVE_FGETGRENT_R #endif +size_t apk_io_bufsize = 2*1024; + static void apk_file_meta_from_fd(int fd, struct apk_file_meta *meta) { struct stat st; @@ -56,6 +58,44 @@ void apk_file_meta_to_fd(int fd, struct apk_file_meta *meta) futimens(fd, times); } +ssize_t apk_istream_read(struct apk_istream *is, void *ptr, size_t size) +{ + ssize_t left = size, r = 0; + + while (left) { + if (is->ptr != is->end) { + r = MIN(left, is->end - is->ptr); + if (ptr) { + memcpy(ptr, is->ptr, r); + ptr += r; + } + is->ptr += r; + left -= r; + continue; + } + if (is->err) break; + + if (ptr && left > is->buf_size/4) { + r = is->ops->read(is, ptr, left); + if (r <= 0) break; + left -= r; + ptr += r; + continue; + } + + r = is->ops->read(is, is->buf, is->buf_size); + if (r <= 0) break; + + is->ptr = is->buf; + is->end = is->buf + r; + } + + if (r < 0) return r; + if (size && left == size && !is->err) is->err = 1; + if (size == left) return is->err < 0 ? is->err : 0; + return size - left; +} + struct apk_fd_istream { struct apk_istream is; int fd; @@ -70,24 +110,11 @@ static void fdi_get_meta(struct apk_istream *is, struct apk_file_meta *meta) static ssize_t fdi_read(struct apk_istream *is, void *ptr, size_t size) { struct apk_fd_istream *fis = container_of(is, struct apk_fd_istream, is); - ssize_t i = 0, r; - - if (ptr == NULL) { - if (lseek(fis->fd, size, SEEK_CUR) < 0) - return -errno; - return size; - } - - while (i < size) { - r = read(fis->fd, ptr + i, size - i); - if (r < 0) - return -errno; - if (r == 0) - break; - i += r; - } + ssize_t r; - return i; + r = read(fis->fd, ptr, size); + if (r < 0) return -errno; + return r; } static void fdi_close(struct apk_istream *is) @@ -110,7 +137,7 @@ struct apk_istream *apk_istream_from_fd(int fd) if (fd < 0) return ERR_PTR(-EBADF); - fis = malloc(sizeof(struct apk_fd_istream)); + fis = malloc(sizeof(*fis) + apk_io_bufsize); if (fis == NULL) { close(fd); return ERR_PTR(-ENOMEM); @@ -118,6 +145,8 @@ struct apk_istream *apk_istream_from_fd(int fd) *fis = (struct apk_fd_istream) { .is.ops = &fd_istream_ops, + .is.buf = (uint8_t *)(fis + 1), + .is.buf_size = apk_io_bufsize, .fd = fd, }; @@ -134,21 +163,6 @@ struct apk_istream *apk_istream_from_file(int atfd, const char *file) return apk_istream_from_fd(fd); } -ssize_t apk_istream_skip(struct apk_istream *is, size_t size) -{ - unsigned char buf[2048]; - size_t done = 0, togo; - ssize_t r; - - while (done < size) { - togo = MIN(size - done, sizeof buf); - r = apk_istream_read(is, buf, togo); - if (r <= 0) return r ?: -EIO; - done += r; - } - return done; -} - ssize_t apk_istream_splice(struct apk_istream *is, int fd, size_t size, apk_progress_cb cb, void *cb_ctx) { |