scan.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #include <dirent.h>
  2. #include <inttypes.h>
  3. #include <sys/file.h>
  4. #include <sys/stat.h>
  5. #include "idmap.h"
  6. #include <memory>
  7. #include <androidfw/ResourceTypes.h>
  8. #include <androidfw/StreamingZipInflater.h>
  9. #include <androidfw/ZipFileRO.h>
  10. #include <cutils/jstring.h>
  11. #include <cutils/properties.h>
  12. #include <private/android_filesystem_config.h> // for AID_SYSTEM
  13. #include <utils/SortedVector.h>
  14. #include <utils/String16.h>
  15. #include <utils/String8.h>
  16. #define NO_OVERLAY_TAG (-1000)
  17. using namespace android;
  18. namespace {
  19. struct Overlay {
  20. Overlay() {}
  21. Overlay(const String8& a, const String8& i, int p) :
  22. apk_path(a), idmap_path(i), priority(p) {}
  23. bool operator<(Overlay const& rhs) const
  24. {
  25. return rhs.priority > priority;
  26. }
  27. String8 apk_path;
  28. String8 idmap_path;
  29. int priority;
  30. };
  31. bool writePackagesList(const char *filename, const SortedVector<Overlay>& overlayVector)
  32. {
  33. // the file is opened for appending so that it doesn't get truncated
  34. // before we can guarantee mutual exclusion via the flock
  35. FILE* fout = fopen(filename, "a");
  36. if (fout == NULL) {
  37. return false;
  38. }
  39. if (TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_EX)) != 0) {
  40. fclose(fout);
  41. return false;
  42. }
  43. if (TEMP_FAILURE_RETRY(ftruncate(fileno(fout), 0)) != 0) {
  44. TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN));
  45. fclose(fout);
  46. return false;
  47. }
  48. for (size_t i = 0; i < overlayVector.size(); ++i) {
  49. const Overlay& overlay = overlayVector[i];
  50. fprintf(fout, "%s %s\n", overlay.apk_path.string(), overlay.idmap_path.string());
  51. }
  52. TEMP_FAILURE_RETRY(fflush(fout));
  53. TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN));
  54. fclose(fout);
  55. // Make file world readable since Zygote (running as root) will read
  56. // it when creating the initial AssetManger object
  57. const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // 0644
  58. if (chmod(filename, mode) == -1) {
  59. unlink(filename);
  60. return false;
  61. }
  62. return true;
  63. }
  64. String8 flatten_path(const char *path)
  65. {
  66. String16 tmp(path);
  67. tmp.replaceAll('/', '@');
  68. return String8(tmp);
  69. }
  70. bool check_property(String16 property, String16 value) {
  71. const char *prop;
  72. const char *val;
  73. prop = strndup16to8(property.string(), property.size());
  74. char propBuf[PROPERTY_VALUE_MAX];
  75. property_get(prop, propBuf, NULL);
  76. val = strndup16to8(value.string(), value.size());
  77. return (strcmp(propBuf, val) == 0);
  78. }
  79. int parse_overlay_tag(const ResXMLTree& parser, const char *target_package_name,
  80. bool* is_static_overlay)
  81. {
  82. const size_t N = parser.getAttributeCount();
  83. String16 target;
  84. int priority = -1;
  85. String16 propName = String16();
  86. String16 propValue = String16();
  87. for (size_t i = 0; i < N; ++i) {
  88. size_t len;
  89. String16 key(parser.getAttributeName(i, &len));
  90. if (key == String16("targetPackage")) {
  91. const char16_t *p = parser.getAttributeStringValue(i, &len);
  92. if (p != NULL) {
  93. target = String16(p, len);
  94. }
  95. } else if (key == String16("priority")) {
  96. Res_value v;
  97. if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) {
  98. priority = v.data;
  99. if (priority < 0 || priority > 9999) {
  100. return -1;
  101. }
  102. }
  103. } else if (key == String16("isStatic")) {
  104. Res_value v;
  105. if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) {
  106. *is_static_overlay = (v.data != 0);
  107. }
  108. } else if (key == String16("requiredSystemPropertyName")) {
  109. const char16_t *p = parser.getAttributeStringValue(i, &len);
  110. if (p != NULL) {
  111. propName = String16(p, len);
  112. }
  113. } else if (key == String16("requiredSystemPropertyValue")) {
  114. const char16_t *p = parser.getAttributeStringValue(i, &len);
  115. if (p != NULL) {
  116. propValue = String16(p, len);
  117. }
  118. }
  119. }
  120. // Note that conditional property enablement/exclusion only applies if
  121. // the attribute is present. In its absence, all overlays are presumed enabled.
  122. if (propName.size() > 0 && propValue.size() > 0) {
  123. // if property set & equal to value, then include overlay - otherwise skip
  124. if (!check_property(propName, propValue)) {
  125. return NO_OVERLAY_TAG;
  126. }
  127. }
  128. if (target == String16(target_package_name)) {
  129. return priority;
  130. }
  131. return NO_OVERLAY_TAG;
  132. }
  133. int parse_manifest(const void *data, size_t size, const char *target_package_name)
  134. {
  135. ResXMLTree parser;
  136. parser.setTo(data, size);
  137. if (parser.getError() != NO_ERROR) {
  138. ALOGD("%s failed to init xml parser, error=0x%08x\n", __FUNCTION__, parser.getError());
  139. return -1;
  140. }
  141. ResXMLParser::event_code_t type;
  142. bool is_static_overlay = false;
  143. int priority = NO_OVERLAY_TAG;
  144. do {
  145. type = parser.next();
  146. if (type == ResXMLParser::START_TAG) {
  147. size_t len;
  148. String16 tag(parser.getElementName(&len));
  149. if (tag == String16("overlay")) {
  150. priority = parse_overlay_tag(parser, target_package_name, &is_static_overlay);
  151. break;
  152. }
  153. }
  154. } while (type != ResXMLParser::BAD_DOCUMENT && type != ResXMLParser::END_DOCUMENT);
  155. if (is_static_overlay) {
  156. return priority;
  157. }
  158. return NO_OVERLAY_TAG;
  159. }
  160. int parse_apk(const char *path, const char *target_package_name)
  161. {
  162. std::unique_ptr<ZipFileRO> zip(ZipFileRO::open(path));
  163. if (zip.get() == NULL) {
  164. ALOGW("%s: failed to open zip %s\n", __FUNCTION__, path);
  165. return -1;
  166. }
  167. ZipEntryRO entry;
  168. if ((entry = zip->findEntryByName("AndroidManifest.xml")) == NULL) {
  169. ALOGW("%s: failed to find entry AndroidManifest.xml\n", __FUNCTION__);
  170. return -1;
  171. }
  172. uint32_t uncompLen = 0;
  173. uint16_t method;
  174. if (!zip->getEntryInfo(entry, &method, &uncompLen, NULL, NULL, NULL, NULL)) {
  175. ALOGW("%s: failed to read entry info\n", __FUNCTION__);
  176. return -1;
  177. }
  178. if (method != ZipFileRO::kCompressDeflated) {
  179. ALOGW("%s: cannot handle zip compression method %" PRIu16 "\n", __FUNCTION__, method);
  180. return -1;
  181. }
  182. FileMap *dataMap = zip->createEntryFileMap(entry);
  183. if (dataMap == NULL) {
  184. ALOGW("%s: failed to create FileMap\n", __FUNCTION__);
  185. return -1;
  186. }
  187. char *buf = new char[uncompLen];
  188. if (NULL == buf) {
  189. ALOGW("%s: failed to allocate %" PRIu32 " byte\n", __FUNCTION__, uncompLen);
  190. delete dataMap;
  191. return -1;
  192. }
  193. StreamingZipInflater inflater(dataMap, uncompLen);
  194. if (inflater.read(buf, uncompLen) < 0) {
  195. ALOGW("%s: failed to inflate %" PRIu32 " byte\n", __FUNCTION__, uncompLen);
  196. delete[] buf;
  197. delete dataMap;
  198. return -1;
  199. }
  200. int priority = parse_manifest(buf, static_cast<size_t>(uncompLen), target_package_name);
  201. delete[] buf;
  202. delete dataMap;
  203. return priority;
  204. }
  205. }
  206. int idmap_scan(const char *target_package_name, const char *target_apk_path,
  207. const char *idmap_dir, const android::Vector<const char *> *overlay_dirs)
  208. {
  209. String8 filename = String8(idmap_dir);
  210. filename.appendPath("overlays.list");
  211. SortedVector<Overlay> overlayVector;
  212. const size_t N = overlay_dirs->size();
  213. for (size_t i = 0; i < N; ++i) {
  214. const char *overlay_dir = overlay_dirs->itemAt(i);
  215. DIR *dir = opendir(overlay_dir);
  216. if (dir == NULL) {
  217. return EXIT_FAILURE;
  218. }
  219. struct dirent *dirent;
  220. while ((dirent = readdir(dir)) != NULL) {
  221. struct stat st;
  222. char overlay_apk_path[PATH_MAX + 1];
  223. snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
  224. if (stat(overlay_apk_path, &st) < 0) {
  225. continue;
  226. }
  227. if (!S_ISREG(st.st_mode)) {
  228. continue;
  229. }
  230. int priority = parse_apk(overlay_apk_path, target_package_name);
  231. if (priority < 0) {
  232. continue;
  233. }
  234. String8 idmap_path(idmap_dir);
  235. idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
  236. idmap_path.append("@idmap");
  237. if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) {
  238. ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
  239. target_apk_path, overlay_apk_path, idmap_path.string());
  240. continue;
  241. }
  242. Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
  243. overlayVector.add(overlay);
  244. }
  245. closedir(dir);
  246. }
  247. if (!writePackagesList(filename.string(), overlayVector)) {
  248. return EXIT_FAILURE;
  249. }
  250. return EXIT_SUCCESS;
  251. }