diff options
-rw-r--r-- | src/apk_io.h | 32 | ||||
-rw-r--r-- | src/database.c | 42 | ||||
-rw-r--r-- | src/gunzip.c | 22 | ||||
-rw-r--r-- | src/io.c | 197 | ||||
-rw-r--r-- | src/manifest.c | 2 | ||||
-rw-r--r-- | src/package.c | 11 | ||||
-rw-r--r-- | src/url.c | 9 | ||||
-rw-r--r-- | src/verify.c | 2 |
8 files changed, 161 insertions, 156 deletions
diff --git a/src/apk_io.h b/src/apk_io.h index db59890..1760e72 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -110,13 +110,28 @@ static inline void apk_istream_close(struct apk_istream *is) is->ops->close(is); } +#define APK_MPART_DATA 1 /* data processed so far */ +#define APK_MPART_BOUNDARY 2 /* final part of data, before boundary */ +#define APK_MPART_END 3 /* signals end of stream */ + +typedef int (*apk_multipart_cb)(void *ctx, int part, apk_blob_t data); + +struct apk_istream *apk_istream_gunzip_mpart(struct apk_istream *, + apk_multipart_cb cb, void *ctx); +static inline struct apk_istream *apk_istream_gunzip(struct apk_istream *is) +{ + return apk_istream_gunzip_mpart(is, NULL, NULL); +} + struct apk_segment_istream { struct apk_istream is; struct apk_istream *pis; size_t bytes_left; time_t mtime; }; -void apk_istream_segment(struct apk_segment_istream *sis, struct apk_istream *is, size_t len, time_t mtime); +struct apk_istream *apk_istream_segment(struct apk_segment_istream *sis, struct apk_istream *is, size_t len, time_t mtime); +struct apk_istream *apk_istream_tee(struct apk_istream *from, int atfd, const char *to, int copy_meta, + apk_progress_cb cb, void *cb_ctx); #define APK_BSTREAM_SINGLE_READ 0x0001 #define APK_BSTREAM_EOF 0x0002 @@ -141,19 +156,6 @@ struct apk_ostream { const struct apk_ostream_ops *ops; }; -#define APK_MPART_DATA 1 /* data processed so far */ -#define APK_MPART_BOUNDARY 2 /* final part of data, before boundary */ -#define APK_MPART_END 3 /* signals end of stream */ - -typedef int (*apk_multipart_cb)(void *ctx, int part, apk_blob_t data); - -struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *, - apk_multipart_cb cb, void *ctx); -static inline struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs) -{ - return apk_bstream_gunzip_mpart(bs, NULL, NULL); -} - struct apk_ostream *apk_ostream_gzip(struct apk_ostream *); struct apk_ostream *apk_ostream_counter(off_t *); @@ -162,8 +164,6 @@ struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream); struct apk_bstream *apk_bstream_from_file(int atfd, const char *file); struct apk_bstream *apk_bstream_from_fd(int fd); struct apk_bstream *apk_bstream_from_fd_url_if_modified(int atfd, const char *url, time_t since); -struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, int atfd, const char *to, int copy_meta, - apk_progress_cb cb, void *cb_ctx); static inline struct apk_bstream *apk_bstream_from_url(const char *url) { diff --git a/src/database.c b/src/database.c index 5b94d5c..b964105 100644 --- a/src/database.c +++ b/src/database.c @@ -619,7 +619,6 @@ int apk_cache_download(struct apk_database *db, struct apk_repository *repo, { struct stat st = {0}; struct apk_istream *is; - struct apk_bstream *bs; struct apk_sign_ctx sctx; char url[PATH_MAX]; char tmpcacheitem[128], *cacheitem = &tmpcacheitem[tmpprefix.len]; @@ -650,9 +649,9 @@ int apk_cache_download(struct apk_database *db, struct apk_repository *repo, if (verify != APK_SIGN_NONE) { apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd); - bs = apk_bstream_from_url_if_modified(url, st.st_mtime); - bs = apk_bstream_tee(bs, db->cache_fd, tmpcacheitem, !autoupdate, cb, cb_ctx); - is = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &sctx); + is = apk_istream_from_url_if_modified(url, st.st_mtime); + is = apk_istream_tee(is, db->cache_fd, tmpcacheitem, !autoupdate, cb, cb_ctx); + is = apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &sctx); if (!IS_ERR_OR_NULL(is)) r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, &db->id_cache); else @@ -2176,22 +2175,21 @@ static int load_apkindex(void *sctx, const struct apk_file_info *fi, return 0; } -static int load_index(struct apk_database *db, struct apk_bstream *bs, +static int load_index(struct apk_database *db, struct apk_istream *is, int targz, int repo) { int r = 0; - if (IS_ERR_OR_NULL(bs)) return bs ? PTR_ERR(bs) : -EINVAL; + if (IS_ERR_OR_NULL(is)) return is ? PTR_ERR(is) : -EINVAL; if (targz) { - struct apk_istream *is; struct apkindex_ctx ctx; ctx.db = db; ctx.repo = repo; ctx.found = 0; apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY, NULL, db->keys_fd); - is = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &ctx.sctx); + is = apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &ctx.sctx); r = apk_tar_parse(is, load_apkindex, &ctx, &db->id_cache); apk_istream_close(is); apk_sign_ctx_free(&ctx.sctx); @@ -2199,7 +2197,7 @@ static int load_index(struct apk_database *db, struct apk_bstream *bs, if (r >= 0 && ctx.found == 0) r = -ENOMSG; } else { - apk_db_index_read(db, apk_bstream_gunzip(bs), repo); + apk_db_index_read(db, apk_istream_gunzip(is), repo); } return r; } @@ -2211,13 +2209,12 @@ int apk_db_index_read_file(struct apk_database *db, const char *file, int repo) if (strstr(file, ".tar.gz") == NULL && strstr(file, ".gz") != NULL) targz = 0; - return load_index(db, apk_bstream_from_file(AT_FDCWD, file), targz, repo); + return load_index(db, apk_istream_from_file(AT_FDCWD, file), targz, repo); } int apk_db_add_repository(apk_database_t _db, apk_blob_t _repository) { struct apk_database *db = _db.db; - struct apk_bstream *bs = NULL; struct apk_repository *repo; apk_blob_t brepo, btag; int repo_num, r, targz = 1, tag_id = 0; @@ -2273,11 +2270,7 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t _repository) r = apk_repo_format_real_url(db, repo, NULL, buf, sizeof(buf)); } if (r == 0) { - bs = apk_bstream_from_fd_url(db->cache_fd, buf); - if (!IS_ERR_OR_NULL(bs)) - r = load_index(db, bs, targz, repo_num); - else - r = PTR_ERR(bs); + r = load_index(db, apk_istream_from_fd_url(db->cache_fd, buf), targz, repo_num); } if (r != 0) { @@ -2760,8 +2753,7 @@ static int apk_db_unpack_pkg(struct apk_database *db, char **script_args) { struct install_ctx ctx; - struct apk_bstream *bs = NULL, *cache_bs; - struct apk_istream *tar; + struct apk_istream *is = NULL, *cache_is, *tar; struct apk_repository *repo; struct apk_package *pkg = ipkg->pkg; char file[PATH_MAX]; @@ -2789,9 +2781,9 @@ static int apk_db_unpack_pkg(struct apk_database *db, if (!apk_db_cache_active(db)) need_copy = FALSE; - bs = apk_bstream_from_fd_url(filefd, file); - if (IS_ERR_OR_NULL(bs)) { - r = PTR_ERR(bs); + is = apk_istream_from_fd_url(filefd, file); + if (IS_ERR_OR_NULL(is)) { + r = PTR_ERR(is); if (r == -ENOENT && pkg->filename == NULL) r = -EAPKSTALEINDEX; goto err_msg; @@ -2800,9 +2792,9 @@ static int apk_db_unpack_pkg(struct apk_database *db, apk_blob_t b = APK_BLOB_BUF(tmpcacheitem); apk_blob_push_blob(&b, tmpprefix); apk_pkg_format_cache_pkg(b, pkg); - cache_bs = apk_bstream_tee(bs, db->cache_fd, tmpcacheitem, 1, NULL, NULL); - if (!IS_ERR_OR_NULL(cache_bs)) - bs = cache_bs; + cache_is = apk_istream_tee(is, db->cache_fd, tmpcacheitem, 1, NULL, NULL); + if (!IS_ERR_OR_NULL(cache_is)) + is = cache_is; else apk_warning(PKG_VER_FMT": unable to cache: %s", PKG_VER_PRINTF(pkg), apk_error_str(errno)); @@ -2819,7 +2811,7 @@ static int apk_db_unpack_pkg(struct apk_database *db, .cb_ctx = cb_ctx, }; apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &pkg->csum, db->keys_fd); - tar = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &ctx.sctx); + tar = apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &ctx.sctx); r = apk_tar_parse(tar, apk_db_install_archive_entry, &ctx, &db->id_cache); apk_sign_ctx_free(&ctx.sctx); apk_istream_close(tar); diff --git a/src/gunzip.c b/src/gunzip.c index 17b74a3..96138b0 100644 --- a/src/gunzip.c +++ b/src/gunzip.c @@ -20,7 +20,7 @@ struct apk_gzip_istream { struct apk_istream is; - struct apk_bstream *bs; + struct apk_istream *zis; z_stream zs; apk_multipart_cb cb; @@ -32,7 +32,7 @@ struct apk_gzip_istream { static void gzi_get_meta(struct apk_istream *is, struct apk_file_meta *meta) { struct apk_gzip_istream *gis = container_of(is, struct apk_gzip_istream, is); - apk_bstream_get_meta(gis->bs, meta); + apk_istream_get_meta(gis->zis, meta); } static int gzi_boundary_change(struct apk_gzip_istream *gis) @@ -68,7 +68,7 @@ static ssize_t gzi_read(struct apk_istream *is, void *ptr, size_t size) APK_BLOB_PTR_LEN(gis->cbprev, (void *)gis->zs.next_in - gis->cbprev)); } - blob = apk_bstream_read(gis->bs, APK_BLOB_NULL); + blob = apk_istream_get_all(gis->zis); gis->cbprev = blob.ptr; gis->zs.avail_in = blob.len; gis->zs.next_in = (void *) gis->cbprev; @@ -87,9 +87,8 @@ static ssize_t gzi_read(struct apk_istream *is, void *ptr, size_t size) switch (r) { case Z_STREAM_END: /* Digest the inflated bytes */ - if ((gis->bs->flags & APK_BSTREAM_EOF) && - gis->zs.avail_in == 0) - gis->is.err = 1; + if (gis->zis->err && gis->zs.avail_in == 0) + gis->is.err = gis->zis->err; if (gis->cb != NULL) { gis->cbarg = APK_BLOB_PTR_LEN(gis->cbprev, (void *) gis->zs.next_in - gis->cbprev); gis->cbprev = gis->zs.next_in; @@ -125,7 +124,7 @@ static void gzi_close(struct apk_istream *is) struct apk_gzip_istream *gis = container_of(is, struct apk_gzip_istream, is); inflateEnd(&gis->zs); - apk_bstream_close(gis->bs); + apk_istream_close(gis->zis); free(gis); } @@ -135,12 +134,11 @@ static const struct apk_istream_ops gunzip_istream_ops = { .close = gzi_close, }; -struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *bs, - apk_multipart_cb cb, void *ctx) +struct apk_istream *apk_istream_gunzip_mpart(struct apk_istream *is, apk_multipart_cb cb, void *ctx) { struct apk_gzip_istream *gis; - if (IS_ERR_OR_NULL(bs)) return ERR_CAST(bs); + if (IS_ERR_OR_NULL(is)) return ERR_CAST(is); gis = malloc(sizeof(*gis) + apk_io_bufsize); if (!gis) goto err; @@ -149,7 +147,7 @@ struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *bs, .is.ops = &gunzip_istream_ops, .is.buf = (uint8_t*)(gis + 1), .is.buf_size = apk_io_bufsize, - .bs = bs, + .zis = is, .cb = cb, .cbctx = ctx, }; @@ -161,7 +159,7 @@ struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *bs, return &gis->is; err: - apk_bstream_close(bs); + apk_istream_close(is); return ERR_PTR(-ENOMEM); } @@ -226,7 +226,7 @@ static const struct apk_istream_ops segment_istream_ops = { .close = segment_close, }; -void apk_istream_segment(struct apk_segment_istream *sis, struct apk_istream *is, size_t len, time_t mtime) +struct apk_istream *apk_istream_segment(struct apk_segment_istream *sis, struct apk_istream *is, size_t len, time_t mtime) { *sis = (struct apk_segment_istream) { .is.ops = &segment_istream_ops, @@ -245,6 +245,114 @@ void apk_istream_segment(struct apk_segment_istream *sis, struct apk_istream *is is->ptr = is->end = 0; } sis->bytes_left -= sis->is.end - sis->is.ptr; + return &sis->is; +} + +struct apk_tee_istream { + struct apk_istream is; + struct apk_istream *inner_is; + int fd, copy_meta; + size_t size; + apk_progress_cb cb; + void *cb_ctx; +}; + +static void tee_get_meta(struct apk_istream *is, struct apk_file_meta *meta) +{ + struct apk_tee_istream *tee = container_of(is, struct apk_tee_istream, is); + apk_istream_get_meta(tee->inner_is, meta); +} + +static ssize_t __tee_write(struct apk_tee_istream *tee, void *ptr, size_t size) +{ + ssize_t w = write(tee->fd, ptr, size); + if (size != w) { + if (w < 0) return w; + return -ENOSPC; + } + tee->size += size; + if (tee->cb) tee->cb(tee->cb_ctx, tee->size); + return size; +} + +static ssize_t tee_read(struct apk_istream *is, void *ptr, size_t size) +{ + struct apk_tee_istream *tee = container_of(is, struct apk_tee_istream, is); + ssize_t r; + + r = tee->inner_is->ops->read(tee->inner_is, ptr, size); + if (r <= 0) return r; + + return __tee_write(tee, ptr, r); +} + +static void tee_close(struct apk_istream *is) +{ + struct apk_tee_istream *tee = container_of(is, struct apk_tee_istream, is); + struct apk_file_meta meta; + + if (tee->copy_meta) { + apk_istream_get_meta(tee->inner_is, &meta); + apk_file_meta_to_fd(tee->fd, &meta); + } + + apk_istream_close(tee->inner_is); + close(tee->fd); + free(tee); +} + +static const struct apk_istream_ops tee_istream_ops = { + .get_meta = tee_get_meta, + .read = tee_read, + .close = tee_close, +}; + +struct apk_istream *apk_istream_tee(struct apk_istream *from, int atfd, const char *to, int copy_meta, apk_progress_cb cb, void *cb_ctx) +{ + struct apk_tee_istream *tee; + int fd, r; + + if (IS_ERR_OR_NULL(from)) return ERR_CAST(from); + + fd = openat(atfd, to, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd < 0) { + r = -errno; + goto err_is; + } + + tee = malloc(sizeof *tee); + if (!tee) { + r = -ENOMEM; + goto err_fd; + } + + *tee = (struct apk_tee_istream) { + .is.ops = &tee_istream_ops, + .is.buf = from->buf, + .is.buf_size = from->buf_size, + .is.ptr = from->ptr, + .is.end = from->end, + .inner_is = from, + .fd = fd, + .copy_meta = copy_meta, + .cb = cb, + .cb_ctx = cb_ctx, + }; + + if (from->ptr != from->end) { + r = __tee_write(tee, from->ptr, from->end - from->ptr); + if (r < 0) goto err_free; + } + + return &tee->is; +err_free: + free(tee); +err_fd: + close(fd); +err_is: + apk_istream_close(from); + return ERR_PTR(r); } struct apk_fd_istream { @@ -571,91 +679,6 @@ struct apk_bstream *apk_bstream_from_file(int atfd, const char *file) } -struct apk_tee_bstream { - struct apk_bstream bs; - struct apk_bstream *inner_bs; - int fd, copy_meta; - size_t size; - apk_progress_cb cb; - void *cb_ctx; -}; - -static void tee_get_meta(struct apk_bstream *bs, struct apk_file_meta *meta) -{ - struct apk_tee_bstream *tbs = container_of(bs, struct apk_tee_bstream, bs); - apk_bstream_get_meta(tbs->inner_bs, meta); -} - -static apk_blob_t tee_read(struct apk_bstream *bs, apk_blob_t token) -{ - struct apk_tee_bstream *tbs = container_of(bs, struct apk_tee_bstream, bs); - apk_blob_t blob; - - blob = apk_bstream_read(tbs->inner_bs, token); - if (!APK_BLOB_IS_NULL(blob)) { - tbs->size += write(tbs->fd, blob.ptr, blob.len); - if (tbs->cb) tbs->cb(tbs->cb_ctx, tbs->size); - } - - return blob; -} - -static void tee_close(struct apk_bstream *bs) -{ - struct apk_file_meta meta; - struct apk_tee_bstream *tbs = container_of(bs, struct apk_tee_bstream, bs); - - if (tbs->copy_meta) { - apk_bstream_get_meta(tbs->inner_bs, &meta); - apk_file_meta_to_fd(tbs->fd, &meta); - } - - apk_bstream_close(tbs->inner_bs); - close(tbs->fd); - free(tbs); -} - -static const struct apk_bstream_ops tee_bstream_ops = { - .get_meta = tee_get_meta, - .read = tee_read, - .close = tee_close, -}; - -struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, int atfd, const char *to, int copy_meta, apk_progress_cb cb, void *cb_ctx) -{ - struct apk_tee_bstream *tbs; - int fd, r; - - if (IS_ERR_OR_NULL(from)) return ERR_CAST(from); - - fd = openat(atfd, to, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (fd < 0) { - r = errno; - apk_bstream_close(from); - return ERR_PTR(-r); - } - - tbs = malloc(sizeof(struct apk_tee_bstream)); - if (!tbs) { - r = errno; - close(fd); - apk_bstream_close(from); - return ERR_PTR(-r); - } - - *tbs = (struct apk_tee_bstream) { - .bs.ops = &tee_bstream_ops, - .inner_bs = from, - .fd = fd, - .copy_meta = copy_meta, - .cb = cb, - .cb_ctx = cb_ctx, - }; - - return &tbs->bs; -} - apk_blob_t apk_blob_from_istream(struct apk_istream *is, size_t size) { void *ptr; @@ -911,7 +934,7 @@ int apk_dir_foreach_file(int dirfd, apk_dir_file_cb cb, void *ctx) struct apk_istream *apk_istream_from_file_gz(int atfd, const char *file) { - return apk_bstream_gunzip(apk_bstream_from_file(atfd, file)); + return apk_istream_gunzip(apk_istream_from_file(atfd, file)); } struct apk_fd_ostream { diff --git a/src/manifest.c b/src/manifest.c index adabe61..55fc0af 100644 --- a/src/manifest.c +++ b/src/manifest.c @@ -91,7 +91,7 @@ static void process_file(struct apk_database *db, const char *match) struct manifest_file_ctx ctx = {match, &sctx}; apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd); - is = apk_bstream_gunzip_mpart(apk_bstream_from_file(AT_FDCWD, match), + is = apk_istream_gunzip_mpart(apk_istream_from_file(AT_FDCWD, match), apk_sign_ctx_mpart_cb, &sctx); if (IS_ERR_OR_NULL(is)) { diff --git a/src/package.c b/src/package.c index 12f2245..cbcdfce 100644 --- a/src/package.c +++ b/src/package.c @@ -904,8 +904,7 @@ int apk_pkg_read(struct apk_database *db, const char *file, { struct read_info_ctx ctx; struct apk_file_info fi; - struct apk_bstream *bs; - struct apk_istream *tar; + struct apk_istream *is, *tar; int r; r = apk_fileinfo_get(AT_FDCWD, file, APK_CHECKSUM_NONE, &fi); @@ -918,16 +917,16 @@ int apk_pkg_read(struct apk_database *db, const char *file, r = -ENOMEM; if (ctx.pkg == NULL) goto err; - bs = apk_bstream_from_file(AT_FDCWD, file); - if (IS_ERR_OR_NULL(bs)) { - r = PTR_ERR(bs) ?: -EIO; + is = apk_istream_from_file(AT_FDCWD, file); + if (IS_ERR_OR_NULL(is)) { + r = PTR_ERR(is) ?: -EIO; goto err; } ctx.db = db; ctx.pkg->size = fi.size; - tar = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, sctx); + tar = apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, sctx); r = apk_tar_parse(tar, read_info_entry, &ctx, &db->id_cache); apk_istream_close(tar); if (r < 0 && r != -ECANCELED) @@ -152,12 +152,5 @@ 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 *file) { - return apk_bstream_gunzip(apk_bstream_from_url(file)); -} - -struct apk_bstream *apk_bstream_from_fd_url_if_modified(int atfd, const char *url, time_t since) -{ - if (apk_url_local_file(url) != NULL) - return apk_bstream_from_file(atfd, apk_url_local_file(url)); - return apk_bstream_from_istream(apk_istream_fetch(url, since)); + return apk_istream_gunzip(apk_istream_from_url(file)); } diff --git a/src/verify.c b/src/verify.c index ed0920b..af48297 100644 --- a/src/verify.c +++ b/src/verify.c @@ -26,7 +26,7 @@ static int verify_main(void *ctx, struct apk_database *db, struct apk_string_arr foreach_array_item(parg, args) { apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd); - is = apk_bstream_gunzip_mpart(apk_bstream_from_file(AT_FDCWD, *parg), + is = apk_istream_gunzip_mpart(apk_istream_from_file(AT_FDCWD, *parg), apk_sign_ctx_mpart_cb, &sctx); if (IS_ERR_OR_NULL(is)) { if (apk_verbosity >= 1) |