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 <utils/Log.h> 23a982dc05d7ca919c07f50e446549ef9dceadf6bdColin Cross#include <utils/ZipFileRO.h> 2466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <ScopedUtfChars.h> 2566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 2666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <zlib.h> 2766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 2866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <fcntl.h> 2966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <stdlib.h> 3066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <string.h> 3166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <time.h> 3266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <unistd.h> 3366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <sys/stat.h> 3466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <sys/types.h> 3566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 3766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define APK_LIB "lib/" 3866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define APK_LIB_LEN (sizeof(APK_LIB) - 1) 3966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_PREFIX "/lib" 4166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_PREFIX_LEN (sizeof(LIB_PREFIX) - 1) 4266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_SUFFIX ".so" 4466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_SUFFIX_LEN (sizeof(LIB_SUFFIX) - 1) 4566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define GDBSERVER "gdbserver" 4766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define GDBSERVER_LEN (sizeof(GDBSERVER) - 1) 4866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 4966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define TMP_FILE_PATTERN "/tmp.XXXXXX" 5066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define TMP_FILE_PATTERN_LEN (sizeof(TMP_FILE_PATTERN) - 1) 5166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 5266269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootnamespace android { 5366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 5466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root// These match PackageManager.java install codes 5566269ea6f68f2f25888ce1080c94ac782742fafcKenny Roottypedef enum { 561ebd74acf9977daa42133507e970dab88e08f0efKenny Root INSTALL_SUCCEEDED = 1, 5766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root INSTALL_FAILED_INVALID_APK = -2, 5866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root INSTALL_FAILED_INSUFFICIENT_STORAGE = -4, 591ebd74acf9977daa42133507e970dab88e08f0efKenny Root INSTALL_FAILED_CONTAINER_ERROR = -18, 601ebd74acf9977daa42133507e970dab88e08f0efKenny Root INSTALL_FAILED_INTERNAL_ERROR = -110, 6166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} install_status_t; 6266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 631ebd74acf9977daa42133507e970dab88e08f0efKenny Roottypedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*); 641ebd74acf9977daa42133507e970dab88e08f0efKenny Root 6566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root// Equivalent to isFilenameSafe 6666269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic bool 6766269ea6f68f2f25888ce1080c94ac782742fafcKenny RootisFilenameSafe(const char* filename) 6866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 6966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root off_t offset = 0; 7066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root for (;;) { 7166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root switch (*(filename + offset)) { 7266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case 0: 7366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Null. 7466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // If we've reached the end, all the other characters are good. 7566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 7666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 7766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case 'A' ... 'Z': 7866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case 'a' ... 'z': 7966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '0' ... '9': 8066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '+': 8166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case ',': 8266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '-': 8366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '.': 8466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '/': 8566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '=': 8666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root case '_': 8766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root offset++; 8866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root break; 8966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 9066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root default: 9166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // We found something that is not good. 9266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return false; 9366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 9466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 9566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Should not reach here. 9666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 9766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 9866269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic bool 9966269ea6f68f2f25888ce1080c94ac782742fafcKenny RootisFileDifferent(const char* filePath, size_t fileSize, time_t modifiedTime, 10066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root long zipCrc, struct stat64* st) 10166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 10266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (lstat64(filePath, st) < 0) { 10366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // File is not found or cannot be read. 10471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Couldn't stat %s, copying: %s\n", filePath, strerror(errno)); 10566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 10666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 10766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 10866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!S_ISREG(st->st_mode)) { 10966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 11066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 11166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 11266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (st->st_size != fileSize) { 11366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 11466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 11566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 11666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // For some reason, bionic doesn't define st_mtime as time_t 11766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (time_t(st->st_mtime) != modifiedTime) { 11871f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("mod time doesn't match: %ld vs. %ld\n", st->st_mtime, modifiedTime); 11966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 12066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 12166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 12266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root int fd = TEMP_FAILURE_RETRY(open(filePath, O_RDONLY)); 12366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (fd < 0) { 12471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Couldn't open file %s: %s", filePath, strerror(errno)); 12566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 12666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 12766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 12866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root long crc = crc32(0L, Z_NULL, 0); 12966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unsigned char crcBuffer[16384]; 13066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ssize_t numBytes; 13166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root while ((numBytes = TEMP_FAILURE_RETRY(read(fd, crcBuffer, sizeof(crcBuffer)))) > 0) { 13266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root crc = crc32(crc, crcBuffer, numBytes); 13366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 13466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root close(fd); 13566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 13671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("%s: crc = %lx, zipCrc = %lx\n", filePath, crc, zipCrc); 13766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 13866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (crc != zipCrc) { 13966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return true; 14066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 14166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 14266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return false; 14366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 14466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 1451ebd74acf9977daa42133507e970dab88e08f0efKenny Rootstatic install_status_t 14666269ea6f68f2f25888ce1080c94ac782742fafcKenny RootsumFiles(JNIEnv* env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName) 14766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 14866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root size_t* total = (size_t*) arg; 14966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root size_t uncompLen; 15066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 15166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, NULL, NULL)) { 1521ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INVALID_APK; 15366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 15466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 15566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *total += uncompLen; 1561ebd74acf9977daa42133507e970dab88e08f0efKenny Root 1571ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_SUCCEEDED; 15866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 15966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 16066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root/* 16166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * Copy the native library if needed. 16266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * 16366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * This function assumes the library and path names passed in are considered safe. 16466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root */ 1651ebd74acf9977daa42133507e970dab88e08f0efKenny Rootstatic install_status_t 16666269ea6f68f2f25888ce1080c94ac782742fafcKenny RootcopyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName) 16766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 16866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root jstring* javaNativeLibPath = (jstring*) arg; 16966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ScopedUtfChars nativeLibPath(env, *javaNativeLibPath); 17066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 17166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root size_t uncompLen; 17266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root long when; 17366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root long crc; 17466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root time_t modTime; 17566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 17666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, &when, &crc)) { 1775baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't read zip entry info\n"); 1781ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INVALID_APK; 17966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } else { 18066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root struct tm t; 18166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ZipFileRO::zipTimeToTimespec(when, &t); 18266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root modTime = mktime(&t); 18366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 18466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 18566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Build local file path 18666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root const size_t fileNameLen = strlen(fileName); 18766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root char localFileName[nativeLibPath.size() + fileNameLen + 2]; 18866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 18966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localFileName, nativeLibPath.c_str(), sizeof(localFileName)) != nativeLibPath.size()) { 1905baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't allocate local file name for library"); 1911ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 19266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 19366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 19466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *(localFileName + nativeLibPath.size()) = '/'; 19566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 19666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localFileName + nativeLibPath.size() + 1, fileName, sizeof(localFileName) 19766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root - nativeLibPath.size() - 1) != fileNameLen) { 1985baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't allocate local file name for library"); 1991ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 20066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 20166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 20266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Only copy out the native file if it's different. 20366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root struct stat st; 20466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!isFileDifferent(localFileName, uncompLen, modTime, crc, &st)) { 2051ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_SUCCEEDED; 20666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 20766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 20866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root char localTmpFileName[nativeLibPath.size() + TMP_FILE_PATTERN_LEN + 2]; 20966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localTmpFileName, nativeLibPath.c_str(), sizeof(localTmpFileName)) 21066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root != nativeLibPath.size()) { 2115baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("Couldn't allocate local file name for library"); 2121ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 21366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 21466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 21566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *(localFileName + nativeLibPath.size()) = '/'; 21666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 21766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strlcpy(localTmpFileName + nativeLibPath.size(), TMP_FILE_PATTERN, 21866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root TMP_FILE_PATTERN_LEN - nativeLibPath.size()) != TMP_FILE_PATTERN_LEN) { 2196215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't allocate temporary file name for library"); 2201ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_INTERNAL_ERROR; 22166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 22266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 22366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root int fd = mkstemp(localTmpFileName); 22466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (fd < 0) { 2256215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't open temporary file name: %s: %s\n", localTmpFileName, strerror(errno)); 2261ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 22766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 22866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 22966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (!zipFile->uncompressEntry(zipEntry, fd)) { 2306215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Failed uncompressing %s to %s\n", fileName, localTmpFileName); 23166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root close(fd); 23266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2331ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 23466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 23566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 23666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root close(fd); 23766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 23866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Set the modification time for this file to the ZIP's mod time. 23966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root struct timeval times[2]; 24066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root times[0].tv_sec = st.st_atime; 24166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root times[1].tv_sec = modTime; 24266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root times[0].tv_usec = times[1].tv_usec = 0; 24366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (utimes(localTmpFileName, times) < 0) { 2446215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't change modification time on %s: %s\n", localTmpFileName, strerror(errno)); 24566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2461ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 24766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 24866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 24966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Set the mode to 755 25066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root static const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 25166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (chmod(localTmpFileName, mode) < 0) { 2526215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't change permissions on %s: %s\n", localTmpFileName, strerror(errno)); 25366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2541ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 25566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 25666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 25766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Finally, rename it to the final name. 25866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (rename(localTmpFileName, localFileName) < 0) { 2596215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't rename %s to %s: %s\n", localTmpFileName, localFileName, strerror(errno)); 26066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root unlink(localTmpFileName); 2611ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_FAILED_CONTAINER_ERROR; 26266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 26366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 26471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Successfully moved %s to %s\n", localTmpFileName, localFileName); 2651ebd74acf9977daa42133507e970dab88e08f0efKenny Root 2661ebd74acf9977daa42133507e970dab88e08f0efKenny Root return INSTALL_SUCCEEDED; 26766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 26866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 26966269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic install_status_t 27066269ea6f68f2f25888ce1080c94ac782742fafcKenny RootiterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2, 27166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root iterFunc callFunc, void* callArg) { 27266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ScopedUtfChars filePath(env, javaFilePath); 27366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ScopedUtfChars cpuAbi(env, javaCpuAbi); 27466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ScopedUtfChars cpuAbi2(env, javaCpuAbi2); 27566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 27666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root ZipFileRO zipFile; 27766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 27866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (zipFile.open(filePath.c_str()) != NO_ERROR) { 2796215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block ALOGI("Couldn't open APK %s\n", filePath.c_str()); 28066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return INSTALL_FAILED_INVALID_APK; 28166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 28266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 28366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root const int N = zipFile.getNumEntries(); 28466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 28566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root char fileName[PATH_MAX]; 28610410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola bool hasPrimaryAbi = false; 28766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 28866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root for (int i = 0; i < N; i++) { 28966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root const ZipEntryRO entry = zipFile.findEntryByIndex(i); 29066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (entry == NULL) { 29166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root continue; 29266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 29366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 29466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Make sure this entry has a filename. 29566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (zipFile.getEntryFileName(entry, fileName, sizeof(fileName))) { 29666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root continue; 29766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 29866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 29966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Make sure we're in the lib directory of the ZIP. 30066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) { 30166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root continue; 30266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 30366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 30466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Make sure the filename is at least to the minimum library name size. 30566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root const size_t fileNameLen = strlen(fileName); 30666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN; 30766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (fileNameLen < minLength) { 30866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root continue; 30966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 31066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 31166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root const char* lastSlash = strrchr(fileName, '/'); 312ec193dec4d9ca2cfc8295c4becfe950a906a15edSteve Block ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName); 31366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 31466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // Check to make sure the CPU ABI of this file is one we support. 31566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root const char* cpuAbiOffset = fileName + APK_LIB_LEN; 31666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset; 31766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 31871f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Comparing ABIs %s and %s versus %s\n", cpuAbi.c_str(), cpuAbi2.c_str(), cpuAbiOffset); 31966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root if (cpuAbi.size() == cpuAbiRegionSize 32066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root && *(cpuAbiOffset + cpuAbi.size()) == '/' 32166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) { 322fcbbaf1d837e96e77d0ec45a050e8a41060ae7f3Kenny Root ALOGV("Using primary ABI %s\n", cpuAbi.c_str()); 32310410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola hasPrimaryAbi = true; 32466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } else if (cpuAbi2.size() == cpuAbiRegionSize 32566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root && *(cpuAbiOffset + cpuAbi2.size()) == '/' 32666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root && !strncmp(cpuAbiOffset, cpuAbi2.c_str(), cpuAbiRegionSize)) { 32710410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola 32810410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola /* 32910410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola * If this library matches both the primary and secondary ABIs, 33010410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola * only use the primary ABI. 33110410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola */ 33210410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola if (hasPrimaryAbi) { 333fcbbaf1d837e96e77d0ec45a050e8a41060ae7f3Kenny Root ALOGV("Already saw primary ABI, skipping secondary ABI %s\n", cpuAbi2.c_str()); 33410410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola continue; 33510410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola } else { 336fcbbaf1d837e96e77d0ec45a050e8a41060ae7f3Kenny Root ALOGV("Using secondary ABI %s\n", cpuAbi2.c_str()); 33710410fc85248ea77c2c1fbbb666c3fe4fcfef1b6Anthony Mazzola } 33866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } else { 33971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("abi didn't match anything: %s (end at %zd)\n", cpuAbiOffset, cpuAbiRegionSize); 34066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root continue; 34166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 34266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 34366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root // If this is a .so file, check to see if we need to copy it. 3441ebd74acf9977daa42133507e970dab88e08f0efKenny Root if ((!strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN) 3451ebd74acf9977daa42133507e970dab88e08f0efKenny Root && !strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN) 3461ebd74acf9977daa42133507e970dab88e08f0efKenny Root && isFilenameSafe(lastSlash + 1)) 3471ebd74acf9977daa42133507e970dab88e08f0efKenny Root || !strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) { 3481ebd74acf9977daa42133507e970dab88e08f0efKenny Root 3491ebd74acf9977daa42133507e970dab88e08f0efKenny Root install_status_t ret = callFunc(env, callArg, &zipFile, entry, lastSlash + 1); 3501ebd74acf9977daa42133507e970dab88e08f0efKenny Root 3511ebd74acf9977daa42133507e970dab88e08f0efKenny Root if (ret != INSTALL_SUCCEEDED) { 35271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Failure for entry %s", lastSlash + 1); 3531ebd74acf9977daa42133507e970dab88e08f0efKenny Root return ret; 3541ebd74acf9977daa42133507e970dab88e08f0efKenny Root } 35566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 35666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root } 35766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 35866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return INSTALL_SUCCEEDED; 35966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 36066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 36166269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic jint 36266269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootcom_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz, 36366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root jstring javaFilePath, jstring javaNativeLibPath, jstring javaCpuAbi, jstring javaCpuAbi2) 36466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 3651ebd74acf9977daa42133507e970dab88e08f0efKenny Root return (jint) iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2, 36666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root copyFileIfChanged, &javaNativeLibPath); 36766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 36866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 36966269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic jlong 37066269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootcom_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz, 37166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2) 37266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 37366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root size_t totalSize = 0; 37466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 37566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2, sumFiles, &totalSize); 37666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 37766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return totalSize; 37866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 37966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 38066269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic JNINativeMethod gMethods[] = { 38166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root {"nativeCopyNativeBinaries", 38266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", 38366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root (void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries}, 38466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root {"nativeSumNativeBinaries", 38566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J", 38666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries}, 38766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}; 38866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 38966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 39066269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootint register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env) 39166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{ 39266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root return AndroidRuntime::registerNativeMethods(env, 39366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root "com/android/internal/content/NativeLibraryHelper", gMethods, NELEM(gMethods)); 39466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} 39566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root 39666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}; 397