166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root/* 266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * Copyright (C) 2011 The Android Open Source Project 366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * 466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * you may not use this file except in compliance with the License. 666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * You may obtain a copy of the License at 766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * 866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * http://www.apache.org/licenses/LICENSE-2.0 966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * 1066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * Unless required by applicable law or agreed to in writing, software 1166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 1266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * See the License for the specific language governing permissions and 1466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * limitations under the License. 1566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root */ 1666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 1766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LOG_TAG "NativeLibraryHelper" 1866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root//#define LOG_NDEBUG 0 1966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 20ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h" 2166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 222279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/ScopedUtfChars.h> 231378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi#include <androidfw/ZipFileRO.h> 241378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi#include <androidfw/ZipUtils.h> 251378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi#include <utils/Log.h> 261378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi#include <utils/Vector.h> 2766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 2866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <zlib.h> 2966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <fcntl.h> 3166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <stdlib.h> 3266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <string.h> 3366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <time.h> 3466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <unistd.h> 35dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov#include <inttypes.h> 3666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <sys/stat.h> 3766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <sys/types.h> 3866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3993bb56ef1525314707dafe5c849916b1d44d15eaElliott Hughes#include <memory> 4066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define APK_LIB "lib/" 4266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define APK_LIB_LEN (sizeof(APK_LIB) - 1) 4366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_PREFIX "/lib" 4566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_PREFIX_LEN (sizeof(LIB_PREFIX) - 1) 4666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_SUFFIX ".so" 4866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_SUFFIX_LEN (sizeof(LIB_SUFFIX) - 1) 4966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 50d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath#define RS_BITCODE_SUFFIX ".bc" 51d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 5266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define TMP_FILE_PATTERN "/tmp.XXXXXX" 5366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define TMP_FILE_PATTERN_LEN (sizeof(TMP_FILE_PATTERN) - 1) 5466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 5566269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootnamespace android { 5666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 5766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root// These match PackageManager.java install codes 581378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghienum install_status_t { 591ebd74acf9977daa42133507e970dab88e08f0efKenny Root INSTALL_SUCCEEDED = 1, 6066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root INSTALL_FAILED_INVALID_APK = -2, 6166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root INSTALL_FAILED_INSUFFICIENT_STORAGE = -4, 621ebd74acf9977daa42133507e970dab88e08f0efKenny Root INSTALL_FAILED_CONTAINER_ERROR = -18, 631ebd74acf9977daa42133507e970dab88e08f0efKenny Root INSTALL_FAILED_INTERNAL_ERROR = -110, 64d11f223c535ed9ce628fe5aaf0fd5692dd0cf9e4Narayan Kamath INSTALL_FAILED_NO_MATCHING_ABIS = -113, 65d11f223c535ed9ce628fe5aaf0fd5692dd0cf9e4Narayan Kamath NO_NATIVE_LIBRARIES = -114 661378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi}; 6766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 681ebd74acf9977daa42133507e970dab88e08f0efKenny Roottypedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*); 691ebd74acf9977daa42133507e970dab88e08f0efKenny Root 701378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi// Equivalent to android.os.FileUtils.isFilenameSafe 7166269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic bool 7266269ea6f68f2f25888ce1080c94ac782742fafcKenny RootisFilenameSafe(const char* filename) 7366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 7466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root off_t offset = 0; 7566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root for (;;) { 7666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root switch (*(filename + offset)) { 7766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case 0: 7866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Null. 7966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // If we've reached the end, all the other characters are good. 8066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 8166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 8266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case 'A' ... 'Z': 8366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case 'a' ... 'z': 8466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '0' ... '9': 8566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '+': 8666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case ',': 8766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '-': 8866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '.': 8966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '/': 9066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '=': 9166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '_': 9266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root offset++; 9366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root break; 9466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 9566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root default: 9666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // We found something that is not good. 9766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return false; 9866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 9966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 10066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Should not reach here. 10166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 10266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 10366269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic bool 104407753c456c1eb2c8556ae7891b6bef43b044e76Narayan KamathisFileDifferent(const char* filePath, uint32_t fileSize, time_t modifiedTime, 105407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath uint32_t zipCrc, struct stat64* st) 10666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 10766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (lstat64(filePath, st) < 0) { 10866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // File is not found or cannot be read. 10971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Couldn't stat %s, copying: %s\n", filePath, strerror(errno)); 11066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 11166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 11266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 11366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!S_ISREG(st->st_mode)) { 11466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 11566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 11666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 1170f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe if (static_cast<uint64_t>(st->st_size) != static_cast<uint64_t>(fileSize)) { 11866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 11966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 12066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 12166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // For some reason, bionic doesn't define st_mtime as time_t 12266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (time_t(st->st_mtime) != modifiedTime) { 12371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("mod time doesn't match: %ld vs. %ld\n", st->st_mtime, modifiedTime); 12466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 12566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 12666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 12766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root int fd = TEMP_FAILURE_RETRY(open(filePath, O_RDONLY)); 12866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (fd < 0) { 12971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Couldn't open file %s: %s", filePath, strerror(errno)); 13066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 13166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 13266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 133407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath // uLong comes from zlib.h. It's a bit of a wart that they're 134407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath // potentially using a 64-bit type for a 32-bit CRC. 135407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath uLong crc = crc32(0L, Z_NULL, 0); 13666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unsigned char crcBuffer[16384]; 13766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ssize_t numBytes; 13866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root while ((numBytes = TEMP_FAILURE_RETRY(read(fd, crcBuffer, sizeof(crcBuffer)))) > 0) { 13966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root crc = crc32(crc, crcBuffer, numBytes); 14066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 14166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root close(fd); 14266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 143407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath ALOGV("%s: crc = %lx, zipCrc = %" PRIu32 "\n", filePath, crc, zipCrc); 14466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 145407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath if (crc != static_cast<uLong>(zipCrc)) { 14666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 14766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 14866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 14966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return false; 15066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 15166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 1521ebd74acf9977daa42133507e970dab88e08f0efKenny Rootstatic install_status_t 153afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan KamathsumFiles(JNIEnv*, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char*) 15466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 15566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root size_t* total = (size_t*) arg; 156407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath uint32_t uncompLen; 15766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 15866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, NULL, NULL)) { 1591ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INVALID_APK; 16066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 16166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 162407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath *total += static_cast<size_t>(uncompLen); 1631ebd74acf9977daa42133507e970dab88e08f0efKenny Root 1641ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_SUCCEEDED; 16566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 16666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 16766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root/* 16866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * Copy the native library if needed. 16966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * 17066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * This function assumes the library and path names passed in are considered safe. 17166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root */ 1721ebd74acf9977daa42133507e970dab88e08f0efKenny Rootstatic install_status_t 17366269ea6f68f2f25888ce1080c94ac782742fafcKenny RootcopyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName) 17466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 175dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov void** args = reinterpret_cast<void**>(arg); 176dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov jstring* javaNativeLibPath = (jstring*) args[0]; 177dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov jboolean extractNativeLibs = *(jboolean*) args[1]; 178dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov jboolean hasNativeBridge = *(jboolean*) args[2]; 179dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov 18066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ScopedUtfChars nativeLibPath(env, *javaNativeLibPath); 18166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 182407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath uint32_t uncompLen; 183407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath uint32_t when; 184407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath uint32_t crc; 18566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 186407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath uint16_t method; 187dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov off64_t offset; 188dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov 189dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov if (!zipFile->getEntryInfo(zipEntry, &method, &uncompLen, NULL, &offset, &when, &crc)) { 1905baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't read zip entry info\n"); 1911ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INVALID_APK; 192dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov } 193dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov 194dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov if (!extractNativeLibs) { 195dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov // check if library is uncompressed and page-aligned 196dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov if (method != ZipFileRO::kCompressStored) { 197dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov ALOGD("Library '%s' is compressed - will not be able to open it directly from apk.\n", 198dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov fileName); 199dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov return INSTALL_FAILED_INVALID_APK; 200dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov } 201dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov 202dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov if (offset % PAGE_SIZE != 0) { 203dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov ALOGD("Library '%s' is not page-aligned - will not be able to open it directly from" 204dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov " apk.\n", fileName); 205dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov return INSTALL_FAILED_INVALID_APK; 206dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov } 207dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov 208dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov if (!hasNativeBridge) { 209dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov return INSTALL_SUCCEEDED; 210dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov } 21166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 21266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 21366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Build local file path 21466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root const size_t fileNameLen = strlen(fileName); 21566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root char localFileName[nativeLibPath.size() + fileNameLen + 2]; 21666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 21766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localFileName, nativeLibPath.c_str(), sizeof(localFileName)) != nativeLibPath.size()) { 2185baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't allocate local file name for library"); 2191ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 22066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 22166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 22266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *(localFileName + nativeLibPath.size()) = '/'; 22366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 22466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localFileName + nativeLibPath.size() + 1, fileName, sizeof(localFileName) 22566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root - nativeLibPath.size() - 1) != fileNameLen) { 2265baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't allocate local file name for library"); 2271ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 22866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 22966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 23066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Only copy out the native file if it's different. 231dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov struct tm t; 232dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov ZipUtils::zipTimeToTimespec(when, &t); 233407753c456c1eb2c8556ae7891b6bef43b044e76Narayan Kamath const time_t modTime = mktime(&t); 234ad076286c3140ce9f1f25b8503bdfd2047a968a7Elliott Hughes struct stat64 st; 23566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!isFileDifferent(localFileName, uncompLen, modTime, crc, &st)) { 2361ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_SUCCEEDED; 23766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 23866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 23962fc14894b32f35641ae2b61ef7ed054c9660288Ivan Lozano char localTmpFileName[nativeLibPath.size() + TMP_FILE_PATTERN_LEN + 1]; 24066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localTmpFileName, nativeLibPath.c_str(), sizeof(localTmpFileName)) 24166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root != nativeLibPath.size()) { 2425baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't allocate local file name for library"); 2431ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 24466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 24566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 24666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localTmpFileName + nativeLibPath.size(), TMP_FILE_PATTERN, 24762fc14894b32f35641ae2b61ef7ed054c9660288Ivan Lozano TMP_FILE_PATTERN_LEN + 1) != TMP_FILE_PATTERN_LEN) { 2486215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't allocate temporary file name for library"); 2491ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 25066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 25166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 25266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root int fd = mkstemp(localTmpFileName); 25366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (fd < 0) { 2546215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't open temporary file name: %s: %s\n", localTmpFileName, strerror(errno)); 2551ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 25666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 25766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 25866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!zipFile->uncompressEntry(zipEntry, fd)) { 2596215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Failed uncompressing %s to %s\n", fileName, localTmpFileName); 26066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root close(fd); 26166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2621ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 26366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 26466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 26566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root close(fd); 26666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 26766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Set the modification time for this file to the ZIP's mod time. 26866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root struct timeval times[2]; 26966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root times[0].tv_sec = st.st_atime; 27066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root times[1].tv_sec = modTime; 27166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root times[0].tv_usec = times[1].tv_usec = 0; 27266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (utimes(localTmpFileName, times) < 0) { 2736215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't change modification time on %s: %s\n", localTmpFileName, strerror(errno)); 27466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2751ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 27666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 27766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 27866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Set the mode to 755 27966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root static const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 28066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (chmod(localTmpFileName, mode) < 0) { 2816215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't change permissions on %s: %s\n", localTmpFileName, strerror(errno)); 28266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2831ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 28466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 28566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 28666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Finally, rename it to the final name. 28766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (rename(localTmpFileName, localFileName) < 0) { 2886215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't rename %s to %s: %s\n", localTmpFileName, localFileName, strerror(errno)); 28966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2901ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 29166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 29266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 29371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Successfully moved %s to %s\n", localTmpFileName, localFileName); 2941ebd74acf9977daa42133507e970dab88e08f0efKenny Root 2951ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_SUCCEEDED; 29666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 29766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 2981378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi/* 2991378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * An iterator over all shared libraries in a zip file. An entry is 3001378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * considered to be a shared library if all of the conditions below are 3011378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * satisfied : 3021378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * 3031378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * - The entry is under the lib/ directory. 3041378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * - The entry name ends with ".so" and the entry name starts with "lib", 3051378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * an exception is made for entries whose name is "gdbserver". 3061378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * - The entry filename is "safe" (as determined by isFilenameSafe). 3071378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * 3081378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi */ 3091378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghiclass NativeLibrariesIterator { 3101378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghiprivate: 311d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer NativeLibrariesIterator(ZipFileRO* zipFile, bool debuggable, void* cookie) 312d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer : mZipFile(zipFile), mDebuggable(debuggable), mCookie(cookie), mLastSlash(NULL) { 3131378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi fileName[0] = '\0'; 31466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 31566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3161378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghipublic: 317d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer static NativeLibrariesIterator* create(ZipFileRO* zipFile, bool debuggable) { 3181378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi void* cookie = NULL; 319957c23775f46c26142bc6d4f9a592ac4586a9ef8Yusuke Sato // Do not specify a suffix to find both .so files and gdbserver. 320957c23775f46c26142bc6d4f9a592ac4586a9ef8Yusuke Sato if (!zipFile->startIteration(&cookie, APK_LIB, NULL /* suffix */)) { 3211378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return NULL; 3221378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 32366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 324d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer return new NativeLibrariesIterator(zipFile, debuggable, cookie); 325afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath } 32666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3271378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipEntryRO next() { 3281378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipEntryRO next = NULL; 3291378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi while ((next = mZipFile->nextEntry(mCookie)) != NULL) { 3301378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Make sure this entry has a filename. 3311378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (mZipFile->getEntryFileName(next, fileName, sizeof(fileName))) { 3321378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi continue; 3331378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 33466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3351378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Make sure the filename is at least to the minimum library name size. 3361378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const size_t fileNameLen = strlen(fileName); 3371378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN; 3381378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (fileNameLen < minLength) { 3391378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi continue; 3401378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 34166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3421378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* lastSlash = strrchr(fileName, '/'); 3431378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName); 34466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 345c012ae38153dd2fe22243c7c5bc81d6f81568ae1Andreas Gampe // Skip directories. 346c012ae38153dd2fe22243c7c5bc81d6f81568ae1Andreas Gampe if (*(lastSlash + 1) == 0) { 347c012ae38153dd2fe22243c7c5bc81d6f81568ae1Andreas Gampe continue; 348c012ae38153dd2fe22243c7c5bc81d6f81568ae1Andreas Gampe } 349c012ae38153dd2fe22243c7c5bc81d6f81568ae1Andreas Gampe 3501378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Make sure the filename is safe. 3511378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (!isFilenameSafe(lastSlash + 1)) { 3521378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi continue; 3531378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3541378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 355d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer if (!mDebuggable) { 356d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer // Make sure the filename starts with lib and ends with ".so". 357d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer if (strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN) 358d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer || strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)) { 359d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer continue; 360d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer } 361d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer } 362d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer 3631378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi mLastSlash = lastSlash; 3641378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi break; 36566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 36666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3671378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return next; 3681378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3691378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3701378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi inline const char* currentEntry() const { 3711378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return fileName; 3721378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3731378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3741378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi inline const char* lastSlash() const { 3751378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return mLastSlash; 3761378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3771378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3781378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi virtual ~NativeLibrariesIterator() { 3791378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi mZipFile->endIteration(mCookie); 3801378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3811378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghiprivate: 3821378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3831378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi char fileName[PATH_MAX]; 3841378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipFileRO* const mZipFile; 385d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer const bool mDebuggable; 3861378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi void* mCookie; 3871378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* mLastSlash; 3881378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi}; 3891ebd74acf9977daa42133507e970dab88e08f0efKenny Root 3901378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghistatic install_status_t 3911378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin ZaghiiterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi, 392d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer jboolean debuggable, iterFunc callFunc, void* callArg) { 3931378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); 3941378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (zipFile == NULL) { 3951378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return INSTALL_FAILED_INVALID_APK; 3961378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3971378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 398d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer std::unique_ptr<NativeLibrariesIterator> it( 399d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer NativeLibrariesIterator::create(zipFile, debuggable)); 4001378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (it.get() == NULL) { 4011378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return INSTALL_FAILED_INVALID_APK; 4021378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4031378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4041378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const ScopedUtfChars cpuAbi(env, javaCpuAbi); 4051378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (cpuAbi.c_str() == NULL) { 4061378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // This would've thrown, so this return code isn't observable by 4071378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Java. 4081378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return INSTALL_FAILED_INVALID_APK; 4091378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4101378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipEntryRO entry = NULL; 4111378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi while ((entry = it->next()) != NULL) { 4121378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* fileName = it->currentEntry(); 4131378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* lastSlash = it->lastSlash(); 4141378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4151378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Check to make sure the CPU ABI of this file is one we support. 4161378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* cpuAbiOffset = fileName + APK_LIB_LEN; 4171378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset; 4181378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4191378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (cpuAbi.size() == cpuAbiRegionSize && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) { 4201378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi install_status_t ret = callFunc(env, callArg, zipFile, entry, lastSlash + 1); 4211ebd74acf9977daa42133507e970dab88e08f0efKenny Root 4221ebd74acf9977daa42133507e970dab88e08f0efKenny Root if (ret != INSTALL_SUCCEEDED) { 42371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Failure for entry %s", lastSlash + 1); 4241ebd74acf9977daa42133507e970dab88e08f0efKenny Root return ret; 4251ebd74acf9977daa42133507e970dab88e08f0efKenny Root } 42666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 42766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 42866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 42966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return INSTALL_SUCCEEDED; 43066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 43166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4321378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 433d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammerstatic int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supportedAbisArray, 434d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer jboolean debuggable) { 4351378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const int numAbis = env->GetArrayLength(supportedAbisArray); 4361378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi Vector<ScopedUtfChars*> supportedAbis; 4371378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4381378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi for (int i = 0; i < numAbis; ++i) { 4391378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi supportedAbis.add(new ScopedUtfChars(env, 4401378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi (jstring) env->GetObjectArrayElement(supportedAbisArray, i))); 4411378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4421378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4431378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); 4441378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (zipFile == NULL) { 4451378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return INSTALL_FAILED_INVALID_APK; 4461378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4471378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 448d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer std::unique_ptr<NativeLibrariesIterator> it( 449d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer NativeLibrariesIterator::create(zipFile, debuggable)); 4501378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (it.get() == NULL) { 4511378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return INSTALL_FAILED_INVALID_APK; 4521378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4531378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4541378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipEntryRO entry = NULL; 4551378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi int status = NO_NATIVE_LIBRARIES; 4561378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi while ((entry = it->next()) != NULL) { 4571378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // We're currently in the lib/ directory of the APK, so it does have some native 4581378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // code. We should return INSTALL_FAILED_NO_MATCHING_ABIS if none of the 4591378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // libraries match. 4601378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (status == NO_NATIVE_LIBRARIES) { 4611378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi status = INSTALL_FAILED_NO_MATCHING_ABIS; 4621378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4631378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4641378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* fileName = it->currentEntry(); 4651378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* lastSlash = it->lastSlash(); 4661378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4671378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Check to see if this CPU ABI matches what we are looking for. 4681378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* abiOffset = fileName + APK_LIB_LEN; 4691378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const size_t abiSize = lastSlash - abiOffset; 4701378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi for (int i = 0; i < numAbis; i++) { 4711378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const ScopedUtfChars* abi = supportedAbis[i]; 4721378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (abi->size() == abiSize && !strncmp(abiOffset, abi->c_str(), abiSize)) { 4731378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // The entry that comes in first (i.e. with a lower index) has the higher priority. 4741378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (((i < status) && (status >= 0)) || (status < 0) ) { 4751378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi status = i; 4761378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4771378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4781378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4791378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4801378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4811378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi for (int i = 0; i < numAbis; ++i) { 4821378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi delete supportedAbis[i]; 4831378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4841378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4851378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return status; 4861378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi} 4871378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 48866269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic jint 48966269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootcom_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz, 490dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi, 491d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer jboolean extractNativeLibs, jboolean hasNativeBridge, jboolean debuggable) 49266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 493dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov void* args[] = { &javaNativeLibPath, &extractNativeLibs, &hasNativeBridge }; 494d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi, debuggable, 495dec4688f40b0018fbd1f00db05581966f531d88fDmitriy Ivanov copyFileIfChanged, reinterpret_cast<void*>(args)); 49666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 49766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 49866269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic jlong 49966269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootcom_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz, 500d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer jlong apkHandle, jstring javaCpuAbi, jboolean debuggable) 50166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 50266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root size_t totalSize = 0; 50366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 504d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer iterateOverNativeFiles(env, apkHandle, javaCpuAbi, debuggable, sumFiles, &totalSize); 50566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 50666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return totalSize; 50766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 50866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 5091378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghistatic jint 5101378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghicom_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz, 511d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer jlong apkHandle, jobjectArray javaCpuAbisToSearch, jboolean debuggable) 5121378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi{ 513d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable); 5141378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi} 5151378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 516d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamathenum bitcode_scan_result_t { 517d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath APK_SCAN_ERROR = -1, 518d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath NO_BITCODE_PRESENT = 0, 519d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath BITCODE_PRESENT = 1, 520d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath}; 521d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 522d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamathstatic jint 523d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamathcom_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode(JNIEnv *env, jclass clazz, 524d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath jlong apkHandle) { 525d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); 526d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath void* cookie = NULL; 527957c23775f46c26142bc6d4f9a592ac4586a9ef8Yusuke Sato if (!zipFile->startIteration(&cookie, NULL /* prefix */, RS_BITCODE_SUFFIX)) { 528d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath return APK_SCAN_ERROR; 529d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 530d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 531d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath char fileName[PATH_MAX]; 532d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath ZipEntryRO next = NULL; 533d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath while ((next = zipFile->nextEntry(cookie)) != NULL) { 534d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath if (zipFile->getEntryFileName(next, fileName, sizeof(fileName))) { 535d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath continue; 536d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 537d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath const char* lastSlash = strrchr(fileName, '/'); 538d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath const char* baseName = (lastSlash == NULL) ? fileName : fileName + 1; 539957c23775f46c26142bc6d4f9a592ac4586a9ef8Yusuke Sato if (isFilenameSafe(baseName)) { 540d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath zipFile->endIteration(cookie); 541d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath return BITCODE_PRESENT; 542d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 543d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 544d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 545d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath zipFile->endIteration(cookie); 546d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath return NO_BITCODE_PRESENT; 547d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath} 548d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 5491378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghistatic jlong 5501378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghicom_android_internal_content_NativeLibraryHelper_openApk(JNIEnv *env, jclass, jstring apkPath) 5511378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi{ 5521378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ScopedUtfChars filePath(env, apkPath); 5531378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipFileRO* zipFile = ZipFileRO::open(filePath.c_str()); 5541378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 5551378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return reinterpret_cast<jlong>(zipFile); 5561378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi} 5571378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 5581704e3cf0c445512f0a9644485dd3449e874556bDianne Hackbornstatic jlong 5591704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborncom_android_internal_content_NativeLibraryHelper_openApkFd(JNIEnv *env, jclass, 5601704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn jobject fileDescriptor, jstring debugPathName) 5611704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn{ 5621704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn ScopedUtfChars debugFilePath(env, debugPathName); 5631704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn 5641704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 5651704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn if (fd < 0) { 5661704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn jniThrowException(env, "java/lang/IllegalArgumentException", "Bad FileDescriptor"); 5671704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn return 0; 5681704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn } 5691704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn 5701704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn ZipFileRO* zipFile = ZipFileRO::openFd(fd, debugFilePath.c_str()); 5711704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn 5721704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn return reinterpret_cast<jlong>(zipFile); 5731704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn} 5741704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn 5751378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghistatic void 5761378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghicom_android_internal_content_NativeLibraryHelper_close(JNIEnv *env, jclass, jlong apkHandle) 5771378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi{ 5781378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi delete reinterpret_cast<ZipFileRO*>(apkHandle); 5791378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi} 5801378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 58176f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = { 5821378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi {"nativeOpenApk", 5831378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi "(Ljava/lang/String;)J", 5841378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi (void *)com_android_internal_content_NativeLibraryHelper_openApk}, 5851704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn {"nativeOpenApkFd", 5861704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn "(Ljava/io/FileDescriptor;Ljava/lang/String;)J", 5871704e3cf0c445512f0a9644485dd3449e874556bDianne Hackborn (void *)com_android_internal_content_NativeLibraryHelper_openApkFd}, 5881378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi {"nativeClose", 5891378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi "(J)V", 5901378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi (void *)com_android_internal_content_NativeLibraryHelper_close}, 59166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root {"nativeCopyNativeBinaries", 592d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer "(JLjava/lang/String;Ljava/lang/String;ZZZ)I", 59366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root (void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries}, 59466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root {"nativeSumNativeBinaries", 595d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer "(JLjava/lang/String;Z)J", 59666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries}, 5971378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi {"nativeFindSupportedAbi", 598d6dd6b8a613c9c91eeebde713f12f18e6cc43c1fTamas Berghammer "(J[Ljava/lang/String;Z)I", 5991378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi}, 600d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath {"hasRenderscriptBitcode", "(J)I", 601d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath (void *)com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode}, 60266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}; 60366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 60466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 60566269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootint register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env) 60666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 607ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return RegisterMethodsOrDie(env, 608ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe "com/android/internal/content/NativeLibraryHelper", gMethods, NELEM(gMethods)); 60966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 61066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 61166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}; 612