com_android_internal_content_NativeLibraryHelper.cpp revision 5baa3a62a97544669fba6d65a11c07f252e654dd
166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root/*
266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * Copyright (C) 2011 The Android Open Source Project
366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *
466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * you may not use this file except in compliance with the License.
666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * You may obtain a copy of the License at
766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *
866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *
1066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * Unless required by applicable law or agreed to in writing, software
1166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
1266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * See the License for the specific language governing permissions and
1466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * limitations under the License.
1566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root */
1666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
1766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LOG_TAG "NativeLibraryHelper"
1866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root//#define LOG_NDEBUG 0
1966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
2066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <android_runtime/AndroidRuntime.h>
2166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
2266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <utils/Log.h>
2366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <ScopedUtfChars.h>
2466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <utils/ZipFileRO.h>
2566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
2666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <zlib.h>
2766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
2866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <fcntl.h>
2966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <stdlib.h>
3066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <string.h>
3166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <time.h>
3266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <unistd.h>
3366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <sys/stat.h>
3466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#include <sys/types.h>
3566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
3666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
3766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define APK_LIB "lib/"
3866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define APK_LIB_LEN (sizeof(APK_LIB) - 1)
3966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
4066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_PREFIX "/lib"
4166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_PREFIX_LEN (sizeof(LIB_PREFIX) - 1)
4266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
4366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_SUFFIX ".so"
4466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define LIB_SUFFIX_LEN (sizeof(LIB_SUFFIX) - 1)
4566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
4666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define GDBSERVER "gdbserver"
4766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define GDBSERVER_LEN (sizeof(GDBSERVER) - 1)
4866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
4966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define TMP_FILE_PATTERN "/tmp.XXXXXX"
5066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root#define TMP_FILE_PATTERN_LEN (sizeof(TMP_FILE_PATTERN) - 1)
5166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
5266269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootnamespace android {
5366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
5466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root// These match PackageManager.java install codes
5566269ea6f68f2f25888ce1080c94ac782742fafcKenny Roottypedef enum {
561ebd74acf9977daa42133507e970dab88e08f0efKenny Root    INSTALL_SUCCEEDED = 1,
5766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    INSTALL_FAILED_INVALID_APK = -2,
5866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    INSTALL_FAILED_INSUFFICIENT_STORAGE = -4,
591ebd74acf9977daa42133507e970dab88e08f0efKenny Root    INSTALL_FAILED_CONTAINER_ERROR = -18,
601ebd74acf9977daa42133507e970dab88e08f0efKenny Root    INSTALL_FAILED_INTERNAL_ERROR = -110,
6166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root} install_status_t;
6266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
631ebd74acf9977daa42133507e970dab88e08f0efKenny Roottypedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*);
641ebd74acf9977daa42133507e970dab88e08f0efKenny Root
6566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root// Equivalent to isFilenameSafe
6666269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic bool
6766269ea6f68f2f25888ce1080c94ac782742fafcKenny RootisFilenameSafe(const char* filename)
6866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{
6966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    off_t offset = 0;
7066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    for (;;) {
7166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        switch (*(filename + offset)) {
7266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case 0:
7366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            // Null.
7466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            // If we've reached the end, all the other characters are good.
7566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            return true;
7666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
7766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case 'A' ... 'Z':
7866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case 'a' ... 'z':
7966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case '0' ... '9':
8066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case '+':
8166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case ',':
8266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case '-':
8366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case '.':
8466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case '/':
8566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case '=':
8666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        case '_':
8766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            offset++;
8866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            break;
8966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
9066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        default:
9166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            // We found something that is not good.
9266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            return false;
9366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        }
9466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
9566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    // Should not reach here.
9666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}
9766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
9866269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic bool
9966269ea6f68f2f25888ce1080c94ac782742fafcKenny RootisFileDifferent(const char* filePath, size_t fileSize, time_t modifiedTime,
10066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        long zipCrc, struct stat64* st)
10166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{
10266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (lstat64(filePath, st) < 0) {
10366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        // File is not found or cannot be read.
10471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Couldn't stat %s, copying: %s\n", filePath, strerror(errno));
10566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        return true;
10666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
10766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
10866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (!S_ISREG(st->st_mode)) {
10966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        return true;
11066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
11166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
11266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (st->st_size != fileSize) {
11366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        return true;
11466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
11566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
11666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    // For some reason, bionic doesn't define st_mtime as time_t
11766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (time_t(st->st_mtime) != modifiedTime) {
11871f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("mod time doesn't match: %ld vs. %ld\n", st->st_mtime, modifiedTime);
11966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        return true;
12066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
12166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
12266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    int fd = TEMP_FAILURE_RETRY(open(filePath, O_RDONLY));
12366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (fd < 0) {
12471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Couldn't open file %s: %s", filePath, strerror(errno));
12566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        return true;
12666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
12766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
12866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    long crc = crc32(0L, Z_NULL, 0);
12966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    unsigned char crcBuffer[16384];
13066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    ssize_t numBytes;
13166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    while ((numBytes = TEMP_FAILURE_RETRY(read(fd, crcBuffer, sizeof(crcBuffer)))) > 0) {
13266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        crc = crc32(crc, crcBuffer, numBytes);
13366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
13466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    close(fd);
13566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
13671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("%s: crc = %lx, zipCrc = %lx\n", filePath, crc, zipCrc);
13766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
13866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (crc != zipCrc) {
13966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        return true;
14066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
14166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
14266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    return false;
14366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}
14466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
1451ebd74acf9977daa42133507e970dab88e08f0efKenny Rootstatic install_status_t
14666269ea6f68f2f25888ce1080c94ac782742fafcKenny RootsumFiles(JNIEnv* env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName)
14766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{
14866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    size_t* total = (size_t*) arg;
14966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    size_t uncompLen;
15066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
15166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, NULL, NULL)) {
1521ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_INVALID_APK;
15366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
15466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
15566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    *total += uncompLen;
1561ebd74acf9977daa42133507e970dab88e08f0efKenny Root
1571ebd74acf9977daa42133507e970dab88e08f0efKenny Root    return INSTALL_SUCCEEDED;
15866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}
15966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
16066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root/*
16166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * Copy the native library if needed.
16266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root *
16366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root * This function assumes the library and path names passed in are considered safe.
16466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root */
1651ebd74acf9977daa42133507e970dab88e08f0efKenny Rootstatic install_status_t
16666269ea6f68f2f25888ce1080c94ac782742fafcKenny RootcopyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName)
16766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{
16866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    jstring* javaNativeLibPath = (jstring*) arg;
16966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    ScopedUtfChars nativeLibPath(env, *javaNativeLibPath);
17066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
17166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    size_t uncompLen;
17266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    long when;
17366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    long crc;
17466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    time_t modTime;
17566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
17666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, &when, &crc)) {
1775baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("Couldn't read zip entry info\n");
1781ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_INVALID_APK;
17966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    } else {
18066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        struct tm t;
18166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        ZipFileRO::zipTimeToTimespec(when, &t);
18266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        modTime = mktime(&t);
18366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
18466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
18566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    // Build local file path
18666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    const size_t fileNameLen = strlen(fileName);
18766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    char localFileName[nativeLibPath.size() + fileNameLen + 2];
18866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
18966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (strlcpy(localFileName, nativeLibPath.c_str(), sizeof(localFileName)) != nativeLibPath.size()) {
1905baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("Couldn't allocate local file name for library");
1911ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_INTERNAL_ERROR;
19266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
19366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
19466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    *(localFileName + nativeLibPath.size()) = '/';
19566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
19666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (strlcpy(localFileName + nativeLibPath.size() + 1, fileName, sizeof(localFileName)
19766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root                    - nativeLibPath.size() - 1) != fileNameLen) {
1985baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("Couldn't allocate local file name for library");
1991ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_INTERNAL_ERROR;
20066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
20166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
20266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    // Only copy out the native file if it's different.
20366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    struct stat st;
20466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (!isFileDifferent(localFileName, uncompLen, modTime, crc, &st)) {
2051ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_SUCCEEDED;
20666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
20766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
20866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    char localTmpFileName[nativeLibPath.size() + TMP_FILE_PATTERN_LEN + 2];
20966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (strlcpy(localTmpFileName, nativeLibPath.c_str(), sizeof(localTmpFileName))
21066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            != nativeLibPath.size()) {
2115baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("Couldn't allocate local file name for library");
2121ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_INTERNAL_ERROR;
21366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
21466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
21566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    *(localFileName + nativeLibPath.size()) = '/';
21666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
21766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (strlcpy(localTmpFileName + nativeLibPath.size(), TMP_FILE_PATTERN,
21866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root                    TMP_FILE_PATTERN_LEN - nativeLibPath.size()) != TMP_FILE_PATTERN_LEN) {
2191ebd74acf9977daa42133507e970dab88e08f0efKenny Root        LOGI("Couldn't allocate temporary file name for library");
2201ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_INTERNAL_ERROR;
22166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
22266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
22366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    int fd = mkstemp(localTmpFileName);
22466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (fd < 0) {
22566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        LOGI("Couldn't open temporary file name: %s: %s\n", localTmpFileName, strerror(errno));
2261ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_CONTAINER_ERROR;
22766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
22866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
22966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (!zipFile->uncompressEntry(zipEntry, fd)) {
2301ebd74acf9977daa42133507e970dab88e08f0efKenny Root        LOGI("Failed uncompressing %s to %s\n", fileName, localTmpFileName);
23166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        close(fd);
23266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        unlink(localTmpFileName);
2331ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_CONTAINER_ERROR;
23466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
23566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
23666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    close(fd);
23766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
23866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    // Set the modification time for this file to the ZIP's mod time.
23966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    struct timeval times[2];
24066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    times[0].tv_sec = st.st_atime;
24166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    times[1].tv_sec = modTime;
24266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    times[0].tv_usec = times[1].tv_usec = 0;
24366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (utimes(localTmpFileName, times) < 0) {
24466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        LOGI("Couldn't change modification time on %s: %s\n", localTmpFileName, strerror(errno));
24566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        unlink(localTmpFileName);
2461ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_CONTAINER_ERROR;
24766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
24866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
24966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    // Set the mode to 755
25066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    static const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |  S_IXGRP | S_IROTH | S_IXOTH;
25166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (chmod(localTmpFileName, mode) < 0) {
25266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        LOGI("Couldn't change permissions on %s: %s\n", localTmpFileName, strerror(errno));
25366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        unlink(localTmpFileName);
2541ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_CONTAINER_ERROR;
25566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
25666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
25766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    // Finally, rename it to the final name.
25866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (rename(localTmpFileName, localFileName) < 0) {
25966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        LOGI("Couldn't rename %s to %s: %s\n", localTmpFileName, localFileName, strerror(errno));
26066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        unlink(localTmpFileName);
2611ebd74acf9977daa42133507e970dab88e08f0efKenny Root        return INSTALL_FAILED_CONTAINER_ERROR;
26266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
26366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
26471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("Successfully moved %s to %s\n", localTmpFileName, localFileName);
2651ebd74acf9977daa42133507e970dab88e08f0efKenny Root
2661ebd74acf9977daa42133507e970dab88e08f0efKenny Root    return INSTALL_SUCCEEDED;
26766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}
26866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
26966269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic install_status_t
27066269ea6f68f2f25888ce1080c94ac782742fafcKenny RootiterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2,
27166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        iterFunc callFunc, void* callArg) {
27266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    ScopedUtfChars filePath(env, javaFilePath);
27366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    ScopedUtfChars cpuAbi(env, javaCpuAbi);
27466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    ScopedUtfChars cpuAbi2(env, javaCpuAbi2);
27566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
27666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    ZipFileRO zipFile;
27766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
27866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    if (zipFile.open(filePath.c_str()) != NO_ERROR) {
27966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        LOGI("Couldn't open APK %s\n", filePath.c_str());
28066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        return INSTALL_FAILED_INVALID_APK;
28166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
28266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
28366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    const int N = zipFile.getNumEntries();
28466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
28566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    char fileName[PATH_MAX];
28666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
28766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    for (int i = 0; i < N; i++) {
28866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        const ZipEntryRO entry = zipFile.findEntryByIndex(i);
28966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        if (entry == NULL) {
29066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            continue;
29166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        }
29266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
29366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        // Make sure this entry has a filename.
29466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        if (zipFile.getEntryFileName(entry, fileName, sizeof(fileName))) {
29566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            continue;
29666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        }
29766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
29866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        // Make sure we're in the lib directory of the ZIP.
29966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
30066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            continue;
30166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        }
30266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
30366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        // Make sure the filename is at least to the minimum library name size.
30466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        const size_t fileNameLen = strlen(fileName);
30566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN;
30666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        if (fileNameLen < minLength) {
30766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            continue;
30866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        }
30966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
31066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        const char* lastSlash = strrchr(fileName, '/');
3111ebd74acf9977daa42133507e970dab88e08f0efKenny Root        LOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName);
31266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
31366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        // Check to make sure the CPU ABI of this file is one we support.
31466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        const char* cpuAbiOffset = fileName + APK_LIB_LEN;
31566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset;
31666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
31771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("Comparing ABIs %s and %s versus %s\n", cpuAbi.c_str(), cpuAbi2.c_str(), cpuAbiOffset);
31866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        if (cpuAbi.size() == cpuAbiRegionSize
31966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root                && *(cpuAbiOffset + cpuAbi.size()) == '/'
32066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root                && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) {
32171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Using ABI %s\n", cpuAbi.c_str());
32266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        } else if (cpuAbi2.size() == cpuAbiRegionSize
32366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root                && *(cpuAbiOffset + cpuAbi2.size()) == '/'
32466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root                && !strncmp(cpuAbiOffset, cpuAbi2.c_str(), cpuAbiRegionSize)) {
32571f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("Using ABI %s\n", cpuAbi2.c_str());
32666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        } else {
32771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ALOGV("abi didn't match anything: %s (end at %zd)\n", cpuAbiOffset, cpuAbiRegionSize);
32866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            continue;
32966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        }
33066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
33166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        // If this is a .so file, check to see if we need to copy it.
3321ebd74acf9977daa42133507e970dab88e08f0efKenny Root        if ((!strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
3331ebd74acf9977daa42133507e970dab88e08f0efKenny Root                    && !strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)
3341ebd74acf9977daa42133507e970dab88e08f0efKenny Root                    && isFilenameSafe(lastSlash + 1))
3351ebd74acf9977daa42133507e970dab88e08f0efKenny Root                || !strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
3361ebd74acf9977daa42133507e970dab88e08f0efKenny Root
3371ebd74acf9977daa42133507e970dab88e08f0efKenny Root            install_status_t ret = callFunc(env, callArg, &zipFile, entry, lastSlash + 1);
3381ebd74acf9977daa42133507e970dab88e08f0efKenny Root
3391ebd74acf9977daa42133507e970dab88e08f0efKenny Root            if (ret != INSTALL_SUCCEEDED) {
34071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block                ALOGV("Failure for entry %s", lastSlash + 1);
3411ebd74acf9977daa42133507e970dab88e08f0efKenny Root                return ret;
3421ebd74acf9977daa42133507e970dab88e08f0efKenny Root            }
34366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        }
34466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    }
34566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
34666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    return INSTALL_SUCCEEDED;
34766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}
34866269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
34966269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic jint
35066269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootcom_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz,
35166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        jstring javaFilePath, jstring javaNativeLibPath, jstring javaCpuAbi, jstring javaCpuAbi2)
35266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{
3531ebd74acf9977daa42133507e970dab88e08f0efKenny Root    return (jint) iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2,
35466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            copyFileIfChanged, &javaNativeLibPath);
35566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}
35666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
35766269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic jlong
35866269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootcom_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz,
35966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root        jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2)
36066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{
36166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    size_t totalSize = 0;
36266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
36366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2, sumFiles, &totalSize);
36466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
36566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    return totalSize;
36666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}
36766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
36866269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootstatic JNINativeMethod gMethods[] = {
36966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    {"nativeCopyNativeBinaries",
37066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
37166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            (void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},
37266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    {"nativeSumNativeBinaries",
37366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J",
37466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root            (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries},
37566269ea6f68f2f25888ce1080c94ac782742fafcKenny Root};
37666269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
37766269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
37866269ea6f68f2f25888ce1080c94ac782742fafcKenny Rootint register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env)
37966269ea6f68f2f25888ce1080c94ac782742fafcKenny Root{
38066269ea6f68f2f25888ce1080c94ac782742fafcKenny Root    return AndroidRuntime::registerNativeMethods(env,
38166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root                "com/android/internal/content/NativeLibraryHelper", gMethods, NELEM(gMethods));
38266269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}
38366269ea6f68f2f25888ce1080c94ac782742fafcKenny Root
38466269ea6f68f2f25888ce1080c94ac782742fafcKenny Root};
385