diff --git a/cmds/idmap/Android.mk b/cmds/idmap/Android.mk deleted file mode 100644 index ffa83f2ba..000000000 --- a/cmds/idmap/Android.mk +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2012 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := idmap.cpp create.cpp scan.cpp inspect.cpp - -LOCAL_SHARED_LIBRARIES := liblog libutils libandroidfw - -LOCAL_MODULE := idmap - -LOCAL_C_INCLUDES := external/zlib - -LOCAL_MODULE_TAGS := optional - -include $(BUILD_EXECUTABLE) diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp deleted file mode 100644 index ae35f7b0a..000000000 --- a/cmds/idmap/create.cpp +++ /dev/null @@ -1,222 +0,0 @@ -#include "idmap.h" - -#include -#include -#include -#include -#include - -#include -#include - -using namespace android; - -namespace { - int get_zip_entry_crc(const char *zip_path, const char *entry_name, uint32_t *crc) - { - UniquePtr zip(ZipFileRO::open(zip_path)); - if (zip.get() == NULL) { - return -1; - } - ZipEntryRO entry = zip->findEntryByName(entry_name); - if (entry == NULL) { - return -1; - } - if (!zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, (long*)crc)) { - return -1; - } - zip->releaseEntry(entry); - return 0; - } - - int open_idmap(const char *path) - { - int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)); - if (fd == -1) { - ALOGD("error: open %s: %s\n", path, strerror(errno)); - goto fail; - } - if (fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { - ALOGD("error: fchmod %s: %s\n", path, strerror(errno)); - goto fail; - } - if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX | LOCK_NB)) != 0) { - ALOGD("error: flock %s: %s\n", path, strerror(errno)); - goto fail; - } - - return fd; -fail: - if (fd != -1) { - close(fd); - unlink(path); - } - return -1; - } - - int write_idmap(int fd, const uint32_t *data, size_t size) - { - if (lseek(fd, SEEK_SET, 0) < 0) { - return -1; - } - size_t bytesLeft = size; - while (bytesLeft > 0) { - ssize_t w = TEMP_FAILURE_RETRY(write(fd, data + size - bytesLeft, bytesLeft)); - if (w < 0) { - fprintf(stderr, "error: write: %s\n", strerror(errno)); - return -1; - } - bytesLeft -= w; - } - return 0; - } - - bool is_idmap_stale_fd(const char *target_apk_path, const char *overlay_apk_path, int idmap_fd) - { - static const size_t N = ResTable::IDMAP_HEADER_SIZE_BYTES; - struct stat st; - if (fstat(idmap_fd, &st) == -1) { - return true; - } - if (st.st_size < N) { - // file is empty or corrupt - return true; - } - - char buf[N]; - ssize_t bytesLeft = N; - if (lseek(idmap_fd, SEEK_SET, 0) < 0) { - return true; - } - for (;;) { - ssize_t r = TEMP_FAILURE_RETRY(read(idmap_fd, buf + N - bytesLeft, bytesLeft)); - if (r < 0) { - return true; - } - bytesLeft -= r; - if (bytesLeft == 0) { - break; - } - if (r == 0) { - // "shouldn't happen" - return true; - } - } - - uint32_t cached_target_crc, cached_overlay_crc; - String8 cached_target_path, cached_overlay_path; - if (!ResTable::getIdmapInfo(buf, N, &cached_target_crc, &cached_overlay_crc, - &cached_target_path, &cached_overlay_path)) { - return true; - } - - if (cached_target_path != target_apk_path) { - return true; - } - if (cached_overlay_path != overlay_apk_path) { - return true; - } - - uint32_t actual_target_crc, actual_overlay_crc; - if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME, - &actual_target_crc) == -1) { - return true; - } - if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME, - &actual_overlay_crc) == -1) { - return true; - } - - return cached_target_crc != actual_target_crc || cached_overlay_crc != actual_overlay_crc; - } - - bool is_idmap_stale_path(const char *target_apk_path, const char *overlay_apk_path, - const char *idmap_path) - { - struct stat st; - if (stat(idmap_path, &st) == -1) { - // non-existing idmap is always stale; on other errors, abort idmap generation - return errno == ENOENT; - } - - int idmap_fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY)); - if (idmap_fd == -1) { - return false; - } - bool is_stale = is_idmap_stale_fd(target_apk_path, overlay_apk_path, idmap_fd); - close(idmap_fd); - return is_stale; - } - - int create_idmap(const char *target_apk_path, const char *overlay_apk_path, - uint32_t **data, size_t *size) - { - uint32_t target_crc, overlay_crc; - if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME, - &target_crc) == -1) { - return -1; - } - if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME, - &overlay_crc) == -1) { - return -1; - } - - AssetManager am; - bool b = am.createIdmap(target_apk_path, overlay_apk_path, target_crc, overlay_crc, - data, size); - return b ? 0 : -1; - } - - int create_and_write_idmap(const char *target_apk_path, const char *overlay_apk_path, - int fd, bool check_if_stale) - { - if (check_if_stale) { - if (!is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd)) { - // already up to date -- nothing to do - return 0; - } - } - - uint32_t *data = NULL; - size_t size; - - if (create_idmap(target_apk_path, overlay_apk_path, &data, &size) == -1) { - return -1; - } - - if (write_idmap(fd, data, size) == -1) { - free(data); - return -1; - } - - free(data); - return 0; - } -} - -int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path, - const char *idmap_path) -{ - if (!is_idmap_stale_path(target_apk_path, overlay_apk_path, idmap_path)) { - // already up to date -- nothing to do - return EXIT_SUCCESS; - } - - int fd = open_idmap(idmap_path); - if (fd == -1) { - return EXIT_FAILURE; - } - - int r = create_and_write_idmap(target_apk_path, overlay_apk_path, fd, false); - close(fd); - if (r != 0) { - unlink(idmap_path); - } - return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; -} - -int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd) -{ - return create_and_write_idmap(target_apk_path, overlay_apk_path, fd, true) == 0 ? - EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/cmds/idmap/idmap.cpp b/cmds/idmap/idmap.cpp deleted file mode 100644 index 46c0edc03..000000000 --- a/cmds/idmap/idmap.cpp +++ /dev/null @@ -1,237 +0,0 @@ -#include "idmap.h" - -#include // for AID_SYSTEM - -#include -#include - -namespace { - const char *usage = "NAME\n\ - idmap - create or display idmap files\n\ -\n\ -SYNOPSIS \n\ - idmap --help \n\ - idmap --fd target overlay fd \n\ - idmap --path target overlay idmap \n\ - idmap --scan dir-to-scan target-to-look-for target dir-to-hold-idmaps \n\ - idmap --inspect idmap \n\ -\n\ -DESCRIPTION \n\ - Idmap files play an integral part in the runtime resource overlay framework. An idmap \n\ - file contains a mapping of resource identifiers between overlay package and its target \n\ - package; this mapping is used during resource lookup. Idmap files also act as control \n\ - files by their existence: if not present, the corresponding overlay package is ignored \n\ - when the resource context is created. \n\ -\n\ - Idmap files are stored in /data/resource-cache. For each pair (target package, overlay \n\ - package), there exists exactly one idmap file, or none if the overlay should not be used. \n\ -\n\ -NOMENCLATURE \n\ - target: the original, non-overlay, package. Each target package may be associated with \n\ - any number of overlay packages. \n\ -\n\ - overlay: an overlay package. Each overlay package is associated with exactly one target \n\ - package, specified in the overlay's manifest using the \n\ - tag. \n\ -\n\ -OPTIONS \n\ - --help: display this help \n\ -\n\ - --fd: create idmap for target package 'target' (path to apk) and overlay package 'overlay' \n\ - (path to apk); write results to file descriptor 'fd' (integer). This invocation \n\ - version is intended to be used by a parent process with higher privileges to call \n\ - idmap in a controlled way: the parent will open a suitable file descriptor, fork, \n\ - drop its privileges and exec. This tool will continue execution without the extra \n\ - privileges, but still have write access to a file it could not have opened on its \n\ - own. \n\ -\n\ - --path: create idmap for target package 'target' (path to apk) and overlay package \n\ - 'overlay' (path to apk); write results to 'idmap' (path). \n\ -\n\ - --scan: non-recursively search directory 'dir-to-scan' (path) for overlay packages with \n\ - target package 'target-to-look-for' (package name) present at 'target' (path to \n\ - apk). For each overlay package found, create an idmap file in 'dir-to-hold-idmaps' \n\ - (path). \n\ -\n\ - --inspect: decode the binary format of 'idmap' (path) and display the contents in a \n\ - debug-friendly format. \n\ -\n\ -EXAMPLES \n\ - Create an idmap file: \n\ -\n\ - $ adb shell idmap --path /system/app/target.apk \\ \n\ - /vendor/overlay/overlay.apk \\ \n\ - /data/resource-cache/vendor@overlay@overlay.apk@idmap \n\ -\n\ - Display an idmap file: \n\ -\n\ - $ adb shell idmap --inspect /data/resource-cache/vendor@overlay@overlay.apk@idmap \n\ - SECTION ENTRY VALUE OFFSET COMMENT \n\ - IDMAP HEADER magic 0x706d6469 0x0 \n\ - base crc 0x484aa77f 0x1 \n\ - overlay crc 0x03c66fa5 0x2 \n\ - base path .......... 0x03-0x42 /system/app/target.apk \n\ - overlay path .......... 0x43-0x82 /vendor/overlay/overlay.apk \n\ - DATA HEADER types count 0x00000003 0x83 \n\ - padding 0x00000000 0x84 \n\ - type offset 0x00000004 0x85 absolute offset 0x87, xml \n\ - type offset 0x00000007 0x86 absolute offset 0x8a, string \n\ - DATA BLOCK entry count 0x00000001 0x87 \n\ - entry offset 0x00000000 0x88 \n\ - entry 0x7f020000 0x89 xml/integer \n\ - DATA BLOCK entry count 0x00000002 0x8a \n\ - entry offset 0x00000000 0x8b \n\ - entry 0x7f030000 0x8c string/str \n\ - entry 0x7f030001 0x8d string/str2 \n\ -\n\ - In this example, the overlay package provides three alternative resource values:\n\ - xml/integer, string/str and string/str2.\n\ -\n\ -NOTES \n\ - This tool and its expected invocation from installd is modelled on dexopt."; - - bool verify_directory_readable(const char *path) - { - return access(path, R_OK | X_OK) == 0; - } - - bool verify_directory_writable(const char *path) - { - return access(path, W_OK) == 0; - } - - bool verify_file_readable(const char *path) - { - return access(path, R_OK) == 0; - } - - bool verify_root_or_system() - { - uid_t uid = getuid(); - gid_t gid = getgid(); - - return (uid == 0 && gid == 0) || (uid == AID_SYSTEM && gid == AID_SYSTEM); - } - - int maybe_create_fd(const char *target_apk_path, const char *overlay_apk_path, - const char *idmap_str) - { - // anyone (not just root or system) may do --fd -- the file has - // already been opened by someone else on our behalf - - char *endptr; - int idmap_fd = strtol(idmap_str, &endptr, 10); - if (*endptr != '\0') { - fprintf(stderr, "error: failed to parse file descriptor argument %s\n", idmap_str); - return -1; - } - - if (!verify_file_readable(target_apk_path)) { - ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno)); - return -1; - } - - if (!verify_file_readable(overlay_apk_path)) { - ALOGD("error: failed to read apk %s: %s\n", overlay_apk_path, strerror(errno)); - return -1; - } - - return idmap_create_fd(target_apk_path, overlay_apk_path, idmap_fd); - } - - int maybe_create_path(const char *target_apk_path, const char *overlay_apk_path, - const char *idmap_path) - { - if (!verify_root_or_system()) { - fprintf(stderr, "error: permission denied: not user root or user system\n"); - return -1; - } - - if (!verify_file_readable(target_apk_path)) { - ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno)); - return -1; - } - - if (!verify_file_readable(overlay_apk_path)) { - ALOGD("error: failed to read apk %s: %s\n", overlay_apk_path, strerror(errno)); - return -1; - } - - return idmap_create_path(target_apk_path, overlay_apk_path, idmap_path); - } - - int maybe_scan(const char *overlay_dir, const char *target_package_name, - const char *target_apk_path, const char *idmap_dir) - { - if (!verify_root_or_system()) { - fprintf(stderr, "error: permission denied: not user root or user system\n"); - return -1; - } - - if (!verify_directory_readable(overlay_dir)) { - ALOGD("error: no read access to %s: %s\n", overlay_dir, strerror(errno)); - return -1; - } - - if (!verify_file_readable(target_apk_path)) { - ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno)); - return -1; - } - - if (!verify_directory_writable(idmap_dir)) { - ALOGD("error: no write access to %s: %s\n", idmap_dir, strerror(errno)); - return -1; - } - - return idmap_scan(overlay_dir, target_package_name, target_apk_path, idmap_dir); - } - - int maybe_inspect(const char *idmap_path) - { - // anyone (not just root or system) may do --inspect - if (!verify_file_readable(idmap_path)) { - ALOGD("error: failed to read idmap %s: %s\n", idmap_path, strerror(errno)); - return -1; - } - return idmap_inspect(idmap_path); - } -} - -int main(int argc, char **argv) -{ -#if 0 - { - char buf[1024]; - buf[0] = '\0'; - for (int i = 0; i < argc; ++i) { - strncat(buf, argv[i], sizeof(buf) - 1); - strncat(buf, " ", sizeof(buf) - 1); - } - ALOGD("%s:%d: uid=%d gid=%d argv=%s\n", __FILE__, __LINE__, getuid(), getgid(), buf); - } -#endif - - if (argc == 2 && !strcmp(argv[1], "--help")) { - printf("%s\n", usage); - return 0; - } - - if (argc == 5 && !strcmp(argv[1], "--fd")) { - return maybe_create_fd(argv[2], argv[3], argv[4]); - } - - if (argc == 5 && !strcmp(argv[1], "--path")) { - return maybe_create_path(argv[2], argv[3], argv[4]); - } - - if (argc == 6 && !strcmp(argv[1], "--scan")) { - return maybe_scan(argv[2], argv[3], argv[4], argv[5]); - } - - if (argc == 3 && !strcmp(argv[1], "--inspect")) { - return maybe_inspect(argv[2]); - } - - fprintf(stderr, "Usage: don't use this (cf dexopt usage).\n"); - return EXIT_FAILURE; -} diff --git a/cmds/idmap/idmap.h b/cmds/idmap/idmap.h deleted file mode 100644 index f507dd853..000000000 --- a/cmds/idmap/idmap.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _IDMAP_H_ -#define _IDMAP_H_ - -#define LOG_TAG "idmap" - -#include - -#include -#include - -#ifndef TEMP_FAILURE_RETRY -// Used to retry syscalls that can return EINTR. -#define TEMP_FAILURE_RETRY(exp) ({ \ - typeof (exp) _rc; \ - do { \ - _rc = (exp); \ - } while (_rc == -1 && errno == EINTR); \ - _rc; }) -#endif - -int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path, - const char *idmap_path); - -int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd); - -// Regarding target_package_name: the idmap_scan implementation should -// be able to extract this from the manifest in target_apk_path, -// simplifying the external API. -int idmap_scan(const char *overlay_dir, const char *target_package_name, - const char *target_apk_path, const char *idmap_dir); - -int idmap_inspect(const char *idmap_path); - -#endif // _IDMAP_H_ diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp deleted file mode 100644 index a59f5d31c..000000000 --- a/cmds/idmap/inspect.cpp +++ /dev/null @@ -1,291 +0,0 @@ -#include "idmap.h" - -#include -#include -#include - -#include -#include -#include - -using namespace android; - -#define NEXT(b, i, o) do { if (buf.next(&i, &o) < 0) { return -1; } } while (0) - -namespace { - static const uint32_t IDMAP_MAGIC = 0x706d6469; - static const size_t PATH_LENGTH = 256; - static const uint32_t IDMAP_HEADER_SIZE = (3 + 2 * (PATH_LENGTH / sizeof(uint32_t))); - - void printe(const char *fmt, ...); - - class IdmapBuffer { - private: - char *buf_; - size_t len_; - mutable size_t pos_; - public: - IdmapBuffer() : buf_((char *)MAP_FAILED), len_(0), pos_(0) {} - - ~IdmapBuffer() { - if (buf_ != MAP_FAILED) { - munmap(buf_, len_); - } - } - - int init(const char *idmap_path) - { - struct stat st; - int fd; - - if (stat(idmap_path, &st) < 0) { - printe("failed to stat idmap '%s': %s\n", idmap_path, strerror(errno)); - return -1; - } - len_ = st.st_size; - if ((fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY))) < 0) { - printe("failed to open idmap '%s': %s\n", idmap_path, strerror(errno)); - return -1; - } - if ((buf_ = (char*)mmap(NULL, len_, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) { - close(fd); - printe("failed to mmap idmap: %s\n", strerror(errno)); - return -1; - } - close(fd); - return 0; - } - - int next(uint32_t *i, uint32_t *offset) const - { - if (!buf_) { - printe("failed to read next uint32_t: buffer not initialized\n"); - return -1; - } - if (pos_ + 4 > len_) { - printe("failed to read next uint32_t: end of buffer reached at pos=0x%08x\n", - pos_); - return -1; - } - *offset = pos_ / sizeof(uint32_t); - char a = buf_[pos_++]; - char b = buf_[pos_++]; - char c = buf_[pos_++]; - char d = buf_[pos_++]; - *i = (d << 24) | (c << 16) | (b << 8) | a; - return 0; - } - - int nextPath(char *b, uint32_t *offset_start, uint32_t *offset_end) const - { - if (!buf_) { - printe("failed to read next path: buffer not initialized\n"); - return -1; - } - if (pos_ + PATH_LENGTH > len_) { - printe("failed to read next path: end of buffer reached at pos=0x%08x\n", pos_); - return -1; - } - memcpy(b, buf_ + pos_, PATH_LENGTH); - *offset_start = pos_ / sizeof(uint32_t); - pos_ += PATH_LENGTH; - *offset_end = pos_ / sizeof(uint32_t) - 1; - return 0; - } - }; - - void printe(const char *fmt, ...) - { - va_list ap; - - va_start(ap, fmt); - fprintf(stderr, "error: "); - vfprintf(stderr, fmt, ap); - va_end(ap); - } - - void print_header() - { - printf("SECTION ENTRY VALUE OFFSET COMMENT\n"); - } - - void print(const char *section, const char *subsection, uint32_t value, uint32_t offset, - const char *fmt, ...) - { - va_list ap; - - va_start(ap, fmt); - printf("%-12s %-12s 0x%08x 0x%-4x ", section, subsection, value, offset); - vprintf(fmt, ap); - printf("\n"); - va_end(ap); - } - - void print_path(const char *section, const char *subsection, uint32_t offset_start, - uint32_t offset_end, const char *fmt, ...) - { - va_list ap; - - va_start(ap, fmt); - printf("%-12s %-12s .......... 0x%02x-0x%02x ", section, subsection, offset_start, - offset_end); - vprintf(fmt, ap); - printf("\n"); - va_end(ap); - } - - int resource_metadata(const AssetManager& am, uint32_t res_id, - String8 *package, String8 *type, String8 *name) - { - const ResTable& rt = am.getResources(); - struct ResTable::resource_name data; - if (!rt.getResourceName(res_id, false, &data)) { - printe("failed to get resource name id=0x%08x\n", res_id); - return -1; - } - if (package) { - *package = String8(String16(data.package, data.packageLen)); - } - if (type) { - *type = String8(String16(data.type, data.typeLen)); - } - if (name) { - *name = String8(String16(data.name, data.nameLen)); - } - return 0; - } - - int package_id(const AssetManager& am) - { - return (am.getResources().getBasePackageId(0)) << 24; - } - - int parse_idmap_header(const IdmapBuffer& buf, AssetManager& am) - { - uint32_t i, o, e; - char path[PATH_LENGTH]; - - NEXT(buf, i, o); - if (i != IDMAP_MAGIC) { - printe("not an idmap file: actual magic constant 0x%08x does not match expected magic " - "constant 0x%08x\n", i, IDMAP_MAGIC); - return -1; - } - print_header(); - print("IDMAP HEADER", "magic", i, o, ""); - - NEXT(buf, i, o); - print("", "base crc", i, o, ""); - - NEXT(buf, i, o); - print("", "overlay crc", i, o, ""); - - if (buf.nextPath(path, &o, &e) < 0) { - // printe done from IdmapBuffer::nextPath - return -1; - } - print_path("", "base path", o, e, "%s", path); - if (!am.addAssetPath(String8(path), NULL)) { - printe("failed to add '%s' as asset path\n", path); - return -1; - } - - if (buf.nextPath(path, &o, &e) < 0) { - // printe done from IdmapBuffer::nextPath - return -1; - } - print_path("", "overlay path", o, e, "%s", path); - - return 0; - } - - int parse_data_header(const IdmapBuffer& buf, const AssetManager& am, Vector& types) - { - uint32_t i, o; - const uint32_t numeric_package = package_id(am); - - NEXT(buf, i, o); - print("DATA HEADER", "types count", i, o, ""); - const uint32_t N = i; - - for (uint32_t j = 0; j < N; ++j) { - NEXT(buf, i, o); - if (i == 0) { - print("", "padding", i, o, ""); - } else { - String8 type; - const uint32_t numeric_type = (j + 1) << 16; - const uint32_t res_id = numeric_package | numeric_type; - if (resource_metadata(am, res_id, NULL, &type, NULL) < 0) { - // printe done from resource_metadata - return -1; - } - print("", "type offset", i, o, "absolute offset 0x%02x, %s", - i + IDMAP_HEADER_SIZE, type.string()); - types.add(numeric_type); - } - } - - return 0; - } - - int parse_data_block(const IdmapBuffer& buf, const AssetManager& am, size_t numeric_type) - { - uint32_t i, o, n, id_offset; - const uint32_t numeric_package = package_id(am); - - NEXT(buf, i, o); - print("DATA BLOCK", "entry count", i, o, ""); - n = i; - - NEXT(buf, i, o); - print("", "entry offset", i, o, ""); - id_offset = i; - - for ( ; n > 0; --n) { - String8 type, name; - - NEXT(buf, i, o); - if (i == 0) { - print("", "padding", i, o, ""); - } else { - uint32_t res_id = numeric_package | numeric_type | id_offset; - if (resource_metadata(am, res_id, NULL, &type, &name) < 0) { - // printe done from resource_metadata - return -1; - } - print("", "entry", i, o, "%s/%s", type.string(), name.string()); - } - ++id_offset; - } - - return 0; - } -} - -int idmap_inspect(const char *idmap_path) -{ - IdmapBuffer buf; - if (buf.init(idmap_path) < 0) { - // printe done from IdmapBuffer::init - return EXIT_FAILURE; - } - AssetManager am; - if (parse_idmap_header(buf, am) < 0) { - // printe done from parse_idmap_header - return EXIT_FAILURE; - } - Vector types; - if (parse_data_header(buf, am, types) < 0) { - // printe done from parse_data_header - return EXIT_FAILURE; - } - const size_t N = types.size(); - for (size_t i = 0; i < N; ++i) { - if (parse_data_block(buf, am, types.itemAt(i)) < 0) { - // printe done from parse_data_block - return EXIT_FAILURE; - } - } - return EXIT_SUCCESS; -} diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp deleted file mode 100644 index c5fc941fa..000000000 --- a/cmds/idmap/scan.cpp +++ /dev/null @@ -1,244 +0,0 @@ -#include "idmap.h" - -#include -#include -#include -#include -#include // for AID_SYSTEM -#include -#include -#include - -#include - -#define NO_OVERLAY_TAG (-1000) - -using namespace android; - -namespace { - struct Overlay { - Overlay() {} - Overlay(const String8& a, const String8& i, int p) : - apk_path(a), idmap_path(i), priority(p) {} - - bool operator<(Overlay const& rhs) const - { - // Note: order is reversed by design - return rhs.priority < priority; - } - - String8 apk_path; - String8 idmap_path; - int priority; - }; - - bool writePackagesList(const char *filename, const SortedVector& overlayVector) - { - FILE* fout = fopen(filename, "w"); - if (fout == NULL) { - return false; - } - - for (size_t i = 0; i < overlayVector.size(); ++i) { - const Overlay& overlay = overlayVector[i]; - fprintf(fout, "%s %s\n", overlay.apk_path.string(), overlay.idmap_path.string()); - } - - fclose(fout); - - // Make file world readable since Zygote (running as root) will read - // it when creating the initial AssetManger object - const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // 0644 - if (chmod(filename, mode) == -1) { - unlink(filename); - return false; - } - - return true; - } - - String8 flatten_path(const char *path) - { - String16 tmp(path); - tmp.replaceAll('/', '@'); - return String8(tmp); - } - - int mkdir_p(const String8& path, uid_t uid, gid_t gid) - { - static const mode_t mode = - S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH; - struct stat st; - - if (stat(path.string(), &st) == 0) { - return 0; - } - if (mkdir_p(path.getPathDir(), uid, gid) < 0) { - return -1; - } - if (mkdir(path.string(), 0755) != 0) { - return -1; - } - if (chown(path.string(), uid, gid) == -1) { - return -1; - } - if (chmod(path.string(), mode) == -1) { - return -1; - } - return 0; - } - - int parse_overlay_tag(const ResXMLTree& parser, const char *target_package_name) - { - const size_t N = parser.getAttributeCount(); - String16 target; - int priority = -1; - for (size_t i = 0; i < N; ++i) { - size_t len; - String16 key(parser.getAttributeName(i, &len)); - if (key == String16("targetPackage")) { - const uint16_t *p = parser.getAttributeStringValue(i, &len); - if (p) { - target = String16(p, len); - } - } else if (key == String16("priority")) { - Res_value v; - if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) { - priority = v.data; - if (priority < 0 || priority > 9999) { - return -1; - } - } - } - } - if (target == String16(target_package_name)) { - return priority; - } - return NO_OVERLAY_TAG; - } - - int parse_manifest(const void *data, size_t size, const char *target_package_name) - { - ResXMLTree parser(data, size); - if (parser.getError() != NO_ERROR) { - ALOGD("%s failed to init xml parser, error=0x%08x\n", __FUNCTION__, parser.getError()); - return -1; - } - - ResXMLParser::event_code_t type; - do { - type = parser.next(); - if (type == ResXMLParser::START_TAG) { - size_t len; - String16 tag(parser.getElementName(&len)); - if (tag == String16("overlay")) { - return parse_overlay_tag(parser, target_package_name); - } - } - } while (type != ResXMLParser::BAD_DOCUMENT && type != ResXMLParser::END_DOCUMENT); - - return NO_OVERLAY_TAG; - } - - int parse_apk(const char *path, const char *target_package_name) - { - UniquePtr zip(ZipFileRO::open(path)); - if (zip.get() == NULL) { - ALOGW("%s: failed to open zip %s\n", __FUNCTION__, path); - return -1; - } - ZipEntryRO entry; - if ((entry = zip->findEntryByName("AndroidManifest.xml")) == NULL) { - ALOGW("%s: failed to find entry AndroidManifest.xml\n", __FUNCTION__); - return -1; - } - size_t uncompLen = 0; - int method; - if (!zip->getEntryInfo(entry, &method, &uncompLen, NULL, NULL, NULL, NULL)) { - ALOGW("%s: failed to read entry info\n", __FUNCTION__); - return -1; - } - if (method != ZipFileRO::kCompressDeflated) { - ALOGW("%s: cannot handle zip compression method %d\n", __FUNCTION__, method); - return -1; - } - FileMap *dataMap = zip->createEntryFileMap(entry); - if (!dataMap) { - ALOGW("%s: failed to create FileMap\n", __FUNCTION__); - return -1; - } - char *buf = new char[uncompLen]; - if (NULL == buf) { - ALOGW("%s: failed to allocate %d byte\n", __FUNCTION__, uncompLen); - dataMap->release(); - return -1; - } - StreamingZipInflater inflater(dataMap, uncompLen); - if (inflater.read(buf, uncompLen) < 0) { - ALOGW("%s: failed to inflate %d byte\n", __FUNCTION__, uncompLen); - delete[] buf; - dataMap->release(); - return -1; - } - - int priority = parse_manifest(buf, uncompLen, target_package_name); - delete[] buf; - dataMap->release(); - return priority; - } -} - -int idmap_scan(const char *overlay_dir, const char *target_package_name, - const char *target_apk_path, const char *idmap_dir) -{ - String8 filename = String8(idmap_dir); - filename.appendPath("overlays.list"); - if (unlink(filename.string()) != 0 && errno != ENOENT) { - return EXIT_FAILURE; - } - - DIR *dir = opendir(overlay_dir); - if (dir == NULL) { - return EXIT_FAILURE; - } - - SortedVector overlayVector; - struct dirent *dirent; - while ((dirent = readdir(dir)) != NULL) { - struct stat st; - char overlay_apk_path[PATH_MAX + 1]; - snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name); - if (stat(overlay_apk_path, &st) < 0) { - continue; - } - if (!S_ISREG(st.st_mode)) { - continue; - } - - int priority = parse_apk(overlay_apk_path, target_package_name); - if (priority < 0) { - continue; - } - - String8 idmap_path(idmap_dir); - idmap_path.appendPath(flatten_path(overlay_apk_path + 1)); - idmap_path.append("@idmap"); - - if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) { - ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n", - target_apk_path, overlay_apk_path, idmap_path.string()); - continue; - } - - Overlay overlay(String8(overlay_apk_path), idmap_path, priority); - overlayVector.add(overlay); - } - - closedir(dir); - - if (!writePackagesList(filename.string(), overlayVector)) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -}