summaryrefslogtreecommitdiff
path: root/src/extract_v2.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2021-07-27 15:34:04 +0300
committerTimo Teräs <timo.teras@iki.fi>2021-07-27 16:28:22 +0300
commit5843daf7a1cdf15cbc76952c60a1d822414b2ef3 (patch)
tree46d5307df67341e3c8f90c3f3746f90c96da9459 /src/extract_v2.c
parent9c843e4ecdfee916ec835b5d35c10b3818aba9e3 (diff)
downloadapk-tools-5843daf7a1cdf15cbc76952c60a1d822414b2ef3.tar.gz
apk-tools-5843daf7a1cdf15cbc76952c60a1d822414b2ef3.tar.bz2
apk-tools-5843daf7a1cdf15cbc76952c60a1d822414b2ef3.tar.xz
apk-tools-5843daf7a1cdf15cbc76952c60a1d822414b2ef3.zip
Further refactor extract API to have separate ops vtable
This splits the callbacks by type, and further prepares the API to be usable for v3 files too.
Diffstat (limited to 'src/extract_v2.c')
-rw-r--r--src/extract_v2.c76
1 files changed, 62 insertions, 14 deletions
diff --git a/src/extract_v2.c b/src/extract_v2.c
index 217a07d..029a5e3 100644
--- a/src/extract_v2.c
+++ b/src/extract_v2.c
@@ -278,31 +278,61 @@ update_digest:
return 0;
}
+static int apk_extract_verify_v2index(struct apk_extract_ctx *ectx, apk_blob_t *desc, struct apk_istream *is)
+{
+ return 0;
+}
+
+static int apk_extract_verify_v2file(struct apk_extract_ctx *ectx, const struct apk_file_info *fi, struct apk_istream *is)
+{
+ return 0;
+}
+
+static const struct apk_extract_ops extract_v2verify_ops = {
+ .v2index = apk_extract_verify_v2index,
+ .v2meta = apk_extract_v2_meta,
+ .file = apk_extract_verify_v2file,
+};
+
static int apk_extract_v2_entry(void *pctx, const struct apk_file_info *fi, struct apk_istream *is)
{
struct apk_extract_ctx *ectx = pctx;
struct apk_sign_ctx *sctx = ectx->pctx;
- int r;
+ int r, type;
r = apk_sign_ctx_process_file(sctx, fi, is);
if (r <= 0) return r;
- ectx->metadata = sctx->control_started && !sctx->data_started;
- ectx->metadata_verified = sctx->control_verified;
-
- r = ectx->cb ? ectx->cb(ectx, fi, is) : 0;
-
- if (ectx->metadata && strcmp(fi->name, ".PKGINFO") == 0) {
- // Parse the .PKGINFO for the data, in case the callback did not do it.
- apk_blob_t l, r, token = APK_BLOB_STR("\n");
- while (apk_istream_get_delim(is, token, &l) == 0) {
- if (l.len < 1 || l.ptr[0] == '#') continue;
- if (apk_blob_split(l, APK_BLOB_STR(" = "), &l, &r))
- apk_extract_v2_control(ectx, l, r);
+ if (!sctx->control_started) return 0;
+ if (!sctx->data_started || !sctx->has_data_checksum) {
+ if (fi->name[0] == '.') {
+ ectx->is_package = 1;
+ if (ectx->is_index) return -APKE_V2NDX_FORMAT;
+ if (!ectx->ops->v2meta) return -APKE_FORMAT_NOT_SUPPORTED;
+ if (strcmp(fi->name, ".PKGINFO") == 0) {
+ return ectx->ops->v2meta(ectx, is);
+ } else if (strcmp(fi->name, ".INSTALL") == 0) {
+ return -APKE_V2PKG_FORMAT;
+ } else if ((type = apk_script_type(&fi->name[1])) != APK_SCRIPT_INVALID) {
+ if (ectx->ops->script) return ectx->ops->script(ectx, type, fi->size, is);
+ }
+ } else {
+ ectx->is_index = 1;
+ if (ectx->is_package) return -APKE_V2PKG_FORMAT;
+ if (!ectx->ops->v2index) return -APKE_FORMAT_NOT_SUPPORTED;
+ if (strcmp(fi->name, "DESCRIPTION") == 0) {
+ free(ectx->desc.ptr);
+ ectx->desc = apk_blob_from_istream(is, fi->size);
+ } else if (strcmp(fi->name, "APKINDEX") == 0) {
+ return ectx->ops->v2index(ectx, &ectx->desc, is);
+ }
}
+ return 0;
}
- return r;
+ if (!sctx->control_verified) return 0;
+ if (!ectx->ops->file) return -ECANCELED;
+ return ectx->ops->file(ectx, fi, is);
}
int apk_extract_v2(struct apk_extract_ctx *ectx, struct apk_istream *is)
@@ -319,13 +349,18 @@ int apk_extract_v2(struct apk_extract_ctx *ectx, struct apk_istream *is)
else
action = trust->allow_untrusted ? APK_SIGN_NONE : APK_SIGN_VERIFY;
+ if (!ectx->ops) ectx->ops = &extract_v2verify_ops;
ectx->pctx = &sctx;
apk_sign_ctx_init(&sctx, action, ectx->identity, trust);
r = apk_tar_parse(
apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &sctx),
apk_extract_v2_entry, ectx, apk_ctx_get_id_cache(ac));
+ if (r == -ECANCELED) r = 0;
+ if (r == 0 && !ectx->is_package && !ectx->is_index)
+ r = ectx->ops->v2index ? -APKE_V2NDX_FORMAT : -APKE_V2PKG_FORMAT;
if (ectx->generate_identity) *ectx->identity = sctx.identity;
apk_sign_ctx_free(&sctx);
+ free(ectx->desc.ptr);
apk_extract_reset(ectx);
return r;
@@ -345,3 +380,16 @@ void apk_extract_v2_control(struct apk_extract_ctx *ectx, apk_blob_t l, apk_blob
EVP_MD_size(sctx->md)));
}
}
+
+int apk_extract_v2_meta(struct apk_extract_ctx *ectx, struct apk_istream *is)
+{
+ apk_blob_t k, v, token = APK_BLOB_STRLIT("\n");
+ while (apk_istream_get_delim(is, token, &k) == 0) {
+ if (k.len < 1 || k.ptr[0] == '#') continue;
+ if (apk_blob_split(k, APK_BLOB_STRLIT(" = "), &k, &v)) {
+ apk_extract_v2_control(ectx, k, v);
+ }
+ }
+ return 0;
+}
+