From 72be8139303d55463e470ee608a27eb4af950aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 18 Dec 2019 12:58:32 +0200 Subject: io: add stream copy helper --- src/apk_io.h | 9 ++++++--- src/database.c | 2 +- src/io.c | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/apk_io.h b/src/apk_io.h index e943a8c..fb784c3 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -74,6 +74,8 @@ struct apk_istream { const struct apk_istream_ops *ops; }; +#define APK_IO_ALL ((size_t)-1) + struct apk_istream *apk_istream_from_file(int atfd, const char *file); struct apk_istream *apk_istream_from_file_gz(int atfd, const char *file); struct apk_istream *apk_istream_from_fd(int fd); @@ -81,12 +83,13 @@ struct apk_istream *apk_istream_from_fd_url_if_modified(int atfd, const char *ur struct apk_istream *apk_istream_from_url_gz(const char *url); ssize_t apk_istream_read(struct apk_istream *is, void *ptr, size_t size); apk_blob_t apk_istream_get(struct apk_istream *is, size_t len); -apk_blob_t apk_istream_get_all(struct apk_istream *is); +apk_blob_t apk_istream_get_max(struct apk_istream *is, size_t size); apk_blob_t apk_istream_get_delim(struct apk_istream *is, apk_blob_t token); - -#define APK_SPLICE_ALL 0xffffffff +static inline apk_blob_t apk_istream_get_all(struct apk_istream *is) { return apk_istream_get_max(is, APK_IO_ALL); } ssize_t apk_istream_splice(struct apk_istream *is, int fd, size_t size, apk_progress_cb cb, void *cb_ctx); +ssize_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, size_t size, + apk_progress_cb cb, void *cb_ctx, EVP_MD_CTX *mdctx); static inline struct apk_istream *apk_istream_from_url(const char *url) { diff --git a/src/database.c b/src/database.c index f358ad1..2ca1286 100644 --- a/src/database.c +++ b/src/database.c @@ -663,7 +663,7 @@ int apk_cache_download(struct apk_database *db, struct apk_repository *repo, if (fd >= 0) { struct apk_file_meta meta; - r = apk_istream_splice(is, fd, APK_SPLICE_ALL, cb, cb_ctx); + r = apk_istream_splice(is, fd, APK_IO_ALL, cb, cb_ctx); if (!autoupdate) { apk_istream_get_meta(is, &meta); apk_file_meta_to_fd(fd, &meta); diff --git a/src/io.c b/src/io.c index fcac97d..6b017ab 100644 --- a/src/io.c +++ b/src/io.c @@ -140,13 +140,13 @@ apk_blob_t apk_istream_get(struct apk_istream *is, size_t len) return (struct apk_blob) { .len = is->err < 0 ? is->err : 0 }; } -apk_blob_t apk_istream_get_all(struct apk_istream *is) +apk_blob_t apk_istream_get_max(struct apk_istream *is, size_t max) { if (is->ptr == is->end) __apk_istream_fill(is); if (is->ptr != is->end) { - apk_blob_t ret = APK_BLOB_PTR_LEN((char*)is->ptr, is->end - is->ptr); + apk_blob_t ret = APK_BLOB_PTR_LEN((char*)is->ptr, min((size_t)(is->end - is->ptr), max)); is->ptr = is->end = 0; return ret; } @@ -486,6 +486,32 @@ struct apk_istream *apk_istream_from_file(int atfd, const char *file) return apk_istream_from_fd(fd); } +ssize_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, size_t size, + apk_progress_cb cb, void *cb_ctx, EVP_MD_CTX *mdctx) +{ + size_t done = 0; + apk_blob_t d; + int r; + + while (done < size) { + if (cb != NULL) cb(cb_ctx, done); + + d = apk_istream_get_max(is, size - done); + if (APK_BLOB_IS_NULL(d)) { + if (d.len) return d.len; + if (size != APK_IO_ALL) return -EBADMSG; + break; + } + if (mdctx) EVP_DigestUpdate(mdctx, d.ptr, d.len); + + r = apk_ostream_write(os, d.ptr, d.len); + if (r < 0) return r; + + done += d.len; + } + return done; +} + ssize_t apk_istream_splice(struct apk_istream *is, int fd, size_t size, apk_progress_cb cb, void *cb_ctx) { @@ -496,7 +522,7 @@ ssize_t apk_istream_splice(struct apk_istream *is, int fd, size_t size, bufsz = size; if (size > 128 * 1024) { - if (size != APK_SPLICE_ALL) { + if (size != APK_IO_ALL) { r = posix_fallocate(fd, 0, size); if (r == 0) mmapbase = mmap(NULL, size, PROT_READ | PROT_WRITE, @@ -521,7 +547,7 @@ ssize_t apk_istream_splice(struct apk_istream *is, int fd, size_t size, r = apk_istream_read(is, buf, togo); if (r <= 0) { if (r) goto err; - if (size != APK_SPLICE_ALL && done != size) { + if (size != APK_IO_ALL && done != size) { r = -EBADMSG; goto err; } -- cgit v1.2.3