diff options
Diffstat (limited to 'main/apk-tools/0001-io-move-csumming-away-from-bstream-to-gunzip.patch')
-rw-r--r-- | main/apk-tools/0001-io-move-csumming-away-from-bstream-to-gunzip.patch | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/main/apk-tools/0001-io-move-csumming-away-from-bstream-to-gunzip.patch b/main/apk-tools/0001-io-move-csumming-away-from-bstream-to-gunzip.patch new file mode 100644 index 0000000000..05f7d2c97a --- /dev/null +++ b/main/apk-tools/0001-io-move-csumming-away-from-bstream-to-gunzip.patch @@ -0,0 +1,539 @@ +From e69b81f5259f532d5f5ae9c0a0f9bbd81240fbaf Mon Sep 17 00:00:00 2001 +From: Timo Teras <timo.teras@iki.fi> +Date: Mon, 13 Jul 2009 20:37:03 +0300 +Subject: [PATCH] io: move csumming away from bstream to gunzip + +in future we want to checksum on gzip boundary basis, not the +full file. +--- + src/apk_io.h | 17 +++++++++++++++-- + src/archive.c | 4 ++-- + src/audit.c | 18 +++++------------- + src/database.c | 42 +++++++++++++++++++++++++++++------------- + src/gunzip.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- + src/io.c | 48 ++++++++++++++++-------------------------------- + src/package.c | 28 +++++++++++++++++++++++----- + 7 files changed, 131 insertions(+), 75 deletions(-) + +diff --git a/src/apk_io.h b/src/apk_io.h +index b5e984a..629729a 100644 +--- a/src/apk_io.h ++++ b/src/apk_io.h +@@ -36,7 +36,7 @@ struct apk_istream { + + struct apk_bstream { + size_t (*read)(void *stream, void **ptr); +- void (*close)(void *stream, csum_p csum, size_t *size); ++ void (*close)(void *stream, size_t *size); + }; + + struct apk_ostream { +@@ -44,7 +44,20 @@ struct apk_ostream { + void (*close)(void *stream); + }; + +-struct apk_istream *apk_bstream_gunzip(struct apk_bstream *, int); ++#define APK_MPART_BEGIN 0 ++#define APK_MPART_BOUNDARY 1 ++#define APK_MPART_END 2 ++ ++typedef int (*apk_multipart_cb)(void *ctx, EVP_MD_CTX *mdctx, int part); ++ ++struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *, int, ++ apk_multipart_cb cb, void *ctx); ++static inline struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs, ++ int autoclose) ++{ ++ return apk_bstream_gunzip_mpart(bs, autoclose, NULL, NULL); ++} ++ + struct apk_ostream *apk_ostream_gzip(struct apk_ostream *); + + struct apk_istream *apk_istream_from_fd(int fd); +diff --git a/src/archive.c b/src/archive.c +index a05aee2..6681b61 100644 +--- a/src/archive.c ++++ b/src/archive.c +@@ -4,7 +4,7 @@ + * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi> + * All rights reserved. + * +- * This program is free software; you can redistribute it and/or modify it ++ * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. See http://www.gnu.org/ for details. + */ +@@ -91,7 +91,7 @@ int apk_parse_tar(struct apk_istream *is, apk_archive_entry_parser parser, + if (buf.name[0] == '\0') { + if (end) { + r = 0; +- break; ++ //break; + } + end++; + continue; +diff --git a/src/audit.c b/src/audit.c +index 9ea0f25..3732aac 100644 +--- a/src/audit.c ++++ b/src/audit.c +@@ -27,12 +27,10 @@ static int audit_directory(apk_hash_item item, void *ctx) + struct apk_db_file *dbf; + struct apk_database *db = (struct apk_database *) ctx; + struct dirent *de; +- struct stat st; +- struct apk_bstream *bs; ++ struct apk_file_info fi; ++ apk_blob_t bdir = APK_BLOB_STR(dbd->dirname); + char tmp[512], reason; + DIR *dir; +- apk_blob_t bdir = APK_BLOB_STR(dbd->dirname); +- csum_t csum; + + if (!(dbd->flags & APK_DBDIRF_PROTECTED)) + return 0; +@@ -49,10 +47,10 @@ static int audit_directory(apk_hash_item item, void *ctx) + snprintf(tmp, sizeof(tmp), "%s/%s", + dbd->dirname, de->d_name); + +- if (stat(tmp, &st) < 0) ++ if (apk_file_get_info(tmp, &fi) < 0) + continue; + +- if (S_ISDIR(st.st_mode)) { ++ if (S_ISDIR(fi.mode)) { + if (apk_db_dir_query(db, APK_BLOB_STR(tmp)) != NULL) + continue; + +@@ -60,13 +58,7 @@ static int audit_directory(apk_hash_item item, void *ctx) + } else { + dbf = apk_db_file_query(db, bdir, APK_BLOB_STR(de->d_name)); + if (dbf != NULL) { +- bs = apk_bstream_from_file(tmp); +- if (bs == NULL) +- continue; +- +- bs->close(bs, csum, NULL); +- +- if (apk_blob_compare(APK_BLOB_BUF(csum), ++ if (apk_blob_compare(APK_BLOB_BUF(fi.csum), + APK_BLOB_BUF(dbf->csum)) == 0) + continue; + +diff --git a/src/database.c b/src/database.c +index 293af4c..10c0b5e 100644 +--- a/src/database.c ++++ b/src/database.c +@@ -36,6 +36,7 @@ struct install_ctx { + + int script; + struct apk_db_dir_instance *diri; ++ csum_t data_csum; + + apk_progress_cb cb; + void *cb_ctx; +@@ -1271,13 +1272,28 @@ static void apk_db_purge_pkg(struct apk_database *db, + apk_pkg_set_state(db, pkg, APK_PKG_NOT_INSTALLED); + } + ++static int apk_db_gzip_part(void *pctx, EVP_MD_CTX *mdctx, int part) ++{ ++ struct install_ctx *ctx = (struct install_ctx *) pctx; ++ ++ switch (part) { ++ case APK_MPART_BEGIN: ++ EVP_DigestInit_ex(mdctx, EVP_md5(), NULL); ++ break; ++ case APK_MPART_END: ++ EVP_DigestFinal_ex(mdctx, ctx->data_csum, NULL); ++ break; ++ } ++ return 0; ++} ++ + static int apk_db_unpack_pkg(struct apk_database *db, + struct apk_package *newpkg, +- int upgrade, csum_t csum, +- apk_progress_cb cb, void *cb_ctx) ++ int upgrade, apk_progress_cb cb, void *cb_ctx) + { + struct install_ctx ctx; + struct apk_bstream *bs = NULL; ++ struct apk_istream *tar; + char pkgname[256], file[256]; + int i, need_copy = FALSE; + size_t length; +@@ -1334,10 +1350,17 @@ static int apk_db_unpack_pkg(struct apk_database *db, + .cb = cb, + .cb_ctx = cb_ctx, + }; +- if (apk_parse_tar_gz(bs, apk_db_install_archive_entry, &ctx) != 0) ++ ++ tar = apk_bstream_gunzip_mpart(bs, FALSE, apk_db_gzip_part, &ctx); ++ if (apk_parse_tar(tar, apk_db_install_archive_entry, &ctx) != 0) + goto err_close; ++ bs->close(bs, &length); ++ ++ /* Check the package checksum */ ++ if (memcmp(ctx.data_csum, newpkg->csum, sizeof(csum_t)) != 0) ++ apk_warning("%s-%s: checksum does not match", ++ newpkg->name->name, newpkg->version); + +- bs->close(bs, csum, &length); + if (need_copy) { + if (length == newpkg->size) { + char file2[256]; +@@ -1351,7 +1374,7 @@ static int apk_db_unpack_pkg(struct apk_database *db, + + return 0; + err_close: +- bs->close(bs, NULL, NULL); ++ bs->close(bs, NULL); + return -1; + } + +@@ -1360,7 +1383,6 @@ int apk_db_install_pkg(struct apk_database *db, + struct apk_package *newpkg, + apk_progress_cb cb, void *cb_ctx) + { +- csum_t csum; + int r; + + if (fchdir(db->root_fd) < 0) +@@ -1382,19 +1404,13 @@ int apk_db_install_pkg(struct apk_database *db, + + /* Install the new stuff */ + if (!(newpkg->name->flags & APK_NAME_VIRTUAL)) { +- r = apk_db_unpack_pkg(db, newpkg, (oldpkg != NULL), csum, +- cb, cb_ctx); ++ r = apk_db_unpack_pkg(db, newpkg, (oldpkg != NULL), cb, cb_ctx); + if (r != 0) + return r; + } + + apk_pkg_set_state(db, newpkg, APK_PKG_INSTALLED); + +- if (!(newpkg->name->flags & APK_NAME_VIRTUAL) && +- memcmp(csum, newpkg->csum, sizeof(csum)) != 0) +- apk_warning("%s-%s: checksum does not match", +- newpkg->name->name, newpkg->version); +- + if (oldpkg != NULL) + apk_db_purge_pkg(db, oldpkg); + +diff --git a/src/gunzip.c b/src/gunzip.c +index 2c7ffc2..1d2881c 100644 +--- a/src/gunzip.c ++++ b/src/gunzip.c +@@ -23,13 +23,18 @@ struct apk_gzip_istream { + z_stream zs; + int z_err; + int autoclose; ++ ++ EVP_MD_CTX mdctx; ++ void *mdblock; ++ ++ apk_multipart_cb cb; ++ void *cbctx; + }; + + static size_t gz_read(void *stream, void *ptr, size_t size) + { + struct apk_gzip_istream *gis = + container_of(stream, struct apk_gzip_istream, is); +- int restart_count = 0; + + if (gis->z_err == Z_DATA_ERROR || gis->z_err == Z_ERRNO) + return -1; +@@ -44,22 +49,40 @@ static size_t gz_read(void *stream, void *ptr, size_t size) + + while (gis->zs.avail_out != 0 && gis->z_err == Z_OK) { + if (gis->zs.avail_in == 0) { +- gis->zs.avail_in = gis->bs->read(gis->bs, (void **) &gis->zs.next_in); ++ if (gis->cb != NULL && gis->mdblock != NULL) { ++ /* Digest the inflated bytes */ ++ EVP_DigestUpdate(&gis->mdctx, gis->mdblock, ++ (void *)gis->zs.next_in - gis->mdblock); ++ } ++ gis->zs.avail_in = gis->bs->read(gis->bs, &gis->mdblock); ++ gis->zs.next_in = (void *) gis->mdblock; + if (gis->zs.avail_in < 0) { + gis->z_err = Z_DATA_ERROR; + return size - gis->zs.avail_out; ++ } else if (gis->zs.avail_in == 0) { ++ if (gis->cb != NULL) ++ gis->cb(gis->cbctx, &gis->mdctx, ++ APK_MPART_END); ++ gis->z_err = Z_STREAM_END; ++ return size - gis->zs.avail_out; + } + } + + gis->z_err = inflate(&gis->zs, Z_NO_FLUSH); +- if (restart_count == 0 && gis->z_err == Z_STREAM_END) { ++ if (gis->z_err == Z_STREAM_END) { ++ /* Digest the inflated bytes */ ++ if (gis->cb != NULL) { ++ EVP_DigestUpdate(&gis->mdctx, gis->mdblock, ++ (void *)gis->zs.next_in - gis->mdblock); ++ gis->mdblock = gis->zs.next_in; ++ gis->cb(gis->cbctx, &gis->mdctx, ++ APK_MPART_BOUNDARY); ++ } + inflateEnd(&gis->zs); ++ + if (inflateInit2(&gis->zs, 15+32) != Z_OK) + return -1; + gis->z_err = Z_OK; +- restart_count++; +- } else { +- restart_count = 0; + } + } + +@@ -74,13 +97,16 @@ static void gz_close(void *stream) + struct apk_gzip_istream *gis = + container_of(stream, struct apk_gzip_istream, is); + ++ if (gis->cb != NULL) ++ EVP_MD_CTX_cleanup(&gis->mdctx); + inflateEnd(&gis->zs); + if (gis->autoclose) +- gis->bs->close(gis->bs, NULL, NULL); ++ gis->bs->close(gis->bs, NULL); + free(gis); + } + +-struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs, int autoclose) ++struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *bs, int autoclose, ++ apk_multipart_cb cb, void *ctx) + { + struct apk_gzip_istream *gis; + +@@ -97,6 +123,8 @@ struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs, int autoclose) + .bs = bs, + .z_err = 0, + .autoclose = autoclose, ++ .cb = cb, ++ .cbctx = ctx, + }; + + if (inflateInit2(&gis->zs, 15+32) != Z_OK) { +@@ -104,6 +132,11 @@ struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs, int autoclose) + return NULL; + } + ++ if (gis->cb != NULL) { ++ EVP_MD_CTX_init(&gis->mdctx); ++ cb(ctx, &gis->mdctx, APK_MPART_BEGIN); ++ } ++ + return &gis->is; + } + +diff --git a/src/io.c b/src/io.c +index 722bccb..a250b27 100644 +--- a/src/io.c ++++ b/src/io.c +@@ -150,7 +150,6 @@ err: + struct apk_istream_bstream { + struct apk_bstream bs; + struct apk_istream *is; +- csum_ctx_t csum_ctx; + unsigned char buffer[8*1024]; + size_t size; + }; +@@ -165,31 +164,17 @@ static size_t is_bs_read(void *stream, void **ptr) + if (size <= 0) + return size; + +- csum_process(&isbs->csum_ctx, isbs->buffer, size); + isbs->size += size; + + *ptr = isbs->buffer; + return size; + } + +-static void is_bs_close(void *stream, csum_t csum, size_t *size) ++static void is_bs_close(void *stream, size_t *size) + { + struct apk_istream_bstream *isbs = + container_of(stream, struct apk_istream_bstream, bs); + +- if (csum != NULL) { +- size_t size; +- +- do { +- size = isbs->is->read(isbs->is, isbs->buffer, +- sizeof(isbs->buffer)); +- csum_process(&isbs->csum_ctx, isbs->buffer, size); +- isbs->size += size; +- } while (size == sizeof(isbs->buffer)); +- +- csum_finish(&isbs->csum_ctx, csum); +- } +- + if (size != NULL) + *size = isbs->size; + +@@ -210,14 +195,12 @@ struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream) + .close = is_bs_close, + }; + isbs->is = istream; +- csum_init(&isbs->csum_ctx); + + return &isbs->bs; + } + + struct apk_mmap_bstream { + struct apk_bstream bs; +- csum_ctx_t csum_ctx; + int fd; + size_t size; + unsigned char *ptr; +@@ -235,24 +218,16 @@ static size_t mmap_read(void *stream, void **ptr) + size = 1024*1024; + + *ptr = (void *) &mbs->ptr[mbs->pos]; +- csum_process(&mbs->csum_ctx, &mbs->ptr[mbs->pos], size); + mbs->pos += size; + + return size; + } + +-static void mmap_close(void *stream, csum_t csum, size_t *size) ++static void mmap_close(void *stream, size_t *size) + { + struct apk_mmap_bstream *mbs = + container_of(stream, struct apk_mmap_bstream, bs); + +- if (csum != NULL) { +- if (mbs->pos != mbs->size) +- csum_process(&mbs->csum_ctx, &mbs->ptr[mbs->pos], +- mbs->size - mbs->pos); +- csum_finish(&mbs->csum_ctx, csum); +- } +- + if (size != NULL) + *size = mbs->size; + +@@ -288,7 +263,6 @@ static struct apk_bstream *apk_mmap_bstream_from_fd(int fd) + mbs->size = st.st_size; + mbs->ptr = ptr; + mbs->pos = 0; +- csum_init(&mbs->csum_ctx); + + return &mbs->bs; + } +@@ -340,12 +314,12 @@ static size_t tee_read(void *stream, void **ptr) + return size; + } + +-static void tee_close(void *stream, csum_t csum, size_t *size) ++static void tee_close(void *stream, size_t *size) + { + struct apk_tee_bstream *tbs = + container_of(stream, struct apk_tee_bstream, bs); + +- tbs->inner_bs->close(tbs->inner_bs, csum, NULL); ++ tbs->inner_bs->close(tbs->inner_bs, NULL); + if (size != NULL) + *size = tbs->size; + close(tbs->fd); +@@ -431,6 +405,7 @@ int apk_file_get_info(const char *filename, struct apk_file_info *fi) + { + struct stat st; + struct apk_bstream *bs; ++ csum_ctx_t ctx; + + if (stat(filename, &st) != 0) + return -1; +@@ -445,8 +420,17 @@ int apk_file_get_info(const char *filename, struct apk_file_info *fi) + }; + + bs = apk_bstream_from_file(filename); +- if (bs != NULL) +- bs->close(bs, fi->csum, NULL); ++ if (bs != NULL) { ++ ssize_t size; ++ void *ptr; ++ ++ csum_init(&ctx); ++ while ((size = bs->read(bs, &ptr)) > 0) ++ csum_process(&ctx, ptr, size); ++ csum_finish(&ctx, fi->csum); ++ ++ bs->close(bs, NULL); ++ } + + return 0; + } +diff --git a/src/package.c b/src/package.c +index 6c51924..30b09b1 100644 +--- a/src/package.c ++++ b/src/package.c +@@ -4,7 +4,7 @@ + * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi> + * All rights reserved. + * +- * This program is free software; you can redistribute it and/or modify it ++ * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. See http://www.gnu.org/ for details. + */ +@@ -415,10 +415,26 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae, + return 0; + } + ++static int apk_pkg_gzip_part(void *ctx, EVP_MD_CTX *mdctx, int part) ++{ ++ struct read_info_ctx *ri = (struct read_info_ctx *) ctx; ++ ++ switch (part) { ++ case APK_MPART_BEGIN: ++ EVP_DigestInit_ex(mdctx, EVP_md5(), NULL); ++ break; ++ case APK_MPART_END: ++ EVP_DigestFinal_ex(mdctx, ri->pkg->csum, NULL); ++ break; ++ } ++ return 0; ++} ++ + struct apk_package *apk_pkg_read(struct apk_database *db, const char *file) + { + struct read_info_ctx ctx; + struct apk_bstream *bs; ++ struct apk_istream *tar; + char realfile[PATH_MAX]; + + if (realpath(file, realfile) < 0) +@@ -434,12 +450,14 @@ struct apk_package *apk_pkg_read(struct apk_database *db, const char *file) + + ctx.db = db; + ctx.has_install = 0; +- if (apk_parse_tar_gz(bs, read_info_entry, &ctx) < 0) { ++ ++ tar = apk_bstream_gunzip_mpart(bs, FALSE, apk_pkg_gzip_part, &ctx); ++ if (apk_parse_tar(tar, read_info_entry, &ctx) < 0) { + apk_error("File %s is not an APK archive", file); +- bs->close(bs, NULL, NULL); ++ bs->close(bs, NULL); + goto err; + } +- bs->close(bs, ctx.pkg->csum, &ctx.pkg->size); ++ bs->close(bs, &ctx.pkg->size); + + if (ctx.pkg->name == NULL) { + apk_error("File %s is corrupted", file); +@@ -682,7 +700,7 @@ struct apk_dependency apk_dep_from_str(struct apk_database *db, + mask = apk_version_result_mask(v++); + if (*v == '=') + v++; +- } ++ } + return (struct apk_dependency) { + .name = apk_db_get_name(db, name), + .version = v, +-- +1.6.3.3 + |