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