Add oatopt drop in replacement for dexopt
Change-Id: I094375230af2d9a88e30245b390cac71be7b50f4
diff --git a/src/oatopt.cc b/src/oatopt.cc
new file mode 100644
index 0000000..367e5bf
--- /dev/null
+++ b/src/oatopt.cc
@@ -0,0 +1,144 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dex_file.h"
+#include "file.h"
+#include "logging.h"
+#include "oat_file.h"
+#include "os.h"
+#include "UniquePtr.h"
+#include "zip_archive.h"
+
+namespace art {
+
+int ProcessZipFile(int zip_fd, int cache_fd, const char* zip_name, const char *flags) {
+ // TODO: need to read/write to installd opened file descriptors
+ if (false) {
+ UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(zip_fd));
+ if (zip_archive.get() == NULL) {
+ LOG(ERROR) << "Failed to open " << zip_name << " when looking for classes.dex";
+ return -1;
+ }
+
+ UniquePtr<ZipEntry> zip_entry(zip_archive->Find(DexFile::kClassesDex));
+ if (zip_entry.get() == NULL) {
+ LOG(ERROR) << "Failed to find classes.dex within " << zip_name;
+ return -1;
+ }
+
+ UniquePtr<File> file(OS::FileFromFd("oatopt cache file descriptor", cache_fd));
+ bool success = zip_entry->Extract(*file);
+ if (!success) {
+ LOG(ERROR) << "Failed to extract classes.dex from " << zip_name;
+ return -1;
+ }
+ }
+
+ // Opening a zip file for a dex will extract to art-cache
+ UniquePtr<const DexFile> dex_file(DexFile::Open(zip_name, ""));
+ if (dex_file.get() == NULL) {
+ LOG(ERROR) << "Failed to open " << zip_name;
+ return -1;
+ }
+
+ std::string dex_file_option("--dex-file=");
+ dex_file_option += zip_name;
+
+ std::string oat_file_option("--oat=");
+ oat_file_option += GetArtCacheOatFilenameOrDie(OatFile::DexFileToOatFilename(*dex_file.get()));
+
+ execl("/system/bin/dex2oatd",
+ "/system/bin/dex2oatd",
+ "-Xms64m",
+ "-Xmx64m",
+ "--boot-image=/data/art-cache/boot.art",
+ dex_file_option.c_str(),
+ oat_file_option.c_str(),
+ NULL);
+ PLOG(FATAL) << "execl(dex2oatd) failed";
+ return -1;
+}
+
+// Parse arguments. We want:
+// 0. (name of command -- ignored)
+// 1. "--zip"
+// 2. zip fd (input, read-only)
+// 3. cache fd (output, read-write, locked with flock)
+// 4. filename of zipfile
+// 5. flags
+int FromZip(const int argc, const char* const argv[]) {
+ if (argc != 6) {
+ LOG(ERROR) << "Wrong number of args for --zip (found " << argc << ")";
+ return -1;
+ }
+
+ // ignore program name
+
+ // verify --zip
+ CHECK_STREQ(argv[1], "--zip");
+
+ char* zip_end;
+ int zip_fd = strtol(argv[2], &zip_end, 0);
+ if (*zip_end != '\0') {
+ LOG(ERROR) << "bad zip fd: " << argv[2];
+ return -1;
+ }
+#ifndef NDEBUG
+ LOG(INFO) << "zip_fd=" << zip_fd;
+#endif
+
+ char* cache_end;
+ int cache_fd = strtol(argv[3], &cache_end, 0);
+ if (*cache_end != '\0') {
+ LOG(ERROR) << "bad cache fd: " << argv[3];
+ return -1;
+ }
+#ifndef NDEBUG
+ LOG(INFO) << "cache_fd=" << cache_fd;
+#endif
+
+ const char* zip_name = argv[4];
+#ifndef NDEBUG
+ LOG(INFO) << "zip_name=" << zip_name;
+#endif
+
+ const char* flags = argv[5];
+#ifndef NDEBUG
+ LOG(INFO) << "flags=" << flags;
+#endif
+
+ return ProcessZipFile(zip_fd, cache_fd, zip_name, flags);
+}
+
+int oatopt(int argc, char** argv) {
+
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ if (true) {
+ for (int i = 0; i < argc; ++i) {
+ LOG(INFO) << "oatopt: option[" << i << "]=" << argv[i];
+ }
+ }
+
+ if (argc > 1) {
+ if (strcmp(argv[1], "--zip") == 0) {
+ return FromZip(argc, argv);
+ }
+ }
+
+ fprintf(stderr,
+ "Usage:\n\n"
+ "Short version: Don't use this.\n\n"
+ "Slightly longer version: This system-internal tool is used to extract\n"
+ "dex files and produce oat files. See the source code for details.\n");
+
+ return 1;
+}
+
+} // namespace art
+
+int main(int argc, char** argv) {
+ return art::oatopt(argc, argv);
+}