summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/apk_extract.h29
-rw-r--r--src/app_convndx.c28
-rw-r--r--src/app_manifest.c10
-rw-r--r--src/app_mkndx.c27
-rw-r--r--src/database.c96
-rw-r--r--src/extract_v2.c76
-rw-r--r--src/package.c31
7 files changed, 162 insertions, 135 deletions
diff --git a/src/apk_extract.h b/src/apk_extract.h
index cc8bae7..94fc401 100644
--- a/src/apk_extract.h
+++ b/src/apk_extract.h
@@ -14,6 +14,7 @@
#include "apk_print.h"
#include "apk_io.h"
+struct adb;
struct apk_ctx;
struct apk_extract_ctx;
@@ -26,26 +27,31 @@ int apk_extract_file(int atfd, const struct apk_file_info *ae,
apk_progress_cb cb, void *cb_ctx, struct apk_digest_ctx *dctx,
unsigned int extract_flags, struct apk_out *out);
-
-typedef int (*apk_extract_cb)(struct apk_extract_ctx *,
- const struct apk_file_info *ae,
- struct apk_istream *istream);
+struct apk_extract_ops {
+ int (*v2index)(struct apk_extract_ctx *, apk_blob_t *desc, struct apk_istream *is);
+ int (*v2meta)(struct apk_extract_ctx *, struct apk_istream *is);
+ int (*v3index)(struct apk_extract_ctx *, struct adb *);
+ int (*v3meta)(struct apk_extract_ctx *, struct adb *);
+ int (*script)(struct apk_extract_ctx *, unsigned int script, size_t size, struct apk_istream *is);
+ int (*file)(struct apk_extract_ctx *, const struct apk_file_info *fi, struct apk_istream *is);
+};
struct apk_extract_ctx {
struct apk_ctx *ac;
- apk_extract_cb cb;
+ const struct apk_extract_ops *ops;
struct apk_checksum *identity;
- unsigned generate_identity : 1;
- unsigned metadata : 1;
- unsigned metadata_verified : 1;
+ apk_blob_t desc;
void *pctx;
+ unsigned generate_identity : 1;
+ unsigned is_package : 1;
+ unsigned is_index : 1;
};
-static inline void apk_extract_init(struct apk_extract_ctx *ectx, struct apk_ctx *ac, apk_extract_cb cb) {
- *ectx = (struct apk_extract_ctx){.ac = ac, .cb = cb};
+static inline void apk_extract_init(struct apk_extract_ctx *ectx, struct apk_ctx *ac, const struct apk_extract_ops *ops) {
+ *ectx = (struct apk_extract_ctx){.ac = ac, .ops = ops};
}
static inline void apk_extract_reset(struct apk_extract_ctx *ectx) {
- apk_extract_init(ectx, ectx->ac, ectx->cb);
+ apk_extract_init(ectx, ectx->ac, ectx->ops);
}
static inline void apk_extract_generate_identity(struct apk_extract_ctx *ctx, struct apk_checksum *id) {
ctx->identity = id;
@@ -58,6 +64,7 @@ int apk_extract(struct apk_extract_ctx *, struct apk_istream *is);
int apk_extract_v2(struct apk_extract_ctx *, struct apk_istream *is);
void apk_extract_v2_control(struct apk_extract_ctx *, apk_blob_t, apk_blob_t);
+int apk_extract_v2_meta(struct apk_extract_ctx *ectx, struct apk_istream *is);
int apk_extract_v3(struct apk_extract_ctx *, struct apk_istream *is);
diff --git a/src/app_convndx.c b/src/app_convndx.c
index d405b03..f8f649e 100644
--- a/src/app_convndx.c
+++ b/src/app_convndx.c
@@ -11,11 +11,11 @@ struct conv_ctx {
struct adb_obj pkgs;
struct adb dbi;
struct apk_extract_ctx ectx;
- int found;
};
-static void convert_index(struct conv_ctx *ctx, struct apk_istream *is)
+static int convert_v2index(struct apk_extract_ctx *ectx, apk_blob_t *desc, struct apk_istream *is)
{
+ struct conv_ctx *ctx = container_of(ectx, struct conv_ctx, ectx);
struct adb_obj pkginfo;
apk_blob_t token = APK_BLOB_STR("\n"), l;
int i;
@@ -30,30 +30,18 @@ static void convert_index(struct conv_ctx *ctx, struct apk_istream *is)
i = adb_pkg_field_index(l.ptr[0]);
if (i > 0) adb_wo_pkginfo(&pkginfo, i, APK_BLOB_PTR_LEN(l.ptr+2, l.len-2));
}
+ return apk_istream_close(is);
}
-static int load_apkindex(struct apk_extract_ctx *ectx, const struct apk_file_info *fi,
- struct apk_istream *is)
-{
- struct conv_ctx *ctx = container_of(ectx, struct conv_ctx, ectx);
-
- if (strcmp(fi->name, "APKINDEX") == 0) {
- ctx->found = 1;
- convert_index(ctx, is);
- return apk_istream_close(is);
- }
- return 0;
-}
+static const struct apk_extract_ops extract_convndx = {
+ .v2index = convert_v2index,
+};
static int load_index(struct conv_ctx *ctx, struct apk_istream *is)
{
- int r = 0;
if (IS_ERR(is)) return PTR_ERR(is);
- ctx->found = 0;
- apk_extract_init(&ctx->ectx, ctx->ac, load_apkindex);
- r = apk_extract(&ctx->ectx, is);
- if (r >= 0 && ctx->found == 0) r = -APKE_V2NDX_FORMAT;
- return r;
+ apk_extract_init(&ctx->ectx, ctx->ac, &extract_convndx);
+ return apk_extract(&ctx->ectx, is);
}
static int conv_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *args)
diff --git a/src/app_manifest.c b/src/app_manifest.c
index ff63d7c..b1cbb3f 100644
--- a/src/app_manifest.c
+++ b/src/app_manifest.c
@@ -65,14 +65,13 @@ struct manifest_file_ctx {
const char *prefix1, *prefix2;
};
-static int read_file_entry(struct apk_extract_ctx *ectx, const struct apk_file_info *fi, struct apk_istream *is)
+static int process_pkg_file(struct apk_extract_ctx *ectx, const struct apk_file_info *fi, struct apk_istream *is)
{
struct manifest_file_ctx *mctx = container_of(ectx, struct manifest_file_ctx, ectx);
struct apk_out *out = mctx->out;
char csum_buf[APK_BLOB_CHECKSUM_BUF];
apk_blob_t csum_blob = APK_BLOB_BUF(csum_buf);
- if (ectx->metadata) return 0;
if ((fi->mode & S_IFMT) != S_IFREG) return 0;
memset(csum_buf, '\0', sizeof(csum_buf));
@@ -86,6 +85,11 @@ static int read_file_entry(struct apk_extract_ctx *ectx, const struct apk_file_i
return 0;
}
+static const struct apk_extract_ops extract_manifest_ops = {
+ .v2meta = apk_extract_v2_meta,
+ .file = process_pkg_file,
+};
+
static void process_file(struct apk_database *db, const char *match)
{
struct apk_out *out = &db->ctx->out;
@@ -96,7 +100,7 @@ static void process_file(struct apk_database *db, const char *match)
};
int r;
- apk_extract_init(&ctx.ectx, db->ctx, read_file_entry);
+ apk_extract_init(&ctx.ectx, db->ctx, &extract_manifest_ops);
if (apk_out_verbosity(out) > 1) {
ctx.prefix1 = match;
ctx.prefix2 = ": ";
diff --git a/src/app_mkndx.c b/src/app_mkndx.c
index c95c494..6e485b5 100644
--- a/src/app_mkndx.c
+++ b/src/app_mkndx.c
@@ -164,23 +164,22 @@ static adb_val_t mkndx_read_v2_pkginfo(struct adb *db, struct apk_istream *is, s
return adb_w_obj(&pkginfo);
}
-static int mkndx_parse_v2_tar(struct apk_extract_ctx *ectx, const struct apk_file_info *ae, struct apk_istream *is)
+static int mkndx_parse_v2meta(struct apk_extract_ctx *ectx, struct apk_istream *is)
{
struct mkndx_ctx *ctx = container_of(ectx, struct mkndx_ctx, ectx);
-
- if (ectx->metadata_verified) return -ECANCELED;
- if (ectx->metadata && strcmp(ae->name, ".PKGINFO") == 0) {
- adb_val_t o = adb_wa_append(
- &ctx->pkgs,
- mkndx_read_v2_pkginfo(
- &ctx->db, is, ctx->file_size, &ctx->ectx,
- ctx->rewrite_arch));
- if (ADB_IS_ERROR(o)) return -ADB_VAL_VALUE(o);
- }
-
+ adb_val_t o = adb_wa_append(
+ &ctx->pkgs,
+ mkndx_read_v2_pkginfo(
+ &ctx->db, is, ctx->file_size, &ctx->ectx,
+ ctx->rewrite_arch));
+ if (ADB_IS_ERROR(o)) return -ADB_VAL_VALUE(o);
return 0;
}
+static const struct apk_extract_ops extract_ndxinfo_ops = {
+ .v2meta = mkndx_parse_v2meta,
+};
+
static int mkndx_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *args)
{
struct apk_out *out = &ac->out;
@@ -199,7 +198,7 @@ static int mkndx_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
return -1;
}
- apk_extract_init(&ctx->ectx, ac, mkndx_parse_v2_tar);
+ apk_extract_init(&ctx->ectx, ac, &extract_ndxinfo_ops);
adb_init(&odb);
adb_w_init_tmp(&tmpdb, 200);
@@ -275,7 +274,7 @@ static int mkndx_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
if (!found) {
do_file:
r = apk_extract(&ctx->ectx, apk_istream_from_file(AT_FDCWD, *parg));
- if (r < 0 && r != -ECANCELED) goto err_pkg;
+ if (r < 0) goto err_pkg;
newpkgs++;
}
}
diff --git a/src/database.c b/src/database.c
index 9ed0085..980efcd 100644
--- a/src/database.c
+++ b/src/database.c
@@ -2163,37 +2163,29 @@ struct apkindex_ctx {
int repo, found;
};
-static int load_apkindex(struct apk_extract_ctx *ectx, const struct apk_file_info *fi,
- struct apk_istream *is)
+static int load_v2index(struct apk_extract_ctx *ectx, apk_blob_t *desc, struct apk_istream *is)
{
struct apkindex_ctx *ctx = container_of(ectx, struct apkindex_ctx, ectx);
- struct apk_repository *repo;
+ struct apk_repository *repo = &ctx->db->repos[ctx->repo];
- repo = &ctx->db->repos[ctx->repo];
- if (strcmp(fi->name, "DESCRIPTION") == 0) {
- repo->description = apk_blob_from_istream(is, fi->size);
- } else if (strcmp(fi->name, "APKINDEX") == 0) {
- ctx->found = 1;
- return apk_db_index_read(ctx->db, is, ctx->repo);
- }
- return 0;
+ repo->description = *desc;
+ *desc = APK_BLOB_NULL;
+ return apk_db_index_read(ctx->db, is, ctx->repo);
}
+static const struct apk_extract_ops extract_index = {
+ .v2index = load_v2index,
+};
+
static int load_index(struct apk_database *db, struct apk_istream *is, int repo)
{
- struct apkindex_ctx ctx;
- int r = 0;
-
+ struct apkindex_ctx ctx = {
+ .db = db,
+ .repo = repo,
+ };
if (IS_ERR(is)) return PTR_ERR(is);
-
- ctx.db = db;
- ctx.repo = repo;
- ctx.found = 0;
- apk_extract_init(&ctx.ectx, db->ctx, load_apkindex);
- r = apk_extract(&ctx.ectx, is);
- if (r >= 0 && ctx.found == 0)
- r = -APKE_V2NDX_FORMAT;
- return r;
+ apk_extract_init(&ctx.ectx, db->ctx, &extract_index);
+ return apk_extract(&ctx.ectx, is);
}
int apk_db_index_read_file(struct apk_database *db, const char *file, int repo)
@@ -2285,10 +2277,9 @@ static void extract_cb(void *_ctx, size_t bytes_done)
static void apk_db_run_pending_script(struct install_ctx *ctx)
{
- if (ctx->script_pending && ctx->ectx.metadata_verified) {
- ctx->script_pending = FALSE;
- apk_ipkg_run_script(ctx->ipkg, ctx->db, ctx->script, ctx->script_args);
- }
+ if (!ctx->script_pending) return;
+ ctx->script_pending = FALSE;
+ apk_ipkg_run_script(ctx->ipkg, ctx->db, ctx->script, ctx->script_args);
}
static int read_info_line(void *_ctx, apk_blob_t line)
@@ -2376,9 +2367,25 @@ static int contains_control_character(const char *str)
return 0;
}
-static int apk_db_install_archive_entry(struct apk_extract_ctx *ectx,
- const struct apk_file_info *ae,
- struct apk_istream *is)
+static int apk_db_install_v2meta(struct apk_extract_ctx *ectx, struct apk_istream *is)
+{
+ struct install_ctx *ctx = container_of(ectx, struct install_ctx, ectx);
+ apk_blob_t l, token = APK_BLOB_STR("\n");
+ while (apk_istream_get_delim(is, token, &l) == 0)
+ read_info_line(ctx, l);
+ return 0;
+}
+
+static int apk_db_install_script(struct apk_extract_ctx *ectx, unsigned int type, size_t size, struct apk_istream *is)
+{
+ struct install_ctx *ctx = container_of(ectx, struct install_ctx, ectx);
+ struct apk_package *pkg = ctx->pkg;
+ apk_ipkg_add_script(pkg->ipkg, is, type, size);
+ ctx->script_pending |= (type == ctx->script);
+ return 0;
+}
+
+static int apk_db_install_file(struct apk_extract_ctx *ectx, const struct apk_file_info *ae, struct apk_istream *is)
{
struct install_ctx *ctx = container_of(ectx, struct install_ctx, ectx);
static const char dot1[] = "/./", dot2[] = "/../";
@@ -2393,28 +2400,7 @@ static int apk_db_install_archive_entry(struct apk_extract_ctx *ectx,
int ret = 0, r;
char tmpname_file[TMPNAME_MAX], tmpname_link_target[TMPNAME_MAX];
- /* Package metainfo and script processing */
- if (ectx->metadata) {
- if (ae->name[0] != '.') return 0;
- if (strcmp(ae->name, ".PKGINFO") == 0) {
- apk_blob_t l, token = APK_BLOB_STR("\n");
- while (apk_istream_get_delim(is, token, &l) == 0)
- read_info_line(ctx, l);
- return 0;
- }
- r = apk_script_type(&ae->name[1]);
- if (r != APK_SCRIPT_INVALID) {
- apk_ipkg_add_script(ipkg, is, r, ae->size);
- ctx->script_pending |= (r == ctx->script);
- apk_db_run_pending_script(ctx);
- }
- return 0;
- }
-
- /* Handle script */
apk_db_run_pending_script(ctx);
-
- /* Rest of files need to be inside data portion */
if (ae->name[0] == '.') return 0;
/* Sanity check the file name */
@@ -2594,6 +2580,12 @@ static int apk_db_install_archive_entry(struct apk_extract_ctx *ectx,
return ret;
}
+static const struct apk_extract_ops extract_installer = {
+ .v2meta = apk_db_install_v2meta,
+ .script = apk_db_install_script,
+ .file = apk_db_install_file,
+};
+
static void apk_db_purge_pkg(struct apk_database *db,
struct apk_installed_package *ipkg,
int is_installed)
@@ -2805,7 +2797,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
.cb = cb,
.cb_ctx = cb_ctx,
};
- apk_extract_init(&ctx.ectx, db->ctx, apk_db_install_archive_entry);
+ apk_extract_init(&ctx.ectx, db->ctx, &extract_installer);
apk_extract_verify_identity(&ctx.ectx, &pkg->csum);
r = apk_extract(&ctx.ectx, is);
if (need_copy && r == 0) pkg->repos |= BIT(APK_REPOSITORY_CACHED);
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;
+}
+
diff --git a/src/package.c b/src/package.c
index 9e272b6..3b634d6 100644
--- a/src/package.c
+++ b/src/package.c
@@ -592,29 +592,19 @@ static int read_info_line(struct read_info_ctx *ri, apk_blob_t line)
return 0;
}
-static int apk_pkg_parse_entry(struct apk_extract_ctx *ectx, const struct apk_file_info *ae,
- struct apk_istream *is)
+static int apk_pkg_v2meta(struct apk_extract_ctx *ectx, struct apk_istream *is)
{
struct read_info_ctx *ri = container_of(ectx, struct read_info_ctx, ectx);
- struct apk_package *pkg = ri->pkg;
-
- if (ectx->metadata_verified) return -ECANCELED;
- if (!ectx->metadata) return 0;
-
- if (strcmp(ae->name, ".PKGINFO") == 0) {
- /* APK 2.0 format */
- apk_blob_t l, token = APK_BLOB_STR("\n");
- while (apk_istream_get_delim(is, token, &l) == 0)
- read_info_line(ri, l);
- } else if (strcmp(ae->name, ".INSTALL") == 0) {
- apk_warn(&ri->db->ctx->out,
- "Package '%s-" BLOB_FMT "' contains deprecated .INSTALL",
- pkg->name->name, BLOB_PRINTF(*pkg->version));
- }
-
+ apk_blob_t l, token = APK_BLOB_STR("\n");
+ while (apk_istream_get_delim(is, token, &l) == 0)
+ read_info_line(ri, l);
return 0;
}
+static const struct apk_extract_ops extract_pkgmeta_ops = {
+ .v2meta = apk_pkg_v2meta,
+};
+
int apk_pkg_read(struct apk_database *db, const char *file, struct apk_package **pkg)
{
struct read_info_ctx ctx;
@@ -633,12 +623,11 @@ int apk_pkg_read(struct apk_database *db, const char *file, struct apk_package *
goto err;
ctx.pkg->size = fi.size;
- apk_extract_init(&ctx.ectx, db->ctx, apk_pkg_parse_entry);
+ apk_extract_init(&ctx.ectx, db->ctx, &extract_pkgmeta_ops);
apk_extract_generate_identity(&ctx.ectx, &ctx.pkg->csum);
r = apk_extract(&ctx.ectx, apk_istream_from_file(AT_FDCWD, file));
- if (r < 0 && r != -ECANCELED)
- goto err;
+ if (r < 0) goto err;
if (ctx.pkg->name == NULL || ctx.pkg->uninstallable) {
r = -ENOTSUP;
goto err;