4 #include <androidfw/AssetManager.h>
5 #include <androidfw/ResourceTypes.h>
6 #include <androidfw/ZipFileRO.h>
7 #include <utils/String8.h>
13 using namespace android;
16 int get_zip_entry_crc(const char *zip_path, const char *entry_name, uint32_t *crc)
18 UniquePtr<ZipFileRO> zip(ZipFileRO::open(zip_path));
19 if (zip.get() == NULL) {
22 ZipEntryRO entry = zip->findEntryByName(entry_name);
26 if (!zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, reinterpret_cast<long*>(crc))) {
29 zip->releaseEntry(entry);
33 int open_idmap(const char *path)
35 int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644));
37 ALOGD("error: open %s: %s\n", path, strerror(errno));
40 if (fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
41 ALOGD("error: fchmod %s: %s\n", path, strerror(errno));
44 if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX | LOCK_NB)) != 0) {
45 ALOGD("error: flock %s: %s\n", path, strerror(errno));
58 int write_idmap(int fd, const uint32_t *data, size_t size)
60 if (lseek(fd, SEEK_SET, 0) < 0) {
63 size_t bytesLeft = size;
64 while (bytesLeft > 0) {
65 ssize_t w = TEMP_FAILURE_RETRY(write(fd, data + size - bytesLeft, bytesLeft));
67 fprintf(stderr, "error: write: %s\n", strerror(errno));
70 bytesLeft -= static_cast<size_t>(w);
75 bool is_idmap_stale_fd(const char *target_apk_path, const char *overlay_apk_path, int idmap_fd)
77 static const size_t N = ResTable::IDMAP_HEADER_SIZE_BYTES;
79 if (fstat(idmap_fd, &st) == -1) {
82 if (st.st_size < static_cast<off_t>(N)) {
83 // file is empty or corrupt
89 if (lseek(idmap_fd, SEEK_SET, 0) < 0) {
93 ssize_t r = TEMP_FAILURE_RETRY(read(idmap_fd, buf + N - bytesLeft, bytesLeft));
97 bytesLeft -= static_cast<size_t>(r);
102 // "shouldn't happen"
107 uint32_t cached_target_crc, cached_overlay_crc;
108 String8 cached_target_path, cached_overlay_path;
109 if (!ResTable::getIdmapInfo(buf, N, NULL, &cached_target_crc, &cached_overlay_crc,
110 &cached_target_path, &cached_overlay_path)) {
114 if (cached_target_path != target_apk_path) {
117 if (cached_overlay_path != overlay_apk_path) {
121 uint32_t actual_target_crc, actual_overlay_crc;
122 if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME,
123 &actual_target_crc) == -1) {
126 if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME,
127 &actual_overlay_crc) == -1) {
131 return cached_target_crc != actual_target_crc || cached_overlay_crc != actual_overlay_crc;
134 bool is_idmap_stale_path(const char *target_apk_path, const char *overlay_apk_path,
135 const char *idmap_path)
138 if (stat(idmap_path, &st) == -1) {
139 // non-existing idmap is always stale; on other errors, abort idmap generation
140 return errno == ENOENT;
143 int idmap_fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY));
144 if (idmap_fd == -1) {
147 bool is_stale = is_idmap_stale_fd(target_apk_path, overlay_apk_path, idmap_fd);
152 int create_idmap(const char *target_apk_path, const char *overlay_apk_path,
153 uint32_t **data, size_t *size)
155 uint32_t target_crc, overlay_crc;
156 if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME,
157 &target_crc) == -1) {
160 if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME,
161 &overlay_crc) == -1) {
166 bool b = am.createIdmap(target_apk_path, overlay_apk_path, target_crc, overlay_crc,
171 int create_and_write_idmap(const char *target_apk_path, const char *overlay_apk_path,
172 int fd, bool check_if_stale)
174 if (check_if_stale) {
175 if (!is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd)) {
176 // already up to date -- nothing to do
181 uint32_t *data = NULL;
184 if (create_idmap(target_apk_path, overlay_apk_path, &data, &size) == -1) {
188 if (write_idmap(fd, data, size) == -1) {
198 int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path,
199 const char *idmap_path)
201 if (!is_idmap_stale_path(target_apk_path, overlay_apk_path, idmap_path)) {
202 // already up to date -- nothing to do
206 int fd = open_idmap(idmap_path);
211 int r = create_and_write_idmap(target_apk_path, overlay_apk_path, fd, false);
216 return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
219 int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd)
221 return create_and_write_idmap(target_apk_path, overlay_apk_path, fd, true) == 0 ?
222 EXIT_SUCCESS : EXIT_FAILURE;