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