diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:14 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:14 -0800 |
| commit | f72d5de56a522ac3be03873bdde26f23a5eeeb3c (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /vm/JarFile.c | |
| parent | 31e30105703263782efd450d356cd67ea01af3b7 (diff) | |
| download | android_dalvik-f72d5de56a522ac3be03873bdde26f23a5eeeb3c.tar.gz android_dalvik-f72d5de56a522ac3be03873bdde26f23a5eeeb3c.tar.bz2 android_dalvik-f72d5de56a522ac3be03873bdde26f23a5eeeb3c.zip | |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'vm/JarFile.c')
| -rw-r--r-- | vm/JarFile.c | 370 |
1 files changed, 0 insertions, 370 deletions
diff --git a/vm/JarFile.c b/vm/JarFile.c deleted file mode 100644 index 4a4eb622e..000000000 --- a/vm/JarFile.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * Access the contents of a Jar file. - * - * This isn't actually concerned with any of the Jar-like elements; it - * just wants a zip archive with "classes.dex" inside. In Android the - * most common example is ".apk". - */ -#include "Dalvik.h" -#include "libdex/OptInvocation.h" - -#include <stdlib.h> -#include <string.h> -#include <zlib.h> -#include <fcntl.h> -#include <errno.h> - -static const char* kDexInJarName = "classes.dex"; - -/* - * Attempt to open a file whose name is similar to <fileName>, - * but with the supplied suffix. E.g., - * openAlternateSuffix("Home.apk", "dex", O_RDONLY) will attempt - * to open "Home.dex". If the open succeeds, a pointer to a - * malloc()ed copy of the opened file name will be put in <*pCachedName>. - * - * <flags> is passed directly to open(). O_CREAT is not supported. - */ -static int openAlternateSuffix(const char *fileName, const char *suffix, - int flags, char **pCachedName) -{ - char *buf, *c; - size_t fileNameLen = strlen(fileName); - size_t suffixLen = strlen(suffix); - size_t bufLen = fileNameLen + suffixLen + 1; - int fd = -1; - - buf = malloc(bufLen); - if (buf == NULL) { - errno = ENOMEM; - return -1; - } - - /* Copy the original filename into the buffer, find - * the last dot, and copy the suffix to just after it. - */ - memcpy(buf, fileName, fileNameLen + 1); - c = strrchr(buf, '.'); - if (c == NULL) { - errno = ENOENT; - goto bail; - } - memcpy(c + 1, suffix, suffixLen + 1); - - fd = open(buf, flags); - if (fd >= 0) { - *pCachedName = buf; - return fd; - } - LOGV("Couldn't open %s: %s\n", buf, strerror(errno)); -bail: - free(buf); - return -1; -} - -/* - * Checks the dependencies of the dex cache file corresponding - * to the jar file at the absolute path "fileName". - */ -DexCacheStatus dvmDexCacheStatus(const char *fileName) -{ - ZipArchive archive; - char* cachedName = NULL; - int fd; - DexCacheStatus result = DEX_CACHE_ERROR; - ZipEntry entry; - - /* Always treat elements of the bootclasspath as up-to-date. - * The fact that interpreted code is running at all means that this - * should be true. - */ - if (dvmClassPathContains(gDvm.bootClassPath, fileName)) { - return DEX_CACHE_OK; - } - - //TODO: match dvmJarFileOpen()'s logic. Not super-important - // (the odex-first logic is only necessary for dexpreopt) - // but it would be nice to be consistent. - - /* Try to find the dex file inside of the archive. - */ - if (dexZipOpenArchive(fileName, &archive) != 0) { - return DEX_CACHE_BAD_ARCHIVE; - } - entry = dexZipFindEntry(&archive, kDexInJarName); - if (entry != NULL) { - bool newFile = false; - - /* - * See if there's an up-to-date copy of the optimized dex - * in the cache, but don't create one if there isn't. - */ - LOGV("dvmDexCacheStatus: Checking cache for %s\n", fileName); - cachedName = dexOptGenerateCacheFileName(fileName, kDexInJarName); - if (cachedName == NULL) - return -1; - - fd = dvmOpenCachedDexFile(fileName, cachedName, - dexGetZipEntryModTime(&archive, entry), - dexGetZipEntryCrc32(&archive, entry), - /*isBootstrap=*/false, &newFile, /*createIfMissing=*/false); - LOGV("dvmOpenCachedDexFile returned fd %d\n", fd); - if (fd < 0) { - result = DEX_CACHE_STALE; - goto bail; - } - - /* dvmOpenCachedDexFile locks the file as a side-effect. - * Unlock and close it. - */ - if (!dvmUnlockCachedDexFile(fd)) { - /* uh oh -- this process needs to exit or we'll wedge the system */ - LOGE("Unable to unlock DEX file\n"); - goto bail; - } - - /* When createIfMissing is false, dvmOpenCachedDexFile() only - * returns a valid fd if the cache file is up-to-date. - */ - } else { - /* - * There's no dex file in the jar file. See if there's an - * optimized dex file living alongside the jar. - */ - fd = openAlternateSuffix(fileName, "odex", O_RDONLY, &cachedName); - if (fd < 0) { - LOGI("Zip is good, but no %s inside, and no .odex " - "file in the same directory\n", kDexInJarName); - result = DEX_CACHE_BAD_ARCHIVE; - goto bail; - } - - LOGV("Using alternate file (odex) for %s ...\n", fileName); - if (!dvmCheckOptHeaderAndDependencies(fd, false, 0, 0, true, true)) { - LOGE("%s odex has stale dependencies\n", fileName); - LOGE("odex source not available -- failing\n"); - result = DEX_CACHE_STALE_ODEX; - goto bail; - } else { - LOGV("%s odex has good dependencies\n", fileName); - } - } - result = DEX_CACHE_OK; - -bail: - dexZipCloseArchive(&archive); - free(cachedName); - if (fd >= 0) { - close(fd); - } - return result; -} - -/* - * Open a Jar file. It's okay if it's just a Zip archive without all of - * the Jar trimmings, but we do insist on finding "classes.dex" inside - * or an appropriately-named ".odex" file alongside. - * - * If "isBootstrap" is not set, the optimizer/verifier regards this DEX as - * being part of a different class loader. - */ -int dvmJarFileOpen(const char* fileName, const char* odexOutputName, - JarFile** ppJarFile, bool isBootstrap) -{ - ZipArchive archive; - DvmDex* pDvmDex = NULL; - char* cachedName = NULL; - bool archiveOpen = false; - bool locked = false; - int fd = -1; - int result = -1; - - /* Even if we're not going to look at the archive, we need to - * open it so we can stuff it into ppJarFile. - */ - if (dexZipOpenArchive(fileName, &archive) != 0) - goto bail; - archiveOpen = true; - - /* If we fork/exec into dexopt, don't let it inherit the archive's fd. - */ - dvmSetCloseOnExec(dexZipGetArchiveFd(&archive)); - - /* First, look for a ".odex" alongside the jar file. It will - * have the same name/path except for the extension. - */ - fd = openAlternateSuffix(fileName, "odex", O_RDONLY, &cachedName); - if (fd >= 0) { - LOGV("Using alternate file (odex) for %s ...\n", fileName); - if (!dvmCheckOptHeaderAndDependencies(fd, false, 0, 0, true, true)) { - LOGE("%s odex has stale dependencies\n", fileName); - free(cachedName); - close(fd); - fd = -1; - goto tryArchive; - } else { - LOGV("%s odex has good dependencies\n", fileName); - //TODO: make sure that the .odex actually corresponds - // to the classes.dex inside the archive (if present). - // For typical use there will be no classes.dex. - } - } else { - ZipEntry entry; - -tryArchive: - /* - * Pre-created .odex absent or stale. Look inside the jar for a - * "classes.dex". - */ - entry = dexZipFindEntry(&archive, kDexInJarName); - if (entry != NULL) { - bool newFile = false; - - /* - * We've found the one we want. See if there's an up-to-date copy - * in the cache. - * - * On return, "fd" will be seeked just past the "opt" header. - * - * If a stale .odex file is present and classes.dex exists in - * the archive, this will *not* return an fd pointing to the - * .odex file; the fd will point into dalvik-cache like any - * other jar. - */ - if (odexOutputName == NULL) { - cachedName = dexOptGenerateCacheFileName(fileName, - kDexInJarName); - if (cachedName == NULL) - goto bail; - } else { - cachedName = strdup(odexOutputName); - } - LOGV("dvmDexCacheStatus: Checking cache for %s (%s)\n", - fileName, cachedName); - fd = dvmOpenCachedDexFile(fileName, cachedName, - dexGetZipEntryModTime(&archive, entry), - dexGetZipEntryCrc32(&archive, entry), - isBootstrap, &newFile, /*createIfMissing=*/true); - if (fd < 0) { - LOGI("Unable to open or create cache for %s\n", fileName); - goto bail; - } - locked = true; - - /* - * If fd points to a new file (because there was no cached version, - * or the cached version was stale), generate the optimized DEX. - * The file descriptor returned is still locked, and is positioned - * just past the optimization header. - */ - if (newFile) { - u8 startWhen, extractWhen, endWhen; - bool result; - off_t dexOffset, fileLen; - - dexOffset = lseek(fd, 0, SEEK_CUR); - result = (dexOffset > 0); - - if (result) { - startWhen = dvmGetRelativeTimeUsec(); - result = dexZipExtractEntryToFile(&archive, entry, fd); - extractWhen = dvmGetRelativeTimeUsec(); - } - if (result) { - result = dvmOptimizeDexFile(fd, dexOffset, - dexGetZipEntryUncompLen(&archive, entry), - fileName, - dexGetZipEntryModTime(&archive, entry), - dexGetZipEntryCrc32(&archive, entry), - isBootstrap); - } - - if (!result) { - LOGE("Unable to extract+optimize DEX from '%s'\n", - fileName); - goto bail; - } - - endWhen = dvmGetRelativeTimeUsec(); - LOGD("DEX prep '%s': unzip in %dms, rewrite %dms\n", - fileName, - (int) (extractWhen - startWhen) / 1000, - (int) (endWhen - extractWhen) / 1000); - } - } else { - LOGI("Zip is good, but no %s inside, and no valid .odex " - "file in the same directory\n", kDexInJarName); - goto bail; - } - } - - /* - * Map the cached version. This immediately rewinds the fd, so it - * doesn't have to be seeked anywhere in particular. - */ - if (dvmDexFileOpenFromFd(fd, &pDvmDex) != 0) { - LOGI("Unable to map %s in %s\n", kDexInJarName, fileName); - goto bail; - } - - if (locked) { - /* unlock the fd */ - if (!dvmUnlockCachedDexFile(fd)) { - /* uh oh -- this process needs to exit or we'll wedge the system */ - LOGE("Unable to unlock DEX file\n"); - goto bail; - } - locked = false; - } - - LOGV("Successfully opened '%s' in '%s'\n", kDexInJarName, fileName); - - *ppJarFile = (JarFile*) calloc(1, sizeof(JarFile)); - (*ppJarFile)->archive = archive; - (*ppJarFile)->cacheFileName = cachedName; - (*ppJarFile)->pDvmDex = pDvmDex; - cachedName = NULL; // don't free it below - result = 0; - -bail: - /* clean up, closing the open file */ - if (archiveOpen && result != 0) - dexZipCloseArchive(&archive); - free(cachedName); - if (fd >= 0) { - if (locked) - (void) dvmUnlockCachedDexFile(fd); - close(fd); - } - return result; -} - -/* - * Close a Jar file and free the struct. - */ -void dvmJarFileFree(JarFile* pJarFile) -{ - if (pJarFile == NULL) - return; - - dvmDexFileFree(pJarFile->pDvmDex); - dexZipCloseArchive(&pJarFile->archive); - free(pJarFile->cacheFileName); - free(pJarFile); -} - |
