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 2066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <android_runtime/AndroidRuntime.h> 2166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 2266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <ScopedUtfChars.h> 23afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath#include <UniquePtr.h> 241378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi#include <androidfw/ZipFileRO.h> 251378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi#include <androidfw/ZipUtils.h> 261378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi#include <utils/Log.h> 271378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi#include <utils/Vector.h> 2866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 2966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <zlib.h> 3066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <fcntl.h> 3266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <stdlib.h> 3366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <string.h> 3466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <time.h> 3566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <unistd.h> 3666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <sys/stat.h> 3766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <sys/types.h> 3866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define APK_LIB "lib/" 4166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define APK_LIB_LEN (sizeof(APK_LIB) - 1) 4266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_PREFIX "/lib" 4466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_PREFIX_LEN (sizeof(LIB_PREFIX) - 1) 4566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_SUFFIX ".so" 4766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_SUFFIX_LEN (sizeof(LIB_SUFFIX) - 1) 4866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 49d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath#define RS_BITCODE_SUFFIX ".bc" 50d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath#define RS_BITCODE_SUFFIX_LEN (sizeof(RS_BITCODE_SUFFIX) -1) 51d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 5266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define GDBSERVER "gdbserver" 5366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define GDBSERVER_LEN (sizeof(GDBSERVER) - 1) 5466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 5566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define TMP_FILE_PATTERN "/tmp.XXXXXX" 5666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define TMP_FILE_PATTERN_LEN (sizeof(TMP_FILE_PATTERN) - 1) 5766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 5866269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootnamespace android { 5966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 6066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root// These match PackageManager.java install codes 611378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghienum install_status_t { 621ebd74acf9977daa42133507e970dab88e08f0efKenny Root INSTALL_SUCCEEDED = 1, 6366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root INSTALL_FAILED_INVALID_APK = -2, 6466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root INSTALL_FAILED_INSUFFICIENT_STORAGE = -4, 651ebd74acf9977daa42133507e970dab88e08f0efKenny Root INSTALL_FAILED_CONTAINER_ERROR = -18, 661ebd74acf9977daa42133507e970dab88e08f0efKenny Root INSTALL_FAILED_INTERNAL_ERROR = -110, 67d11f223c535ed9ce628fe5aaf0fd5692dd0cf9e4Narayan Kamath INSTALL_FAILED_NO_MATCHING_ABIS = -113, 68d11f223c535ed9ce628fe5aaf0fd5692dd0cf9e4Narayan Kamath NO_NATIVE_LIBRARIES = -114 691378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi}; 7066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 711ebd74acf9977daa42133507e970dab88e08f0efKenny Roottypedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*); 721ebd74acf9977daa42133507e970dab88e08f0efKenny Root 731378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi// Equivalent to android.os.FileUtils.isFilenameSafe 7466269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic bool 7566269ea6f68f2f25888ce1080c94ac782742fafcKenny RootisFilenameSafe(const char* filename) 7666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 7766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root off_t offset = 0; 7866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root for (;;) { 7966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root switch (*(filename + offset)) { 8066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case 0: 8166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Null. 8266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // If we've reached the end, all the other characters are good. 8366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 8466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 8566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case 'A' ... 'Z': 8666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case 'a' ... 'z': 8766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '0' ... '9': 8866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '+': 8966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case ',': 9066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '-': 9166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '.': 9266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '/': 9366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '=': 9466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '_': 9566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root offset++; 9666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root break; 9766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 9866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root default: 9966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // We found something that is not good. 10066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return false; 10166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 10266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 10366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Should not reach here. 10466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 10566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 10666269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic bool 10766269ea6f68f2f25888ce1080c94ac782742fafcKenny RootisFileDifferent(const char* filePath, size_t fileSize, time_t modifiedTime, 10866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root long zipCrc, struct stat64* st) 10966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 11066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (lstat64(filePath, st) < 0) { 11166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // File is not found or cannot be read. 11271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Couldn't stat %s, copying: %s\n", filePath, strerror(errno)); 11366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 11466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 11566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 11666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!S_ISREG(st->st_mode)) { 11766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 11866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 11966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 12066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (st->st_size != fileSize) { 12166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 12266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 12366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 12466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // For some reason, bionic doesn't define st_mtime as time_t 12566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (time_t(st->st_mtime) != modifiedTime) { 12671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("mod time doesn't match: %ld vs. %ld\n", st->st_mtime, modifiedTime); 12766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 12866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 12966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 13066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root int fd = TEMP_FAILURE_RETRY(open(filePath, O_RDONLY)); 13166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (fd < 0) { 13271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Couldn't open file %s: %s", filePath, strerror(errno)); 13366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 13466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 13566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 13666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root long crc = crc32(0L, Z_NULL, 0); 13766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unsigned char crcBuffer[16384]; 13866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ssize_t numBytes; 13966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root while ((numBytes = TEMP_FAILURE_RETRY(read(fd, crcBuffer, sizeof(crcBuffer)))) > 0) { 14066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root crc = crc32(crc, crcBuffer, numBytes); 14166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 14266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root close(fd); 14366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 14471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("%s: crc = %lx, zipCrc = %lx\n", filePath, crc, zipCrc); 14566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 14666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (crc != zipCrc) { 14766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 14866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 14966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 15066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return false; 15166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 15266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 1531ebd74acf9977daa42133507e970dab88e08f0efKenny Rootstatic install_status_t 154afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan KamathsumFiles(JNIEnv*, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char*) 15566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 15666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root size_t* total = (size_t*) arg; 15766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root size_t uncompLen; 15866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 15966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, NULL, NULL)) { 1601ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INVALID_APK; 16166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 16266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 16366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *total += uncompLen; 1641ebd74acf9977daa42133507e970dab88e08f0efKenny Root 1651ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_SUCCEEDED; 16666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 16766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 16866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root/* 16966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * Copy the native library if needed. 17066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * 17166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * This function assumes the library and path names passed in are considered safe. 17266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root */ 1731ebd74acf9977daa42133507e970dab88e08f0efKenny Rootstatic install_status_t 17466269ea6f68f2f25888ce1080c94ac782742fafcKenny RootcopyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName) 17566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 17666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root jstring* javaNativeLibPath = (jstring*) arg; 17766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ScopedUtfChars nativeLibPath(env, *javaNativeLibPath); 17866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 17966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root size_t uncompLen; 18066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root long when; 18166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root long crc; 18266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root time_t modTime; 18366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 18466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, &when, &crc)) { 1855baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't read zip entry info\n"); 1861ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INVALID_APK; 18766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } else { 18866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root struct tm t; 189afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ZipUtils::zipTimeToTimespec(when, &t); 19066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root modTime = mktime(&t); 19166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 19266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 19366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Build local file path 19466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root const size_t fileNameLen = strlen(fileName); 19566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root char localFileName[nativeLibPath.size() + fileNameLen + 2]; 19666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 19766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localFileName, nativeLibPath.c_str(), sizeof(localFileName)) != nativeLibPath.size()) { 1985baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't allocate local file name for library"); 1991ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 20066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 20166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 20266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *(localFileName + nativeLibPath.size()) = '/'; 20366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 20466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localFileName + nativeLibPath.size() + 1, fileName, sizeof(localFileName) 20566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root - nativeLibPath.size() - 1) != fileNameLen) { 2065baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't allocate local file name for library"); 2071ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 20866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 20966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 21066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Only copy out the native file if it's different. 211ad076286c3140ce9f1f25b8503bdfd2047a968a7Elliott Hughes struct stat64 st; 21266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!isFileDifferent(localFileName, uncompLen, modTime, crc, &st)) { 2131ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_SUCCEEDED; 21466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 21566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 21666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root char localTmpFileName[nativeLibPath.size() + TMP_FILE_PATTERN_LEN + 2]; 21766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localTmpFileName, nativeLibPath.c_str(), sizeof(localTmpFileName)) 21866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root != nativeLibPath.size()) { 2195baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't allocate local file name for library"); 2201ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 22166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 22266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 22366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *(localFileName + nativeLibPath.size()) = '/'; 22466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 22566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localTmpFileName + nativeLibPath.size(), TMP_FILE_PATTERN, 22666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root TMP_FILE_PATTERN_LEN - nativeLibPath.size()) != TMP_FILE_PATTERN_LEN) { 2276215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't allocate temporary file name for library"); 2281ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 22966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 23066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 23166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root int fd = mkstemp(localTmpFileName); 23266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (fd < 0) { 2336215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't open temporary file name: %s: %s\n", localTmpFileName, strerror(errno)); 2341ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 23566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 23666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 23766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!zipFile->uncompressEntry(zipEntry, fd)) { 2386215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Failed uncompressing %s to %s\n", fileName, localTmpFileName); 23966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root close(fd); 24066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2411ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 24266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 24366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 24466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root close(fd); 24566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 24666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Set the modification time for this file to the ZIP's mod time. 24766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root struct timeval times[2]; 24866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root times[0].tv_sec = st.st_atime; 24966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root times[1].tv_sec = modTime; 25066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root times[0].tv_usec = times[1].tv_usec = 0; 25166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (utimes(localTmpFileName, times) < 0) { 2526215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't change modification time on %s: %s\n", localTmpFileName, strerror(errno)); 25366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2541ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 25566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 25666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 25766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Set the mode to 755 25866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root static const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 25966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (chmod(localTmpFileName, mode) < 0) { 2606215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't change permissions on %s: %s\n", localTmpFileName, strerror(errno)); 26166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2621ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 26366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 26466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 26566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Finally, rename it to the final name. 26666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (rename(localTmpFileName, localFileName) < 0) { 2676215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't rename %s to %s: %s\n", localTmpFileName, localFileName, strerror(errno)); 26866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2691ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 27066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 27166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 27271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Successfully moved %s to %s\n", localTmpFileName, localFileName); 2731ebd74acf9977daa42133507e970dab88e08f0efKenny Root 2741ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_SUCCEEDED; 27566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 27666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 2771378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi/* 2781378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * An iterator over all shared libraries in a zip file. An entry is 2791378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * considered to be a shared library if all of the conditions below are 2801378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * satisfied : 2811378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * 2821378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * - The entry is under the lib/ directory. 2831378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * - The entry name ends with ".so" and the entry name starts with "lib", 2841378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * an exception is made for entries whose name is "gdbserver". 2851378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * - The entry filename is "safe" (as determined by isFilenameSafe). 2861378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi * 2871378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi */ 2881378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghiclass NativeLibrariesIterator { 2891378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghiprivate: 2901378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi NativeLibrariesIterator(ZipFileRO* zipFile, void* cookie) 2911378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi : mZipFile(zipFile), mCookie(cookie), mLastSlash(NULL) { 2921378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi fileName[0] = '\0'; 29366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 29466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 2951378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghipublic: 2961378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi static NativeLibrariesIterator* create(ZipFileRO* zipFile) { 2971378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi void* cookie = NULL; 2981378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (!zipFile->startIteration(&cookie)) { 2991378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return NULL; 3001378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 30166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3021378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return new NativeLibrariesIterator(zipFile, cookie); 303afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath } 30466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3051378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipEntryRO next() { 3061378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipEntryRO next = NULL; 3071378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi while ((next = mZipFile->nextEntry(mCookie)) != NULL) { 3081378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Make sure this entry has a filename. 3091378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (mZipFile->getEntryFileName(next, fileName, sizeof(fileName))) { 3101378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi continue; 3111378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 31266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3131378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Make sure we're in the lib directory of the ZIP. 3141378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) { 3151378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi continue; 3161378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 31766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3181378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Make sure the filename is at least to the minimum library name size. 3191378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const size_t fileNameLen = strlen(fileName); 3201378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN; 3211378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (fileNameLen < minLength) { 3221378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi continue; 3231378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 32466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3251378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* lastSlash = strrchr(fileName, '/'); 3261378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName); 32766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3281378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Exception: If we find the gdbserver binary, return it. 3291378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (!strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) { 330195b23ef712c51dc8d2f3a1f1943a27054dc4e74Nick Kralevich mLastSlash = lastSlash; 3311378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi break; 3321378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 33366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3341378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Make sure the filename starts with lib and ends with ".so". 3351378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN) 3361378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi || strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)) { 33710410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola continue; 33810410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola } 3391378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3401378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Make sure the filename is safe. 3411378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (!isFilenameSafe(lastSlash + 1)) { 3421378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi continue; 3431378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3441378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3451378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi mLastSlash = lastSlash; 3461378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi break; 34766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 34866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3491378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return next; 3501378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3511378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3521378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi inline const char* currentEntry() const { 3531378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return fileName; 3541378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3551378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3561378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi inline const char* lastSlash() const { 3571378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return mLastSlash; 3581378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3591378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3601378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi virtual ~NativeLibrariesIterator() { 3611378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi mZipFile->endIteration(mCookie); 3621378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3631378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghiprivate: 3641378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3651378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi char fileName[PATH_MAX]; 3661378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipFileRO* const mZipFile; 3671378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi void* mCookie; 3681378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* mLastSlash; 3691378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi}; 3701ebd74acf9977daa42133507e970dab88e08f0efKenny Root 3711378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghistatic install_status_t 3721378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin ZaghiiterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi, 3731378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi iterFunc callFunc, void* callArg) { 3741378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); 3751378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (zipFile == NULL) { 3761378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return INSTALL_FAILED_INVALID_APK; 3771378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3781378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3791378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile)); 3801378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (it.get() == NULL) { 3811378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return INSTALL_FAILED_INVALID_APK; 3821378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3831378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3841378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const ScopedUtfChars cpuAbi(env, javaCpuAbi); 3851378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (cpuAbi.c_str() == NULL) { 3861378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // This would've thrown, so this return code isn't observable by 3871378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Java. 3881378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return INSTALL_FAILED_INVALID_APK; 3891378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 3901378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipEntryRO entry = NULL; 3911378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi while ((entry = it->next()) != NULL) { 3921378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* fileName = it->currentEntry(); 3931378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* lastSlash = it->lastSlash(); 3941378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3951378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Check to make sure the CPU ABI of this file is one we support. 3961378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* cpuAbiOffset = fileName + APK_LIB_LEN; 3971378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset; 3981378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 3991378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (cpuAbi.size() == cpuAbiRegionSize && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) { 4001378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi install_status_t ret = callFunc(env, callArg, zipFile, entry, lastSlash + 1); 4011ebd74acf9977daa42133507e970dab88e08f0efKenny Root 4021ebd74acf9977daa42133507e970dab88e08f0efKenny Root if (ret != INSTALL_SUCCEEDED) { 40371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Failure for entry %s", lastSlash + 1); 4041ebd74acf9977daa42133507e970dab88e08f0efKenny Root return ret; 4051ebd74acf9977daa42133507e970dab88e08f0efKenny Root } 40666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 40766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 40866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 40966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return INSTALL_SUCCEEDED; 41066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 41166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4121378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4131378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghistatic int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supportedAbisArray) { 4141378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const int numAbis = env->GetArrayLength(supportedAbisArray); 4151378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi Vector<ScopedUtfChars*> supportedAbis; 4161378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4171378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi for (int i = 0; i < numAbis; ++i) { 4181378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi supportedAbis.add(new ScopedUtfChars(env, 4191378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi (jstring) env->GetObjectArrayElement(supportedAbisArray, i))); 4201378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4211378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4221378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); 4231378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (zipFile == NULL) { 4241378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return INSTALL_FAILED_INVALID_APK; 4251378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4261378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4271378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile)); 4281378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (it.get() == NULL) { 4291378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return INSTALL_FAILED_INVALID_APK; 4301378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4311378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4321378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipEntryRO entry = NULL; 4331378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi char fileName[PATH_MAX]; 4341378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi int status = NO_NATIVE_LIBRARIES; 4351378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi while ((entry = it->next()) != NULL) { 4361378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // We're currently in the lib/ directory of the APK, so it does have some native 4371378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // code. We should return INSTALL_FAILED_NO_MATCHING_ABIS if none of the 4381378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // libraries match. 4391378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (status == NO_NATIVE_LIBRARIES) { 4401378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi status = INSTALL_FAILED_NO_MATCHING_ABIS; 4411378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4421378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4431378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* fileName = it->currentEntry(); 4441378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* lastSlash = it->lastSlash(); 4451378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4461378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // Check to see if this CPU ABI matches what we are looking for. 4471378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const char* abiOffset = fileName + APK_LIB_LEN; 4481378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const size_t abiSize = lastSlash - abiOffset; 4491378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi for (int i = 0; i < numAbis; i++) { 4501378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi const ScopedUtfChars* abi = supportedAbis[i]; 4511378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (abi->size() == abiSize && !strncmp(abiOffset, abi->c_str(), abiSize)) { 4521378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi // The entry that comes in first (i.e. with a lower index) has the higher priority. 4531378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi if (((i < status) && (status >= 0)) || (status < 0) ) { 4541378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi status = i; 4551378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4561378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4571378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4581378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4591378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4601378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi for (int i = 0; i < numAbis; ++i) { 4611378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi delete supportedAbis[i]; 4621378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi } 4631378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 4641378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return status; 4651378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi} 4661378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 46766269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic jint 46866269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootcom_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz, 4691378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi) 47066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 4711378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi, 47266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root copyFileIfChanged, &javaNativeLibPath); 47366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 47466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 47566269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic jlong 47666269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootcom_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz, 4771378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi jlong apkHandle, jstring javaCpuAbi) 47866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 47966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root size_t totalSize = 0; 48066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4811378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi iterateOverNativeFiles(env, apkHandle, javaCpuAbi, sumFiles, &totalSize); 48266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 48366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return totalSize; 48466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 48566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4861378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghistatic jint 4871378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghicom_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz, 4881378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi jlong apkHandle, jobjectArray javaCpuAbisToSearch) 4891378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi{ 4901378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch); 4911378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi} 4921378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 493d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamathenum bitcode_scan_result_t { 494d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath APK_SCAN_ERROR = -1, 495d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath NO_BITCODE_PRESENT = 0, 496d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath BITCODE_PRESENT = 1, 497d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath}; 498d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 499d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamathstatic jint 500d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamathcom_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode(JNIEnv *env, jclass clazz, 501d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath jlong apkHandle) { 502d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); 503d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath void* cookie = NULL; 504d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath if (!zipFile->startIteration(&cookie)) { 505d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath return APK_SCAN_ERROR; 506d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 507d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 508d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath char fileName[PATH_MAX]; 509d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath ZipEntryRO next = NULL; 510d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath while ((next = zipFile->nextEntry(cookie)) != NULL) { 511d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath if (zipFile->getEntryFileName(next, fileName, sizeof(fileName))) { 512d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath continue; 513d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 514d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 515d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath const size_t fileNameLen = strlen(fileName); 516d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath const char* lastSlash = strrchr(fileName, '/'); 517d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath const char* baseName = (lastSlash == NULL) ? fileName : fileName + 1; 518d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath if (!strncmp(fileName + fileNameLen - RS_BITCODE_SUFFIX_LEN, RS_BITCODE_SUFFIX, 519d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath RS_BITCODE_SUFFIX_LEN) && isFilenameSafe(baseName)) { 520d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath zipFile->endIteration(cookie); 521d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath return BITCODE_PRESENT; 522d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 523d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath } 524d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 525d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath zipFile->endIteration(cookie); 526d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath return NO_BITCODE_PRESENT; 527d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath} 528d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath 5291378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghistatic jlong 5301378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghicom_android_internal_content_NativeLibraryHelper_openApk(JNIEnv *env, jclass, jstring apkPath) 5311378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi{ 5321378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ScopedUtfChars filePath(env, apkPath); 5331378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi ZipFileRO* zipFile = ZipFileRO::open(filePath.c_str()); 5341378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 5351378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi return reinterpret_cast<jlong>(zipFile); 5361378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi} 5371378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 5381378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghistatic void 5391378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghicom_android_internal_content_NativeLibraryHelper_close(JNIEnv *env, jclass, jlong apkHandle) 5401378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi{ 5411378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi delete reinterpret_cast<ZipFileRO*>(apkHandle); 5421378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi} 5431378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi 54466269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic JNINativeMethod gMethods[] = { 5451378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi {"nativeOpenApk", 5461378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi "(Ljava/lang/String;)J", 5471378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi (void *)com_android_internal_content_NativeLibraryHelper_openApk}, 5481378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi {"nativeClose", 5491378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi "(J)V", 5501378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi (void *)com_android_internal_content_NativeLibraryHelper_close}, 55166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root {"nativeCopyNativeBinaries", 5521378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi "(JLjava/lang/String;Ljava/lang/String;)I", 55366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root (void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries}, 55466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root {"nativeSumNativeBinaries", 5551378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi "(JLjava/lang/String;)J", 55666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries}, 5571378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi {"nativeFindSupportedAbi", 5581378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi "(J[Ljava/lang/String;)I", 5591378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi}, 560d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath {"hasRenderscriptBitcode", "(J)I", 561d47e38b6342fea93b007319431634a4bcfee452cNarayan Kamath (void *)com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode}, 56266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}; 56366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 56466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 56566269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootint register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env) 56666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 56766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return AndroidRuntime::registerNativeMethods(env, 56866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root "com/android/internal/content/NativeLibraryHelper", gMethods, NELEM(gMethods)); 56966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 57066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 57166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}; 572