diff options
Diffstat (limited to 'src/app_adbdump.c')
-rw-r--r-- | src/app_adbdump.c | 207 |
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; |