1 #include "idmap.h" 2 3 #include <memory> 4 #include <androidfw/AssetManager.h> 5 #include <androidfw/ResourceTypes.h> 6 #include <androidfw/ZipFileRO.h> 7 #include <utils/String8.h> 8 9 #include <fcntl.h> 10 #include <sys/file.h> 11 #include <sys/stat.h> 12 13 using namespace android; 14 15 namespace { 16 int get_zip_entry_crc(const char *zip_path, const char *entry_name, uint32_t *crc) 17 { 18 std::unique_ptr<ZipFileRO> zip(ZipFileRO::open(zip_path)); 19 if (zip.get() == NULL) { 20 return -1; 21 } 22 ZipEntryRO entry = zip->findEntryByName(entry_name); 23 if (entry == NULL) { 24 return -1; 25 } 26 if (!zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, crc)) { 27 return -1; 28 } 29 zip->releaseEntry(entry); 30 return 0; 31 } 32 33 int open_idmap(const char *path) 34 { 35 int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)); 36 if (fd == -1) { 37 ALOGD("error: open %s: %s\n", path, strerror(errno)); 38 goto fail; 39 } 40 if (fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { 41 ALOGD("error: fchmod %s: %s\n", path, strerror(errno)); 42 goto fail; 43 } 44 if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX)) != 0) { 45 ALOGD("error: flock %s: %s\n", path, strerror(errno)); 46 goto fail; 47 } 48 49 return fd; 50 fail: 51 if (fd != -1) { 52 close(fd); 53 unlink(path); 54 } 55 return -1; 56 } 57 58 int write_idmap(int fd, const uint32_t *data, size_t size) 59 { 60 if (lseek(fd, 0, SEEK_SET) < 0) { 61 return -1; 62 } 63 size_t bytesLeft = size; 64 while (bytesLeft > 0) { 65 ssize_t w = TEMP_FAILURE_RETRY(write(fd, data + size - bytesLeft, bytesLeft)); 66 if (w < 0) { 67 fprintf(stderr, "error: write: %s\n", strerror(errno)); 68 return -1; 69 } 70 bytesLeft -= static_cast<size_t>(w); 71 } 72 return 0; 73 } 74 75 bool is_idmap_stale_fd(const char *target_apk_path, const char *overlay_apk_path, int idmap_fd) 76 { 77 static const size_t N = ResTable::IDMAP_HEADER_SIZE_BYTES; 78 struct stat st; 79 if (fstat(idmap_fd, &st) == -1) { 80 return true; 81 } 82 if (st.st_size < static_cast<off_t>(N)) { 83 // file is empty or corrupt 84 return true; 85 } 86 87 char buf[N]; 88 size_t bytesLeft = N; 89 if (lseek(idmap_fd, 0, SEEK_SET) < 0) { 90 return true; 91 } 92 for (;;) { 93 ssize_t r = TEMP_FAILURE_RETRY(read(idmap_fd, buf + N - bytesLeft, bytesLeft)); 94 if (r < 0) { 95 return true; 96 } 97 bytesLeft -= static_cast<size_t>(r); 98 if (bytesLeft == 0) { 99 break; 100 } 101 if (r == 0) { 102 // "shouldn't happen" 103 return true; 104 } 105 } 106 107 uint32_t version, cached_target_crc, cached_overlay_crc; 108 String8 cached_target_path, cached_overlay_path; 109 if (!ResTable::getIdmapInfo(buf, N, &version, &cached_target_crc, &cached_overlay_crc, 110 &cached_target_path, &cached_overlay_path)) { 111 return true; 112 } 113 114 if (version != ResTable::IDMAP_CURRENT_VERSION) { 115 return true; 116 } 117 118 if (cached_target_path != target_apk_path) { 119 return true; 120 } 121 if (cached_overlay_path != overlay_apk_path) { 122 return true; 123 } 124 125 uint32_t actual_target_crc, actual_overlay_crc; 126 if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME, 127 &actual_target_crc) == -1) { 128 return true; 129 } 130 if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME, 131 &actual_overlay_crc) == -1) { 132 return true; 133 } 134 135 return cached_target_crc != actual_target_crc || cached_overlay_crc != actual_overlay_crc; 136 } 137 138 bool is_idmap_stale_path(const char *target_apk_path, const char *overlay_apk_path, 139 const char *idmap_path) 140 { 141 struct stat st; 142 if (stat(idmap_path, &st) == -1) { 143 // non-existing idmap is always stale; on other errors, abort idmap generation 144 return errno == ENOENT; 145 } 146 147 int idmap_fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY)); 148 if (idmap_fd == -1) { 149 return false; 150 } 151 bool is_stale = is_idmap_stale_fd(target_apk_path, overlay_apk_path, idmap_fd); 152 close(idmap_fd); 153 return is_stale; 154 } 155 156 int create_idmap(const char *target_apk_path, const char *overlay_apk_path, 157 uint32_t **data, size_t *size) 158 { 159 uint32_t target_crc, overlay_crc; 160 if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME, 161 &target_crc) == -1) { 162 return -1; 163 } 164 if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME, 165 &overlay_crc) == -1) { 166 return -1; 167 } 168 169 AssetManager am; 170 bool b = am.createIdmap(target_apk_path, overlay_apk_path, target_crc, overlay_crc, 171 data, size); 172 return b ? 0 : -1; 173 } 174 175 int create_and_write_idmap(const char *target_apk_path, const char *overlay_apk_path, 176 int fd, bool check_if_stale) 177 { 178 if (check_if_stale) { 179 if (!is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd)) { 180 // already up to date -- nothing to do 181 return 0; 182 } 183 } 184 185 uint32_t *data = NULL; 186 size_t size; 187 188 if (create_idmap(target_apk_path, overlay_apk_path, &data, &size) == -1) { 189 return -1; 190 } 191 192 if (write_idmap(fd, data, size) == -1) { 193 free(data); 194 return -1; 195 } 196 197 free(data); 198 return 0; 199 } 200 } 201 202 int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path, 203 const char *idmap_path) 204 { 205 if (!is_idmap_stale_path(target_apk_path, overlay_apk_path, idmap_path)) { 206 // already up to date -- nothing to do 207 return EXIT_SUCCESS; 208 } 209 210 int fd = open_idmap(idmap_path); 211 if (fd == -1) { 212 return EXIT_FAILURE; 213 } 214 215 int r = create_and_write_idmap(target_apk_path, overlay_apk_path, fd, false); 216 close(fd); 217 if (r != 0) { 218 unlink(idmap_path); 219 } 220 return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; 221 } 222 223 int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd) 224 { 225 return create_and_write_idmap(target_apk_path, overlay_apk_path, fd, true) == 0 ? 226 EXIT_SUCCESS : EXIT_FAILURE; 227 } 228 229 int idmap_verify_fd(const char *target_apk_path, const char *overlay_apk_path, int fd) 230 { 231 return !is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd) ? 232 EXIT_SUCCESS : EXIT_FAILURE; 233 } 234