1#include <utils/ResourceTypes.h>
2#include <utils/String8.h>
3#include <utils/String16.h>
4#include <zipfile/zipfile.h>
5#include <stdio.h>
6#include <fcntl.h>
7#include <unistd.h>
8#include <stdlib.h>
9
10using namespace android;
11
12static int
13usage()
14{
15    fprintf(stderr,
16            "usage: apk APKFILE\n"
17            "\n"
18            "APKFILE   an android packge file produced by aapt.\n"
19            );
20    return 1;
21}
22
23
24int
25main(int argc, char** argv)
26{
27    const char* filename;
28    int fd;
29    ssize_t amt;
30    off_t size;
31    void* buf;
32    zipfile_t zip;
33    zipentry_t entry;
34    void* cookie;
35    void* resfile;
36    int bufsize;
37    int err;
38
39    if (argc != 2) {
40        return usage();
41    }
42
43    filename = argv[1];
44    fd = open(filename, O_RDONLY);
45    if (fd == -1) {
46        fprintf(stderr, "apk: couldn't open file for read: %s\n", filename);
47        return 1;
48    }
49
50    size = lseek(fd, 0, SEEK_END);
51    amt = lseek(fd, 0, SEEK_SET);
52
53    if (size < 0 || amt < 0) {
54        fprintf(stderr, "apk: error determining file size: %s\n", filename);
55        return 1;
56    }
57
58    buf = malloc(size);
59    if (buf == NULL) {
60        fprintf(stderr, "apk: file too big: %s\n", filename);
61        return 1;
62    }
63
64    amt = read(fd, buf, size);
65    if (amt != size) {
66        fprintf(stderr, "apk: error reading file: %s\n", filename);
67        return 1;
68    }
69
70    close(fd);
71
72    zip = init_zipfile(buf, size);
73    if (zip == NULL) {
74        fprintf(stderr, "apk: file doesn't seem to be a zip file: %s\n",
75                filename);
76        return 1;
77    }
78
79    printf("files:\n");
80    cookie = NULL;
81    while ((entry = iterate_zipfile(zip, &cookie))) {
82        char* name = get_zipentry_name(entry);
83        printf("  %s\n", name);
84        free(name);
85    }
86
87    entry = lookup_zipentry(zip, "resources.arsc");
88    if (entry != NULL) {
89        size = get_zipentry_size(entry);
90        bufsize = size + (size / 1000) + 1;
91        resfile = malloc(bufsize);
92
93        err = decompress_zipentry(entry, resfile, bufsize);
94        if (err != 0) {
95            fprintf(stderr, "apk: error decompressing resources.arsc");
96            return 1;
97        }
98
99        ResTable res(resfile, size, resfile);
100        res.print();
101#if 0
102        size_t tableCount = res.getTableCount();
103        printf("Tables: %d\n", (int)tableCount);
104        for (size_t tableIndex=0; tableIndex<tableCount; tableIndex++) {
105            const ResStringPool* strings = res.getTableStringBlock(tableIndex);
106            size_t stringCount = strings->size();
107            for (size_t stringIndex=0; stringIndex<stringCount; stringIndex++) {
108                size_t len;
109                const char16_t* ch = strings->stringAt(stringIndex, &len);
110                String8 s(String16(ch, len));
111                printf("  [%3d] %s\n", (int)stringIndex, s.string());
112            }
113        }
114
115        size_t basePackageCount = res.getBasePackageCount();
116        printf("Base Packages: %d\n", (int)basePackageCount);
117        for (size_t bpIndex=0; bpIndex<basePackageCount; bpIndex++) {
118            const char16_t* ch = res.getBasePackageName(bpIndex);
119            String8 s = String8(String16(ch));
120            printf("  [%3d] %s\n", (int)bpIndex, s.string());
121        }
122#endif
123    }
124
125
126    return 0;
127}
128