17de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <dirent.h>
27de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <inttypes.h>
37de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <sys/file.h>
47de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <sys/stat.h>
57de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
67de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include "idmap.h"
77de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
87de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <memory>
97de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <androidfw/ResourceTypes.h>
107de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <androidfw/StreamingZipInflater.h>
117de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <androidfw/ZipFileRO.h>
120434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok#include <cutils/jstring.h>
13d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee#include <cutils/properties.h>
147de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <private/android_filesystem_config.h> // for AID_SYSTEM
157de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <utils/SortedVector.h>
167de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <utils/String16.h>
177de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#include <utils/String8.h>
187de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
197de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok#define NO_OVERLAY_TAG (-1000)
207de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
217de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seokusing namespace android;
227de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
237de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seoknamespace {
247de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    struct Overlay {
257de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        Overlay() {}
267de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        Overlay(const String8& a, const String8& i, int p) :
277de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            apk_path(a), idmap_path(i), priority(p) {}
287de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
297de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        bool operator<(Overlay const& rhs) const
307de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        {
317de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return rhs.priority > priority;
327de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
337de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
347de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        String8 apk_path;
357de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        String8 idmap_path;
367de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        int priority;
377de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    };
387de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
397de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    bool writePackagesList(const char *filename, const SortedVector<Overlay>& overlayVector)
407de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    {
417de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        // the file is opened for appending so that it doesn't get truncated
427de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        // before we can guarantee mutual exclusion via the flock
437de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        FILE* fout = fopen(filename, "a");
447de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (fout == NULL) {
457de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return false;
467de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
477de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
487de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_EX)) != 0) {
497de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            fclose(fout);
507de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return false;
517de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
527de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
537de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (TEMP_FAILURE_RETRY(ftruncate(fileno(fout), 0)) != 0) {
547de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN));
557de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            fclose(fout);
567de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return false;
577de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
587de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
597de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        for (size_t i = 0; i < overlayVector.size(); ++i) {
607de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            const Overlay& overlay = overlayVector[i];
617de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            fprintf(fout, "%s %s\n", overlay.apk_path.string(), overlay.idmap_path.string());
627de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
637de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
647de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        TEMP_FAILURE_RETRY(fflush(fout));
657de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN));
667de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        fclose(fout);
677de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
687de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        // Make file world readable since Zygote (running as root) will read
697de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        // it when creating the initial AssetManger object
707de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // 0644
717de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (chmod(filename, mode) == -1) {
727de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            unlink(filename);
737de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return false;
747de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
757de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
767de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        return true;
777de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    }
787de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
797de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    String8 flatten_path(const char *path)
807de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    {
817de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        String16 tmp(path);
827de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        tmp.replaceAll('/', '@');
837de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        return String8(tmp);
847de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    }
857de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
86d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee    bool check_property(String16 property, String16 value) {
87d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        const char *prop;
88d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        const char *val;
89d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee
90d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        prop = strndup16to8(property.string(), property.size());
91d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        char propBuf[PROPERTY_VALUE_MAX];
92d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        property_get(prop, propBuf, NULL);
93d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        val = strndup16to8(value.string(), value.size());
94d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee
95d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        return (strcmp(propBuf, val) == 0);
96d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee    }
97d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee
980434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok    int parse_overlay_tag(const ResXMLTree& parser, const char *target_package_name,
990434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok            bool* is_static_overlay)
1007de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    {
1017de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        const size_t N = parser.getAttributeCount();
1027de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        String16 target;
1037de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        int priority = -1;
104d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        String16 propName = String16();
105d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        String16 propValue = String16();
1067de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        for (size_t i = 0; i < N; ++i) {
1077de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            size_t len;
1087de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            String16 key(parser.getAttributeName(i, &len));
1097de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            if (key == String16("targetPackage")) {
1107de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                const char16_t *p = parser.getAttributeStringValue(i, &len);
1117de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                if (p != NULL) {
1127de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                    target = String16(p, len);
1137de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                }
1147de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            } else if (key == String16("priority")) {
1157de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                Res_value v;
1167de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) {
1177de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                    priority = v.data;
1187de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                    if (priority < 0 || priority > 9999) {
1197de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                        return -1;
1207de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                    }
1217de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                }
1220434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok            } else if (key == String16("isStatic")) {
1230434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok                Res_value v;
1240434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok                if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) {
1250434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok                    *is_static_overlay = (v.data != 0);
1260434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok                }
127d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee            } else if (key == String16("requiredSystemPropertyName")) {
1280434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok                const char16_t *p = parser.getAttributeStringValue(i, &len);
1290434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok                if (p != NULL) {
130d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee                    propName = String16(p, len);
131d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee                }
132d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee            } else if (key == String16("requiredSystemPropertyValue")) {
133d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee                const char16_t *p = parser.getAttributeStringValue(i, &len);
134d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee                if (p != NULL) {
135d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee                    propValue = String16(p, len);
1360434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok                }
1370434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok            }
1380434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        }
1390434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok
140d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        // Note that conditional property enablement/exclusion only applies if
141d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        // the attribute is present. In its absence, all overlays are presumed enabled.
142d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        if (propName.size() > 0 && propValue.size() > 0) {
143d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee            // if property set & equal to value, then include overlay - otherwise skip
144d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee            if (!check_property(propName, propValue)) {
145d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee                return NO_OVERLAY_TAG;
146d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee            }
147d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        }
148d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee
149d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        if (target == String16(target_package_name)) {
150d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee            return priority;
151d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        }
152d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        return NO_OVERLAY_TAG;
1530434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok    }
1540434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok
1557de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    int parse_manifest(const void *data, size_t size, const char *target_package_name)
1567de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    {
1577de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        ResXMLTree parser;
1587de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        parser.setTo(data, size);
1597de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (parser.getError() != NO_ERROR) {
1607de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            ALOGD("%s failed to init xml parser, error=0x%08x\n", __FUNCTION__, parser.getError());
1617de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return -1;
1627de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
1637de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
1647de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        ResXMLParser::event_code_t type;
1650434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        bool is_static_overlay = false;
1660434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        int priority = NO_OVERLAY_TAG;
1677de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        do {
1687de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            type = parser.next();
1697de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            if (type == ResXMLParser::START_TAG) {
1707de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                size_t len;
1717de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                String16 tag(parser.getElementName(&len));
172d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee                if (tag == String16("overlay")) {
1730434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok                    priority = parse_overlay_tag(parser, target_package_name, &is_static_overlay);
1740434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok                    break;
1757de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                }
1767de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            }
1777de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        } while (type != ResXMLParser::BAD_DOCUMENT && type != ResXMLParser::END_DOCUMENT);
1787de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
179d5566c6c47faa6b9dda282741e25ac78c9487d58Todd Lee        if (is_static_overlay) {
1800434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok            return priority;
1810434289c45bc18f81f26d66e6bcbf8facf128665Jaekyun Seok        }
1827de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        return NO_OVERLAY_TAG;
1837de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    }
1847de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
1857de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    int parse_apk(const char *path, const char *target_package_name)
1867de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    {
1877de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        std::unique_ptr<ZipFileRO> zip(ZipFileRO::open(path));
1887de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (zip.get() == NULL) {
1897de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            ALOGW("%s: failed to open zip %s\n", __FUNCTION__, path);
1907de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return -1;
1917de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
1927de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        ZipEntryRO entry;
1937de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if ((entry = zip->findEntryByName("AndroidManifest.xml")) == NULL) {
1947de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            ALOGW("%s: failed to find entry AndroidManifest.xml\n", __FUNCTION__);
1957de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return -1;
1967de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
1977de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        uint32_t uncompLen = 0;
1987de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        uint16_t method;
1997de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (!zip->getEntryInfo(entry, &method, &uncompLen, NULL, NULL, NULL, NULL)) {
2007de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            ALOGW("%s: failed to read entry info\n", __FUNCTION__);
2017de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return -1;
2027de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
2037de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (method != ZipFileRO::kCompressDeflated) {
2047de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            ALOGW("%s: cannot handle zip compression method %" PRIu16 "\n", __FUNCTION__, method);
2057de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return -1;
2067de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
2077de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        FileMap *dataMap = zip->createEntryFileMap(entry);
2087de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (dataMap == NULL) {
2097de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            ALOGW("%s: failed to create FileMap\n", __FUNCTION__);
2107de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return -1;
2117de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
2127de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        char *buf = new char[uncompLen];
2137de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (NULL == buf) {
2147de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            ALOGW("%s: failed to allocate %" PRIu32 " byte\n", __FUNCTION__, uncompLen);
2157de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            delete dataMap;
2167de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return -1;
2177de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
2187de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        StreamingZipInflater inflater(dataMap, uncompLen);
2197de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (inflater.read(buf, uncompLen) < 0) {
2207de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            ALOGW("%s: failed to inflate %" PRIu32 " byte\n", __FUNCTION__, uncompLen);
2217de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            delete[] buf;
2227de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            delete dataMap;
2237de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return -1;
2247de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
2257de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2267de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        int priority = parse_manifest(buf, static_cast<size_t>(uncompLen), target_package_name);
2277de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        delete[] buf;
2287de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        delete dataMap;
2297de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        return priority;
2307de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    }
2317de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok}
2327de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2337de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seokint idmap_scan(const char *target_package_name, const char *target_apk_path,
2347de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        const char *idmap_dir, const android::Vector<const char *> *overlay_dirs)
2357de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok{
2367de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    String8 filename = String8(idmap_dir);
2377de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    filename.appendPath("overlays.list");
2387de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2397de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    SortedVector<Overlay> overlayVector;
2407de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    const size_t N = overlay_dirs->size();
2417de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    for (size_t i = 0; i < N; ++i) {
2427de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        const char *overlay_dir = overlay_dirs->itemAt(i);
2437de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        DIR *dir = opendir(overlay_dir);
2447de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        if (dir == NULL) {
2457de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            return EXIT_FAILURE;
2467de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
2477de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2487de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        struct dirent *dirent;
2497de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        while ((dirent = readdir(dir)) != NULL) {
2507de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            struct stat st;
2517de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            char overlay_apk_path[PATH_MAX + 1];
2527de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
2537de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            if (stat(overlay_apk_path, &st) < 0) {
2547de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                continue;
2557de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            }
2567de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            if (!S_ISREG(st.st_mode)) {
2577de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                continue;
2587de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            }
2597de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2607de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            int priority = parse_apk(overlay_apk_path, target_package_name);
2617de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            if (priority < 0) {
2627de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                continue;
2637de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            }
2647de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2657de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            String8 idmap_path(idmap_dir);
2667de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
2677de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            idmap_path.append("@idmap");
2687de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2697de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) {
2707de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
2717de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                        target_apk_path, overlay_apk_path, idmap_path.string());
2727de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok                continue;
2737de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            }
2747de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2757de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
2767de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok            overlayVector.add(overlay);
2777de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        }
2787de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2797de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        closedir(dir);
2807de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    }
2817de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2827de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    if (!writePackagesList(filename.string(), overlayVector)) {
2837de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok        return EXIT_FAILURE;
2847de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    }
2857de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
2867de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok    return EXIT_SUCCESS;
2877de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok}
2887de2f9c73fbe93bfb7dff3c046cf7a3137599f6cJaekyun Seok
289