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