113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include "idmap.h" 213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <UniquePtr.h> 413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <androidfw/AssetManager.h> 513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <androidfw/ResourceTypes.h> 613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <androidfw/ZipFileRO.h> 713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <utils/String8.h> 813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <fcntl.h> 1013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <sys/stat.h> 1113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 1213221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossusing namespace android; 1313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 1413221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossnamespace { 1513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int get_zip_entry_crc(const char *zip_path, const char *entry_name, uint32_t *crc) 1613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 1713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross UniquePtr<ZipFileRO> zip(ZipFileRO::open(zip_path)); 1813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (zip.get() == NULL) { 1913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 2013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 2113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ZipEntryRO entry = zip->findEntryByName(entry_name); 2213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (entry == NULL) { 2313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 2413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 2513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (!zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, (long*)crc)) { 2613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 2713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 2813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross zip->releaseEntry(entry); 2913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return 0; 3013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 3113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 3213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int open_idmap(const char *path) 3313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 3413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)); 3513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (fd == -1) { 3613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ALOGD("error: open %s: %s\n", path, strerror(errno)); 3713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross goto fail; 3813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 3913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { 4013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ALOGD("error: fchmod %s: %s\n", path, strerror(errno)); 4113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross goto fail; 4213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 4313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX | LOCK_NB)) != 0) { 4413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ALOGD("error: flock %s: %s\n", path, strerror(errno)); 4513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross goto fail; 4613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 4713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 4813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return fd; 4913221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossfail: 5013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (fd != -1) { 5113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross close(fd); 5213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross unlink(path); 5313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 5413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 5513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 5613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 5713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int write_idmap(int fd, const uint32_t *data, size_t size) 5813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 5913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (lseek(fd, SEEK_SET, 0) < 0) { 6013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 6113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 6213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross size_t bytesLeft = size; 6313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross while (bytesLeft > 0) { 6413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ssize_t w = TEMP_FAILURE_RETRY(write(fd, data + size - bytesLeft, bytesLeft)); 6513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (w < 0) { 6613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross fprintf(stderr, "error: write: %s\n", strerror(errno)); 6713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 6813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 6913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross bytesLeft -= w; 7013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 7113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return 0; 7213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 7313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 7413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross bool is_idmap_stale_fd(const char *target_apk_path, const char *overlay_apk_path, int idmap_fd) 7513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 7613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross static const size_t N = ResTable::IDMAP_HEADER_SIZE_BYTES; 7713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross struct stat st; 7813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (fstat(idmap_fd, &st) == -1) { 7913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 8013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 8113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (st.st_size < N) { 8213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross // file is empty or corrupt 8313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 8413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 8513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 8613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross char buf[N]; 8713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ssize_t bytesLeft = N; 8813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (lseek(idmap_fd, SEEK_SET, 0) < 0) { 8913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 9013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 9113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross for (;;) { 9213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ssize_t r = TEMP_FAILURE_RETRY(read(idmap_fd, buf + N - bytesLeft, bytesLeft)); 9313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (r < 0) { 9413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 9513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 9613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross bytesLeft -= r; 9713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (bytesLeft == 0) { 9813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross break; 9913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 10013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (r == 0) { 10113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross // "shouldn't happen" 10213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 10313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 10413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 10513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 10613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross uint32_t cached_target_crc, cached_overlay_crc; 10713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross String8 cached_target_path, cached_overlay_path; 108f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski if (!ResTable::getIdmapInfo(buf, N, NULL, &cached_target_crc, &cached_overlay_crc, 10913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross &cached_target_path, &cached_overlay_path)) { 11013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 11113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 11213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 11313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (cached_target_path != target_apk_path) { 11413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 11513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 11613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (cached_overlay_path != overlay_apk_path) { 11713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 11813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 11913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 12013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross uint32_t actual_target_crc, actual_overlay_crc; 12113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME, 12213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross &actual_target_crc) == -1) { 12313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 12413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 12513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME, 12613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross &actual_overlay_crc) == -1) { 12713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 12813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 12913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 13013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return cached_target_crc != actual_target_crc || cached_overlay_crc != actual_overlay_crc; 13113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 13213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 13313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross bool is_idmap_stale_path(const char *target_apk_path, const char *overlay_apk_path, 13413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross const char *idmap_path) 13513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 13613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross struct stat st; 13713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (stat(idmap_path, &st) == -1) { 13813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross // non-existing idmap is always stale; on other errors, abort idmap generation 13913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return errno == ENOENT; 14013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 14113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 14213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int idmap_fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY)); 14313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (idmap_fd == -1) { 14413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return false; 14513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 14613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross bool is_stale = is_idmap_stale_fd(target_apk_path, overlay_apk_path, idmap_fd); 14713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross close(idmap_fd); 14813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return is_stale; 14913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 15013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 15113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int create_idmap(const char *target_apk_path, const char *overlay_apk_path, 15213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross uint32_t **data, size_t *size) 15313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 15413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross uint32_t target_crc, overlay_crc; 15513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME, 15613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross &target_crc) == -1) { 15713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 15813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 15913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME, 16013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross &overlay_crc) == -1) { 16113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 16213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 16313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 16413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross AssetManager am; 16513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross bool b = am.createIdmap(target_apk_path, overlay_apk_path, target_crc, overlay_crc, 16613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross data, size); 16713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return b ? 0 : -1; 16813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 16913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 17013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int create_and_write_idmap(const char *target_apk_path, const char *overlay_apk_path, 17113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int fd, bool check_if_stale) 17213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 17313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (check_if_stale) { 17413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (!is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd)) { 17513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross // already up to date -- nothing to do 17613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return 0; 17713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 17813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 17913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 18013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross uint32_t *data = NULL; 18113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross size_t size; 18213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 18313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (create_idmap(target_apk_path, overlay_apk_path, &data, &size) == -1) { 18413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 18513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 18613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 18713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (write_idmap(fd, data, size) == -1) { 18813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross free(data); 18913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 19013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 19113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 19213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross free(data); 19313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return 0; 19413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 19513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross} 19613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 19713221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossint idmap_create_path(const char *target_apk_path, const char *overlay_apk_path, 19813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross const char *idmap_path) 19913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross{ 20013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (!is_idmap_stale_path(target_apk_path, overlay_apk_path, idmap_path)) { 20113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross // already up to date -- nothing to do 20213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return EXIT_SUCCESS; 20313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 20413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 20513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int fd = open_idmap(idmap_path); 20613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (fd == -1) { 20713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return EXIT_FAILURE; 20813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 20913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 21013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int r = create_and_write_idmap(target_apk_path, overlay_apk_path, fd, false); 21113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross close(fd); 21213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (r != 0) { 21313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross unlink(idmap_path); 21413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 21513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; 21613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross} 21713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 21813221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossint idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd) 21913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross{ 22013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return create_and_write_idmap(target_apk_path, overlay_apk_path, fd, true) == 0 ? 22113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross EXIT_SUCCESS : EXIT_FAILURE; 22213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross} 223