summaryrefslogtreecommitdiff
path: root/src/app_adbdump.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/app_adbdump.c')
-rw-r--r--src/app_adbdump.c207
1 files changed, 8 insertions, 199 deletions
diff --git a/src/app_adbdump.c b/src/app_adbdump.c
index 40da2c5..5020314 100644
--- a/src/app_adbdump.c
+++ b/src/app_adbdump.c
@@ -5,218 +5,27 @@
#include "apk_applet.h"
#include "apk_print.h"
-struct adb_dump_ctx {
- struct adb *db;
- struct apk_trust *trust;
- char prefix[128], *pfx;
-};
-
-struct adb_db_schema {
- unsigned long magic;
- const struct adb_object_schema *root;
-};
-
-static void ctx_nest(struct adb_dump_ctx *ctx, unsigned depth)
-{
- while (depth--) *ctx->pfx++ = ' ';
- assert(ctx->pfx < &ctx->prefix[ARRAY_SIZE(ctx->prefix)]);
- *ctx->pfx = 0;
-}
-
-static void ctx_unnest(struct adb_dump_ctx *ctx, unsigned depth)
-{
- ctx->pfx -= depth;
- assert(ctx->pfx >= ctx->prefix);
- *ctx->pfx = 0;
-}
-
-static void ctx_itemstart(struct adb_dump_ctx *ctx)
-{
- ctx->pfx[-2] = '-';
-}
-
-static void ctx_itemdone(struct adb_dump_ctx *ctx)
-{
- memset(ctx->prefix, ' ', ctx->pfx - ctx->prefix);
-}
-
-static void dump_object(struct adb_dump_ctx *ctx, const struct adb_object_schema *schema, adb_val_t v);
-static void dump_adb(struct adb_dump_ctx *ctx);
-
-static void dump_item(struct adb_dump_ctx *ctx, const char *name, const uint8_t *kind, adb_val_t v)
-{
- struct adb db, *origdb;
- struct adb_obj o;
- struct adb_object_schema *obj_schema;
- char tmp[256];
- apk_blob_t b, nl = APK_BLOB_STR("\n");
-
- switch (*kind) {
- case ADB_KIND_ARRAY:
- obj_schema = container_of(kind, struct adb_object_schema, kind);
- adb_r_obj(ctx->db, v, &o, obj_schema);
- if (!adb_ra_num(&o)) return;
-
- fprintf(stdout, "%s%s: # %u items\n", ctx->prefix, name, adb_ra_num(&o));
- ctx_nest(ctx, 4);
- for (size_t i = ADBI_FIRST; i <= adb_ra_num(&o); i++) {
- ctx_itemstart(ctx);
- dump_item(ctx, NULL, obj_schema->fields[0].kind, adb_ro_val(&o, i));
- ctx_itemdone(ctx);
- }
- ctx_unnest(ctx, 4);
- break;
- case ADB_KIND_ADB:
- db.hdr.schema = container_of(kind, struct adb_adb_schema, kind)->schema_id;
- db.data = adb_r_blob(ctx->db, v);
- origdb = ctx->db;
- ctx->db = &db;
- dump_adb(ctx);
- ctx->db = origdb;
- break;
- case ADB_KIND_OBJECT:
- if (name) {
- fprintf(stdout, "%s%s:\n", ctx->prefix, name);
- ctx_nest(ctx, 4);
- }
- dump_object(ctx, container_of(kind, struct adb_object_schema, kind), v);
- if (name) ctx_unnest(ctx, 4);
- break;
- case ADB_KIND_BLOB:
- case ADB_KIND_INT:;
- struct adb_scalar_schema *scalar = container_of(kind, struct adb_scalar_schema, kind);
- if (scalar->tostring) {
- b = scalar->tostring(ctx->db, v, tmp, sizeof tmp);
- } else {
- b = APK_BLOB_STR("(unknown)");
- }
- if (!APK_BLOB_IS_NULL(b)) {
- fputs(ctx->prefix, stdout);
- if (name) fprintf(stdout, "%s: ", name);
- if (b.len >= 60 || scalar->multiline) {
- /* long or multiline */
- apk_blob_t l;
- fprintf(stdout, "|\n");
- ctx_itemdone(ctx);
- ctx_nest(ctx, 4);
- while (apk_blob_split(b, nl, &l, &b)) {
- fprintf(stdout, "%s"BLOB_FMT"\n",
- ctx->prefix, BLOB_PRINTF(l));
- }
- if (b.len) {
- fprintf(stdout, "%s"BLOB_FMT"\n",
- ctx->prefix, BLOB_PRINTF(b));
- }
- ctx_unnest(ctx, 4);
- } else {
- fwrite(b.ptr, 1, b.len, stdout);
- fputc('\n', stdout);
- }
- }
- break;
- }
-}
-
-static void dump_object(struct adb_dump_ctx *ctx, const struct adb_object_schema *schema, adb_val_t v)
-{
- size_t schema_len = 0;
- struct adb_obj o;
- char tmp[256];
- apk_blob_t b;
-
- adb_r_obj(ctx->db, v, &o, schema);
- if (schema) {
- if (schema->tostring) {
- b = schema->tostring(&o, tmp, sizeof tmp);
- if (!APK_BLOB_IS_NULL(b))
- fprintf(stdout, "%s"BLOB_FMT"\n", ctx->prefix, BLOB_PRINTF(b));
- ctx_itemdone(ctx);
- return;
- }
- schema_len = schema->num_fields;
- }
-
- for (size_t i = ADBI_FIRST; i < adb_ro_num(&o); i++) {
- adb_val_t val = adb_ro_val(&o, i);
- if (val == ADB_NULL) continue;
- if (i < schema_len && schema->fields[i-1].kind != 0) {
- dump_item(ctx, schema->fields[i-1].name, schema->fields[i-1].kind, val);
- ctx_itemdone(ctx);
- }
- }
-}
-
static const struct adb_db_schema dbschemas[] = {
{ .magic = ADB_SCHEMA_INDEX, .root = &schema_index, },
{ .magic = ADB_SCHEMA_INSTALLED_DB, .root = &schema_idb, },
{ .magic = ADB_SCHEMA_PACKAGE, .root = &schema_package },
+ {},
};
-static void dump_adb(struct adb_dump_ctx *ctx)
-{
- struct adb_block *blk;
- struct adb_sign_hdr *s;
- struct adb_verify_ctx vfy = {};
- const struct adb_db_schema *ds;
- unsigned char *id;
- uint32_t schema_magic = ctx->db->hdr.schema;
- int r;
-
- for (ds = dbschemas; ds < &dbschemas[ARRAY_SIZE(dbschemas)]; ds++)
- if (ds->magic == schema_magic) break;
- if (ds >= &dbschemas[ARRAY_SIZE(dbschemas)]) ds = NULL;
-
- adb_foreach_block(blk, ctx->db->data) {
- apk_blob_t b = APK_BLOB_PTR_LEN((char*)(blk+1), ADB_BLOCK_SIZE(blk));
- switch (ADB_BLOCK_TYPE(blk)) {
- case ADB_BLOCK_ADB:
- fprintf(stdout, "%s# ADB block, size: %d\n", ctx->prefix, ADB_BLOCK_SIZE(blk));
- ctx_itemdone(ctx);
- ctx->db->adb = b;
- if (ds)
- dump_object(ctx, ds->root, adb_r_root(ctx->db));
- else
- fprintf(stdout, "%s# Unrecognized schema: 0x%08x\n", ctx->prefix, schema_magic);
- break;
- case ADB_BLOCK_SIG:
- s = (struct adb_sign_hdr*) b.ptr;
- fprintf(stdout, "%s# signature: v%d ", ctx->prefix, s->sign_ver);
- ctx_itemdone(ctx);
- r = adb_trust_verify_signature(ctx->trust, ctx->db, &vfy, b);
- switch (s->sign_ver) {
- case 0:
- id = (unsigned char*)(s + 1);
- for (size_t j = 0; j < 16; j++)
- fprintf(stdout, "%02x", id[j]);
- break;
- default:
- break;
- }
- fprintf(stdout, ": %s\n", r ? apk_error_str(r) : "OK");
- break;
- default:
- fprintf(stdout, "%s# unknown block %d, size: %d\n",
- ctx->prefix, ADB_BLOCK_TYPE(blk), ADB_BLOCK_SIZE(blk));
- ctx_itemdone(ctx);
- }
- }
- if (IS_ERR(blk)) fprintf(stdout, "%s# block enumeration error: corrupt data area\n", ctx->prefix);
-}
-
-static int mmap_and_dump_adb(struct apk_trust *trust, int fd)
+static int mmap_and_dump_adb(struct apk_trust *trust, int fd, struct apk_out *out)
{
struct adb db;
- struct adb_dump_ctx ctx = {
- .db = &db,
- .pfx = ctx.prefix,
- .trust = trust,
+ struct adb_walk_gentext td = {
+ .d.ops = &adb_walk_gentext_ops,
+ .d.schemas = dbschemas,
+ .out = out->out,
};
int r;
r = adb_m_map(&db, fd, 0, NULL);
if (r) return r;
- dump_adb(&ctx);
+ adb_walk_adb(&td.d, &db, trust);
adb_free(&db);
return 0;
}
@@ -228,7 +37,7 @@ static int adbdump_main(void *pctx, struct apk_ctx *ac, struct apk_string_array
int r;
foreach_array_item(arg, args) {
- r = mmap_and_dump_adb(apk_ctx_get_trust(ac), open(*arg, O_RDONLY));
+ r = mmap_and_dump_adb(apk_ctx_get_trust(ac), open(*arg, O_RDONLY), out);
if (r) {
apk_err(out, "%s: %s", *arg, apk_error_str(r));
return r;