1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Utility functions for managing an invocation of "dexopt".
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "vm/DalvikVersion.h"
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdint.h>
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <fcntl.h>
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/stat.h>
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/file.h>
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "OptInvocation.h"
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "DexFile.h"
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kClassesDex = "classes.dex";
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given the filename of a .jar or .dex file, construct the DEX file cache
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * name.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For a Jar, "subFileName" is the name of the entry (usually "classes.dex").
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For a DEX, it may be NULL.
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a newly-allocated string, or NULL on failure.
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar* dexOptGenerateCacheFileName(const char* fileName, const char* subFileName)
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char nameBuf[512];
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static const char kDexCachePath[] = "dalvik-cache";
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char absoluteFile[sizeof(nameBuf)];
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const size_t kBufLen = sizeof(nameBuf) - 1;
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* dataRoot;
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* cp;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Get the absolute path of the Jar or DEX file.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    absoluteFile[0] = '\0';
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fileName[0] != '/') {
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Generate the absolute path.  This doesn't do everything it
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * should, e.g. if filename is "./out/whatever" it doesn't crunch
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the leading "./" out, but it'll do.
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (getcwd(absoluteFile, kBufLen) == NULL) {
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Can't get CWD while opening jar file\n");
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        strncat(absoluteFile, "/", kBufLen);
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    strncat(absoluteFile, fileName, kBufLen);
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Append the name of the Jar file entry, if any.  This is not currently
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * required, but will be if we start putting more than one DEX file
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in a Jar.
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (subFileName != NULL) {
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        strncat(absoluteFile, "/", kBufLen);
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        strncat(absoluteFile, subFileName, kBufLen);
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Turn the path into a flat filename by replacing
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * any slashes after the first one with '@' characters.
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cp = absoluteFile + 1;
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*cp != '\0') {
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == '/') {
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *cp = '@';
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cp++;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Build the name of the cache directory.
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataRoot = getenv("ANDROID_DATA");
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dataRoot == NULL)
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dataRoot = "/data";
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kDexCachePath);
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Tack on the file name for the actual cache file path.
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    strncat(nameBuf, absoluteFile, kBufLen);
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return strdup(nameBuf);
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a skeletal "opt" header in a new file.  Most of the fields are
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initialized to garbage, but we fill in "dexOffset" so others can
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * see how large the header is.
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "fd" must be positioned at the start of the file.  On return, it will
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be positioned just past the header, and the place where the DEX data
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should go.
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns 0 on success, errno on failure.
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dexOptCreateEmptyHeader(int fd)
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOptHeader optHdr;
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ssize_t actual;
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(lseek(fd, 0, SEEK_CUR) == 0);
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The data is only expected to be readable on the current system, so
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we just write the structure.  We do need the file offset to be 64-bit
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * aligned to fulfill a DEX requirement.
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert((sizeof(optHdr) & 0x07) == 0);
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&optHdr, 0xff, sizeof(optHdr));
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    optHdr.dexOffset = sizeof(optHdr);
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    actual = write(fd, &optHdr, sizeof(optHdr));
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (actual != sizeof(optHdr)) {
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int err = errno ? errno : -1;
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("opt header write failed: %s", strerror(errno));
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return errno;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
143