summaryrefslogtreecommitdiff
path: root/src/io.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2020-01-10 11:02:48 +0200
committerTimo Teräs <timo.teras@iki.fi>2020-01-11 03:44:23 +0200
commit7ca0d146ecaf2f99781653d1203bd3db7afc85ba (patch)
tree0b167bd627a174be8e0d24f2af0f3697904ad5de /src/io.c
parent9dda2d3c21d1116077257caafa065b659ffe419b (diff)
downloadapk-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.c80
1 files changed, 47 insertions, 33 deletions
diff --git a/src/io.c b/src/io.c
index 8aac019..d7c3bb9 100644
--- a/src/io.c
+++ b/src/io.c
@@ -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)
{